class RDoc::Comment

A comment holds the text comment for a RDoc::CodeObject and provides a unified way of cleaning it up and parsing it into an RDoc::Markup::Document.

Each comment may have a different markup format set by format=. By default ‘rdoc’ is used. The :markup: directive tells RDoc which format to use.

See RDoc Markup Reference.

Attributes

Overrides the content returned by parse. Use when there is no text source for this comment

The format of this comment. Defaults to RDoc::Markup

Line where this Comment was written

The RDoc::TopLevel this comment was found in

The text for this comment

The text for this comment

Public Class Methods

Creates a new comment with text that is found in the RDoc::TopLevel location.

# File lib/rdoc/comment.rb, line 57
def initialize(text = nil, location = nil, language = nil)
  @location = location
  @text     = text.nil? ? nil : text.dup
  @language = language

  @document   = nil
  @format     = 'rdoc'
  @normalized = false
end

Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash] This method expands include and removes everything not needed in the document text, such as private section, directive line, comment characters ‘# /* * */` and indent spaces.

RDoc comment consists of include, directive, multiline directive, private section and comment text.

Include

# :include: filename

Directive

# :directive-without-value:
# :directive-with-value: value

Multiline directive (only :call-seq:)

# :multiline-directive:
#   value1
#   value2

Private section

#--
# private comment
#++
# File lib/rdoc/comment.rb, line 212
def parse(text, filename, line_no, type, &include_callback)
  case type
  when :ruby
    text = text.gsub(/^#+/, '') if text.start_with?('#')
    private_start_regexp = /^-{2,}$/
    private_end_regexp = /^\+{2}$/
    indent_regexp = /^\s*/
  when :c
    private_start_regexp = /^(\s*\*)?-{2,}$/
    private_end_regexp = /^(\s*\*)?\+{2}$/
    indent_regexp = /^\s*(\/\*+|\*)?\s*/
    text = text.gsub(/\s*\*+\/\s*\z/, '')
  when :simple
    # Unlike other types, this implementation only looks for two dashes at
    # the beginning of the line. Three or more dashes are considered to be
    # a rule and ignored.
    private_start_regexp = /^-{2}$/
    private_end_regexp = /^\+{2}$/
    indent_regexp = /^\s*/
  end

  directives = {}
  lines = text.split("\n")
  in_private = false
  comment_lines = []
  until lines.empty?
    line = lines.shift
    read_lines = 1
    if in_private
      # If `++` appears in a private section that starts with `--`, private section ends.
      in_private = false if line.match?(private_end_regexp)
      line_no += read_lines
      next
    elsif line.match?(private_start_regexp)
      # If `--` appears in a line, private section starts.
      in_private = true
      line_no += read_lines
      next
    end

    prefix = line[indent_regexp]
    prefix_indent = ' ' * prefix.size
    line = line.byteslice(prefix.bytesize..)

    if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
      colon = directive_match[:colon]
      directive = directive_match[:directive]
      raw_param = directive_match[:param]
      param = raw_param.strip
    else
      colon = directive = raw_param = param = nil
    end

    if !directive
      comment_lines << prefix_indent + line
    elsif colon == '\\:'
      # If directive is escaped, unescape it
      comment_lines << prefix_indent + line.sub('\\:', ':')
    elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
      # Something like `:toto::` is not a directive
      # Only few directives allows to start without a colon
      comment_lines << prefix_indent + line
    elsif directive == 'include'
      filename_to_include = param
      include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
    elsif MULTILINE_DIRECTIVES.include?(directive)
      value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
      read_lines += value_lines.size
      lines.shift(value_lines.size)
      unless param.empty?
        # Accept `:call-seq: first-line\n  second-line` for now
        value_lines.unshift(param)
      end
      value = value_lines.join("\n")
      directives[directive] = [value.empty? ? nil : value, line_no]
    else
      directives[directive] = [param.empty? ? nil : param, line_no]
    end
    line_no += read_lines
  end

  normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
  [normalized_comment, directives]
end

Public Instance Methods

A comment is empty if its text String is empty.

# File lib/rdoc/comment.rb, line 83
def empty?
  @text.empty? && (@document.nil? || @document.empty?)
end

HACK dubious

# File lib/rdoc/comment.rb, line 90
def encode!(encoding)
  @text = String.new @text, encoding: encoding
  self
end

Sets the format of this comment and resets any parsed document

# File lib/rdoc/comment.rb, line 98
def format=(format)
  @format = format
  @document = nil
end

Normalizes the text. See RDoc::Text#normalize_comment for details

# File lib/rdoc/comment.rb, line 112
def normalize
  return self unless @text
  return self if @normalized # TODO eliminate duplicate normalization

  @text = normalize_comment @text

  @normalized = true

  self
end

Change normalized, when creating already normalized comment.

# File lib/rdoc/comment.rb, line 125
def normalized=(value)
  @normalized = value
end

Parses the comment into an RDoc::Markup::Document. The parsed document is cached until the text is changed.

Calls superclass method RDoc::Text#parse
# File lib/rdoc/comment.rb, line 140
def parse
  return @document if @document

  @document = super @text, @format
  @document.file = @location
  @document
end

Replaces this comment’s text with text and resets the parsed document.

An error is raised if the comment contains a document but no text.

# File lib/rdoc/comment.rb, line 153
def text=(text)
  raise Error, 'replacing document-only comment is not allowed' if
    @text.nil? and @document

  @document = nil
  @text = text.nil? ? nil : text.dup
end

Returns true if this comment is in TomDoc format.

# File lib/rdoc/comment.rb, line 164
def tomdoc?
  @format == 'tomdoc'
end