Class: YARD::DocstringParser
- Inherits:
-
Object
- Object
- YARD::DocstringParser
- 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 subtituted during parsing by setting the YARD::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 collapse
- META_MATCH =
The regular expression to match the tag syntax
/^@(!)?((?:\w\.?)+)(?:\s+(.*))?$/i
Instance Attribute Summary collapse
-
#directives ⇒ Array<Directive>
readonly
A list of directives identified by the parser.
-
#handler ⇒ Handlers::Base?
The handler parsing this docstring.
-
#library ⇒ Tags::Library
The tag library being used to identify registered tags in the docstring.
-
#object ⇒ CodeObjects::Base?
The object associated with the docstring being parsed.
-
#raw_text ⇒ String
readonly
The complete input string to the parser.
-
#state ⇒ OpenStruct
readonly
Any arbitrary state to be passed between tags during parsing.
-
#tags ⇒ Array<Tag>
readonly
The list of meta-data tags identified by the parser.
-
#text ⇒ String
readonly
The parsed text portion of the docstring, with tags removed.
Creation and Conversion Methods collapse
-
#initialize(library = Tags::Library.instance) ⇒ DocstringParser
constructor
Creates a new parser to parse docstring data.
-
#to_docstring ⇒ Docstring
Translates parsed text into a Docstring object.
Parsing Methods collapse
-
#parse(content, object = nil, handler = nil) ⇒ self
Parses all content and returns itself.
-
#parse_content(content) ⇒ Object
Parses a given block of text.
Tag Manipulation Methods collapse
-
#create_directive(tag_name, tag_buf) ⇒ Directive
Creates a new directive using the registered #library.
-
#create_ref_tag(tag_name, name, object_name) ⇒ Object
Creates a Tags::RefTag.
-
#create_tag(tag_name, tag_buf = '') ⇒ Tags::Tag, Tags::RefTag
Creates a tag from the tag factory.
-
#tag_is_directive?(tag_name) ⇒ Boolean
Backward compatibility to detect old tags that should be specified as directives in 0.8 and onward.
Parser Callback Methods collapse
-
.after_parse {|parser| ... } ⇒ void
Creates a callback that is called after a docstring is successfully parsed.
-
.after_parse_callbacks ⇒ Array<Proc>
The #after_parse callback proc objects.
Constructor Details
#initialize(library = Tags::Library.instance) ⇒ DocstringParser
Creates a new parser to parse docstring data
75 76 77 78 79 80 81 82 83 84 |
# 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 |
Instance Attribute Details
#directives ⇒ Array<Directive> (readonly)
Returns a list of directives identified by the parser. This list will not be passed on to the Docstring object.
44 45 46 |
# File 'lib/yard/docstring_parser.rb', line 44 def directives @directives end |
#handler ⇒ Handlers::Base?
Returns the handler parsing this docstring. May be nil if this docstring parser is not initialized through.
60 61 62 |
# File 'lib/yard/docstring_parser.rb', line 60 def handler @handler end |
#library ⇒ Tags::Library
Returns the tag library being used to identify registered tags in the docstring.
64 65 66 |
# File 'lib/yard/docstring_parser.rb', line 64 def library @library end |
#object ⇒ CodeObjects::Base?
Returns the object associated with the docstring being parsed. May be nil if the docstring is not attached to any object.
55 56 57 |
# File 'lib/yard/docstring_parser.rb', line 55 def object @object end |
#raw_text ⇒ String (readonly)
Returns the complete input string to the parser.
35 36 37 |
# File 'lib/yard/docstring_parser.rb', line 35 def raw_text @raw_text end |
#state ⇒ OpenStruct (readonly)
Returns any arbitrary state to be passed between tags during parsing. Mainly used by directives to coordinate behaviour (so that directives can be aware of other directives used in a docstring).
50 51 52 |
# File 'lib/yard/docstring_parser.rb', line 50 def state @state end |
#tags ⇒ Array<Tag> (readonly)
Returns the list of meta-data tags identified by the parser.
39 40 41 |
# File 'lib/yard/docstring_parser.rb', line 39 def @tags end |
#text ⇒ String (readonly)
Returns the parsed text portion of the docstring, with tags removed.
32 33 34 |
# File 'lib/yard/docstring_parser.rb', line 32 def text @text end |
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.
263 264 265 |
# File 'lib/yard/docstring_parser.rb', line 263 def self.after_parse(&block) self.after_parse_callbacks << block end |
.after_parse_callbacks ⇒ Array<Proc>
Returns the #after_parse callback proc objects.
268 269 270 |
# File 'lib/yard/docstring_parser.rb', line 268 def self.after_parse_callbacks @after_parse_callbacks ||= [] end |
Instance Method Details
#create_directive(tag_name, tag_buf) ⇒ Directive
Creates a new directive using the registered #library
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# 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 |
#create_ref_tag(tag_name, name, object_name) ⇒ Object
Creates a Tags::RefTag
202 203 204 |
# 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 |
#create_tag(tag_name, tag_buf = '') ⇒ Tags::Tag, Tags::RefTag
Creates a tag from the tag factory.
To add an already created tag object, use #add_tag
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# 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 |
#parse(content, object = nil, handler = nil) ⇒ self
Parses all content and returns itself.
106 107 108 109 110 111 112 113 114 115 116 |
# 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 |
#parse_content(content) ⇒ Object
Subclasses can override this method to perform custom parsing of content data.
Parses a given block of text.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# 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.).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 |
#tag_is_directive?(tag_name) ⇒ Boolean
Backward compatibility to detect old tags that should be specified as directives in 0.8 and onward.
228 229 230 231 |
# File 'lib/yard/docstring_parser.rb', line 228 def tag_is_directive?(tag_name) list = %w(attribute endgroup group macro method scope visibility) list.include?(tag_name) end |