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

META_MATCH =

Matches a tag at the start of a comment line

/^@([a-z_0-9]+)(?:\s+(.*))?$/i

Instance Attribute Summary (collapse)

Creating a Docstring Object (collapse)

Creating and Accessing Meta-data (collapse)

Instance Method Summary (collapse)

Methods inherited from String

#shell_split

Constructor Details

- (Docstring) initialize(content = '', object = nil)

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

Examples:

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


47
48
49
50
51
52
53
# File 'lib/yard/docstring.rb', line 47

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

  self.all = content
end

Instance Attribute Details

- (String) all (readonly)



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

def all
  @all
end

- (Boolean) hash_flag



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

def hash_flag
  @hash_flag
end

- (Range) line_range



23
24
25
# File 'lib/yard/docstring.rb', line 23

def line_range
  @line_range
end

- (CodeObjects::Base) object



20
21
22
# File 'lib/yard/docstring.rb', line 20

def object
  @object
end

- (Array<Tags::RefTag>) ref_tags (readonly)



17
18
19
# File 'lib/yard/docstring.rb', line 17

def ref_tags
  @ref_tags
end

Instance Method Details

- (Docstring) +(other)

Adds another YARD::Docstring, copying over tags.



60
61
62
63
64
65
66
67
# File 'lib/yard/docstring.rb', line 60

def +(other)
  case other
  when Docstring
    Docstring.new([all, other.all].join("\n"), object)
  else
    super
  end
end

- (void) add_tag(*tags)

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



185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/yard/docstring.rb', line 185

def add_tag(*tags)
  tags.each_with_index do |tag, i|
    case tag
    when Tags::Tag
      tag.object = object
      @tags << tag
    when Tags::RefTag
      @ref_tags << tag
    else
      raise ArgumentError, "expected Tag or RefTag, got #{tag.class} (at index #{i})"
    end
  end
end

- (Boolean) blank?(only_visible_tags = true)

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



253
254
255
256
257
258
259
# File 'lib/yard/docstring.rb', line 253

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

- (Tags::Tag, Tags::RefTag) create_tag(tag_name, tag_buf)

Creates a tag from the tag factory.

To add an already created tag object, use #add_tag



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/yard/docstring.rb', line 163

def create_tag(tag_name, tag_buf)
  if tag_buf =~ /\A\s*(?:(\S+)\s+)?\(\s*see\s+(\S+)\s*\)\s*\Z/
    return create_ref_tag(tag_name, $1, $2)
  end

  tag_factory = Tags::Library.instance
  tag_method = "#{tag_name}_tag"
  if tag_name && tag_factory.respond_to?(tag_method)
    add_tag(*[tag_factory.send(tag_method, tag_buf)].flatten)
  else
    log.warn "Unknown tag @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
  end
rescue Tags::TagFormatError
  log.warn "Invalid tag format for @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
end

- (void) delete_tag_if {|tag| ... }

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



243
244
245
246
# File 'lib/yard/docstring.rb', line 243

def delete_tag_if(&block)
  @tags.delete_if(&block)
  @ref_tags.delete_if(&block)
end

- (void) delete_tags(name)

This method returns an undefined value.

Delete all tags with name

Since:

  • 0.7.0



234
235
236
# File 'lib/yard/docstring.rb', line 234

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

- (Docstring) dup

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

Since:

  • 0.7.0



86
87
88
89
90
91
92
93
# File 'lib/yard/docstring.rb', line 86

def dup
  obj = super
  %w(all summary tags ref_tags).each do |name|
    val = instance_variable_get("@#{name}")
    obj.instance_variable_set("@#{name}", val ? val.dup : nil)
  end
  obj
end

- (Boolean) has_tag?(name)

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



226
227
228
# File 'lib/yard/docstring.rb', line 226

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

- (Fixnum?) line



99
100
101
# File 'lib/yard/docstring.rb', line 99

def line
  line_range ? line_range.first : nil
end

- (Object) replace(content) Also known as: all=

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



71
72
73
74
75
76
# File 'lib/yard/docstring.rb', line 71

def replace(content)
  content = content.join("\n") if content.is_a?(Array)
  @tags, @ref_tags = [], []
  @all = content
  super parse_comments(content)
end

- (String) summary

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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/yard/docstring.rb', line 105

def summary
  return @summary if @summary
  open_parens = ['{', '(', '[']
  close_parens = ['}', ')', ']']
  num_parens = 0
  idx = length.times do |index|
    case self[index, 1]
    when ".", "\r", "\n"
      next_char = self[index + 1, 1].to_s
      if num_parens == 0 && next_char =~ /^\s*$/
        break index - 1
      end
    when "{", "(", "["
      num_parens += 1
    when "}", ")", "]"
      num_parens -= 1
    end
  end
  @summary = self[0..idx]
  @summary += '.' unless @summary.empty?
  @summary
end

- (Tags::Tag) tag(name)

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"


208
209
210
# File 'lib/yard/docstring.rb', line 208

def tag(name)
  tags.find {|tag| tag.tag_name.to_s == name.to_s }
end

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

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



216
217
218
219
220
# File 'lib/yard/docstring.rb', line 216

def tags(name = nil)
  list = @tags + convert_ref_tags
  return list unless name
  list.select {|tag| tag.tag_name.to_s == name.to_s }
end

- (String) to_raw

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.

Since:

  • 0.7.0



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/yard/docstring.rb', line 134

def to_raw
  tag_data = tags.sort_by {|t| t.tag_name }.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
    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 {|l| l.empty? }.compact.join("\n")
end