123456789_123456789_123456789_123456789_123456789_

Class: YARD::Docstring

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ::String
Instance Chain:
self, ::String
Inherits: String
  • Object
Defined in: lib/yard/docstring.rb

Overview

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.

Constant Summary

Creating a Docstring Object

Creating and Accessing Meta-data

Class Attribute Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

::String - Inherited

#shell_split

Splits text into tokens the way a shell would, handling quoted text as a single token.

Constructor Details

.new(content = '', object = nil) ⇒ Docstring

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.

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

Examples:

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

Parameters:

  • content (String) (defaults to: '')

    the raw comments to be parsed into a docstring and associated meta-data.

  • object (CodeObjects::Base) (defaults to: nil)

    an object to associate the docstring with.

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 103

def initialize(content = '', object = nil)
  @object = object
  @summary = nil
  @hash_flag = false

  self.all = content
end

Class Attribute Details

.default_parserClass<DocstringParser> (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.

Returns:

See Also:

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 28

attr_accessor :default_parser

Class Method Details

.new!(text, tags = [], object = nil, raw_data = nil, ref_object = nil)

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

Parameters:

  • text (String)

    the textual portion of the docstring

  • tags (Array<Tags::Tag>) (defaults to: [])

    the list of tag objects in the docstring

  • object (CodeObjects::Base, nil) (defaults to: nil)

    the object associated with the docstring. May be nil.

  • raw_data (String) (defaults to: nil)

    the complete docstring, including all original formatting and any unparsed tags/directives.

  • ref_object (CodeObjects::Base, nil) (defaults to: nil)

    a reference object used for the base set of documentation / tag information.

[ GitHub ]

  
# 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) ⇒ DocstringParser

Creates a parser object using the current .default_parser. Equivalent to: Docstring.default_parser.new(*args)

Parameters:

  • args

    arguments are passed to the DocstringParser class. See DocstringParser#initialize for details on arguments.

Returns:

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 38

def parser(*args) default_parser.new(*args) end

Instance Attribute Details

#hash_flagBoolean (rw)

Returns:

  • (Boolean)

    whether the docstring was started with "##"

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 56

attr_reader :hash_flag

#hash_flag=(v) (rw)

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 57

def hash_flag=(v) @hash_flag = v.nil? ? false : v end

#line_rangeRange (rw)

Returns:

  • (Range)

    line range in the #object's file where the docstring was parsed from

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 50

attr_accessor :line_range

#objectCodeObjects::Base (rw)

Returns:

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 47

attr_accessor :object

#ref_tagsArray<Tags::RefTag> (readonly)

Returns:

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 44

attr_reader :ref_tags

Instance Method Details

#+(other) ⇒ Docstring

Adds another Docstring, copying over tags.

Parameters:

  • other (Docstring, String)

    the other docstring (or string) to add.

Returns:

  • (Docstring)

    a new docstring with both docstrings combines

[ GitHub ]

  
# 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) ⇒ void

This method returns an undefined value.

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.

Parameters:

[ GitHub ]

  
# 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

#allString

Returns:

  • (String)

    the raw documentation (including raw tag text)

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 53

attr_reader :all

#all=(content, parse = true)

Alias for #replace.

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 144

alias all= replace

#blank?(only_visible_tags = true) ⇒ Boolean

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

Parameters:

  • only_visible_tags (Boolean) (defaults to: true)

    whether only Tags::Library.visible_tags should be checked, or if all tags should be considered.

Returns:

  • (Boolean)

    whether or not the docstring has content

[ GitHub ]

  
# 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

#convert_ref_tagsArray<Tags::RefTag> (private)

Maps valid reference tags

Returns:

[ GitHub ]

  
# 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

#delete_tag_if {|tag| ... } ⇒ void

This method returns an undefined value.

Deletes all tags where the block returns true

Yield Parameters:

  • tag (Tags::Tag)

    the tag that is being tested

Yield Returns:

  • (Boolean)

    true if the tag should be deleted

Since:

  • 0.7.0

[ GitHub ]

  
# 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) ⇒ void

This method returns an undefined value.

Delete all tags with name

Parameters:

  • name (String)

    the tag name

Since:

  • 0.7.0

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 291

def delete_tags(name)
  delete_tag_if {|tag| tag.tag_name.to_s == name.to_s }
end

#dupDocstring

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.

Deep-copies a docstring

Returns:

  • (Docstring)

    a new copied docstring

Since:

  • 0.7.0

[ GitHub ]

  
# 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) ⇒ Boolean

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

Parameters:

  • name (String)

    the tag name to search for

Returns:

  • (Boolean)

    whether or not the tag name was declared

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 283

def has_tag?(name)
  tags.any? {|tag| tag.tag_name.to_s == name.to_s }
end

#lineFixnum?

Returns:

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 167

def line
  line_range ? line_range.first : nil
end

#parse_comments(comments) ⇒ String (private)

Parses out comments split by newlines into a new code object

Parameters:

  • comments (String)

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

Returns:

  • (String)

    the non-metadata portion of the comments to be used as a docstring

[ GitHub ]

  
# 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

#replace(content, parse = true) Also known as: #all=

Replaces the docstring with new raw content. Called by #all=.

Parameters:

  • content (String)

    the raw comments to be parsed

[ GitHub ]

  
# 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

#resolve_referencevoid

This method returns an undefined value.

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.

[ GitHub ]

  
# 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

#stable_sort_by(list) ⇒ Array (private)

A stable sort_by method.

Parameters:

  • list (Enumerable)

    the list to sort.

Returns:

  • (Array)

    a stable sorted list.

[ GitHub ]

  
# 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

#summaryString

Gets the first line of a docstring to the period or the first paragraph.

Returns:

  • (String)

    The first line or paragraph of the docstring; always ends with a period.

[ GitHub ]

  
# 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) ⇒ Tags::Tag

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

Examples:

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

Parameters:

  • name (#to_s)

    the tag name to return data for

Returns:

[ GitHub ]

  
# 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) ⇒ Array<Tags::Tag>

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

Parameters:

  • name (#to_s) (defaults to: nil)

    the tag name to return data for, or nil for all tags

Returns:

[ GitHub ]

  
# 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_rawString

TODO:

Add Tags::Tag#to_raw and refactor

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

Returns:

  • (String)

    the updated raw formatted docstring data

Since:

  • 0.7.0

[ GitHub ]

  
# 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

[ GitHub ]

  
# File 'lib/yard/docstring.rb', line 125

def to_s
  resolve_reference
  super
end