diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index 339b42c003a..136ccad44c3 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -469,12 +469,71 @@ def visit_break_node(node) # foo.bar() {} # ^^^^^^^^^^^^ def visit_call_node(node) - return visit_aref_node(node) if node.name == :[] - return visit_aref_field_node(node) if node.name == :[]= + case node.name + when :[] + if node.opening == "[" + receiver = visit(node.receiver) + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments << block + block = nil + end - if node.variable_call? - raise NoMethodError, __method__ unless node.receiver.nil? + arguments = + if arguments.any? + args = visit_arguments(arguments) + + if node.block.is_a?(BlockArgumentNode) + args + else + bounds(arguments.first.location) + on_args_add_block(args, false) + end + end + + bounds(node.location) + call = on_aref(receiver, arguments) + if block.nil? + return call + else + block = visit(block) + + bounds(node.location) + return on_method_add_block(call, block) + end + end + when :[]= + if node.opening == "[" + 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(last_argument) + bounds(last_argument.location) + return on_assign(call, value) + end + end + + if node.variable_call? bounds(node.message_loc) return on_vcall(on_ident(node.message)) end @@ -2432,23 +2491,6 @@ def visit_no_paren_call(node) end end - # In Prism this is a CallNode with :[] as the operator. - # In Ripper it's an :aref. - def visit_aref_node(node) - first_arg_val = visit(node.arguments.arguments[0]) - args_val = on_args_add_block(on_args_add(on_args_new, first_arg_val), false) - on_aref(visit(node.receiver), args_val) - end - - # In Prism this is a CallNode with :[]= as the operator. - # In Ripper it's an :aref_field. - def visit_aref_field_node(node) - first_arg_val = visit(node.arguments.arguments[0]) - args_val = on_args_add_block(on_args_add(on_args_new, first_arg_val), false) - assign_val = visit(node.arguments.arguments[1]) - on_assign(on_aref_field(visit(node.receiver), args_val), assign_val) - end - # Ripper has several methods of emitting a symbol literal. Inside an alias # sometimes it suppresses the [:symbol] wrapper around ident. If the symbol # is also the name of a keyword (e.g. :if) it will emit a :@kw wrapper, not diff --git a/test/prism/ripper_test.rb b/test/prism/ripper_test.rb index bdc65297903..0deb486999e 100644 --- a/test/prism/ripper_test.rb +++ b/test/prism/ripper_test.rb @@ -148,7 +148,6 @@ class RipperTest < TestCase seattlerb/heredoc_with_only_carriage_returns.txt seattlerb/heredoc_with_only_carriage_returns_windows.txt seattlerb/if_elsif.txt - seattlerb/index_0.txt seattlerb/interpolated_symbol_array_line_breaks.txt seattlerb/interpolated_word_array_line_breaks.txt seattlerb/lambda_do_vs_brace.txt @@ -401,18 +400,13 @@ class RipperTest < TestCase whitequark/ruby_bug_12073.txt whitequark/ruby_bug_12402.txt whitequark/ruby_bug_12686.txt - whitequark/ruby_bug_13547.txt whitequark/ruby_bug_14690.txt whitequark/ruby_bug_15789.txt whitequark/send_attr_asgn.txt whitequark/send_attr_asgn_conditional.txt whitequark/send_block_chain_cmd.txt whitequark/send_call.txt - whitequark/send_index.txt - whitequark/send_index_asgn.txt - whitequark/send_index_asgn_legacy.txt whitequark/send_index_cmd.txt - whitequark/send_index_legacy.txt whitequark/send_lambda.txt whitequark/send_lambda_args_noparen.txt whitequark/send_lambda_legacy.txt