class JsDuck::Doc::Parser

Parses doc-comment into array of @tags

For each @tag it produces Hash like the following:

{
  :tagname => :cfg/:property/:type/:extends/...,
  :doc => "Some documentation for this tag",
  ...@tag specific stuff like :name, :type, and so on...
}

When doc-comment begins with comment, not preceded by @tag, then the comment will be placed into Hash with :tagname => :default.

Unrecognized @tags are left as is into documentation as if they were normal text.

@example, {@img}, {@link} and {@video} are parsed separately in JsDuck::DocFormatter.

Public Instance Methods

add_tag(tag) click to toggle source

Appends new @tag to parsed tags list

# File lib/jsduck/doc/parser.rb, line 64
def add_tag(tag)
  @tags << tag

  if tag[:doc] == :multiline
    tag[:doc] = ""
    @multiline_tag = tag
  end
end
indented_as_code?() click to toggle source
# File lib/jsduck/doc/parser.rb, line 129
def indented_as_code?
  @multiline_tag[:doc] =~ /^ {4,}[^\n]*\z/
end
parse(input, filename="", linenr = 0) click to toggle source
# File lib/jsduck/doc/parser.rb, line 30
def parse(input, filename="", linenr = 0)
  @position = {:filename => filename, :linenr => linenr}
  @tags = []
  @non_repeatable_tags = {}
  @input = StringScanner.new(Doc::Comment.purify(input))

  parse_loop

  strip_docs
  @tags
end
parse_at_tag() click to toggle source

Processes anything beginning with @-sign.

  • When @ is not followed by any word chars, do nothing.

  • When it's one of the builtin tags, process it as such.

  • When it's something else, print a warning.

# File lib/jsduck/doc/parser.rb, line 79
def parse_at_tag
  match(/@/)
  name = look(/\w+/)

  if !name
    # ignore
  elsif tag = TagRegistry.get_by_pattern(name)
    match(/\w+/)
    hw # Skip the whitespace right after the tag.

    tags = tag.parse_doc(self, @position)
    if tags.is_a?(Hash)
      add_tag(tags)
    elsif tags.is_a?(Array)
      tags.each {|t| add_tag(t) }
    end

    if !tag.repeatable
      if @non_repeatable_tags[name]
        warn(:tag_repeated, "@#{name} tag can occur only once per doc-comment")
      end
      @non_repeatable_tags[name] = true
    end

    skip_white
  else
    warn(:tag, "Unsupported tag: @#{name}", [name.to_sym])
    @multiline_tag[:doc] += "@"
  end
end
parse_loop() click to toggle source

The main loop of the DocParser

# File lib/jsduck/doc/parser.rb, line 51
def parse_loop
  add_tag({:tagname => :doc, :doc => :multiline})

  while !@input.eos? do
    if look(/@/)
      parse_at_tag
    elsif look(/[^@]/)
      skip_to_next_at_tag
    end
  end
end
prev_char_is_whitespace?() click to toggle source
# File lib/jsduck/doc/parser.rb, line 125
def prev_char_is_whitespace?
  @multiline_tag[:doc][-1,1] =~ /\s/
end
skip_to_next_at_tag() click to toggle source

Skips until the beginning of next @tag.

There must be space before the next @tag - this ensures that we don't detect tags inside “foo@example.com” or “{@link}”.

Also check that the @tag is not part of an indented code block - in which case we also ignore the tag.

# File lib/jsduck/doc/parser.rb, line 117
def skip_to_next_at_tag
  @multiline_tag[:doc] += match(/[^@]+/)

  while look(/@/) && (!prev_char_is_whitespace? || indented_as_code?)
    @multiline_tag[:doc] += match(/@+[^@]+/)
  end
end
strip_docs() click to toggle source

The parsing process can leave whitespace at the ends of doc-strings, here we get rid of it.

# File lib/jsduck/doc/parser.rb, line 44
def strip_docs
  @tags.each do |tag|
    tag[:doc].strip! if tag[:doc]
  end
end