class Prism::Translation::Ripper
此类提供了 prism 和 Ripper 之间的兼容层。它通过首先解析整个树,然后遍历该树并在遍历过程中执行每个 Ripper 回调来工作。要使用此类,您可以将 Prism::Translation::Ripper 视为 Ripper 类一样对待。
请注意,此类将满足最常见的用例,但 Ripper 的 API 非常广泛且未被记录。它依赖于在任何给定时间报告解析器的状态。我们在此尽力复制这一点,但由于这是一个不同的架构,因此无法完美地复制 Ripper 的行为。
主要已知区别在于,我们有时可能会省略某些事件的派发。这会影响以下事件:
-
on_assign_error
-
on_comma
-
on_ignored_nl
-
on_ignored_sp
-
on_kw
-
on_label_end
-
on_lbrace
-
on_lbracket
-
on_lparen
-
on_nl
-
on_op
-
on_operator_ambiguous
-
on_rbrace
-
on_rbracket
-
on_rparen
-
on_semicolon
-
on_sp
-
on_symbeg
-
on_tstring_beg
-
on_tstring_end
Constants
- BINARY_OPERATORS
-
所有 Ruby 二元运算符的列表。
- 事件
-
此数组包含所有 ripper 事件的名称。
- KEYWORDS
-
所有 Ruby 关键字的列表。
- PARSER_EVENTS
-
此数组包含解析器事件的名称。
- PARSER_EVENT_TABLE
-
这包含所有解析器事件及其对应元数的表。
- SCANNER_EVENTS
-
此数组包含扫描器事件的名称。
- SCANNER_EVENT_TABLE
-
这包含所有扫描器事件及其对应元数的表。
属性
解析器的当前列号。
正在解析的源文件的名称。
解析器的当前行号。
正在解析的源。
Public Class Methods
Source
# File lib/prism/translation/ripper.rb, line 73 def self.lex(src, filename = "-", lineno = 1, raise_errors: false) result = Prism.lex_compat(src, filepath: filename, line: lineno, version: "current") if result.failure? && raise_errors raise SyntaxError, result.errors.first.message else result.value end end
将 Ruby 程序分词,并返回一个数组的数组,格式为 [[lineno, column], type, token, state]。filename 参数基本被忽略。默认情况下,此方法不处理 src 中的语法错误,使用 raise_errors 关键字来为 src 中的错误引发 SyntaxError。
require "ripper"
require "pp"
pp Ripper.lex("def m(a) nil end")
#=> [[[1, 0], :on_kw, "def", FNAME ],
[[1, 3], :on_sp, " ", FNAME ],
[[1, 4], :on_ident, "m", ENDFN ],
[[1, 5], :on_lparen, "(", BEG|LABEL],
[[1, 6], :on_ident, "a", ARG ],
[[1, 7], :on_rparen, ")", ENDFN ],
[[1, 8], :on_sp, " ", BEG ],
[[1, 9], :on_kw, "nil", END ],
[[1, 12], :on_sp, " ", END ],
[[1, 13], :on_kw, "end", END ]]
Source
# File lib/prism/translation/ripper.rb, line 445 def initialize(source, filename = "(ripper)", lineno = 1) @source = source @filename = filename @lineno = lineno @column = 0 @result = nil end
使用给定的源创建新的 Translation::Ripper 对象。
Source
# File lib/prism/translation/ripper.rb, line 47 def self.parse(src, filename = "(ripper)", lineno = 1) new(src, filename, lineno).parse end
Source
# File lib/prism/translation/ripper.rb, line 382 def self.sexp(src, filename = "-", lineno = 1, raise_errors: false) builder = SexpBuilderPP.new(src, filename, lineno) sexp = builder.parse if builder.error? if raise_errors raise SyntaxError, builder.error end else sexp end end
解析 src 并创建 S-exp 树。返回的树比 Ripper.sexp_raw 更易读。此方法主要供开发人员使用。filename 参数基本被忽略。默认情况下,此方法不处理 src 中的语法错误,在这种情况下返回 nil。使用 raise_errors 关键字来为 src 中的错误引发 SyntaxError。
require "ripper"
require "pp"
pp Ripper.sexp("def m(a) nil end")
#=> [:program,
[[:def,
[:@ident, "m", [1, 4]],
[:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
[:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
Source
# File lib/prism/translation/ripper.rb, line 417 def self.sexp_raw(src, filename = "-", lineno = 1, raise_errors: false) builder = SexpBuilder.new(src, filename, lineno) sexp = builder.parse if builder.error? if raise_errors raise SyntaxError, builder.error end else sexp end end
解析 src 并创建 S-exp 树。此方法主要供开发人员使用。filename 参数基本被忽略。默认情况下,此方法不处理 src 中的语法错误,在这种情况下返回 nil。使用 raise_errors 关键字来为 src 中的错误引发 SyntaxError。
require "ripper"
require "pp"
pp Ripper.sexp_raw("def m(a) nil end")
#=> [:program,
[:stmts_add,
[:stmts_new],
[:def,
[:@ident, "m", [1, 4]],
[:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
[:bodystmt,
[:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
nil,
nil,
nil]]]]
Public Instance Methods
Source
# File lib/prism/translation/ripper.rb, line 458 def error? result.failure? end
如果解析器在解析过程中遇到错误,则返回 true。
Source
# File lib/prism/translation/ripper.rb, line 463 def parse result.comments.each do |comment| location = comment.location bounds(location) if comment.is_a?(InlineComment) on_comment(comment.slice) else offset = location.start_offset lines = comment.slice.lines lines.each_with_index do |line, index| bounds(location.copy(start_offset: offset)) if index == 0 on_embdoc_beg(line) elsif index == lines.size - 1 on_embdoc_end(line) else on_embdoc(line) end offset += line.bytesize end end end result.magic_comments.each do |magic_comment| on_magic_comment(magic_comment.key, magic_comment.value) end unless result.data_loc.nil? on___end__(result.data_loc.slice.each_line.first) end result.warnings.each do |warning| bounds(warning.location) if warning.level == :default warning(warning.message) else case warning.type when :ambiguous_first_argument_plus on_arg_ambiguous("+") when :ambiguous_first_argument_minus on_arg_ambiguous("-") when :ambiguous_slash on_arg_ambiguous("/") else warn(warning.message) end end end if error? result.errors.each do |error| location = error.location bounds(location) case error.type when :alias_argument on_alias_error("can't make alias for the number variables", location.slice) when :argument_formal_class on_param_error("formal argument cannot be a class variable", location.slice) when :argument_format_constant on_param_error("formal argument cannot be a constant", location.slice) when :argument_formal_global on_param_error("formal argument cannot be a global variable", location.slice) when :argument_formal_ivar on_param_error("formal argument cannot be an instance variable", location.slice) when :class_name, :module_name on_class_name_error("class/module name must be CONSTANT", location.slice) else on_parse_error(error.message) end end nil else result.value.accept(self) end end
解析源并返回结果。
Source
# File lib/prism/translation/ripper.rb, line 562 def visit_alias_global_variable_node(node) new_name = visit_alias_global_variable_node_value(node.new_name) old_name = visit_alias_global_variable_node_value(node.old_name) bounds(node.location) on_var_alias(new_name, old_name) end
alias $foo $bar ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 552 def visit_alias_method_node(node) new_name = visit(node.new_name) old_name = visit(node.old_name) bounds(node.location) on_alias(new_name, old_name) end
alias foo bar ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 586 def visit_alternation_pattern_node(node) left = visit_pattern_node(node.left) right = visit_pattern_node(node.right) bounds(node.location) on_binary(left, :|, right) end
foo => bar | baz ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 606 def visit_and_node(node) left = visit(node.left) right = visit(node.right) bounds(node.location) on_binary(left, node.operator.to_sym, right) end
a and b ^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 797 def visit_arguments_node(node) arguments, _ = visit_call_node_arguments(node, nil, false) arguments end
foo(bar) ^^^
Source
# File lib/prism/translation/ripper.rb, line 616 def visit_array_node(node) case (opening = node.opening) when /^%w/ opening_loc = node.opening_loc bounds(opening_loc) on_qwords_beg(opening) elements = on_qwords_new previous = nil node.elements.each do |element| visit_words_sep(opening_loc, previous, element) bounds(element.location) elements = on_qwords_add(elements, on_tstring_content(element.content)) previous = element end bounds(node.closing_loc) on_tstring_end(node.closing) when /^%i/ opening_loc = node.opening_loc bounds(opening_loc) on_qsymbols_beg(opening) elements = on_qsymbols_new previous = nil node.elements.each do |element| visit_words_sep(opening_loc, previous, element) bounds(element.location) elements = on_qsymbols_add(elements, on_tstring_content(element.value)) previous = element end bounds(node.closing_loc) on_tstring_end(node.closing) when /^%W/ opening_loc = node.opening_loc bounds(opening_loc) on_words_beg(opening) elements = on_words_new previous = nil node.elements.each do |element| visit_words_sep(opening_loc, previous, element) bounds(element.location) elements = on_words_add( elements, if element.is_a?(StringNode) on_word_add(on_word_new, on_tstring_content(element.content)) else element.parts.inject(on_word_new) do |word, part| word_part = if part.is_a?(StringNode) bounds(part.location) on_tstring_content(part.content) else visit(part) end on_word_add(word, word_part) end end ) previous = element end bounds(node.closing_loc) on_tstring_end(node.closing) when /^%I/ opening_loc = node.opening_loc bounds(opening_loc) on_symbols_beg(opening) elements = on_symbols_new previous = nil node.elements.each do |element| visit_words_sep(opening_loc, previous, element) bounds(element.location) elements = on_symbols_add( elements, if element.is_a?(SymbolNode) on_word_add(on_word_new, on_tstring_content(element.value)) else element.parts.inject(on_word_new) do |word, part| word_part = if part.is_a?(StringNode) bounds(part.location) on_tstring_content(part.content) else visit(part) end on_word_add(word, word_part) end end ) previous = element end bounds(node.closing_loc) on_tstring_end(node.closing) else bounds(node.opening_loc) on_lbracket(opening) elements = visit_arguments(node.elements) unless node.elements.empty? bounds(node.closing_loc) on_rbracket(node.closing) end bounds(node.location) on_array(elements) end
[] ^^
Source
# File lib/prism/translation/ripper.rb, line 776 def visit_array_pattern_node(node) constant = visit(node.constant) requireds = visit_all(node.requireds) if node.requireds.any? rest = if (rest_node = node.rest).is_a?(SplatNode) if rest_node.expression.nil? bounds(rest_node.location) on_var_field(nil) else visit(rest_node.expression) end end posts = visit_all(node.posts) if node.posts.any? bounds(node.location) on_aryptn(constant, requireds, rest, posts) end
foo => [bar] ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 804 def visit_assoc_node(node) key = visit(node.key) value = visit(node.value) bounds(node.location) on_assoc_new(key, value) end
{ a: 1 } ^^^^
Source
# File lib/prism/translation/ripper.rb, line 817 def visit_assoc_splat_node(node) value = visit(node.value) bounds(node.location) on_assoc_splat(value) end
def foo(); bar(); end ^^
{ **foo } ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 826 def visit_back_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
$+ ^^
Source
# File lib/prism/translation/ripper.rb, line 833 def visit_begin_node(node) clauses = visit_begin_node_clauses(node.begin_keyword_loc, node, false) bounds(node.location) on_begin(clauses) end
begin end ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 897 def visit_block_argument_node(node) visit(node.expression) end
foo(&bar) ^^^^
Source
# File lib/prism/translation/ripper.rb, line 903 def visit_block_local_variable_node(node) bounds(node.location) on_ident(node.name.to_s) end
foo { |; bar| } ^^^
Source
# File lib/prism/translation/ripper.rb, line 909 def visit_block_node(node) braces = node.opening == "{" parameters = visit(node.parameters) body = case node.body when nil bounds(node.location) stmts = on_stmts_add(on_stmts_new, on_void_stmt) bounds(node.location) braces ? stmts : on_bodystmt(stmts, nil, nil, nil) when StatementsNode stmts = node.body.body stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false) stmts = visit_statements_node_body(stmts) bounds(node.body.location) braces ? stmts : on_bodystmt(stmts, nil, nil, nil) when BeginNode visit_body_node(node.parameters&.location || node.opening_loc, node.body) else raise end if braces bounds(node.location) on_brace_block(parameters, body) else bounds(node.location) on_do_block(parameters, body) end end
访问 BlockNode。
Source
# File lib/prism/translation/ripper.rb, line 945 def visit_block_parameter_node(node) if node.name_loc.nil? bounds(node.location) on_blockarg(nil) else bounds(node.name_loc) name = visit_token(node.name.to_s) bounds(node.location) on_blockarg(name) end end
def foo(&bar); end ^^^^
Source
# File lib/prism/translation/ripper.rb, line 959 def visit_block_parameters_node(node) parameters = if node.parameters.nil? on_params(nil, nil, nil, nil, nil, nil, nil) else visit(node.parameters) end locals = if node.locals.any? visit_all(node.locals) else false end bounds(node.location) on_block_var(parameters, locals) end
一个块的参数。
Source
# File lib/prism/translation/ripper.rb, line 983 def visit_break_node(node) if node.arguments.nil? bounds(node.location) on_break(on_args_new) else arguments = visit(node.arguments) bounds(node.location) on_break(arguments) end end
break ^^^^^
break foo ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1205 def visit_call_and_write_node(node) receiver = visit(node.receiver) bounds(node.call_operator_loc) call_operator = visit_token(node.call_operator) bounds(node.message_loc) message = visit_token(node.message) bounds(node.location) target = on_field(receiver, call_operator, message) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo.bar &&= baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1003 def visit_call_node(node) if node.call_operator_loc.nil? case node.name when :[] receiver = visit(node.receiver) arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) bounds(node.location) call = on_aref(receiver, arguments) if block.nil? call else bounds(node.location) on_method_add_block(call, block) end when :[]= receiver = visit(node.receiver) *arguments, last_argument = node.arguments.arguments arguments << node.block if !node.block.nil? arguments = if arguments.any? args = visit_arguments(arguments) if !node.block.nil? args else bounds(arguments.first.location) on_args_add_block(args, false) end end bounds(node.location) call = on_aref_field(receiver, arguments) value = visit_write_value(last_argument) bounds(last_argument.location) on_assign(call, value) when :-@, :+@, :~ receiver = visit(node.receiver) bounds(node.location) on_unary(node.name, receiver) when :! if node.message == "not" receiver = if !node.receiver.is_a?(ParenthesesNode) || !node.receiver.body.nil? visit(node.receiver) end bounds(node.location) on_unary(:not, receiver) else receiver = visit(node.receiver) bounds(node.location) on_unary(:!, receiver) end when *BINARY_OPERATORS receiver = visit(node.receiver) value = visit(node.arguments.arguments.first) bounds(node.location) on_binary(receiver, node.name, value) else bounds(node.message_loc) message = visit_token(node.message, false) if node.variable_call? on_vcall(message) else arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location)) call = if node.opening_loc.nil? && arguments&.any? bounds(node.location) on_command(message, arguments) elsif !node.opening_loc.nil? bounds(node.location) on_method_add_arg(on_fcall(message), on_arg_paren(arguments)) else bounds(node.location) on_method_add_arg(on_fcall(message), on_args_new) end if block.nil? call else bounds(node.block.location) on_method_add_block(call, block) end end end else receiver = visit(node.receiver) bounds(node.call_operator_loc) call_operator = visit_token(node.call_operator) message = if node.message_loc.nil? :call else bounds(node.message_loc) visit_token(node.message, false) end if node.name.end_with?("=") && !node.message.end_with?("=") && !node.arguments.nil? && node.block.nil? value = visit_write_value(node.arguments.arguments.first) bounds(node.location) on_assign(on_field(receiver, call_operator, message), value) else arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location)) call = if node.opening_loc.nil? bounds(node.location) if node.arguments.nil? && !node.block.is_a?(BlockArgumentNode) on_call(receiver, call_operator, message) else on_command_call(receiver, call_operator, message, arguments) end else bounds(node.opening_loc) arguments = on_arg_paren(arguments) bounds(node.location) on_method_add_arg(on_call(receiver, call_operator, message), arguments) end if block.nil? call else bounds(node.block.location) on_method_add_block(call, block) end end end end
foo ^^^
foo.bar ^^^^^^^
foo.bar() {} ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1183 def visit_call_operator_write_node(node) receiver = visit(node.receiver) bounds(node.call_operator_loc) call_operator = visit_token(node.call_operator) bounds(node.message_loc) message = visit_token(node.message) bounds(node.location) target = on_field(receiver, call_operator, message) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo.bar += baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1227 def visit_call_or_write_node(node) receiver = visit(node.receiver) bounds(node.call_operator_loc) call_operator = visit_token(node.call_operator) bounds(node.message_loc) message = visit_token(node.message) bounds(node.location) target = on_field(receiver, call_operator, message) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo.bar ||= baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1249 def visit_call_target_node(node) if node.call_operator == "::" receiver = visit(node.receiver) bounds(node.message_loc) message = visit_token(node.message) bounds(node.location) on_const_path_field(receiver, message) else receiver = visit(node.receiver) bounds(node.call_operator_loc) call_operator = visit_token(node.call_operator) bounds(node.message_loc) message = visit_token(node.message) bounds(node.location) on_field(receiver, call_operator, message) end end
foo.bar, = 1 ^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1274 def visit_capture_pattern_node(node) value = visit(node.value) target = visit(node.target) bounds(node.location) on_binary(value, :"=>", target) end
foo => bar => baz ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1297 def visit_case_match_node(node) predicate = visit(node.predicate) clauses = node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| on_in(*visit(condition), current) end bounds(node.location) on_case(predicate, clauses) end
case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1284 def visit_case_node(node) predicate = visit(node.predicate) clauses = node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| on_when(*visit(condition), current) end bounds(node.location) on_case(predicate, clauses) end
case foo; when bar; end ^^^^^^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1310 def visit_class_node(node) constant_path = if node.constant_path.is_a?(ConstantReadNode) bounds(node.constant_path.location) on_const_ref(on_const(node.constant_path.name.to_s)) else visit(node.constant_path) end superclass = visit(node.superclass) bodystmt = visit_body_node(node.superclass&.location || node.constant_path.location, node.body, node.superclass.nil?) bounds(node.location) on_class(constant_path, superclass, bodystmt) end
class Foo; end ^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1363 def visit_class_variable_and_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@@foo &&= bar ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1349 def visit_class_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@@foo += bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1377 def visit_class_variable_or_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@@foo ||= bar ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1328 def visit_class_variable_read_node(node) bounds(node.location) on_var_ref(on_cvar(node.slice)) end
@@foo ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1391 def visit_class_variable_target_node(node) bounds(node.location) on_var_field(on_cvar(node.name.to_s)) end
@@foo, = bar ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1338 def visit_class_variable_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
@@foo = 1 ^^^^^^^^^
@@foo, @@bar = 1 ^^^^^ ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1433 def visit_constant_and_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo &&= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1419 def visit_constant_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo += bar ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1447 def visit_constant_or_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo ||= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1534 def visit_constant_path_and_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit(node.value) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo::Bar &&= baz ^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1468 def visit_constant_path_node(node) if node.parent.nil? bounds(node.name_loc) child = on_const(node.name.to_s) bounds(node.location) on_top_const_ref(child) else parent = visit(node.parent) bounds(node.name_loc) child = on_const(node.name.to_s) bounds(node.location) on_const_path_ref(parent, child) end end
Foo::Bar ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1520 def visit_constant_path_operator_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit(node.value) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo::Bar += baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1548 def visit_constant_path_or_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit(node.value) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
Foo::Bar ||= baz ^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1562 def visit_constant_path_target_node(node) visit_constant_path_write_node_target(node) end
Foo::Bar, = baz ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1491 def visit_constant_path_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
Foo::Bar = 1 ^^^^^^^^^^^^
Foo::Foo, Bar::Bar = 1 ^^^^^^^^ ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1398 def visit_constant_read_node(node) bounds(node.location) on_var_ref(on_const(node.name.to_s)) end
Foo ^^^
Source
# File lib/prism/translation/ripper.rb, line 1461 def visit_constant_target_node(node) bounds(node.location) on_var_field(on_const(node.name.to_s)) end
Foo, = bar ^^^
Source
# File lib/prism/translation/ripper.rb, line 1408 def visit_constant_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
Foo = 1 ^^^^^^^
Foo, Bar = 1 ^^^ ^^^
Source
# File lib/prism/translation/ripper.rb, line 1571 def visit_def_node(node) receiver = visit(node.receiver) operator = if !node.operator_loc.nil? bounds(node.operator_loc) visit_token(node.operator) end bounds(node.name_loc) name = visit_token(node.name_loc.slice) parameters = if node.parameters.nil? bounds(node.location) on_params(nil, nil, nil, nil, nil, nil, nil) else visit(node.parameters) end if !node.lparen_loc.nil? bounds(node.lparen_loc) parameters = on_paren(parameters) end bodystmt = if node.equal_loc.nil? visit_body_node(node.rparen_loc || node.end_keyword_loc, node.body) else body = visit(node.body.body.first) bounds(node.body.location) on_bodystmt(body, nil, nil, nil) end bounds(node.location) if receiver.nil? on_def(name, parameters, bodystmt) else on_defs(receiver, operator, name, parameters, bodystmt) end end
def foo; end ^^^^^^^^^^^^
def self.foo; end ^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1618 def visit_defined_node(node) expression = visit(node.value) # Very weird circumstances here where something like: # # defined? # (1) # # gets parsed in Ruby as having only the `1` expression but in Ripper it # gets parsed as having a parentheses node. In this case we need to # synthesize that node to match Ripper's behavior. if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n") bounds(node.lparen_loc.join(node.rparen_loc)) expression = on_paren(on_stmts_add(on_stmts_new, expression)) end bounds(node.location) on_defined(expression) end
defined? a ^^^^^^^^^^
defined?(a) ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1640 def visit_else_node(node) statements = if node.statements.nil? [nil] else body = node.statements.body body.unshift(nil) if void_stmt?(node.else_keyword_loc, node.statements.body[0].location, false) body end bounds(node.location) on_else(visit_statements_node_body(statements)) end
if foo then bar else baz end ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1656 def visit_embedded_statements_node(node) bounds(node.opening_loc) on_embexpr_beg(node.opening) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.closing_loc) on_embexpr_end(node.closing) bounds(node.location) on_string_embexpr(statements) end
“foo #{bar}” ^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1677 def visit_embedded_variable_node(node) bounds(node.operator_loc) on_embvar(node.operator) variable = visit(node.variable) bounds(node.location) on_string_dvar(variable) end
“foo #@bar” ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1688 def visit_ensure_node(node) statements = if node.statements.nil? [nil] else body = node.statements.body body.unshift(nil) if void_stmt?(node.ensure_keyword_loc, body[0].location, false) body end statements = visit_statements_node_body(statements) bounds(node.location) on_ensure(statements) end
访问 EnsureNode 节点。
Source
# File lib/prism/translation/ripper.rb, line 1706 def visit_false_node(node) bounds(node.location) on_var_ref(on_kw("false")) end
false ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1713 def visit_find_pattern_node(node) constant = visit(node.constant) left = if node.left.expression.nil? bounds(node.left.location) on_var_field(nil) else visit(node.left.expression) end requireds = visit_all(node.requireds) if node.requireds.any? right = if node.right.expression.nil? bounds(node.right.location) on_var_field(nil) else visit(node.right.expression) end bounds(node.location) on_fndptn(constant, left, requireds, right) end
foo => [, bar, ] ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1738 def visit_flip_flop_node(node) left = visit(node.left) right = visit(node.right) bounds(node.location) if node.exclude_end? on_dot3(left, right) else on_dot2(left, right) end end
if foo .. bar; end ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1752 def visit_float_node(node) visit_number_node(node) { |text| on_float(text) } end
1.0 ^^^
Source
# File lib/prism/translation/ripper.rb, line 1758 def visit_for_node(node) index = visit(node.index) collection = visit(node.collection) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.location) on_for(index, collection, statements) end
for foo in bar do end ^^^^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1775 def visit_forwarding_arguments_node(node) bounds(node.location) on_args_forward end
def foo(…); bar(…); end ^^^
Source
# File lib/prism/translation/ripper.rb, line 1782 def visit_forwarding_parameter_node(node) bounds(node.location) on_args_forward end
def foo(…); end ^^^
Source
# File lib/prism/translation/ripper.rb, line 1792 def visit_forwarding_super_node(node) if node.block.nil? bounds(node.location) on_zsuper else block = visit(node.block) bounds(node.location) on_method_add_block(on_zsuper, block) end end
super ^^^^^
super {} ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1841 def visit_global_variable_and_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
$foo &&= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1827 def visit_global_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
$foo += bar ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1855 def visit_global_variable_or_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
$foo ||= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1806 def visit_global_variable_read_node(node) bounds(node.location) on_var_ref(on_gvar(node.name.to_s)) end
$foo ^^^^
Source
# File lib/prism/translation/ripper.rb, line 1869 def visit_global_variable_target_node(node) bounds(node.location) on_var_field(on_gvar(node.name.to_s)) end
$foo, = bar ^^^^
Source
# File lib/prism/translation/ripper.rb, line 1816 def visit_global_variable_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
$foo = 1 ^^^^^^^^
$foo, $bar = 1 ^^^^ ^^^^
Source
# File lib/prism/translation/ripper.rb, line 1876 def visit_hash_node(node) elements = if node.elements.any? args = visit_all(node.elements) bounds(node.elements.first.location) on_assoclist_from_args(args) end bounds(node.location) on_hash(elements) end
{} ^^
Source
# File lib/prism/translation/ripper.rb, line 1891 def visit_hash_pattern_node(node) constant = visit(node.constant) elements = if node.elements.any? || !node.rest.nil? node.elements.map do |element| [ if (key = element.key).opening_loc.nil? visit(key) else bounds(key.value_loc) if (value = key.value).empty? on_string_content else on_string_add(on_string_content, on_tstring_content(value)) end end, visit(element.value) ] end end rest = case node.rest when AssocSplatNode visit(node.rest.value) when NoKeywordsParameterNode bounds(node.rest.location) on_var_field(visit(node.rest)) end bounds(node.location) on_hshptn(constant, elements, rest) end
foo => {} ^^
Source
# File lib/prism/translation/ripper.rb, line 1933 def visit_if_node(node) if node.then_keyword == "?" predicate = visit(node.predicate) truthy = visit(node.statements.body.first) falsy = visit(node.subsequent.statements.body.first) bounds(node.location) on_ifop(predicate, truthy, falsy) elsif node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) predicate = visit(node.predicate) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end subsequent = visit(node.subsequent) bounds(node.location) if node.if_keyword == "if" on_if(predicate, statements, subsequent) else on_elsif(predicate, statements, subsequent) end else statements = visit(node.statements.body.first) predicate = visit(node.predicate) bounds(node.location) on_if_mod(predicate, statements) end end
if foo then bar end ^^^^^^^^^^^^^^^^^^^
bar if foo ^^^^^^^^^^
foo ? bar : baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 1969 def visit_imaginary_node(node) visit_number_node(node) { |text| on_imaginary(text) } end
1i ^^
Source
# File lib/prism/translation/ripper.rb, line 1975 def visit_implicit_node(node) end
{ foo: } ^^^^
Source
# File lib/prism/translation/ripper.rb, line 1980 def visit_implicit_rest_node(node) bounds(node.location) on_excessed_comma end
foo { |bar,| } ^
Source
# File lib/prism/translation/ripper.rb, line 1987 def visit_in_node(node) # This is a special case where we're not going to call on_in directly # because we don't have access to the subsequent. Instead, we'll return # the component parts and let the parent node handle it. pattern = visit_pattern_node(node.pattern) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end [pattern, statements] end
case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2022 def visit_index_and_write_node(node) receiver = visit(node.receiver) arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) bounds(node.location) target = on_aref_field(receiver, arguments) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo &&= baz ^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2005 def visit_index_operator_write_node(node) receiver = visit(node.receiver) arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) bounds(node.location) target = on_aref_field(receiver, arguments) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo += baz ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2039 def visit_index_or_write_node(node) receiver = visit(node.receiver) arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) bounds(node.location) target = on_aref_field(receiver, arguments) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo ||= baz ^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2056 def visit_index_target_node(node) receiver = visit(node.receiver) arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) bounds(node.location) on_aref_field(receiver, arguments) end
foo, = 1 ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2098 def visit_instance_variable_and_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@foo &&= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2084 def visit_instance_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@foo += bar ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2112 def visit_instance_variable_or_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
@foo ||= bar ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2066 def visit_instance_variable_read_node(node) bounds(node.location) on_var_ref(on_ivar(node.name.to_s)) end
@foo ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2126 def visit_instance_variable_target_node(node) bounds(node.location) on_var_field(on_ivar(node.name.to_s)) end
@foo, = bar ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2073 def visit_instance_variable_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
@foo = 1 ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2133 def visit_integer_node(node) visit_number_node(node) { |text| on_int(text) } end
1 ^
Source
# File lib/prism/translation/ripper.rb, line 2139 def visit_interpolated_match_last_line_node(node) bounds(node.opening_loc) on_regexp_beg(node.opening) bounds(node.parts.first.location) parts = node.parts.inject(on_regexp_new) do |content, part| on_regexp_add(content, visit_string_content(part)) end bounds(node.closing_loc) closing = on_regexp_end(node.closing) bounds(node.location) on_regexp_literal(parts, closing) end
if /foo #{bar}/ then end ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2158 def visit_interpolated_regular_expression_node(node) bounds(node.opening_loc) on_regexp_beg(node.opening) bounds(node.parts.first.location) parts = node.parts.inject(on_regexp_new) do |content, part| on_regexp_add(content, visit_string_content(part)) end bounds(node.closing_loc) closing = on_regexp_end(node.closing) bounds(node.location) on_regexp_literal(parts, closing) end
/foo #{bar}/ ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2177 def visit_interpolated_string_node(node) if node.opening&.start_with?("<<~") heredoc = visit_heredoc_string_node(node) bounds(node.location) on_string_literal(heredoc) elsif !node.heredoc? && node.parts.length > 1 && node.parts.any? { |part| (part.is_a?(StringNode) || part.is_a?(InterpolatedStringNode)) && !part.opening_loc.nil? } first, *rest = node.parts rest.inject(visit(first)) do |content, part| concat = visit(part) bounds(part.location) on_string_concat(content, concat) end else bounds(node.parts.first.location) parts = node.parts.inject(on_string_content) do |content, part| on_string_add(content, visit_string_content(part)) end bounds(node.location) on_string_literal(parts) end end
“foo #{bar}” ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2205 def visit_interpolated_symbol_node(node) bounds(node.parts.first.location) parts = node.parts.inject(on_string_content) do |content, part| on_string_add(content, visit_string_content(part)) end bounds(node.location) on_dyna_symbol(parts) end
:“foo #{bar}” ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2218 def visit_interpolated_x_string_node(node) if node.opening.start_with?("<<~") heredoc = visit_heredoc_x_string_node(node) bounds(node.location) on_xstring_literal(heredoc) else bounds(node.parts.first.location) parts = node.parts.inject(on_xstring_new) do |content, part| on_xstring_add(content, visit_string_content(part)) end bounds(node.location) on_xstring_literal(parts) end end
foo #{bar} ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2248 def visit_it_local_variable_read_node(node) bounds(node.location) on_vcall(on_ident(node.slice)) end
-> { it } ^^
Source
# File lib/prism/translation/ripper.rb, line 2255 def visit_it_parameters_node(node) end
-> { it } ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2260 def visit_keyword_hash_node(node) elements = visit_all(node.elements) bounds(node.location) on_bare_assoc_hash(elements) end
foo(bar: baz) ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2272 def visit_keyword_rest_parameter_node(node) if node.name_loc.nil? bounds(node.location) on_kwrest_param(nil) else bounds(node.name_loc) name = on_ident(node.name.to_s) bounds(node.location) on_kwrest_param(name) end end
def foo(**bar); end ^^^^^
def foo(**); end ^^
Source
# File lib/prism/translation/ripper.rb, line 2286 def visit_lambda_node(node) bounds(node.operator_loc) on_tlambda(node.operator) parameters = if node.parameters.is_a?(BlockParametersNode) # Ripper does not track block-locals within lambdas, so we skip # directly to the parameters here. params = if node.parameters.parameters.nil? bounds(node.location) on_params(nil, nil, nil, nil, nil, nil, nil) else visit(node.parameters.parameters) end if node.parameters.opening_loc.nil? params else bounds(node.parameters.opening_loc) on_paren(params) end else bounds(node.location) on_params(nil, nil, nil, nil, nil, nil, nil) end braces = node.opening == "{" if braces bounds(node.opening_loc) on_tlambeg(node.opening) end body = case node.body when nil bounds(node.location) stmts = on_stmts_add(on_stmts_new, on_void_stmt) bounds(node.location) braces ? stmts : on_bodystmt(stmts, nil, nil, nil) when StatementsNode stmts = node.body.body stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false) stmts = visit_statements_node_body(stmts) bounds(node.body.location) braces ? stmts : on_bodystmt(stmts, nil, nil, nil) when BeginNode visit_body_node(node.opening_loc, node.body) else raise end bounds(node.location) on_lambda(parameters, body) end
-> {}
Source
# File lib/prism/translation/ripper.rb, line 2378 def visit_local_variable_and_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) bounds(node.operator_loc) operator = on_op("&&=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo &&= bar ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2364 def visit_local_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) bounds(node.binary_operator_loc) operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo += bar ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2392 def visit_local_variable_or_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) bounds(node.operator_loc) operator = on_op("||=") value = visit_write_value(node.value) bounds(node.location) on_opassign(target, operator, value) end
foo ||= bar ^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2346 def visit_local_variable_read_node(node) bounds(node.location) on_var_ref(on_ident(node.slice)) end
foo ^^^
Source
# File lib/prism/translation/ripper.rb, line 2406 def visit_local_variable_target_node(node) bounds(node.location) on_var_field(on_ident(node.name.to_s)) end
foo, = bar ^^^
Source
# File lib/prism/translation/ripper.rb, line 2353 def visit_local_variable_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) value = visit_write_value(node.value) bounds(node.location) on_assign(target, value) end
foo = 1 ^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2413 def visit_match_last_line_node(node) bounds(node.opening_loc) on_regexp_beg(node.opening) bounds(node.content_loc) tstring_content = on_tstring_content(node.content) bounds(node.closing_loc) closing = on_regexp_end(node.closing) on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing) end
if /foo/ then end ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2428 def visit_match_predicate_node(node) value = visit(node.value) pattern = on_in(visit_pattern_node(node.pattern), nil, nil) on_case(value, pattern) end
foo in bar ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2437 def visit_match_required_node(node) value = visit(node.value) pattern = on_in(visit_pattern_node(node.pattern), nil, nil) on_case(value, pattern) end
foo => bar ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2446 def visit_match_write_node(node) visit(node.call) end
/(?<foo>foo)/ =~ bar ^^^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2452 def visit_missing_node(node) raise "Cannot visit missing nodes directly." end
语法树中缺失的节点。这仅在出现语法错误时使用。
Source
# File lib/prism/translation/ripper.rb, line 2458 def visit_module_node(node) constant_path = if node.constant_path.is_a?(ConstantReadNode) bounds(node.constant_path.location) on_const_ref(on_const(node.constant_path.name.to_s)) else visit(node.constant_path) end bodystmt = visit_body_node(node.constant_path.location, node.body, true) bounds(node.location) on_module(constant_path, bodystmt) end
module Foo; end ^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2475 def visit_multi_target_node(node) bounds(node.location) targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true) if node.lparen_loc.nil? targets else bounds(node.lparen_loc) on_mlhs_paren(targets) end end
(foo, bar), bar = qux ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2529 def visit_multi_write_node(node) bounds(node.location) targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true) unless node.lparen_loc.nil? bounds(node.lparen_loc) targets = on_mlhs_paren(targets) end value = visit_write_value(node.value) bounds(node.location) on_massign(targets, value) end
foo, bar = baz ^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2549 def visit_next_node(node) if node.arguments.nil? bounds(node.location) on_next(on_args_new) else arguments = visit(node.arguments) bounds(node.location) on_next(arguments) end end
next ^^^^
next foo ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2563 def visit_nil_node(node) bounds(node.location) on_var_ref(on_kw("nil")) end
nil ^^^
Source
# File lib/prism/translation/ripper.rb, line 2570 def visit_no_keywords_parameter_node(node) bounds(node.location) on_nokw_param(nil) :nil end
def foo(**nil); end ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2579 def visit_numbered_parameters_node(node) end
-> { 1 + 2 } ^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2584 def visit_numbered_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
$1 ^^
Source
# File lib/prism/translation/ripper.rb, line 2591 def visit_optional_keyword_parameter_node(node) bounds(node.name_loc) name = on_label("#{node.name}:") value = visit(node.value) [name, value] end
def foo(bar: baz); end ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2601 def visit_optional_parameter_node(node) bounds(node.name_loc) name = visit_token(node.name.to_s) value = visit(node.value) [name, value] end
def foo(bar = 1); end ^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2611 def visit_or_node(node) left = visit(node.left) right = visit(node.right) bounds(node.location) on_binary(left, node.operator.to_sym, right) end
a or b ^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2621 def visit_parameters_node(node) requireds = node.requireds.map { |required| required.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(required) : visit(required) } if node.requireds.any? optionals = visit_all(node.optionals) if node.optionals.any? rest = visit(node.rest) posts = node.posts.map { |post| post.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(post) : visit(post) } if node.posts.any? keywords = visit_all(node.keywords) if node.keywords.any? keyword_rest = visit(node.keyword_rest) block = visit(node.block) bounds(node.location) on_params(requireds, optionals, rest, posts, keywords, keyword_rest, block) end
def foo(bar, *baz); end ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2648 def visit_parentheses_node(node) body = if node.body.nil? on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.body) end bounds(node.location) on_paren(body) end
() ^^
(1) ^^^
Source
# File lib/prism/translation/ripper.rb, line 2662 def visit_pinned_expression_node(node) expression = visit(node.expression) bounds(node.location) on_begin(expression) end
foo => ^(bar) ^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2671 def visit_pinned_variable_node(node) visit(node.variable) end
foo = 1 and bar => ^foo ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2677 def visit_post_execution_node(node) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.location) on_END(statements) end
END {} ^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2692 def visit_pre_execution_node(node) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.location) on_BEGIN(statements) end
BEGIN {} ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2706 def visit_program_node(node) body = node.statements.body body << nil if body.empty? statements = visit_statements_node_body(body) bounds(node.location) on_program(statements) end
顶层程序节点。
Source
# File lib/prism/translation/ripper.rb, line 2717 def visit_range_node(node) left = visit(node.left) right = visit(node.right) bounds(node.location) if node.exclude_end? on_dot3(left, right) else on_dot2(left, right) end end
0..5 ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2731 def visit_rational_node(node) visit_number_node(node) { |text| on_rational(text) } end
1r ^^
Source
# File lib/prism/translation/ripper.rb, line 2737 def visit_redo_node(node) bounds(node.location) on_redo end
redo ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2744 def visit_regular_expression_node(node) bounds(node.opening_loc) on_regexp_beg(node.opening) if node.content.empty? bounds(node.closing_loc) closing = on_regexp_end(node.closing) on_regexp_literal(on_regexp_new, closing) else bounds(node.content_loc) tstring_content = on_tstring_content(node.content) bounds(node.closing_loc) closing = on_regexp_end(node.closing) on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing) end end
/foo/ ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2766 def visit_required_keyword_parameter_node(node) bounds(node.name_loc) [on_label("#{node.name}:"), false] end
def foo(bar:); end ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2773 def visit_required_parameter_node(node) bounds(node.location) on_ident(node.name.to_s) end
def foo(bar); end ^^^
Source
# File lib/prism/translation/ripper.rb, line 2780 def visit_rescue_modifier_node(node) expression = visit_write_value(node.expression) rescue_expression = visit(node.rescue_expression) bounds(node.location) on_rescue_mod(expression, rescue_expression) end
foo rescue bar ^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2790 def visit_rescue_node(node) exceptions = case node.exceptions.length when 0 nil when 1 if (exception = node.exceptions.first).is_a?(SplatNode) bounds(exception.location) on_mrhs_add_star(on_mrhs_new, visit(exception)) else [visit(node.exceptions.first)] end else bounds(node.location) length = node.exceptions.length node.exceptions.each_with_index.inject(on_args_new) do |mrhs, (exception, index)| arg = visit(exception) bounds(exception.location) mrhs = on_mrhs_new_from_args(mrhs) if index == length - 1 if exception.is_a?(SplatNode) if index == length - 1 on_mrhs_add_star(mrhs, arg) else on_args_add_star(mrhs, arg) end else if index == length - 1 on_mrhs_add(mrhs, arg) else on_args_add(mrhs, arg) end end end end reference = visit(node.reference) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end subsequent = visit(node.subsequent) bounds(node.location) on_rescue(exceptions, reference, statements, subsequent) end
begin; rescue; end ^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2848 def visit_rest_parameter_node(node) if node.name_loc.nil? bounds(node.location) on_rest_param(nil) else bounds(node.name_loc) on_rest_param(visit_token(node.name.to_s)) end end
def foo(*bar); end ^^^^
def foo(*); end ^
Source
# File lib/prism/translation/ripper.rb, line 2860 def visit_retry_node(node) bounds(node.location) on_retry end
retry ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2870 def visit_return_node(node) if node.arguments.nil? bounds(node.location) on_return0 else arguments = visit(node.arguments) bounds(node.location) on_return(arguments) end end
return ^^^^^^
return 1 ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2884 def visit_self_node(node) bounds(node.location) on_var_ref(on_kw("self")) end
self ^^^^
Source
# File lib/prism/translation/ripper.rb, line 2896 def visit_singleton_class_node(node) expression = visit(node.expression) bodystmt = visit_body_node(node.body&.location || node.end_keyword_loc, node.body) bounds(node.location) on_sclass(expression, bodystmt) end
class << self; end ^^^^^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2906 def visit_source_encoding_node(node) bounds(node.location) on_var_ref(on_kw("__ENCODING__")) end
ENCODING ^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2913 def visit_source_file_node(node) bounds(node.location) on_var_ref(on_kw("__FILE__")) end
FILE ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2920 def visit_source_line_node(node) bounds(node.location) on_var_ref(on_kw("__LINE__")) end
LINE ^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 2933 def visit_splat_node(node) visit(node.expression) end
foo(*bar) ^^^^
def foo((bar, *baz)); end ^^^^
def foo(); bar(); end ^
Source
# File lib/prism/translation/ripper.rb, line 2938 def visit_statements_node(node) bounds(node.location) visit_statements_node_body(node.body) end
一个语句列表。
Source
# File lib/prism/translation/ripper.rb, line 2955 def visit_string_node(node) if (content = node.content).empty? bounds(node.location) on_string_literal(on_string_content) elsif (opening = node.opening) == "?" bounds(node.location) on_CHAR("?#{node.content}") elsif opening.start_with?("<<~") heredoc = visit_heredoc_string_node(node.to_interpolated) bounds(node.location) on_string_literal(heredoc) else bounds(node.content_loc) tstring_content = on_tstring_content(content) bounds(node.location) on_string_literal(on_string_add(on_string_content, tstring_content)) end end
“foo” ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3087 def visit_super_node(node) arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location)) if !node.lparen_loc.nil? bounds(node.lparen_loc) arguments = on_arg_paren(arguments) end bounds(node.location) call = on_super(arguments) if block.nil? call else bounds(node.block.location) on_method_add_block(call, block) end end
super(foo) ^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3108 def visit_symbol_node(node) if (opening = node.opening)&.match?(/^%s|['"]:?$/) bounds(node.value_loc) content = on_string_content if !(value = node.value).empty? content = on_string_add(content, on_tstring_content(value)) end on_dyna_symbol(content) elsif (closing = node.closing) == ":" bounds(node.location) on_label("#{node.value}:") elsif opening.nil? && node.closing_loc.nil? bounds(node.value_loc) on_symbol_literal(visit_token(node.value)) else bounds(node.value_loc) on_symbol_literal(on_symbol(visit_token(node.value))) end end
:foo ^^^^
Source
# File lib/prism/translation/ripper.rb, line 3132 def visit_true_node(node) bounds(node.location) on_var_ref(on_kw("true")) end
true ^^^^
Source
# File lib/prism/translation/ripper.rb, line 3139 def visit_undef_node(node) names = visit_all(node.names) bounds(node.location) on_undef(names) end
undef foo ^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3151 def visit_unless_node(node) if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) predicate = visit(node.predicate) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end else_clause = visit(node.else_clause) bounds(node.location) on_unless(predicate, statements, else_clause) else statements = visit(node.statements.body.first) predicate = visit(node.predicate) bounds(node.location) on_unless_mod(predicate, statements) end end
unless foo; bar end ^^^^^^^^^^^^^^^^^^^
bar unless foo ^^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3179 def visit_until_node(node) if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) predicate = visit(node.predicate) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.location) on_until(predicate, statements) else statements = visit(node.statements.body.first) predicate = visit(node.predicate) bounds(node.location) on_until_mod(predicate, statements) end end
until foo; bar end ^^^^^^^^^^^^^^^^^
bar until foo ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3203 def visit_when_node(node) # This is a special case where we're not going to call on_when directly # because we don't have access to the subsequent. Instead, we'll return # the component parts and let the parent node handle it. conditions = visit_arguments(node.conditions) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end [conditions, statements] end
case foo; when bar; end ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3224 def visit_while_node(node) if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) predicate = visit(node.predicate) statements = if node.statements.nil? bounds(node.location) on_stmts_add(on_stmts_new, on_void_stmt) else visit(node.statements) end bounds(node.location) on_while(predicate, statements) else statements = visit(node.statements.body.first) predicate = visit(node.predicate) bounds(node.location) on_while_mod(predicate, statements) end end
while foo; bar end ^^^^^^^^^^^^^^^^^^
bar while foo ^^^^^^^^^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3248 def visit_x_string_node(node) if node.unescaped.empty? bounds(node.location) on_xstring_literal(on_xstring_new) elsif node.opening.start_with?("<<~") heredoc = visit_heredoc_x_string_node(node.to_interpolated) bounds(node.location) on_xstring_literal(heredoc) else bounds(node.content_loc) content = on_tstring_content(node.content) bounds(node.location) on_xstring_literal(on_xstring_add(on_xstring_new, content)) end end
foo ^^^^^
Source
# File lib/prism/translation/ripper.rb, line 3271 def visit_yield_node(node) if node.arguments.nil? && node.lparen_loc.nil? bounds(node.location) on_yield0 else arguments = if node.arguments.nil? bounds(node.location) on_args_new else visit(node.arguments) end unless node.lparen_loc.nil? bounds(node.lparen_loc) arguments = on_paren(arguments) end bounds(node.location) on_yield(arguments) end end
yield ^^^^^
yield 1 ^^^^^^^
私有实例方法
Source
# File lib/prism/translation/ripper.rb, line 3401 def bounds(location) @lineno = location.start_line @column = location.start_column end
此方法负责更新 lineno 和 column 信息以反映当前节点。
此方法可以通过对每行的开头进行一些缓存来得到极大改进,但目前为止已经足够好了。
Source
# File lib/prism/translation/ripper.rb, line 1174 def command?(node) node.is_a?(CallNode) && node.opening_loc.nil? && (!node.arguments.nil? || node.block.is_a?(BlockArgumentNode)) && !BINARY_OPERATORS.include?(node.name) end
如果给定节点是命令节点,则返回 true。
Source
# File lib/prism/translation/ripper.rb, line 3439 def compile_error(msg) end
解析器发现语法错误时会调用此方法。
Source
# File lib/prism/translation/ripper.rb, line 3454 def dedent_string(string, width) whitespace = 0 cursor = 0 while cursor < string.length && string[cursor].match?(/\s/) && whitespace < width if string[cursor] == "\t" whitespace = ((whitespace / 8 + 1) * 8) break if whitespace > width else whitespace += 1 end cursor += 1 end string.replace(string[cursor..]) cursor end
此方法由 Ripper C 扩展提供。当字符串因波浪号 heredoc 需要去缩进时会调用它。它应该会就地修改字符串并返回被删除的字节数。
Source
# File lib/prism/translation/ripper.rb, line 3297 def result @result ||= Prism.parse(source, partial_script: true, version: "current") end
延迟初始化解析结果。
Source
# File lib/prism/translation/ripper.rb, line 3306 def trailing_comma?(left, right) source.byteslice(left.end_offset...right.start_offset).include?(",") end
如果两个位置之间有逗号,则返回 true。
Source
# File lib/prism/translation/ripper.rb, line 571 def visit_alias_global_variable_node_value(node) bounds(node.location) case node when BackReferenceReadNode on_backref(node.slice) when GlobalVariableReadNode on_gvar(node.name.to_s) else raise end end
访问别名全局变量节点的一侧。
Source
# File lib/prism/translation/ripper.rb, line 757 def visit_arguments(elements) bounds(elements.first.location) elements.inject(on_args_new) do |args, element| arg = visit(element) bounds(element.location) case element when BlockArgumentNode on_args_add_block(args, arg) when SplatNode on_args_add_star(args, arg) else on_args_add(args, arg) end end end
访问元素列表,例如数组的元素或参数。
Source
# File lib/prism/translation/ripper.rb, line 841 def visit_begin_node_clauses(location, node, allow_newline) statements = if node.statements.nil? on_stmts_add(on_stmts_new, on_void_stmt) else body = node.statements.body body.unshift(nil) if void_stmt?(location, node.statements.body[0].location, allow_newline) bounds(node.statements.location) visit_statements_node_body(body) end rescue_clause = visit(node.rescue_clause) else_clause = unless (else_clause_node = node.else_clause).nil? else_statements = if else_clause_node.statements.nil? [nil] else body = else_clause_node.statements.body body.unshift(nil) if void_stmt?(else_clause_node.else_keyword_loc, else_clause_node.statements.body[0].location, allow_newline) body end bounds(else_clause_node.location) visit_statements_node_body(else_statements) end ensure_clause = visit(node.ensure_clause) bounds(node.location) on_bodystmt(statements, rescue_clause, else_clause, ensure_clause) end
访问 begin 节点的子句以形成 on_bodystmt 调用。
Source
# File lib/prism/translation/ripper.rb, line 876 def visit_body_node(location, node, allow_newline = false) case node when nil bounds(location) on_bodystmt(visit_statements_node_body([nil]), nil, nil, nil) when StatementsNode body = [*node.body] body.unshift(nil) if void_stmt?(location, body[0].location, allow_newline) stmts = visit_statements_node_body(body) bounds(node.body.first.location) on_bodystmt(stmts, nil, nil, nil) when BeginNode visit_begin_node_clauses(location, node, allow_newline) else raise end end
访问可以包含语句集或包装在 rescue/else/ensure 中的语句的结构体的主体。
Source
# File lib/prism/translation/ripper.rb, line 1147 def visit_call_node_arguments(arguments_node, block_node, trailing_comma) arguments = arguments_node&.arguments || [] block = block_node if block.is_a?(BlockArgumentNode) arguments << block block = nil end [ if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode) visit(arguments.first) elsif arguments.any? args = visit_arguments(arguments) if block_node.is_a?(BlockArgumentNode) || arguments.last.is_a?(ForwardingArgumentsNode) || command?(arguments.last) || trailing_comma args else bounds(arguments.first.location) on_args_add_block(args, false) end end, visit(block) ] end
访问调用节点的参数和块,并以应使用的方式返回参数和块。
Source
# File lib/prism/translation/ripper.rb, line 1500 def visit_constant_path_write_node_target(node) if node.parent.nil? bounds(node.name_loc) child = on_const(node.name.to_s) bounds(node.location) on_top_const_field(child) else parent = visit(node.parent) bounds(node.name_loc) child = on_const(node.name.to_s) bounds(node.location) on_const_path_field(parent, child) end end
访问作为写入节点一部分的常量路径。
Source
# File lib/prism/translation/ripper.rb, line 2635 def visit_destructured_parameter_node(node) bounds(node.location) targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, false) bounds(node.lparen_loc) on_mlhs_paren(targets) end
访问解构的位置参数节点。
Source
# File lib/prism/translation/ripper.rb, line 3006 def visit_heredoc_node(parts, base) common_whitespace = visit_heredoc_node_whitespace(parts) if common_whitespace == 0 bounds(parts.first.location) string = [] result = base parts.each do |part| if part.is_a?(StringNode) if string.empty? string = [part] else string << part end else unless string.empty? bounds(string[0].location) result = yield result, on_tstring_content(string.map(&:content).join) string = [] end result = yield result, visit(part) end end unless string.empty? bounds(string[0].location) result = yield result, on_tstring_content(string.map(&:content).join) end result else bounds(parts.first.location) result = parts.inject(base) do |string_content, part| yield string_content, visit_string_content(part) end bounds(parts.first.location) on_heredoc_dedent(result, common_whitespace) end end
访问使用 <<~ heredoc 表示的字符串。
Source
# File lib/prism/translation/ripper.rb, line 2981 def visit_heredoc_node_whitespace(parts) common_whitespace = nil dedent_next = true parts.each do |part| if part.is_a?(StringNode) if dedent_next && !(content = part.content).chomp.empty? common_whitespace = [ common_whitespace || Float::INFINITY, content[/\A\s*/].each_char.inject(0) do |part_whitespace, char| char == "\t" ? ((part_whitespace / 8 + 1) * 8) : (part_whitespace + 1) end ].min end dedent_next = true else dedent_next = false end end common_whitespace || 0 end
Source
# File lib/prism/translation/ripper.rb, line 3052 def visit_heredoc_string_node(node) bounds(node.opening_loc) on_heredoc_beg(node.opening) bounds(node.location) result = visit_heredoc_node(node.parts, on_string_content) do |parts, part| on_string_add(parts, part) end bounds(node.closing_loc) on_heredoc_end(node.closing) result end
访问表示字符串的 heredoc 节点。
Source
# File lib/prism/translation/ripper.rb, line 3069 def visit_heredoc_x_string_node(node) bounds(node.opening_loc) on_heredoc_beg(node.opening) bounds(node.location) result = visit_heredoc_node(node.parts, on_xstring_new) do |parts, part| on_xstring_add(parts, part) end bounds(node.closing_loc) on_heredoc_end(node.closing) result end
访问表示 xstring 的 heredoc 节点。
Source
# File lib/prism/translation/ripper.rb, line 2488 def visit_multi_target_node_targets(lefts, rest, rights, skippable) if skippable && lefts.length == 1 && lefts.first.is_a?(MultiTargetNode) && rest.nil? && rights.empty? return visit(lefts.first) end mlhs = on_mlhs_new lefts.each do |left| bounds(left.location) mlhs = on_mlhs_add(mlhs, visit(left)) end case rest when nil # do nothing when ImplicitRestNode # these do not get put into the generated tree bounds(rest.location) on_excessed_comma else bounds(rest.location) mlhs = on_mlhs_add_star(mlhs, visit(rest)) end if rights.any? bounds(rights.first.location) post = on_mlhs_new rights.each do |right| bounds(right.location) post = on_mlhs_add(post, visit(right)) end mlhs = on_mlhs_add_post(mlhs, post) end mlhs end
访问多目标节点的 target。
Source
# File lib/prism/translation/ripper.rb, line 3345 def visit_number_node(node) slice = node.slice location = node.location if slice[0] == "-" bounds(location.copy(start_offset: location.start_offset + 1)) value = yield slice[1..-1] bounds(node.location) on_unary(:-@, value) else bounds(location) yield slice end end
访问表示数字的节点。我们需要显式处理一元 - 运算符。
Source
# File lib/prism/translation/ripper.rb, line 596 def visit_pattern_node(node) if node.is_a?(ParenthesesNode) visit(node.body) else visit(node) end end
访问模式匹配中的模式。这用于绕过可用于包装模式的括号节点。
Source
# File lib/prism/translation/ripper.rb, line 2947 def visit_statements_node_body(body) body.inject(on_stmts_new) do |stmts, stmt| on_stmts_add(stmts, stmt.nil? ? on_void_stmt : visit(stmt)) end end
访问 statements 节点的语句列表。我们支持列表中的 nil 语句。这通常不允许通过 prism 解析树的结构,但我们在此手动添加它们,以便我们可以镜像 Ripper 的 void stmt。
Source
# File lib/prism/translation/ripper.rb, line 2237 def visit_string_content(part) if part.is_a?(StringNode) bounds(part.content_loc) on_tstring_content(part.content) else visit(part) end end
访问字符串类节点中的单个部分。
Source
# File lib/prism/translation/ripper.rb, line 3318 def visit_token(token, allow_keywords = true) case token when "." on_period(token) when "`" on_backtick(token) when *(allow_keywords ? KEYWORDS : []) on_kw(token) when /^_/ on_ident(token) when /^[[:upper:]]\w*$/ on_const(token) when /^@@/ on_cvar(token) when /^@/ on_ivar(token) when /^\$/ on_gvar(token) when /^[[:punct:]]/ on_op(token) else on_ident(token) end end
访问特定节点的字符串内容。此方法用于拆分为各种 token 类型。
Source
# File lib/prism/translation/ripper.rb, line 746 def visit_words_sep(opening_loc, previous, current) end_offset = (previous.nil? ? opening_loc : previous.location).end_offset start_offset = current.location.start_offset if end_offset != start_offset bounds(current.location.copy(start_offset: end_offset)) on_words_sep(source.byteslice(end_offset...start_offset)) end end
派发一个 words_sep 事件,其中包含列表字面量元素之间的空格。
Source
# File lib/prism/translation/ripper.rb, line 3363 def visit_write_value(node) if node.is_a?(ArrayNode) && node.opening_loc.nil? elements = node.elements length = elements.length bounds(elements.first.location) elements.each_with_index.inject((elements.first.is_a?(SplatNode) && length == 1) ? on_mrhs_new : on_args_new) do |args, (element, index)| arg = visit(element) bounds(element.location) if index == length - 1 if element.is_a?(SplatNode) mrhs = index == 0 ? args : on_mrhs_new_from_args(args) on_mrhs_add_star(mrhs, arg) else on_mrhs_add(on_mrhs_new_from_args(args), arg) end else case element when BlockArgumentNode on_args_add_block(args, arg) when SplatNode on_args_add_star(args, arg) else on_args_add(args, arg) end end end else visit(node) end end
访问表示写入值的节点。这用于处理没有括号而生成的隐式数组的特殊情况。
Source
# File lib/prism/translation/ripper.rb, line 3311 def void_stmt?(left, right, allow_newline) pattern = allow_newline ? /[;\n]/ : /;/ source.byteslice(left.end_offset...right.start_offset).match?(pattern) end
如果两个位置之间有分号,则返回 true。
Source
# File lib/prism/translation/ripper.rb, line 3430 def warn(fmt, *args) end
解析器产生弱警告时会调用此方法。fmt 和 args 是 printf 样式。
Source
# File lib/prism/translation/ripper.rb, line 3435 def warning(fmt, *args) end
解析器产生强警告时会调用此方法。fmt 和 args 是 printf 样式。