Class: YARD::Docstring

Inherits:
String
  • Object
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 =

Matches a tag at the start of a comment line

DocstringParser::META_MATCH

Class Attribute Summary collapse

Instance Attribute Summary collapse

Creating a Docstring Object collapse

Creating and Accessing Meta-data collapse

Class Method Summary collapse

Instance Method Summary collapse

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

See Also:



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

def default_parser
  @default_parser
end

Instance Attribute Details

#allString (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_flagBoolean

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_rangeRange

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

#objectCodeObjects::Base

Returns the object that owns the docstring.

Returns:



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

def object
  @object
end

#ref_tagsArray<Tags::RefTag> (readonly)

Returns the list of reference tags.

Returns:



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:

Returns:



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:

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:



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

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

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

#lineFixnum?

Returns:



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_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.



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

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



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:



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:



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



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_sObject



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

def to_s
  resolve_reference
  super
end