123456789_123456789_123456789_123456789_123456789_

Class: YARD::CodeObjects::Base Abstract

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Inherits: Object
Defined in: lib/yard/code_objects/base.rb

Overview

This class is abstract.

This class should not be used directly. Instead, create a subclass that implements #path, #sep or #type. You might also need to register custom separators if #sep uses alternate separator tokens.

Base is the superclass of all code objects recognized by ::YARD. A code object is any entity in the Ruby language (class, method, module). A DSL might subclass Base to create a new custom object representing a new entity type.

Registry Integration

Any created object associated with a namespace is immediately registered with the registry. This allows the ::YARD::Registry to act as an identity map to ensure that no object is represented by more than one Ruby object in memory. A unique #path is essential for this identity map to work correctly.

Custom Attributes

Code objects allow arbitrary custom attributes to be set using the #[]= assignment method.

Namespaces

There is a special type of object called a "namespace". These are subclasses of the NamespaceObject and represent Ruby entities that can have objects defined within them. Classically these are modules and classes, though a DSL might create a custom NamespaceObject to describe a specific set of objects.

Separators

Custom classes with different separator tokens should define their own separators using the NamespaceMapper#register_separator method. The standard Ruby separators have already been defined ('::', '#', '.', etc).

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(namespace, name, *args) {|obj| ... } ⇒ Base

Allocates a new code object

Yields:

  • (obj)

Raises:

  • (ArgumentError)

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 189

