diff options
| author | Kevin Newton <kddnewton@gmail.com> | 2024-02-06 21:31:12 -0500 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2024-02-07 03:21:02 +0000 |
| commit | 2dba441397d338617e1b605104d8b42b5311a482 (patch) | |
| tree | d5ea76a529cdd2b46c7c3b45e0045058c1146739 | |
| parent | 64b6a018a38f200c957fdbbe7d0cbe0e64781c9f (diff) | |
[ruby/prism] Even more ripper compat
https://github.com/ruby/prism/commit/47a602dc1c
| -rw-r--r-- | lib/prism/ripper_compat.rb | 127 | ||||
| -rw-r--r-- | test/prism/ripper_compat_test.rb | 18 |
2 files changed, 92 insertions, 53 deletions
diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb index 739d587541..912114cfef 100644 --- a/lib/prism/ripper_compat.rb +++ b/lib/prism/ripper_compat.rb @@ -97,6 +97,8 @@ module Prism result.errors.each do |error| on_parse_error(error.message) end + + nil else result.value.accept(self) end @@ -106,14 +108,22 @@ module Prism # Visitor methods ############################################################################ - # Visit a CallNode node. - def visit_call_node(node) + # Visit an ArrayNode node. + def visit_array_node(node) + elements = visit_elements(node.elements) unless node.elements.empty? bounds(node.location) + on_array(elements) + end - if node.message.match?(/^[[:alpha:]_]/) - val = on_ident(node.message) + # Visit a CallNode node. + def visit_call_node(node) + if node.variable_call? + if node.message.match?(/^[[:alpha:]_]/) + bounds(node.message_loc) + return on_vcall(on_ident(node.message)) + end - return on_vcall(val) + raise NotImplementedError, "Non-alpha variable call" end if node.opening_loc.nil? @@ -128,67 +138,61 @@ module Prism raise NotImplementedError, "More than two arguments for operator" end else - # This is a method call, not an operator raise NotImplementedError, "Non-nil opening_loc" end end - # Visit a RangeNode - def visit_range_node(node) - bounds(node.location) - left = visit(node.left) - right = visit(node.right) - - if node.operator_loc.slice == "..." - on_dot3(left, right) - else - on_dot2(left, right) - end - end - - # Visit a ParenthesesNode - def visit_parentheses_node(node) - bounds(node.location) - val = visit(node.body) - on_paren(val) - end - # Visit a FloatNode node. def visit_float_node(node) - bounds(node.location) - on_float(node.slice) + visit_number(node) { |text| on_float(text) } end # Visit a ImaginaryNode node. def visit_imaginary_node(node) - bounds(node.location) - on_imaginary(node.slice) + visit_number(node) { |text| on_imaginary(text) } end # Visit an IntegerNode node. def visit_integer_node(node) - text = node.slice - loc = node.location - if text[0] == "-" - # TODO: This is ugly. We test that a newline between - and 7 doesn't give an error, but this could still be bad somehow. - bounds_line_col(loc.start_line, loc.start_column + 1) - on_int_val = on_int(text[1..-1]) - bounds(node.location) - if RUBY_ENGINE == "jruby" - on_unary(:-, on_int_val) + visit_number(node) { |text| on_int(text) } + end + + # Visit a ParenthesesNode node. + def visit_parentheses_node(node) + body = + if node.body.nil? + on_stmts_add(on_stmts_new, on_void_stmt) else - on_unary(:-@, on_int_val) + visit(node.body) end + + bounds(node.location) + on_paren(body) + end + + # Visit a ProgramNode node. + def visit_program_node(node) + statements = visit(node.statements) + bounds(node.location) + on_program(statements) + end + + # Visit a RangeNode node. + 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 - bounds(node.location) - on_int(text) + on_dot2(left, right) end end # Visit a RationalNode node. def visit_rational_node(node) - bounds(node.location) - on_rational(node.slice) + visit_number(node) { |text| on_rational(text) } end # Visit a StatementsNode node. @@ -199,13 +203,6 @@ module Prism end end - # Visit a ProgramNode node. - def visit_program_node(node) - statements = visit(node.statements) - bounds(node.location) - on_program(statements) - end - ############################################################################ # Entrypoints for subclasses ############################################################################ @@ -222,6 +219,32 @@ module Prism private + # Visit a list of elements, like the elements of an array or arguments. + def visit_elements(elements) + bounds(elements.first.location) + elements.inject(on_args_new) do |args, element| + on_args_add(args, visit(element)) + end + end + + # Visit a node that represents a number. We need to explicitly handle the + # unary - operator. + def visit_number(node) + slice = node.slice + location = node.location + + if slice[0] == "-" + bounds_values(location.start_line, location.start_column + 1) + value = yield slice[1..-1] + + bounds(node.location) + on_unary(RUBY_ENGINE == "jruby" ? :- : :-@, value) + else + bounds(location) + yield slice + end + end + # This method is responsible for updating lineno and column information # to reflect the current node. # @@ -234,7 +257,7 @@ module Prism # If we need to do something unusual, we can directly update the line number # and column to reflect the current node. - def bounds_line_col(lineno, column) + def bounds_values(lineno, column) @lineno = lineno @column = column end diff --git a/test/prism/ripper_compat_test.rb b/test/prism/ripper_compat_test.rb index 0bdef53038..8ca8545add 100644 --- a/test/prism/ripper_compat_test.rb +++ b/test/prism/ripper_compat_test.rb @@ -36,10 +36,26 @@ module Prism assert_equivalent("(foo..-7)") end + def test_parentheses + assert_equivalent("()") + assert_equivalent("(1)") + assert_equivalent("(1; 2)") + end + + def test_numbers + assert_equivalent("[1, -1, +1, 1.0, -1.0, +1.0]") + assert_equivalent("[1r, -1r, +1r, 1.5r, -1.5r, +1.5r]") + assert_equivalent("[1i, -1i, +1i, 1.5i, -1.5i, +1.5i]") + assert_equivalent("[1ri, -1ri, +1ri, 1.5ri, -1.5ri, +1.5ri]") + end + private def assert_equivalent(source) - assert_equal Ripper.sexp_raw(source), RipperCompat.sexp_raw(source) + expected = Ripper.sexp_raw(source) + + refute_nil expected + assert_equal expected, RipperCompat.sexp_raw(source) end end end |
