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
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
# File lib/jsduck/doc/parser.rb, line 129 def indented_as_code? @multiline_tag[:doc] =~ /^ {4,}[^\n]*\z/ end
# 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
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
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
# File lib/jsduck/doc/parser.rb, line 125 def prev_char_is_whitespace? @multiline_tag[:doc][-1,1] =~ /\s/ end
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
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