Skip to content

Commit 372200f

Browse files
committed
Revisit call nodes for ripper translation
1 parent d31cf63 commit 372200f

File tree

2 files changed

+99
-142
lines changed

2 files changed

+99
-142
lines changed

lib/prism/translation/ripper.rb

Lines changed: 99 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -469,44 +469,22 @@ def visit_break_node(node)
469469
# foo.bar() {}
470470
# ^^^^^^^^^^^^
471471
def visit_call_node(node)
472-
case node.name
473-
when :[]
474-
if node.opening == "["
472+
if node.call_operator_loc.nil?
473+
case node.name
474+
when :[]
475475
receiver = visit(node.receiver)
476-
arguments = node.arguments&.arguments || []
477-
block = node.block
478-
479-
if block.is_a?(BlockArgumentNode)
480-
arguments << block
481-
block = nil
482-
end
483-
484-
arguments =
485-
if arguments.any?
486-
args = visit_arguments(arguments)
487-
488-
if node.block.is_a?(BlockArgumentNode)
489-
args
490-
else
491-
bounds(arguments.first.location)
492-
on_args_add_block(args, false)
493-
end
494-
end
476+
arguments, block = visit_call_node_arguments(node.arguments, node.block)
495477

496478
bounds(node.location)
497479
call = on_aref(receiver, arguments)
498480

499481
if block.nil?
500-
return call
482+
call
501483
else
502-
block = visit(block)
503-
504484
bounds(node.location)
505-
return on_method_add_block(call, block)
485+
on_method_add_block(call, block)
506486
end
507-
end
508-
when :[]=
509-
if node.opening == "["
487+
when :[]=
510488
receiver = visit(node.receiver)
511489

512490
*arguments, last_argument = node.arguments.arguments
@@ -529,34 +507,107 @@ def visit_call_node(node)
529507

530508
value = visit(last_argument)
531509
bounds(last_argument.location)
532-
return on_assign(call, value)
510+
on_assign(call, value)
511+
when :-@, :+@, :~@, :!@
512+
receiver = visit(node.receiver)
513+
514+
bounds(node.location)
515+
on_unary(node.message == "not" ? :not : node.name, receiver)
516+
when :!=, :!~, :=~, :==, :===, :<=>, :>, :>=, :<, :<=, :&, :|, :^, :>>, :<<, :-, :+, :%, :/, :*, :**
517+
receiver = visit(node.receiver)
518+
value = visit(node.arguments.arguments.first)
519+
520+
bounds(node.location)
521+
on_binary(receiver, node.name, value)
522+
else
523+
bounds(node.message_loc)
524+
message = on_ident(node.message)
525+
526+
if node.variable_call?
527+
on_vcall(message)
528+
else
529+
arguments, block = visit_call_node_arguments(node.arguments, node.block)
530+
call =
531+
if node.opening_loc.nil? && (arguments&.any? || block.nil?)
532+
bounds(node.location)
533+
on_command(message, arguments)
534+
elsif !node.opening_loc.nil?
535+
bounds(node.location)
536+
on_method_add_arg(on_fcall(message), on_arg_paren(arguments))
537+
else
538+
bounds(node.location)
539+
on_method_add_arg(on_fcall(message), on_args_new)
540+
end
541+
542+
if block.nil?
543+
call
544+
else
545+
bounds(node.block.location)
546+
on_method_add_block(call, block)
547+
end
548+
end
533549
end
534-
end
550+
else
551+
receiver = visit(node.receiver)
552+
553+
bounds(node.call_operator_loc)
554+
call_operator = visit_token(node.call_operator)
535555

536-
if node.variable_call?
537556
bounds(node.message_loc)
538-
return on_vcall(on_ident(node.message))
539-
end
557+
message = visit_token(node.message)
540558

541-
if node.opening_loc.nil?
542-
return visit_no_paren_call(node)
543-
end
559+
arguments, block = visit_call_node_arguments(node.arguments, node.block)
560+
call =
561+
if node.opening_loc.nil?
562+
bounds(node.location)
544563

545-
# A non-operator method call with parentheses
546-
args = on_arg_paren(node.arguments.nil? ? nil : visit(node.arguments))
564+
if !arguments || arguments.empty?
565+
on_call(receiver, call_operator, message)
566+
else
567+
on_command_call(receiver, call_operator, message, arguments)
568+
end
569+
else
570+
bounds(node.opening_loc)
571+
arguments = on_arg_paren(arguments)
547572

