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
常量
- BINARY_OPERATORS
所有 Ruby 二元运算符的列表。
- EVENTS
此数组包含所有 ripper 事件的名称。
- KEYWORDS
所有 Ruby 关键字的列表。
- PARSER_EVENTS
此数组包含解析器事件的名称。
- PARSER_EVENT_TABLE
这包含所有解析器事件及其对应元数的表。
- SCANNER_EVENTS
此数组包含扫描器事件的名称。
- SCANNER_EVENT_TABLE
这包含所有扫描器事件及其对应元数的表。
属性
解析器当前的列号。
正在解析的源文件的文件名。
解析器当前的行号。
正在解析的源代码。
公共类方法
对 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 ]]
# File prism/translation/ripper.rb, line 72 def self.lex(src, filename = "-", lineno = 1, raise_errors: false) result = Prism.lex_compat(src, filepath: filename, line: lineno) if result.failure? && raise_errors raise SyntaxError, result.errors.first.message else result.value end end
使用给定的源创建新的 Translation::Ripper
对象。
# File prism/translation/ripper.rb, line 444 def initialize(source, filename = "(ripper)", lineno = 1) @source = source @filename = filename @lineno = lineno @column = 0 @result = nil end
解析从 `src` 读取的给定 Ruby 程序。 `src` 必须是字符串、IO 或具有 gets 方法的对象。
# File prism/translation/ripper.rb, line 46 def self.parse(src, filename = "(ripper)", lineno = 1) new(src, filename, lineno).parse 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]]]]
# File prism/translation/ripper.rb, line 381 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 树。此方法主要供开发人员使用。 `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]]]]
# File prism/translation/ripper.rb, line 416 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
公共实例方法
如果在解析过程中解析器遇到错误,则为 True。
# File prism/translation/ripper.rb, line 457 def error? result.failure? end
解析源代码并返回结果。
# File prism/translation/ripper.rb, line 462 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
alias $foo $bar ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 561 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 ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 551 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
foo => bar | baz
^^^^^^^^^
# File prism/translation/ripper.rb, line 585 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
a and b ^^^^^^^
# File prism/translation/ripper.rb, line 605 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
foo(bar)
^^^
# File prism/translation/ripper.rb, line 796 def visit_arguments_node(node) arguments, _ = visit_call_node_arguments(node, nil, false) arguments end
-
^^
# File prism/translation/ripper.rb, line 615 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
foo => [bar]
^^^^^
# File prism/translation/ripper.rb, line 775 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
{ a: 1 }
^^^^
# File prism/translation/ripper.rb, line 803 def visit_assoc_node(node) key = visit(node.key) value = visit(node.value) bounds(node.location) on_assoc_new(key, value) end
def foo(**); bar(**); end
^^
{ **foo }
^^^^^
# File prism/translation/ripper.rb, line 816 def visit_assoc_splat_node(node) value = visit(node.value) bounds(node.location) on_assoc_splat(value) end
$+ ^^
# File prism/translation/ripper.rb, line 825 def visit_back_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
begin end ^^^^^^^^^
# File prism/translation/ripper.rb, line 832 def visit_begin_node(node) clauses = visit_begin_node_clauses(node.begin_keyword_loc, node, false) bounds(node.location) on_begin(clauses) end
foo(&bar)
^^^^
# File prism/translation/ripper.rb, line 896 def visit_block_argument_node(node) visit(node.expression) end
foo { |; bar| }
^^^
# File prism/translation/ripper.rb, line 902 def visit_block_local_variable_node(node) bounds(node.location) on_ident(node.name.to_s) end
访问一个 BlockNode
。
# File prism/translation/ripper.rb, line 908 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
def foo(&bar); end
^^^^
# File prism/translation/ripper.rb, line 944 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
一个代码块的参数。
# File prism/translation/ripper.rb, line 958 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
break ^^^^^
break foo ^^^^^^^^^
# File prism/translation/ripper.rb, line 982 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
foo.bar &&= baz ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1194 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 ^^^
foo.bar ^^^^^^^
foo.bar() {} ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1002 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 :! receiver = visit(node.receiver) bounds(node.location) on_unary(node.message == "not" ? :not : :!, receiver) 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.bar += baz ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1172 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 ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1216 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, = 1 ^^^^^^^
# File prism/translation/ripper.rb, line 1238 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 => baz
^^^^^^^^^^
# File prism/translation/ripper.rb, line 1263 def visit_capture_pattern_node(node) value = visit(node.value) target = visit(node.target) bounds(node.location) on_binary(value, :"=>", target) end
case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1286 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; when bar; end ^^^^^^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1273 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
class Foo; end ^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1299 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
@@foo &&= bar ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1352 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 ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1338 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 ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1366 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 ^^^^^
# File prism/translation/ripper.rb, line 1317 def visit_class_variable_read_node(node) bounds(node.location) on_var_ref(on_cvar(node.slice)) end
@@foo, = bar ^^^^^
# File prism/translation/ripper.rb, line 1380 def visit_class_variable_target_node(node) bounds(node.location) on_var_field(on_cvar(node.name.to_s)) end
@@foo = 1 ^^^^^^^^^
@@foo, @@bar = 1 ^^^^^ ^^^^^
# File prism/translation/ripper.rb, line 1327 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 &&= bar ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1422 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 ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1408 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 ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1436 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 &&= baz ^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1523 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 ^^^^^^^^
# File prism/translation/ripper.rb, line 1457 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 += baz ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1509 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 ^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1537 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 ^^^^^^^^
# File prism/translation/ripper.rb, line 1551 def visit_constant_path_target_node(node) visit_constant_path_write_node_target(node) end
Foo::Bar = 1 ^^^^^^^^^^^^
Foo::Foo, Bar::Bar = 1 ^^^^^^^^ ^^^^^^^^
# File prism/translation/ripper.rb, line 1480 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 ^^^
# File prism/translation/ripper.rb, line 1387 def visit_constant_read_node(node) bounds(node.location) on_var_ref(on_const(node.name.to_s)) end
Foo, = bar ^^^
# File prism/translation/ripper.rb, line 1450 def visit_constant_target_node(node) bounds(node.location) on_var_field(on_const(node.name.to_s)) end
Foo = 1 ^^^^^^^
Foo, Bar = 1 ^^^ ^^^
# File prism/translation/ripper.rb, line 1397 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
def foo; end ^^^^^^^^^^^^
def self.foo; end ^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1560 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
defined? a ^^^^^^^^^^
defined?(a) ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1607 def visit_defined_node(node) bounds(node.location) on_defined(visit(node.value)) end
if foo then bar else baz end
^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1614 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
“foo #{bar}”
^^^^^^
# File prism/translation/ripper.rb, line 1630 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”
^^^^^
# File prism/translation/ripper.rb, line 1651 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
访问一个 EnsureNode
节点。
# File prism/translation/ripper.rb, line 1662 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
false ^^^^^
# File prism/translation/ripper.rb, line 1680 def visit_false_node(node) bounds(node.location) on_var_ref(on_kw("false")) end
foo => [*, bar, *]
^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1687 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
if foo .. bar; end
^^^^^^^^^^
# File prism/translation/ripper.rb, line 1712 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
1.0 ^^^
# File prism/translation/ripper.rb, line 1726 def visit_float_node(node) visit_number_node(node) { |text| on_float(text) } end
for foo in bar do end ^^^^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1732 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
def foo(…); bar(…); end
^^^
# File prism/translation/ripper.rb, line 1749 def visit_forwarding_arguments_node(node) bounds(node.location) on_args_forward end
def foo(…); end
^^^
# File prism/translation/ripper.rb, line 1756 def visit_forwarding_parameter_node(node) bounds(node.location) on_args_forward end
super ^^^^^
super {} ^^^^^^^^
# File prism/translation/ripper.rb, line 1766 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
$foo &&= bar ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1815 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 ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1801 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 ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1829 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 ^^^^
# File prism/translation/ripper.rb, line 1780 def visit_global_variable_read_node(node) bounds(node.location) on_var_ref(on_gvar(node.name.to_s)) end
$foo, = bar ^^^^
# File prism/translation/ripper.rb, line 1843 def visit_global_variable_target_node(node) bounds(node.location) on_var_field(on_gvar(node.name.to_s)) end
$foo = 1 ^^^^^^^^
$foo, $bar = 1 ^^^^ ^^^^
# File prism/translation/ripper.rb, line 1790 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
{} ^^
# File prism/translation/ripper.rb, line 1850 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
foo => {}
^^
# File prism/translation/ripper.rb, line 1865 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
if foo then bar end ^^^^^^^^^^^^^^^^^^^
bar if foo ^^^^^^^^^^
foo ? bar : baz ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1907 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
1i ^^
# File prism/translation/ripper.rb, line 1943 def visit_imaginary_node(node) visit_number_node(node) { |text| on_imaginary(text) } end
{ foo: }
^^^^
# File prism/translation/ripper.rb, line 1949 def visit_implicit_node(node) end
foo { |bar,| }
^
# File prism/translation/ripper.rb, line 1954 def visit_implicit_rest_node(node) bounds(node.location) on_excessed_comma end
case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1961 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
foo &&= baz ^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1996 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 ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 1979 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 ^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2013 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, = 1 ^^^^^^^^
# File prism/translation/ripper.rb, line 2030 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 &&= bar ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2072 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 ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2058 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 ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2086 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 ^^^^
# File prism/translation/ripper.rb, line 2040 def visit_instance_variable_read_node(node) bounds(node.location) on_var_ref(on_ivar(node.name.to_s)) end
@foo, = bar ^^^^
# File prism/translation/ripper.rb, line 2100 def visit_instance_variable_target_node(node) bounds(node.location) on_var_field(on_ivar(node.name.to_s)) end
@foo = 1 ^^^^^^^^
# File prism/translation/ripper.rb, line 2047 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
1 ^
# File prism/translation/ripper.rb, line 2107 def visit_integer_node(node) visit_number_node(node) { |text| on_int(text) } end
if /foo #{bar}/ then end
^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2113 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
/foo #{bar}/ ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2132 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}” ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2151 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}” ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2179 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}` ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2192 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
-> { it }
^^
# File prism/translation/ripper.rb, line 2222 def visit_it_local_variable_read_node(node) bounds(node.location) on_vcall(on_ident(node.slice)) end
-> { it } ^^^^^^^^^
# File prism/translation/ripper.rb, line 2229 def visit_it_parameters_node(node) end
foo(bar: baz)
^^^^^^^^
# File prism/translation/ripper.rb, line 2234 def visit_keyword_hash_node(node) elements = visit_all(node.elements) bounds(node.location) on_bare_assoc_hash(elements) end
def foo(**bar); end
^^^^^
def foo(**); end
^^
# File prism/translation/ripper.rb, line 2246 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
-> {}
# File prism/translation/ripper.rb, line 2260 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
foo &&= bar ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2352 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 ^^^^^^^^^^
# File prism/translation/ripper.rb, line 2338 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 ^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2366 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 ^^^
# File prism/translation/ripper.rb, line 2320 def visit_local_variable_read_node(node) bounds(node.location) on_var_ref(on_ident(node.slice)) end
foo, = bar ^^^
# File prism/translation/ripper.rb, line 2380 def visit_local_variable_target_node(node) bounds(node.location) on_var_field(on_ident(node.name.to_s)) end
foo = 1 ^^^^^^^
# File prism/translation/ripper.rb, line 2327 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
if /foo/ then end
^^^^^
# File prism/translation/ripper.rb, line 2387 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
foo in bar ^^^^^^^^^^
# File prism/translation/ripper.rb, line 2402 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 => bar ^^^^^^^^^^
# File prism/translation/ripper.rb, line 2411 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>foo)/ =~ bar ^^^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2420 def visit_match_write_node(node) visit(node.call) end
语法树中缺失的节点。仅在出现语法错误时使用。
# File prism/translation/ripper.rb, line 2426 def visit_missing_node(node) raise "Cannot visit missing nodes directly." end
module Foo; end ^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2432 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
(foo, bar), bar = qux ^^^^^^^^^^
# File prism/translation/ripper.rb, line 2449 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 = baz ^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2503 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
next ^^^^
next foo ^^^^^^^^
# File prism/translation/ripper.rb, line 2523 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
nil ^^^
# File prism/translation/ripper.rb, line 2537 def visit_nil_node(node) bounds(node.location) on_var_ref(on_kw("nil")) end
def foo(**nil); end
^^^^^
# File prism/translation/ripper.rb, line 2544 def visit_no_keywords_parameter_node(node) bounds(node.location) on_nokw_param(nil) :nil end
-> { _1 + _2 } ^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2553 def visit_numbered_parameters_node(node) end
$1 ^^
# File prism/translation/ripper.rb, line 2558 def visit_numbered_reference_read_node(node) bounds(node.location) on_backref(node.slice) end
def foo(bar: baz); end
^^^^^^^^
# File prism/translation/ripper.rb, line 2565 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 = 1); end
^^^^^^^
# File prism/translation/ripper.rb, line 2575 def visit_optional_parameter_node(node) bounds(node.name_loc) name = visit_token(node.name.to_s) value = visit(node.value) [name, value] end
a or b ^^^^^^
# File prism/translation/ripper.rb, line 2585 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
def foo(bar, *baz); end
^^^^^^^^^
# File prism/translation/ripper.rb, line 2595 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
() ^^
(1) ^^^
# File prism/translation/ripper.rb, line 2622 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
foo => ^(bar)
^^^^^^
# File prism/translation/ripper.rb, line 2636 def visit_pinned_expression_node(node) expression = visit(node.expression) bounds(node.location) on_begin(expression) end
foo = 1 and bar => ^foo
^^^^
# File prism/translation/ripper.rb, line 2645 def visit_pinned_variable_node(node) visit(node.variable) end
END {} ^^^^^^
# File prism/translation/ripper.rb, line 2651 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
BEGIN {} ^^^^^^^^
# File prism/translation/ripper.rb, line 2666 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
顶层程序节点。
# File prism/translation/ripper.rb, line 2680 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
0..5 ^^^^
# File prism/translation/ripper.rb, line 2691 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
1r ^^
# File prism/translation/ripper.rb, line 2705 def visit_rational_node(node) visit_number_node(node) { |text| on_rational(text) } end
redo ^^^^
# File prism/translation/ripper.rb, line 2711 def visit_redo_node(node) bounds(node.location) on_redo end
/foo/ ^^^^^
# File prism/translation/ripper.rb, line 2718 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
def foo(bar:); end
^^^^
# File prism/translation/ripper.rb, line 2740 def visit_required_keyword_parameter_node(node) bounds(node.name_loc) [on_label("#{node.name}:"), false] end
def foo(bar); end
^^^
# File prism/translation/ripper.rb, line 2747 def visit_required_parameter_node(node) bounds(node.location) on_ident(node.name.to_s) end
foo rescue bar ^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2754 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
begin; rescue; end
^^^^^^^
# File prism/translation/ripper.rb, line 2764 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
def foo(*bar); end
^^^^
def foo(*); end
^
# File prism/translation/ripper.rb, line 2822 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
retry ^^^^^
# File prism/translation/ripper.rb, line 2834 def visit_retry_node(node) bounds(node.location) on_retry end
return ^^^^^^
return 1 ^^^^^^^^
# File prism/translation/ripper.rb, line 2844 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
self ^^^^
# File prism/translation/ripper.rb, line 2858 def visit_self_node(node) bounds(node.location) on_var_ref(on_kw("self")) end
class << self; end ^^^^^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2870 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
__ENCODING__ ^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 2880 def visit_source_encoding_node(node) bounds(node.location) on_var_ref(on_kw("__ENCODING__")) end
__FILE__ ^^^^^^^^
# File prism/translation/ripper.rb, line 2887 def visit_source_file_node(node) bounds(node.location) on_var_ref(on_kw("__FILE__")) end
__LINE__ ^^^^^^^^
# File prism/translation/ripper.rb, line 2894 def visit_source_line_node(node) bounds(node.location) on_var_ref(on_kw("__LINE__")) end
foo(*bar)
^^^^
def foo((bar, *baz)); end
^^^^
def foo(*); bar(*); end
^
# File prism/translation/ripper.rb, line 2907 def visit_splat_node(node) visit(node.expression) end
语句列表。
# File prism/translation/ripper.rb, line 2912 def visit_statements_node(node) bounds(node.location) visit_statements_node_body(node.body) end
“foo” ^^^^^
# File prism/translation/ripper.rb, line 2929 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
super(foo) ^^^^^^^^^^
# File prism/translation/ripper.rb, line 3061 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
:foo ^^^^
# File prism/translation/ripper.rb, line 3082 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
true ^^^^
# File prism/translation/ripper.rb, line 3106 def visit_true_node(node) bounds(node.location) on_var_ref(on_kw("true")) end
undef foo ^^^^^^^^^
# File prism/translation/ripper.rb, line 3113 def visit_undef_node(node) names = visit_all(node.names) bounds(node.location) on_undef(names) end
unless foo; bar end ^^^^^^^^^^^^^^^^^^^
bar unless foo ^^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 3125 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
until foo; bar end ^^^^^^^^^^^^^^^^^
bar until foo ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 3153 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
case foo; when bar; end
^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 3177 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
while foo; bar end ^^^^^^^^^^^^^^^^^^
bar while foo ^^^^^^^^^^^^^
# File prism/translation/ripper.rb, line 3198 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
‘foo` ^^^^^
# File prism/translation/ripper.rb, line 3222 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
yield ^^^^^
yield 1 ^^^^^^^
# File prism/translation/ripper.rb, line 3245 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
私有实例方法
此方法负责更新行号和列信息以反映当前节点。
可以通过在每行开头进行一些缓存来大幅改进此方法,但目前来说已经足够好了。
# File prism/translation/ripper.rb, line 3375 def bounds(location) @lineno = location.start_line @column = location.start_column end
如果给定节点是命令节点,则返回 true。
# File prism/translation/ripper.rb, line 1163 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
当解析器发现语法错误时,调用此方法。
# File prism/translation/ripper.rb, line 3413 def compile_error(msg) end
此方法由 Ripper
C 扩展提供。当由于波浪号 heredoc 需要对字符串进行缩进时,会调用此方法。它应该就地修改字符串,并返回删除的字节数。
# File prism/translation/ripper.rb, line 3428 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
延迟初始化解析结果。
# File prism/translation/ripper.rb, line 3271 def result @result ||= Prism.parse(source, partial_script: true) end
如果两个位置之间存在逗号,则返回 true。
# File prism/translation/ripper.rb, line 3280 def trailing_comma?(left, right) source.byteslice(left.end_offset...right.start_offset).include?(",") end
访问别名全局变量节点的一侧。
# File prism/translation/ripper.rb, line 570 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
访问元素列表,例如数组或参数的元素。
# File prism/translation/ripper.rb, line 756 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
访问 begin 节点的子句以形成 on_bodystmt 调用。
# File prism/translation/ripper.rb, line 840 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
访问一个结构体的主体,该结构体可以包含一组语句,或者包含在 rescue/else/ensure 中的语句。
# File prism/translation/ripper.rb, line 875 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
访问调用节点的参数和代码块,并返回应使用的参数和代码块。
# File prism/translation/ripper.rb, line 1136 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
访问作为写入节点一部分的常量路径。
# File prism/translation/ripper.rb, line 1489 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
访问解构的位置参数节点。
# File prism/translation/ripper.rb, line 2609 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
访问使用 <<~ heredoc 表示的字符串。
# File prism/translation/ripper.rb, line 2980 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
Ripper
返回转义的字符串内容,但会去除常见的开头空白。 Prism
返回未转义的字符串内容以及转义字符串内容的位置。不幸的是,它们不能很好地协同工作,因此这里我们需要重新推导出常见的开头空白。
# File prism/translation/ripper.rb, line 2955 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
访问表示字符串的 heredoc 节点。
# File prism/translation/ripper.rb, line 3026 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
访问表示 xstring 的 heredoc 节点。
# File prism/translation/ripper.rb, line 3043 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
访问多目标节点的目标。
# File prism/translation/ripper.rb, line 2462 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
访问表示数字的节点。我们需要显式处理一元 - 运算符。
# File prism/translation/ripper.rb, line 3319 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
访问模式匹配中的模式。这用于绕过可以用来包装模式的括号节点。
# File prism/translation/ripper.rb, line 595 def visit_pattern_node(node) if node.is_a?(ParenthesesNode) visit(node.body) else visit(node) end end
访问语句节点的语句列表。我们支持列表中的 nil 语句。这通常不会被 prism 解析树的结构允许,但我们在这里手动添加它们,以便我们可以镜像 Ripper 的 void stmt。
# File prism/translation/ripper.rb, line 2921 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
访问类字符串节点的单个部分。
# File prism/translation/ripper.rb, line 2211 def visit_string_content(part) if part.is_a?(StringNode) bounds(part.content_loc) on_tstring_content(part.content) else visit(part) end end
访问特定节点的字符串内容。此方法用于拆分为各种令牌类型。
# File prism/translation/ripper.rb, line 3292 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
分派一个 words_sep 事件,其中包含列表字面量的元素之间的空格。
# File prism/translation/ripper.rb, line 745 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
访问表示写入值的节点。这用于处理不带括号生成的隐式数组的特殊情况。
# File prism/translation/ripper.rb, line 3337 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
如果两个位置之间存在分号,则返回 true。
# File prism/translation/ripper.rb, line 3285 def void_stmt?(left, right, allow_newline) pattern = allow_newline ? /[;\n]/ : /;/ source.byteslice(left.end_offset...right.start_offset).match?(pattern) end
当解析器产生弱警告时调用此方法。 fmt
和 args
是 printf 风格。
# File prism/translation/ripper.rb, line 3404 def warn(fmt, *args) end
当解析器产生强警告时调用此方法。 fmt
和 args
是 printf 风格。
# File prism/translation/ripper.rb, line 3409 def warning(fmt, *args) end