Class: YARD::DocstringParser
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/yard/docstring_parser.rb |
Overview
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.
Subclassing Notes
The DocstringParser can be subclassed and substituted 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.
Constant Summary
-
META_MATCH =
The regular expression to match the tag syntax
/^@(!)?((?:\w\.?)+)(?:\s+(.*))?$/i
Creation and Conversion Methods
-
.new(library = Tags::Library.instance) ⇒ DocstringParser
constructor
Creates a new parser to parse docstring data.
- #to_docstring ⇒ Docstring
Parsing Methods
-
#parse(content, object = nil, handler = nil) ⇒ self
Parses all content and returns itself.
-
#parse_content(content)
Parses a given block of text.
Parser Callback Methods
-
#call_after_parse_callbacks
private
Calls all .after_parse callbacks.
-
#call_directives_after_parse
private
Calls the Tags::Directive#after_parse callback on all the created directives.
-
#post_process ⇒ void
Call post processing callbacks on parser.
Tag Manipulation Methods
-
.after_parse {|parser| ... } ⇒ void
Creates a callback that is called after a docstring is successfully parsed.
- .after_parse_callbacks ⇒ Array<Proc>
-
#create_directive(tag_name, tag_buf) ⇒ Tags::Directive
Creates a new directive using the registered #library
-
#create_ref_tag(tag_name, name, object_name)
Creates a
Tags::RefTag
-
#create_tag(tag_name, tag_buf = '') ⇒ Tags::Tag, Tags::RefTag
Creates a tag from the tag factory.
- #detect_reference(content) private
- #namespace private
-
#tag_is_directive?(tag_name) ⇒ Boolean
Backward compatibility to detect old tags that should be specified as directives in 0.8 and onward.
Instance Attribute Summary
Constructor Details
.new(library = Tags::Library.instance) ⇒ DocstringParser
Creates a new parser to parse docstring data
Class Method Details
.after_parse {|parser| ... } ⇒ void
This method returns an undefined value.
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.
# File 'lib/yard/docstring_parser.rb', line 265
def self.after_parse(&block) after_parse_callbacks << block end
.after_parse_callbacks ⇒ Array<Proc
>
# File 'lib/yard/docstring_parser.rb', line 270
def self.after_parse_callbacks @after_parse_callbacks ||= [] end
Instance Attribute Details
#directives ⇒ Array<Tags::Directive> (rw)
# File 'lib/yard/docstring_parser.rb', line 44
attr_accessor :directives
#handler ⇒ Handlers::Base? (rw)
# File 'lib/yard/docstring_parser.rb', line 65
attr_accessor :handler
#library ⇒ Tags::Library (rw)
# File 'lib/yard/docstring_parser.rb', line 69
attr_accessor :library
#object ⇒ CodeObjects::Base? (rw)
# File 'lib/yard/docstring_parser.rb', line 55
attr_accessor :object
#raw_text ⇒ String (rw)
# File 'lib/yard/docstring_parser.rb', line 35
attr_accessor :raw_text
#reference ⇒ CodeObjects::Base? (rw)
# File 'lib/yard/docstring_parser.rb', line 60
attr_accessor :reference
#state ⇒ OpenStruct (rw)
# File 'lib/yard/docstring_parser.rb', line 50
attr_accessor :state
#tags ⇒ Array<Tags::Tag> (rw)
# File 'lib/yard/docstring_parser.rb', line 39
attr_accessor :
#text ⇒ String (rw)
# File 'lib/yard/docstring_parser.rb', line 32
attr_accessor :text
Instance Method Details
#call_after_parse_callbacks (private)
Calls all .after_parse callbacks
# File 'lib/yard/docstring_parser.rb', line 323
def call_after_parse_callbacks self.class.after_parse_callbacks.each do |cb| cb.call(self) end end
#call_directives_after_parse (private)
Calls the Tags::Directive#after_parse callback on all the created directives.
# File 'lib/yard/docstring_parser.rb', line 318
def call_directives_after_parse directives.each(&:after_parse) end
#create_directive(tag_name, tag_buf) ⇒ Tags::Directive
Creates a new directive using the registered #library
# File 'lib/yard/docstring_parser.rb', line 231
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
#create_ref_tag(tag_name, name, object_name)
Creates a Tags::RefTag
# File 'lib/yard/docstring_parser.rb', line 225
def create_ref_tag(tag_name, name, object_name) @tags << Tags::RefTagList.new(tag_name, P(object, object_name), name) end
#create_tag(tag_name, tag_buf = '') ⇒ Tags::Tag, Tags::RefTag
Creates a tag from the tag factory.
To add an already created tag object, append it to #tags.
# File 'lib/yard/docstring_parser.rb', line 208
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
#detect_reference(content) (private)
# File 'lib/yard/docstring_parser.rb', line 304
def detect_reference(content) if content =~ /\A\s*\(see (\S+)\s*\)(?:\s|$)/ path = $1 extra = $' [CodeObjects::Proxy.new(namespace, path), extra] else [nil, content] end end
#namespace (private)
#parse(content, object = nil, handler = nil) ⇒ self
Parses all content and returns itself.
# File 'lib/yard/docstring_parser.rb', line 112
def parse(content, object = nil, handler = nil) @object = object @handler = handler @reference, @raw_text = detect_reference(content) text = parse_content(@raw_text) @text = text.strip call_directives_after_parse post_process self end
#parse_content(content)
Subclasses can override this method to perform custom parsing of content data.
Parses a given block of text.
# File 'lib/yard/docstring_parser.rb', line 128
def parse_content(content) content = content.split(/\r?\n/) if content.is_a?(String) return '' if !content || content.empty? docstring = String.new("") indent = content.first[/^\s*/].length last_indent = 0 orig_indent = 0 directive = false last_line = "" tag_name = nil tag_buf = [] (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. ).chomp end else create_tag(tag_name, buf) end tag_name = nil tag_buf = [] directive = false orig_indent = 0 end # Found a meta tag if line =~ META_MATCH directive = $1 tag_name = $2 tag_buf = [($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 docstring << "\n" end last_indent = indent last_line = line end docstring end
#post_process ⇒ void
This method returns an undefined value.
Call post processing callbacks on parser.
This is called implicitly by parser. Use this when
manually configuring a Docstring
object.
# File 'lib/yard/docstring_parser.rb', line 195
def post_process call_after_parse_callbacks end
#tag_is_directive?(tag_name) ⇒ Boolean
Backward compatibility to detect old tags that should be specified as directives in 0.8 and onward.
# File 'lib/yard/docstring_parser.rb', line 251
def tag_is_directive?(tag_name) list = %w(attribute endgroup group macro method scope visibility) list.include?(tag_name) end