548-
bounds(node.message_loc)
549-
ident_val = on_ident(node.message)
573+
bounds(node.location)
574+
on_method_add_arg(on_call(receiver, call_operator, message), arguments)
575+
end
550576

551-
bounds(node.location)
552-
args_call_val = on_method_add_arg(on_fcall(ident_val), args)
553-
if node.block
554-
block_val = visit(node.block)
577+
if block.nil?
578+
call
579+
else
580+
bounds(node.block.location)
581+
on_method_add_block(call, block)
582+
end
583+
end
584+
end
555585

556-
return on_method_add_block(args_call_val, block_val)
557-
else
558-
return args_call_val
586+
# Visit the arguments and block of a call node and return the arguments
587+
# and block as they should be used.
588+
private def visit_call_node_arguments(arguments_node, block_node)
589+
arguments = arguments_node&.arguments || []
590+
block = block_node
591+
592+
if block.is_a?(BlockArgumentNode)
593+
arguments << block
594+
block = nil
559595
end
596+
597+
arguments =
598+
if arguments.any?
599+
args = visit_arguments(arguments)
600+
601+
if block.is_a?(BlockArgumentNode)
602+
args
603+
else
604+
bounds(arguments.first.location)
605+
on_args_add_block(args, false)
606+
end
607+
end
608+
609+
block = visit(block) if !block.nil?
610+
[arguments, block]
560611
end
561612

562613
# foo.bar += baz
@@ -2427,70 +2478,6 @@ def visit_token(token)
24272478
end
24282479
end
24292480

2430-
# Generate Ripper events for a CallNode with no opening_loc
2431-
def visit_no_paren_call(node)
2432-
# No opening_loc can mean an operator. It can also mean a
2433-
# method call with no parentheses.
2434-
if node.message.match?(/^[[:punct:]]/)
2435-
left = visit(node.receiver)
2436-
if node.arguments&.arguments&.length == 1
2437-
right = visit(node.arguments.arguments.first)
2438-
2439-
return on_binary(left, node.name, right)
2440-
elsif !node.arguments || node.arguments.empty?
2441-
return on_unary(node.name, left)
2442-
else
2443-
raise NoMethodError, __method__, "More than two arguments for operator"
2444-
end
2445-
elsif node.call_operator_loc.nil?
2446-
# In Ripper a method call like "puts myvar" with no parentheses is a "command".
2447-
bounds(node.message_loc)
2448-
ident_val = on_ident(node.message)
2449-
2450-
# Unless it has a block, and then it's an fcall (e.g. "foo { bar }")
2451-
if node.block
2452-
block_val = visit(node.block)
2453-
# In these calls, even if node.arguments is nil, we still get an :args_new call.
2454-
args = if node.arguments.nil?
2455-
on_args_new
2456-
else
2457-
on_args_add_block(visit_arguments(node.arguments.arguments))
2458-
end
2459-
method_args_val = on_method_add_arg(on_fcall(ident_val), args)
2460-
return on_method_add_block(method_args_val, block_val)
2461-
else
2462-
if node.arguments.nil?
2463-
return on_command(ident_val, nil)
2464-
else
2465-
args = on_args_add_block(visit_arguments(node.arguments.arguments), false)
2466-
return on_command(ident_val, args)
2467-
end
2468-
end
2469-
else
2470-
operator = node.call_operator_loc.slice
2471-
if operator == "." || operator == "&."
2472-
left_val = visit(node.receiver)
2473-
2474-
bounds(node.call_operator_loc)
2475-
operator_val = operator == "." ? on_period(node.call_operator) : on_op(node.call_operator)
2476-
2477-
bounds(node.message_loc)
2478-
right_val = on_ident(node.message)
2479-
2480-
call_val = on_call(left_val, operator_val, right_val)
2481-
2482-
if node.block
2483-
block_val = visit(node.block)
2484-
return on_method_add_block(call_val, block_val)
2485-
else
2486-
return call_val
2487-
end
2488-
else
2489-
raise NoMethodError, __method__, "operator other than . or &. for call: #{operator.inspect}"
2490-
end
2491-
end
2492-
end
2493-
24942481
# Ripper has several methods of emitting a symbol literal. Inside an alias
24952482
# sometimes it suppresses the [:symbol] wrapper around ident. If the symbol
24962483
# is also the name of a keyword (e.g. :if) it will emit a :@kw wrapper, not

0 commit comments

Comments
 (0)