def new(namespace, name, *args, &block)
  raise ArgumentError, "invalid empty object name" if name.to_s.empty?
  if namespace.is_a?(ConstantObject)
    unless namespace.value =~ /\A#{NAMESPACEMATCH}\Z/
      raise Parser::UndocumentableError, "constant mapping"
    end

    namespace = Proxy.new(namespace.namespace, namespace.value)
  end

  if name.to_s[0, 2] == NSEP
    name = name.to_s[2..-1]
    namespace = Registry.root
  end

  if name =~ /(?:#{NSEPQ})([^:]+)$/
    return new(Proxy.new(namespace, $`), $1, *args, &block)
  end

  obj = super(namespace, name, *args)
  existing_obj = Registry.at(obj.path)
  obj = existing_obj if existing_obj && existing_obj.class == self
  yield(obj) if block_given?
  obj
end

#initialize(namespace, name) {|self| ... } ⇒ Base

Creates a new code object

Examples:

Create a method in the root namespace

CodeObjects::Base.new(:root, '#method') # => #<yardoc method #method>

Create class Z inside namespace X::Y

CodeObjects::Base.new(P("X::Y"), :Z) # or
CodeObjects::Base.new(Registry.root, "X::Y")

Parameters:

  • namespace (NamespaceObject)

    the namespace the object belongs in, Registry.root or :root should be provided if it is associated with the top level namespace.

  • name (Symbol, String)

    the name (or complex path) of the object.

Yields:

  • (self)

    a block to perform any extra initialization on the object

Yield Parameters:

  • self (Base)

    the newly initialized code object

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 238

def initialize(namespace, name, *)
  if namespace && namespace != :root &&
     !namespace.is_a?(NamespaceObject) && !namespace.is_a?(Proxy)
    raise ArgumentError, "Invalid namespace object: #{namespace}"
  end

  @files = []
  @current_file_has_comments = false
  @name = name.to_sym
  @source_type = :ruby
  @visibility = :public
  @tags = []
  @docstrings = {}
  @docstring = Docstring.new!('', [], self)
  @namespace = nil
  self.namespace = namespace
  yield(self) if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#dynamic_attr_nameObject #dynamic_attr_name=(value) ⇒ Object

Overloads:

  • #dynamic_attr_nameObject

    Returns:

    • the value of attribute named by the method attribute name

    Raises:

    • (NoMethodError)

      if no method or custom attribute exists by the attribute name

    See Also:

  • #dynamic_attr_name=(value) ⇒ Object

    Parameters:

    • value

      a value to set

    Returns:

    • value

    See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 373

def method_missing(meth, *args, &block)
  if meth.to_s =~ /=$/
    self[meth.to_s[0..-2]] = args.first
  elsif instance_variable_get("@#{meth}")
    self[meth]
  else
    super
  end
end

Class Method Details

.===(other) ⇒ Boolean

Compares the class with subclasses

Parameters:

  • other (Object)

    the other object to compare classes with

Returns:

  • (Boolean)

    true if other is a subclass of self

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 219

def ===(other)
  other.is_a?(self)
end

Instance Attribute Details

#base_docstringDocstring (readonly)

The non-localized documentation string associated with the object

Returns:

Since:

  • 0.8.4

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 166

attr_reader :base_docstring

#dynamicBoolean (rw)

Marks whether or not the method is conditionally defined at runtime

Returns:

  • (Boolean)

    true if the method is conditionally defined at runtime

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 170

attr_accessor :dynamic

#dynamic?Boolean (rw)

Is the object defined conditionally at runtime?

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 178

def dynamic?; @dynamic end

#filesArray<Array(String, Integer)> (readonly)

The files the object was defined in. To add a file, use #add_file.

Returns:

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 137

attr_reader :files

#groupString (rw)

Returns:

  • (String)

    the group this object is associated with

Since:

  • 0.6.0

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 174

attr_accessor :group

#namespaceNamespaceObject (rw) Also known as: #parent

The namespace the object is defined in. If the object is in the top level namespace, this is Registry.root

Returns:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 142

attr_reader :namespace

#namespace=(obj) (rw) Also known as: #parent=

Sets the namespace the object is defined in.

Parameters:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 522

def namespace=(obj)
  if @namespace
    @namespace.children.delete(self)
    Registry.delete(self)
  end

  @namespace = (obj == :root ? Registry.root : obj)

  if @namespace
    reg_obj = Registry.at(path)
    return if reg_obj && reg_obj.class == self.class

    unless @namespace.is_a?(Proxy)
      # remove prior objects from obj's children that match this one
      @namespace.children.delete_if {|o| o.path == path }
      @namespace.children << self
    end
    Registry.register(self)
  end
end

#parent (rw)

Alias for #namespace.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 543

alias parent namespace

#root?Boolean (readonly)

Returns:

  • (Boolean)

    whether or not this object is a RootObject

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 567

def root?; false end

#signatureString (rw)

The one line signature representing an object. For a method, this will be of the form "def meth(arguments...)". This is usually the first source line.

Returns:

  • (String)

    a line of source

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 159

attr_accessor :signature

#sourceString? (rw)

The source code associated with the object

Returns:

  • (String, nil)

    source, if present, or nil

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 146

attr_reader :source

#source=(statement) (rw)

Attaches source code to a code object with an optional file location

Parameters:

  • statement (#source, String)

    the Parser::Statement holding the source code or the raw source as a ::String for the definition of the code object only (not the block)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 388

def source=(statement)
  if statement.respond_to?(:source)
    @source = format_source(statement.source.strip)
  else
    @source = format_source(statement.to_s)
  end

  if statement.respond_to?(:signature)
    self.signature = statement.signature
  end
end

#source_typeSymbol (rw)

Language of the source code associated with the object. Defaults to :ruby.

Returns:

  • (Symbol)

    the language type

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 152

attr_accessor :source_type

#visibilitySymbol (rw)

Returns:

  • (Symbol)

    the visibility of an object (:public, :private, :protected)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 181

attr_accessor :visibility

#visibility=(v) ⇒ Symbol (rw)

Returns:

  • (Symbol)

    the visibility of an object (:public, :private, :protected)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 183

attr_accessor :visibility

Instance Method Details

#==(other)

Alias for #equal?.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 330

alias == equal?

#[](key) ⇒ Object?

Accesses a custom attribute on the object

Parameters:

  • key (#to_s)

    the name of the custom attribute

Returns:

  • (Object, nil)

    the custom attribute or nil if not found.

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 343

def [](key)
  if respond_to?(key)
    send(key)
  elsif instance_variable_defined?("@#{key}")
    instance_variable_get("@#{key}")
  end
end

#[]=(key, value) ⇒ void

This method returns an undefined value.

Sets a custom attribute on the object

Parameters:

  • key (#to_s)

    the name of the custom attribute

  • value (Object)

    the value to associate

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 356

def []=(key, value)
  if respond_to?("#{key}=")
    send("#{key}=", value)
  else
    instance_variable_set("@#{key}", value)
  end
end

#add_file(file, line = nil, has_comments = false)

Associates a file with a code object, optionally adding the line where it was defined. By convention, '' should be used to associate code that comes form standard input.

Parameters:

  • file (String)

    the filename ('' for standard input)

  • line (Fixnum, nil) (defaults to: nil)

    the line number where the object lies in the file

  • has_comments (Boolean) (defaults to: false)

    whether or not the definition has comments associated. This will allow #file to return the definition where the comments were made instead of any empty definitions that might have been parsed before (module namespaces for instance).

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 290

def add_file(file, line = nil, has_comments = false)
  raise(ArgumentError, "file cannot be nil or empty") if file.nil? || file == ''
  obj = [file.to_s, line]
  return if files.include?(obj)
  if has_comments && !@current_file_has_comments
    @current_file_has_comments = true
    @files.unshift(obj)
  else
    @files << obj # back of the line
  end
end

#add_tag(*tags)

Add tags to the #docstring

See Also:

Since:

  • 0.8.4

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 561

def add_tag(*tags)
  @docstrings.clear
  @docstring.add_tag(*tags)
end

#copy_to(other) ⇒ Base

Copies all data in this object to another code object, except for uniquely identifying information (path, namespace, name, scope).

Parameters:

  • other (Base)

    the object to copy data to

Returns:

  • (Base)

    the other object

Since:

  • 0.8.0

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 263

def copy_to(other)
  copyable_attributes.each do |ivar|
    ivar = "@#{ivar}"
    other.instance_variable_set(ivar, instance_variable_get(ivar))
  end
  other.docstring = @docstring.to_raw
  other
end

#docstring(locale = I18n::Locale.default) ⇒ Docstring

The documentation string associated with the object

Parameters:

  • locale (String, I18n::Locale) (defaults to: I18n::Locale.default)

    (I18n::Locale.default) the locale of the documentation string.

Returns:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 405

def docstring(locale = I18n::Locale.default)
  if locale.nil?
    @docstring.resolve_reference
    return @docstring
  end

  if locale.is_a?(String)
    locale_name = locale
    locale = nil
  else
    locale_name = locale.name
  end
  @docstrings[locale_name] ||=
    translate_docstring(locale || Registry.locale(locale_name))
end

#docstring=(comments)

Attaches a docstring to a code object by parsing the comments attached to the statement and filling the #tags and #docstring methods with the parsed information.

Parameters:

  • comments (String, Array<String>, Docstring)

    the comments attached to the code object to be parsed into a docstring and meta tags.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 427

def docstring=(comments)
  @docstrings.clear
  @docstring = Docstring === comments ?
    comments : Docstring.new(comments, self)
end

#eql?(other)

Alias for #equal?.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 331

alias eql? equal?

#equal?(other) ⇒ Boolean Also known as: #==, #eql?

Tests if another object is equal to this, including a proxy

Parameters:

  • other (Base, Proxy)

    if other is a Proxy, tests if the paths are equal

Returns:

  • (Boolean)

    whether or not the objects are considered the same

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 323

def equal?(other)
  if other.is_a?(Base) || other.is_a?(Proxy)
    path == other.path
  else
    super
  end
end

#fileString?

Returns the filename the object was first parsed at, taking definitions with docstrings first.

Returns:

  • (String)

    a filename

  • (nil)

    if there is no file associated with the object

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 307

def file
  @files.first ? @files.first[0] : nil
end

#format(options = {}) ⇒ String

Renders the object using the templating system.

Examples:

Formats a class in plaintext

puts P('MyClass').format

Formats a method in html with rdoc markup

puts P('MyClass#meth').format(:format => :html, :markup => :rdoc)

Parameters:

  • options (Hash) (defaults to: {})

    a set of options to pass to the template

Options Hash (options):

  • :format (Symbol) — default: :text

    :html, :text or another output format

  • :template (Symbol) — default: :default

    a specific template to use

  • :markup (Symbol) — default: nil

    the markup type (:rdoc, :markdown, :textile)

  • :serializer (Serializers::Base) — default: nil

Returns:

  • (String)

    the rendered template

See Also:

  • Templates::Engine#render
[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 505

def format(options = {})
  options = options.merge(:object => self)
  options = options.merge(:type => type) unless options[:type]
  Templates::Engine.render(options)
end

#format_source(source) ⇒ String (private)

Formats source code by removing leading indentation

Parameters:

  • source (String)

    the source code to format

Returns:

  • (String)

    formatted source

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 599

def format_source(source)
  source = source.chomp
  last = source.split(/\r?\n/).last
  indent = last ? last[/^([ \t]*)/, 1].length : 0
  source.gsub(/^[ \t]{#{indent}}/, '')
end

#has_tag?(name) ⇒ Boolean

Tests if the #docstring has a tag

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 556

def has_tag?(name); docstring.has_tag?(name) end

#hashInteger

Returns:

  • (Integer)

    the object's hash value (for equality checking)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 334

def hash; path.hash end

#inspectString

Inspects the object, returning the type and path

Returns:

  • (String)

    a string describing the object

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 513

def inspect
  "#<yardoc #{type} #{path}>"
end

#lineFixnum?

Returns the line the object was first parsed at (or nil)

Returns:

  • (Fixnum)

    the line where the object was first defined.

  • (nil)

    if there is no line associated with the object

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 315

def line
  @files.first ? @files.first[1] : nil
end

#name(prefix = false) ⇒ Symbol, String

The name of the object

Parameters:

  • prefix (Boolean) (defaults to: false)

    whether to show a prefix. Implement this in a subclass to define how the prefix is showed.

Returns:

  • (Symbol)

    if prefix is false, the symbolized name

  • (String)

    if prefix is true, prefix + the name as a ::String. This must be implemented by the subclass.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 278

def name(prefix = false)
  prefix ? @name.to_s : (defined?(@name) && @name)
end

#pathString Also known as: #to_s

Represents the unique path of the object. The default implementation joins the path of #namespace with #name via the value of #sep. Custom code objects should ensure that the path is unique to the code object by either overriding #sep or this method.

Examples:

The path of an instance method

MethodObject.new(P("A::B"), :c).path # => "A::B#c"

Returns:

  • (String)

    the unique path of the object

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 453

def path
  @path ||= if parent && !parent.root?
              [parent.path, name.to_s].join(sep)
            else
              name.to_s
            end
end

#relative_path(other) ⇒ String

Parameters:

  • other (Base, String)

    another code object (or object path)

Returns:

  • (String)

    the shortest relative path from this object to other

Since:

  • 0.5.3

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 475

def relative_path(other)
  other = Registry.at(other) if String === other && Registry.at(other)
  same_parent = false
  if other.respond_to?(:path)
    same_parent = other.parent == parent
    other = other.path
  end
  return other unless namespace
  common = [path, other].join(" ").match(/^(\S*)\S*(?: \1\S*)*$/)[1]
  common = path unless common =~ /(\.|::|#)$/
  common = common.sub(/(\.|::|#)[^:#\.]*?$/, '') if same_parent
  suffix = %w(. :).include?(common[-1, 1]) || other[common.size, 1] == '#' ?
    '' : '(::|\.)'
  result = other.sub(/^#{Regexp.quote common}#{suffix}/, '')
  result.empty? ? other : result
end

#sepString

Override this method with a custom component separator. For instance, MethodObject implements sep as '#' or '.' (depending on if the method is instance or class respectively). #path depends on this value to generate the full path in the form: namespace.path + sep + name

Returns:

  • (String)

    the component that separates the namespace path and the name (default is NSEP)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 576

def sep; NSEP end

#tag(name)

Gets a tag from the #docstring

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 548

def tag(name); docstring.tag(name) end

#tags(name = nil)

Gets a list of tags from the #docstring

See Also:

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 552

def tags(name = nil); docstring.tags(name) end

#titleString

Note:

Override this method if your object has a special title that does not match the #path attribute value. This title will be used when linking or displaying the object.

Returns:

  • (String)

    the display title for an object

See Also:

  • 0.8.4
[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 468

def title
  path
end

#to_arynil

Returns:

  • (nil)

    this object does not turn into an array

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 337

def to_ary; nil end

#to_s

Alias for #path.

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 460

alias to_s path

#translate_docstring(locale) (private)

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 606

def translate_docstring(locale)
  @docstring.resolve_reference
  return @docstring if locale.nil?

  text = I18n::Text.new(@docstring)
  localized_text = text.translate(locale)
  docstring = Docstring.new(localized_text, self)
  @docstring.tags.each do |tag|
    if tag.is_a?(Tags::Tag)
      localized_tag = tag.clone
      localized_tag.text = I18n::Text.new(tag.text).translate(locale)
      docstring.add_tag(localized_tag)
    else
      docstring.add_tag(tag)
    end
  end
  docstring
end

#typeSymbol

Default type is the lowercase class name without the "Object" suffix. Override this method to provide a custom object type

Returns:

  • (Symbol)

    the type of code object this represents

[ GitHub ]

  
# File 'lib/yard/code_objects/base.rb', line 437

def type
  obj_name = self.class.name.split('::').last
  obj_name.gsub!(/Object$/, '')
  obj_name.downcase!
  obj_name.to_sym
end