# Class: YARD::Docstring

Inherits:
  String
  - Object
  - String
  - YARD::Docstring
  show all

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 collapse

META_MATCH =
Deprecated.

Use YARD::DocstringParser::META_MATCH

Matches a tag at the start of a comment line

      DocstringParser::META_MATCH

## Class Attribute Summary collapse

- .default_parser ⇒ Class<DocstringParser>

  The parser class used to parse text and optional meta-data from docstrings.

## Instance Attribute Summary collapse

- #all ⇒ String readonly

  The raw documentation (including raw tag text).

- #hash_flag ⇒ Boolean

  Whether the docstring was started with “##”.

- #line_range ⇒ Range

  Line range in the #object‘s file where the docstring was parsed from.

- #object ⇒ CodeObjects::Base

  The object that owns the docstring.

- #ref_tags ⇒ Array<Tags::RefTag> readonly

  The list of reference tags.

## Creating a Docstring Object collapse

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

  Creates a new docstring without performing any parsing through a DocstringParser.

- #+(other) ⇒ Docstring

  Adds another Docstring, copying over tags.

- #dup ⇒ Docstring

  Deep-copies a docstring.

- #initialize(content = '', object = nil) ⇒ Docstring constructor

  Creates a new docstring with the raw contents attached to an optional object.

- #replace(content, parse = true) ⇒ Object (also: #all=)

  Replaces the docstring with new raw content.

- #to_s ⇒ Object

## Creating and Accessing Meta-data collapse

- #add_tag(*tags) ⇒ void

  Adds a tag or reftag object to the tag list.

- #blank?(only_visible_tags = true) ⇒ Boolean

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

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

  Deletes all tags where the block returns true.

- #delete_tags(name) ⇒ void

  Delete all tags with `name`.

- #has_tag?(name) ⇒ Boolean

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

- #tag(name) ⇒ Tags::Tag

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

- #tags(name = nil) ⇒ Array<Tags::Tag>

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

## Class Method Summary collapse

- .parser(*args) ⇒ DocstringParser

  Creates a parser object using the current Docstring.default_parser.

## Instance Method Summary collapse

- #line ⇒ Fixnum?
- #resolve_reference ⇒ void

  Resolves unresolved other docstring reference if there is unresolved reference.

- #summary ⇒ String

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

- #to_raw ⇒ String

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

## Constructor Details

### #initialize(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 YARD::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.

    103
    104
    105
    106
    107
    108
    109

    # 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_parser ⇒ `Class<DocstringParser>`

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 the parser class used to parse text and optional meta-data from docstrings. Defaults to YARD::DocstringParser.

Returns:

- (`Class<DocstringParser>`) —

  the parser class used to parse text and optional meta-data from docstrings. Defaults to YARD::DocstringParser.

See Also:

- YARD::DocstringParser
- Parser::SourceParser.after_parse_list

    28
    29
    30

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

    def default_parser
      @default_parser
    end

## Instance Attribute Details

### #all ⇒ `String` (readonly)

Returns the raw documentation (including raw tag text).

Returns:

- (`String`) —

  the raw documentation (including raw tag text)

    53
    54
    55

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

    def all
      @all
    end

### #hash_flag ⇒ `Boolean`

Returns whether the docstring was started with “##”.

Returns:

- (`Boolean`) —

  whether the docstring was started with “##”

    56
    57
    58

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

    def hash_flag
      @hash_flag
    end

### #line_range ⇒ `Range`

Returns line range in the #object‘s file where the docstring was parsed from.

Returns:

- (`Range`) —

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

    50
    51
    52

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

    def line_range
      @line_range
    end

### #object ⇒ `CodeObjects::Base`

Returns the object that owns the docstring.

Returns:

- (`CodeObjects::Base`) —

  the object that owns the docstring.

    47
    48
    49

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

    def object
      @object
    end

### #ref_tags ⇒ `Array<Tags::RefTag>` (readonly)

Returns the list of reference tags.

Returns:

- (`Array<Tags::RefTag>`) —

  the list of reference tags

    44
    45
    46

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

    def ref_tags
      @ref_tags
    end

## Class Method Details

### .new!(text, tags = [], object = nil, raw_data = nil, ref_object = nil) ⇒ `Object`

Creates a new docstring without performing any parsing through a YARD::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.

    77
    78
    79
    80
    81
    82
    83
    84
    85

    # 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 YARD::DocstringParser class. See YARD::DocstringParser#initialize for details on arguments.

Returns:

- (`DocstringParser`) —

  the parser object used to parse a docstring.

    38

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

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

## Instance Method Details

### #+(other) ⇒ `Docstring`

Adds another YARD::Docstring, copying over tags.

Parameters:

- other (`Docstring`, `String`) —

  the other docstring (or string) to add.

Returns:

- (`Docstring`) —

  a new docstring with both docstrings combines

    116
    117
    118
    119
    120
    121
    122
    123

    # 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 YARD::DocstringParser instead.

Parameters:

- tags (`Tags::Tag`, `Tags::RefTag`) —

  list of tag objects to add

    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254

    # 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

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

    310
    311
    312
    313
    314
    315
    316

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

    300
    301
    302
    303

    # 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

    291
    292
    293

    # 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 ⇒ `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.

Deep-copies a docstring

Returns:

- (`Docstring`) —

  a new copied docstring

Since:

- 0.7.0

    153
    154
    155
    156
    157
    158
    159
    160
    161

    # 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

    283
    284
    285

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

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

### #line ⇒ `Fixnum`?

Returns:

- (`Fixnum`) —

  the first line of the #line_range

- (`nil`) —

  if there is no associated #line_range

    167
    168
    169

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

    def line
      line_range ? line_range.first : nil
    end

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

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

Parameters:

- content (`String`) —

  the raw comments to be parsed

    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143

    # 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_reference ⇒ `void`

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.

    328
    329
    330
    331
    332
    333
    334
    335
    336
    337

    # 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 ⇒ `String`

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.

    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199

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

- (`Tags::Tag`) —

  the first tag in the list of #tags

    265
    266
    267

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

- (`Array<Tags::Tag>`) —

  the list of tags by the specified tag name

    273
    274
    275
    276
    277

    # 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 ⇒ `String`

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

    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232

    # 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 ⇒ `Object`

    125
    126
    127
    128

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

    def to_s
      resolve_reference
      super
    end