class YARD::Docstring

A documentation string, or “docstring” for short, encapsulates the comments and metadata, or “tags”, of an object. Meta-data is expressed in the form +@tag VALUE+, where VALUE can span over multiple lines as long as they are indented. The following +@example+ tag shows how tags can be indented:

# @example My example
#   a = "hello world"
#   a.reverse
# @version 1.0

Tags can be nested in a documentation string, though the {Tags::Tag} itself is responsible for parsing the inner tags.

Constants

META_MATCH

Matches a tag at the start of a comment line @deprecated Use {DocstringParser::META_MATCH}

Attributes

default_parser[RW]

@note Plugin developers should make sure to reset this value

after parsing finishes. This can be done via the
{Parser::SourceParser.after_parse_list} callback. This will
ensure that YARD can properly parse multiple projects in
the same process.

@return [Class<DocstringParser>] the parser class used to parse

text and optional meta-data from docstrings. Defaults to
{DocstringParser}.

@see DocstringParser @see Parser::SourceParser.after_parse_list

all[R]

@return [String] the raw documentation (including raw tag text)

hash_flag[R]

@return [Boolean] whether the docstring was started with “##”

line_range[RW]

@return [Range] line range in the {#object}‘s file where the docstring was parsed from

object[RW]

@return [CodeObjects::Base] the object that owns the docstring.

ref_tags[R]

@return [Array<Tags::RefTag>] the list of reference tags

Public Class Methods

new(content = '', object = nil) click to toggle source

Creates a new docstring with the raw contents attached to an optional object. Parsing will be done by the {DocstringParser} class.

@note To properly parse directives with proper parser context within

handlers, you should not use this method to create a Docstring.
Instead, use the {parser}, which takes a handler object that
can pass parser state onto directives. If a Docstring is created
with this method, directives do not have access to any parser
state, and may not function as expected.

@example

Docstring.new("hello world\n@return Object return", someobj)

@param [String] content the raw comments to be parsed into a docstring

and associated meta-data.

@param [CodeObjects::Base] object an object to associate the docstring

with.
# File lib/yard/docstring.rb, line 103
def initialize(content = '', object = nil)
  @object = object
  @summary = nil
  @hash_flag = false

  self.all = content
end
new!(text, tags = [], object = nil, raw_data = nil, ref_object = nil) click to toggle source

Creates a new docstring without performing any parsing through a {DocstringParser}. This method is called by DocstringParser when creating the new docstring object.

@param [String] text the textual portion of the docstring @param [Array<Tags::Tag>] tags the list of tag objects in the docstring @param [CodeObjects::Base, nil] object the object associated with the

docstring. May be nil.

@param [String] raw_data the complete docstring, including all

original formatting and any unparsed tags/directives.

@param [CodeObjects::Base, nil] ref_object a reference object used for

the base set of documentation / tag information.
# File lib/yard/docstring.rb, line 77
def self.new!(text, tags = [], object = nil, raw_data = nil, ref_object = nil)
  docstring = allocate
  docstring.replace(text, false)
  docstring.object = object
  docstring.add_tag(*tags)
  docstring.instance_variable_set("@unresolved_reference", ref_object)
  docstring.instance_variable_set("@all", raw_data) if raw_data
  docstring
end
parser(*args) click to toggle source

Creates a parser object using the current {default_parser}. Equivalent to:

Docstring.default_parser.new(*args)

@param args arguments are passed to the {DocstringParser}

class. See {DocstringParser#initialize} for details on
arguments.

@return [DocstringParser] the parser object used to parse a

docstring.
# File lib/yard/docstring.rb, line 38
def parser(*args) default_parser.new(*args) end

Public Instance Methods

+(other) click to toggle source

Adds another {Docstring}, copying over tags.

@param [Docstring, String] other the other docstring (or string) to

add.

@return [Docstring] a new docstring with both docstrings combines

Calls superclass method
# File lib/yard/docstring.rb, line 116
def +(other)
  case other
  when Docstring
    Docstring.new([all, other.all].join("\n"), object)
  else
    super
  end
end
add_tag(*tags) click to toggle source

Adds a tag or reftag object to the tag list. If you want to parse tag data based on the {Tags::DefaultFactory} tag factory, use {DocstringParser} instead.

@param [Tags::Tag, Tags::RefTag] tags list of tag objects to add @return [void]

# File lib/yard/docstring.rb, line 242
def add_tag(*tags)
  tags.each_with_index do |tag, i|
    case tag
    when Tags::Tag
      tag.object = object
      @tags << tag
    when Tags::RefTag, Tags::RefTagList
      @ref_tags << tag
    else
      raise ArgumentError, "expected Tag or RefTag, got #{tag.class} (at index #{i})"
    end
  end
end
all=(content, parse = true)
Alias for: replace
blank?(only_visible_tags = true) click to toggle source

Returns true if the docstring has no content that is visible to a template.

@param [Boolean] only_visible_tags whether only {Tags::Library.visible_tags}

should be checked, or if all tags should be considered.

@return [Boolean] whether or not the docstring has content

# File lib/yard/docstring.rb, line 310
def blank?(only_visible_tags = true)
  if only_visible_tags
    empty? && !tags.any? {|tag| Tags::Library.visible_tags.include?(tag.tag_name.to_sym) }
  else
    empty? && @tags.empty? && @ref_tags.empty?
  end
end
delete_tag_if(&block) click to toggle source

Deletes all tags where the block returns true @yieldparam [Tags::Tag] tag the tag that is being tested @yieldreturn [Boolean] true if the tag should be deleted @return [void] @since 0.7.0

# File lib/yard/docstring.rb, line 300
def delete_tag_if(&block)
  @tags.delete_if(&block)
  @ref_tags.delete_if(&block)
end
delete_tags(name) click to toggle source

Delete all tags with name @param [String] name the tag name @return [void] @since 0.7.0

# File lib/yard/docstring.rb, line 291
def delete_tags(name)
  delete_tag_if {|tag| tag.tag_name.to_s == name.to_s }
end
dup() click to toggle source

Deep-copies a docstring

@note This method creates a new docstring with new tag lists, but does

not create new individual tags. Modifying the tag objects will still
affect the original tags.

@return [Docstring] a new copied docstring @since 0.7.0

Calls superclass method
# File lib/yard/docstring.rb, line 153
def dup
  resolve_reference
  obj = super
  %w(all summary tags ref_tags).each do |name|
    val = instance_variable_defined?("@#{name}") && instance_variable_get("@#{name}")
    obj.instance_variable_set("@#{name}", val ? val.dup : nil)
  end
  obj
end
has_tag?(name) click to toggle source

Returns true if at least one tag by the name name was declared

@param [String] name the tag name to search for @return [Boolean] whether or not the tag name was declared

# File lib/yard/docstring.rb, line 283
def has_tag?(name)
  tags.any? {|tag| tag.tag_name.to_s == name.to_s }
end
hash_flag=(v) click to toggle source
# File lib/yard/docstring.rb, line 57
def hash_flag=(v) @hash_flag = v.nil? ? false : v end
line() click to toggle source

@return [Fixnum] the first line of the {#line_range} @return [nil] if there is no associated {#line_range}

# File lib/yard/docstring.rb, line 167
def line
  line_range ? line_range.first : nil
end
replace(content, parse = true) click to toggle source

Replaces the docstring with new raw content. Called by {#all=}. @param [String] content the raw comments to be parsed

Calls superclass method
# File lib/yard/docstring.rb, line 132
def replace(content, parse = true)
  content = content.join("\n") if content.is_a?(Array)
  @tags = []
  @ref_tags = []
  if parse
    super(parse_comments(content))
  else
    @all = content
    @unresolved_reference = nil
    super(content)
  end
end
Also aliased as: all=
resolve_reference() click to toggle source

Resolves unresolved other docstring reference if there is unresolved reference. Does nothing if there is no unresolved reference.

Normally, you don’t need to call this method explicitly. Resolving unresolved reference is done implicitly.

@return [void]

# File lib/yard/docstring.rb, line 328
def resolve_reference
  loop do
    return if defined?(@unresolved_reference).nil? || @unresolved_reference.nil?
    return if CodeObjects::Proxy === @unresolved_reference

    reference = @unresolved_reference
    @unresolved_reference = nil
    self.all = [reference.docstring.all, @all].join("\n")
  end
end
summary() click to toggle source

Gets the first line of a docstring to the period or the first paragraph. @return [String] The first line or paragraph of the docstring; always ends with a period.

# File lib/yard/docstring.rb, line 173
def summary
  resolve_reference
  return @summary if defined?(@summary) && @summary
  stripped = gsub(/[\r\n](?![\r\n])/, ' ').strip
  num_parens = 0
  idx = length.times do |index|
    case stripped[index, 1]
    when "."
      next_char = stripped[index + 1, 1].to_s
      break index - 1 if num_parens <= 0 && next_char =~ /^\s*$/
    when "\r", "\n"
      next_char = stripped[index + 1, 1].to_s
      if next_char =~ /^\s*$/
        break stripped[index - 1, 1] == '.' ? index - 2 : index - 1
      end
    when "{", "(", "["
      num_parens += 1
    when "}", ")", "]"
      num_parens -= 1
    end
  end
  @summary = stripped[0..idx]
  if !@summary.empty? && @summary !~ /\A\s*\{include:.+\}\s*\Z/
    @summary += '.'
  end
  @summary
end
tag(name) click to toggle source

Convenience method to return the first tag object in the list of tag objects of that name

@example

doc = Docstring.new("@return zero when nil")
doc.tag(:return).text  # => "zero when nil"

@param [#to_s] name the tag name to return data for @return [Tags::Tag] the first tag in the list of {#tags}

# File lib/yard/docstring.rb, line 265
def tag(name)
  tags.find {|tag| tag.tag_name.to_s == name.to_s }
end
tags(name = nil) click to toggle source

Returns a list of tags specified by name or all tags if name is not specified.

@param [#to_s] name the tag name to return data for, or nil for all tags @return [Array<Tags::Tag>] the list of tags by the specified tag name

# File lib/yard/docstring.rb, line 273
def tags(name = nil)
  list = stable_sort_by(@tags + convert_ref_tags, &:tag_name)
  return list unless name
  list.select {|tag| tag.tag_name.to_s == name.to_s }
end
to_raw() click to toggle source

Reformats and returns a raw representation of the tag data using the current tag and docstring data, not the original text.

@return [String] the updated raw formatted docstring data @since 0.7.0 @todo Add Tags::Tag#to_raw and refactor

# File lib/yard/docstring.rb, line 207
def to_raw
  tag_data = tags.map do |tag|
    case tag
    when Tags::OverloadTag
      tag_text = "@#{tag.tag_name} #{tag.signature}\n"
      unless tag.docstring.blank?
        tag_text += "\n  " + tag.docstring.all.gsub(/\r?\n/, "\n  ")
      end
    when Tags::OptionTag
      tag_text = "@#{tag.tag_name} #{tag.name}"
      tag_text += ' [' + tag.pair.types.join(', ') + ']' if tag.pair.types
      tag_text += ' ' + tag.pair.name.to_s if tag.pair.name
      tag_text += "\n " if tag.name && tag.text
      tag_text += ' (' + tag.pair.defaults.join(', ') + ')' if tag.pair.defaults
      tag_text += " " + tag.pair.text.strip.gsub(/\n/, "\n  ") if tag.pair.text
    else
      tag_text = '@' + tag.tag_name
      tag_text += ' [' + tag.types.join(', ') + ']' if tag.types
      tag_text += ' ' + tag.name.to_s if tag.name
      tag_text += "\n " if tag.name && tag.text
      tag_text += ' ' + tag.text.strip.gsub(/\n/, "\n  ") if tag.text
    end
    tag_text
  end
  [strip, tag_data.join("\n")].reject(&:empty?).compact.join("\n")
end
to_s() click to toggle source
Calls superclass method
# File lib/yard/docstring.rb, line 125
def to_s
  resolve_reference
  super
end

Private Instance Methods

convert_ref_tags() click to toggle source

Maps valid reference tags

@return [Array<Tags::RefTag>] the list of valid reference tags

# File lib/yard/docstring.rb, line 344
def convert_ref_tags
  list = @ref_tags.reject {|t| CodeObjects::Proxy === t.owner }

  @ref_tag_recurse_count ||= 0
  @ref_tag_recurse_count += 1
  if @ref_tag_recurse_count > 2
    log.error "#{@object.file}:#{@object.line}: Detected circular reference tag in " \
              "`#{@object}', ignoring all reference tags for this object " \
              "(#{@ref_tags.map {|t| "@#{t.tag_name}" }.join(", ")})."
    @ref_tags = []
    return @ref_tags
  end
  list = list.map(&:tags).flatten
  @ref_tag_recurse_count -= 1
  list
end
parse_comments(comments) click to toggle source

Parses out comments split by newlines into a new code object

@param [String] comments

the newline delimited array of comments. If the comments
are passed as a String, they will be split by newlines.

@return [String] the non-metadata portion of the comments to

be used as a docstring
# File lib/yard/docstring.rb, line 369
def parse_comments(comments)
  parser = self.class.parser
  parser.parse(comments, object)
  @all = parser.raw_text
  @unresolved_reference = parser.reference
  add_tag(*parser.tags)
  parser.text
end
stable_sort_by(list) { |tag| ... } click to toggle source

A stable sort_by method.

@param list [Enumerable] the list to sort. @return [Array] a stable sorted list.

# File lib/yard/docstring.rb, line 382
def stable_sort_by(list)
  list.each_with_index.sort_by {|tag, i| [yield(tag), i] }.map(&:first)
end