Parses text and creates a {Docstring} object to represent documentation for a {CodeObjects::Base}. To create a new docstring, you should initialize the parser and call {parse} followed by {to_docstring}.
The DocstringParser can be subclassed and subtituted during parsing by setting the {Docstring.default_parser} attribute with the name of the subclass. This allows developers to change the way docstrings are parsed, allowing for completely different docstring syntaxes.
@example Creating a Docstring with a DocstringParser
DocstringParser.new.parse("text here").to_docstring
@example Creating a Custom DocstringParser
# Parses docstrings backwards! class ReverseDocstringParser def parse_content(content) super(content.reverse) end end # Set the parser as default when parsing YARD::Docstring.default_parser = ReverseDocstringParser
@see parse_content @since 0.8.0
The regular expression to match the tag syntax
@return [Array<Directive>] a list of directives identified
by the parser. This list will not be passed on to the Docstring object.
@return [Handlers::Base, nil] the handler parsing this
docstring. May be nil if this docstring parser is not initialized through
@return [Tags::Library] the tag library being used to
identify registered tags in the docstring.
@return [CodeObjects::Base, nil] the object associated with
the docstring being parsed. May be nil if the docstring is not attached to any object.
Creates a callback that is called after a docstring is successfully parsed. Use this method to perform sanity checks on a docstring's tag data, or add any extra tags automatically to a docstring.
@yield [parser] a block to be called after a docstring is parsed @yieldparam [DocstringParser] parser the docstring parser object
with all directives and tags created.
@yieldreturn [void] @return [void]
# File lib/yard/docstring_parser.rb, line 263 def self.after_parse(&block) self.after_parse_callbacks << block end
@return [Array<Proc>] the {after_parse} callback proc objects
# File lib/yard/docstring_parser.rb, line 268 def self.after_parse_callbacks @after_parse_callbacks ||= [] end
Creates a new parser to parse docstring data
@param [Tags::Library] library a tag library for recognizing
tags.
# File lib/yard/docstring_parser.rb, line 75 def initialize(library = Tags::Library.instance) @text = "" @raw_text = "" @tags = [] @directives = [] @library = library @object = nil @handler = nil @state = OpenStruct.new end
Creates a new directive using the registered {library} @return [Directive] the directive object that is created
# File lib/yard/docstring_parser.rb, line 208 def create_directive(tag_name, tag_buf) if library.has_directive?(tag_name) dir = library.directive_create(tag_name, tag_buf, self) if dir.is_a?(Tags::Directive) @directives << dir dir end else log.warn "Unknown directive @!#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "") nil end rescue Tags::TagFormatError log.warn "Invalid directive format for @!#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "") nil end
Creates a {Tags::RefTag}
# File lib/yard/docstring_parser.rb, line 202 def create_ref_tag(tag_name, name, object_name) @tags << Tags::RefTagList.new(tag_name, P(object, object_name), name) end
Creates a tag from the {Tags::DefaultFactory tag factory}.
To add an already created tag object, append it to {tags}.
@param [String] tag_name the tag name @param [String] tag_buf the text attached to the tag with newlines removed. @return [Tags::Tag, Tags::RefTag] a tag
# File lib/yard/docstring_parser.rb, line 185 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 if library.has_tag?(tag_name) @tags += [library.tag_create(tag_name, 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
Parses all content and returns itself.
@param [String] content the docstring text to parse @param [CodeObjects::Base] object the object that the docstring
is attached to. Will be passed to directives to act on this object.
@param [Handlers::Base, nil] handler the handler object that is
parsing this object. May be nil if this parser is not being called from a {Parser::SourceParser} context.
@return [self] the parser object. To get the docstring,
call {#to_docstring}.
@see to_docstring
# File lib/yard/docstring_parser.rb, line 106 def parse(content, object = nil, handler = nil) @object = object @handler = handler @raw_text = content text = parse_content(content) # Remove trailing/leading whitespace / newlines @text = text.gsub(/\A[\r\n\s]+|[\r\n\s]+\Z/, '') call_directives_after_parse call_after_parse_callbacks self end
Parses a given block of text.
@param [String] content the content to parse @note Subclasses can override this method to perform custom
parsing of content data.
# File lib/yard/docstring_parser.rb, line 123 def parse_content(content) content = content.split(/\r?\n/) if content.is_a?(String) return '' if !content || content.empty? docstring = "" indent, last_indent = content.first[/^\s*/].length, 0 orig_indent = 0 directive = false last_line = "" tag_name, tag_klass, tag_buf = nil, nil, [] (content+['']).each_with_index do |line, index| indent = line[/^\s*/].length empty = (line =~ /^\s*$/ ? true : false) done = content.size == index if tag_name && (((indent < orig_indent && !empty) || done || (indent == 0 && !empty)) || (indent <= last_indent && line =~ META_MATCH)) buf = tag_buf.join("\n") if directive || tag_is_directive?(tag_name) directive = create_directive(tag_name, buf) if directive docstring << parse_content(directive.expanded_text).chomp end else create_tag(tag_name, buf) end tag_name, tag_buf, directive = nil, [], false orig_indent = 0 end # Found a meta tag if line =~ META_MATCH directive, tag_name, tag_buf = $1, $2, [($3 || '')] elsif tag_name && indent >= orig_indent && !empty orig_indent = indent if orig_indent == 0 # Extra data added to the tag on the next line last_empty = last_line =~ /^[ \t]*$/ ? true : false tag_buf << '' if last_empty tag_buf << line.gsub(/^[ \t]{#{orig_indent}}/, '') elsif !tag_name # Regular docstring text docstring << line << "\n" end last_indent = indent last_line = line end docstring end
Backward compatibility to detect old tags that should be specified as directives in 0.8 and onward.
# File lib/yard/docstring_parser.rb, line 228 def tag_is_directive?(tag_name) list = %(attribute endgroup group macro method scope visibility) list.include?(tag_name) end
Generated with the Darkfish Rdoc Generator 2.