class YARD::Parser::Ruby::RipperParser
Internal parser class @since 0.5.6
Constants
- AST_TOKENS
- MAPPINGS
- REV_MAPPINGS
Attributes
ast[R]
charno[R]
comments[R]
encoding_line[R]
file[R]
root[R]
shebang_line[R]
tokens[R]
Public Class Methods
new(source, filename, *args)
click to toggle source
Calls superclass method
# File lib/yard/parser/ruby/ruby_parser.rb, line 29 def initialize(source, filename, *args) super @last_ns_token = nil @file = filename @source = source @tokens = [] @comments = {} @comments_range = {} @comments_flags = {} @heredoc_tokens = nil @heredoc_state = nil @map = {} @ns_charno = 0 @list = [] @charno = 0 @shebang_line = nil @encoding_line = nil @file_encoding = nil end
Public Instance Methods
enumerator()
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 58 def enumerator ast.children end
file_encoding()
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 62 def file_encoding return nil unless defined?(::Encoding) return @file_encoding if @file_encoding return Encoding.default_internal unless @encoding_line if match = @encoding_line.match(SourceParser::ENCODING_LINE) @file_encoding = match.captures.last end end
parse()
click to toggle source
Calls superclass method
# File lib/yard/parser/ruby/ruby_parser.rb, line 49 def parse @ast = super @ast.full_source = @source @ast.file = @file freeze_tree insert_comments self end
Private Instance Methods
add_comment(line, node = nil, before_node = nil, into = false)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 601 def add_comment(line, node = nil, before_node = nil, into = false) comment = @comments[line] source_range = @comments_range[line] line_range = ((line - comment.count("\n"))..line) if node.nil? node = CommentNode.new(:comment, [comment], :line => line_range, :char => source_range) if into before_node.push(node) before_node.unfreeze node.parent = before_node elsif before_node parent_node = before_node.parent idx = parent_node.index(before_node) parent_node.insert(idx, node) parent_node.unfreeze node.parent = parent_node end end node.docstring = comment node.docstring_hash_flag = @comments_flags[line] node.docstring_range = line_range @comments.delete(line) @comments_range.delete(line) @comments_flags.delete(line) end
add_token(token, data)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 247 def add_token(token, data) if @tokens.last && @tokens.last[0] == :symbeg @tokens[-1] = [:symbol, ":" + data, @tokens.last[2]] elsif @heredoc_state == :started @heredoc_tokens << [token, data, [lineno, charno]] # fix ripper encoding of heredoc bug # (see http://bugs.ruby-lang.org/issues/6200) data.force_encoding(file_encoding) if file_encoding @heredoc_state = :ended if token == :heredoc_end elsif (token == :nl || token == :comment) && @heredoc_state == :ended @heredoc_tokens.unshift([token, data, [lineno, charno]]) @tokens += @heredoc_tokens @heredoc_tokens = nil @heredoc_state = nil else @tokens << [token, data, [lineno, charno]] if token == :heredoc_beg @heredoc_state = :started @heredoc_tokens = [] end end end
comment_starts_line?(charno)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 548 def comment_starts_line?(charno) (charno-1).downto(0) do |i| ch = @source[i] break if ch == "\n" return false if ch != " " && ch != "\t" end true end
freeze_tree(node = nil)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 627 def freeze_tree(node = nil) node ||= root node.children.each do |child| child.parent = node freeze_tree(child) end end
insert_comments()
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 557 def insert_comments root.traverse do |node| next if node.type == :comment || node.type == :list || node.parent.type != :list # check upwards from line before node; check node's line at the end ((node.line-1).downto(node.line-2).to_a + [node.line]).each do |line| comment = @comments[line] if comment && !comment.empty? add_comment(line, node) break end end @comments.keys.each do |line| if node.line > line add_comment(line, nil, node) end end end # insert any lone unadded comments before node root.traverse do |node| next if node.type == :list || node.parent.type != :list @comments.keys.each do |line| if node.line_range.include?(line) pick = nil node.traverse do |subnode| next unless subnode.type == :list pick ||= subnode next unless subnode.line_range.include?(line) pick = subnode end add_comment(line, nil, pick, true) if pick end end end if @comments.size > 0 # insert all remaining comments @comments.each do |line, comment| add_comment(line, nil, root, true) end @comments = {} end
on_aref(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 335 def on_aref(*args) @map[:lbracket].pop ll, lc = *@map[:aref].pop sr = args.first.source_range.first..lc lr = args.first.line_range.first..ll AstNode.new(:aref, args, :char => sr, :line => lr) end
on_aref_field(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 343 def on_aref_field(*args) @map[:lbracket].pop AstNode.new(:aref_field, args, :listline => lineno..lineno, :listchar => charno...charno) end
on_array(other)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 349 def on_array(other) node = AstNode.node_class_for(:array).new(:array, [other]) map = @map[MAPPINGS[node.type]] if map && !map.empty? lstart, sstart = *map.pop node.source_range = Range.new(sstart, @ns_charno - 1) node.line_range = Range.new(lstart, lineno) else sstart = other.source_range.begin lstart = other.line_range.begin node.source_range = Range.new(sstart, @ns_charno - 1) node.line_range = Range.new(lstart, lineno) node.source_range = other.source_range node.line_range = other.line_range end node end
on_assoc_new(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 310 def on_assoc_new(*args) AstNode.new(:assoc, args) end
on_assoclist_from_args(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 322 def on_assoclist_from_args(*args) args.first end
on_bare_assoc_hash(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 318 def on_bare_assoc_hash(*args) AstNode.new(:list, args.first) end
on_body_stmt(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 305 def on_body_stmt(*args) args.compact.size == 1 ? args.first : AstNode.new(:list, args) end
Also aliased as: on_bodystmt
on_comment(comment)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 483 def on_comment(comment) not_comment = false if @last_ns_token.nil? || @last_ns_token.size == 0 if comment =~ SourceParser::SHEBANG_LINE && !@encoding_line @shebang_line = comment not_comment = true elsif comment =~ SourceParser::ENCODING_LINE @encoding_line = comment not_comment = true end end ch = charno visit_ns_token(:comment, comment) if not_comment @last_ns_token = nil return end source_range = ch..(charno-1) comment = comment.gsub(/^(\#+)\s{0,1}/, '').chomp append_comment = @comments[lineno - 1] hash_flag = $1 == '##' ? true : false if append_comment && @comments_last_column && @comments_last_column == column && comment_starts_line?(ch) @comments.delete(lineno - 1) @comments_flags[lineno] = @comments_flags[lineno - 1] @comments_flags.delete(lineno - 1) range = @comments_range.delete(lineno - 1) source_range = range.first..source_range.last comment = append_comment + "\n" + comment end @comments[lineno] = comment @comments_range[lineno] = source_range @comments_flags[lineno] = hash_flag if !append_comment @comments_last_column = column end
on_const_path_ref(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 389 def on_const_path_ref(*args) ReferenceNode.new(:const_path_ref, args, :listline => lineno..lineno, :listchar => charno..charno) end
on_embdoc(text)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 530 def on_embdoc(text) visit_ns_token(:embdoc, text) @embdoc << text end
on_embdoc_beg(text)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 524 def on_embdoc_beg(text) visit_ns_token(:embdoc_beg, text) @embdoc_start = charno-text.length @embdoc = "" end
on_embdoc_end(text)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 535 def on_embdoc_end(text) visit_ns_token(:embdoc_end, text) @comments_last_column = nil @comments[lineno] = @embdoc @comments_range[lineno] = @embdoc_start...charno @embdoc_start = nil @embdoc = nil end
on_hash(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 314 def on_hash(*args) visit_event AstNode.new(:hash, args.first || []) end
on_label(data)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 475 def on_label(data) add_token(:label, data) ch = charno @charno += data.length @ns_charno = charno AstNode.new(:label, [data[0...-1]], :line => lineno..lineno, :char => ch..charno-1, :token => true) end
on_lambda(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 436 def on_lambda(*args) visit_event_arr AstNode.new(:lambda, args) end
on_lbracket(tok)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 367 def on_lbracket(tok) (@map[:lbracket] ||= []) << [lineno, charno] visit_ns_token(:lbracket, tok, false) end
on_params(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 453 def on_params(*args) args.map! do |arg| next arg unless arg.class == Array if arg.first.class == Array arg.map! do |sub_arg| next sub_arg unless sub_arg.class == Array if sub_arg[0].type == :label type = :named_arg else type = :unnamed_optional_arg end AstNode.new(type, sub_arg, :listline => lineno..lineno, :listchar => charno..charno) end end AstNode.new(:list, arg, :listline => lineno..lineno, :listchar => charno..charno) end ParameterNode.new(:params, args, :listline => lineno..lineno, :listchar => charno..charno) end
on_parse_error(msg)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 544 def on_parse_error(msg) raise ParserSyntaxError, "syntax error in `#{file}`:(#{lineno},#{column}): #{msg}" end
on_program(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 301 def on_program(*args) args.first end
on_qwords_add(list, item)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 415 def on_qwords_add(list, item) last = @source[@ns_charno,1] == "\n" ? @ns_charno - 1 : @ns_charno list.source_range = (list.source_range.first..last) list.line_range = (list.line_range.first..lineno) list.push(item) list end
on_qwords_new(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 405 def on_qwords_new(*args) node = LiteralNode.new(:qwords_literal, args) if @map[:qwords_beg] lstart, sstart = *@map[:qwords_beg].pop node.source_range = Range.new(sstart, @ns_charno-1) node.line_range = Range.new(lstart, lineno) end node end
on_rbracket(tok)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 372 def on_rbracket(tok) (@map[:aref] ||= []) << [lineno, charno] visit_ns_token(:rbracket, tok, false) end
on_rescue(exc, *args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 444 def on_rescue(exc, *args) exc = AstNode.new(:list, exc) if exc visit_event AstNode.new(:rescue, [exc, *args]) end
on_string_content(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 440 def on_string_content(*args) AstNode.new(:string_content, args, :listline => lineno..lineno, :listchar => charno..charno) end
on_string_literal(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 423 def on_string_literal(*args) node = visit_event_arr(LiteralNode.new(:string_literal, args)) if args.size == 1 r = args[0].source_range if node.source_range != Range.new(r.first - 1, r.last + 1) klass = AstNode.node_class_for(node[0].type) r = Range.new(node.source_range.first + 1, node.source_range.last - 1) node[0] = klass.new(node[0].type, [@source[r]], :line => node.line_range, :char => r) end end node end
on_top_const_ref(*args)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 377 def on_top_const_ref(*args) type = :top_const_ref node = AstNode.node_class_for(type).new(type, args) mapping = @map[MAPPINGS[type]] extra_op = mapping.last[1] + 2 == charno ? mapping.pop : nil lstart, sstart = *mapping.pop node.source_range = Range.new(sstart, args.last.source_range.last) node.line_range = Range.new(lstart, args.last.line_range.last) mapping.push(extra_op) if extra_op node end
on_unary(op, val)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 326 def on_unary(op, val) map = @map[op.to_s[0,1]] lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1]) node = AstNode.node_class_for(:unary).new(:unary, [op, val]) node.source_range = Range.new(sstart, @ns_charno - 1) node.line_range = Range.new(lstart, lineno) node end
on_void_stmt()
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 449 def on_void_stmt AstNode.new(:void_stmt, [], :line => lineno..lineno, :char => charno...charno) end
visit_event(node)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 215 def visit_event(node) map = @map[MAPPINGS[node.type]] lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1]) node.source_range = Range.new(sstart, @ns_charno - 1) node.line_range = Range.new(lstart, lineno) if node.respond_to?(:block) sr, lr = node.block.source_range, node.block.line_range node.block.source_range = Range.new(sr.first, @tokens.last[2][1]) node.block.line_range = Range.new(lr.first, @tokens.last[2][0]) end node end
visit_event_arr(node)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 228 def visit_event_arr(node) mapping = MAPPINGS[node.type].find {|k| @map[k] && !@map[k].empty? } lstart, sstart = *@map[mapping].pop node.source_range = Range.new(sstart, @ns_charno - 1) node.line_range = Range.new(lstart, lineno) node end
visit_ns_token(token, data, ast_token = false)
click to toggle source
# File lib/yard/parser/ruby/ruby_parser.rb, line 236 def visit_ns_token(token, data, ast_token = false) add_token(token, data) ch = charno @last_ns_token = [token, data] @charno += data.length @ns_charno = charno if ast_token AstNode.new(token, [data], :line => lineno..lineno, :char => ch..charno-1, :token => true) end end