Skip to content

Commit 5ea83ca

Browse files
authored
Merge pull request #3867 from eregon/check-if-array-before-calling-any
Check using Prism nodes if a command call has any arguments in Ripper translator
2 parents 1f00a20 + 52c4fa7 commit 5ea83ca

2 files changed

Lines changed: 55 additions & 30 deletions

File tree

lib/prism/translation/ripper.rb

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ def visit_array_pattern_node(node)
832832
# foo(bar)
833833
# ^^^
834834
def visit_arguments_node(node)
835-
arguments, _ = visit_call_node_arguments(node, nil, false)
835+
arguments, _, _ = visit_call_node_arguments(node, nil, false)
836836
arguments
837837
end
838838

@@ -1042,16 +1042,16 @@ def visit_call_node(node)
10421042
case node.name
10431043
when :[]
10441044
receiver = visit(node.receiver)
1045-
arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
1045+
arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
10461046

10471047
bounds(node.location)
10481048
call = on_aref(receiver, arguments)
10491049

1050-
if block.nil?
1051-
call
1052-
else
1050+
if has_ripper_block
10531051
bounds(node.location)
10541052
on_method_add_block(call, block)
1053+
else
1054+
call
10551055
end
10561056
when :[]=
10571057
receiver = visit(node.receiver)
@@ -1110,9 +1110,9 @@ def visit_call_node(node)
11101110
if node.variable_call?
11111111
on_vcall(message)
11121112
else
1113-
arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1113+
arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
11141114
call =
1115-
if node.opening_loc.nil? && arguments&.any?
1115+
if node.opening_loc.nil? && get_arguments_and_block(node.arguments, node.block).first.any?
11161116
bounds(node.location)
11171117
on_command(message, arguments)
11181118
elsif !node.opening_loc.nil?
@@ -1123,11 +1123,11 @@ def visit_call_node(node)
11231123
on_method_add_arg(on_fcall(message), on_args_new)
11241124
end
11251125

1126-
if block.nil?
1127-
call
1128-
else
1126+
if has_ripper_block
11291127
bounds(node.block.location)
11301128
on_method_add_block(call, block)
1129+
else
1130+
call
11311131
end
11321132
end
11331133
end
@@ -1151,7 +1151,7 @@ def visit_call_node(node)
11511151
bounds(node.location)
11521152
on_assign(on_field(receiver, call_operator, message), value)
11531153
else
1154-
arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1154+
arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
11551155
call =
11561156
if node.opening_loc.nil?
11571157
bounds(node.location)
@@ -1169,27 +1169,35 @@ def visit_call_node(node)
11691169
on_method_add_arg(on_call(receiver, call_operator, message), arguments)
11701170
end
11711171

1172-
if block.nil?
1173-
call
1174-
else
1172+
if has_ripper_block
11751173
bounds(node.block.location)
11761174
on_method_add_block(call, block)
1175+
else
1176+
call
11771177
end
11781178
end
11791179
end
11801180
end
11811181

1182-
# Visit the arguments and block of a call node and return the arguments
1183-
# and block as they should be used.
1184-
private def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
1182+
# Extract the arguments and block Ripper-style, which means if the block
1183+
# is like `&b` then it's moved to arguments.
1184+
private def get_arguments_and_block(arguments_node, block_node)
11851185
arguments = arguments_node&.arguments || []
11861186
block = block_node
11871187

11881188
if block.is_a?(BlockArgumentNode)
1189-
arguments << block
1189+
arguments += [block]
11901190
block = nil
11911191
end
11921192

1193+
[arguments, block]
1194+
end
1195+
1196+
# Visit the arguments and block of a call node and return the arguments
1197+
# and block as they should be used.
1198+
private def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
1199+
arguments, block = get_arguments_and_block(arguments_node, block_node)
1200+
11931201
[
11941202
if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode)
11951203
visit(arguments.first)
@@ -1203,7 +1211,8 @@ def visit_call_node(node)
12031211
on_args_add_block(args, false)
12041212
end
12051213
end,
1206-
visit(block)
1214+
visit(block),
1215+
block != nil,
12071216
]
12081217
end
12091218

@@ -1640,10 +1649,10 @@ def visit_def_node(node)
16401649
end
16411650

16421651
bounds(node.location)
1643-
if receiver.nil?
1644-
on_def(name, parameters, bodystmt)
1645-
else
1652+
if receiver
16461653
on_defs(receiver, operator, name, parameters, bodystmt)
1654+
else
1655+
on_def(name, parameters, bodystmt)
16471656
end
16481657
end
16491658

@@ -2041,7 +2050,7 @@ def visit_in_node(node)
20412050
# ^^^^^^^^^^^^^^^
20422051
def visit_index_operator_write_node(node)
20432052
receiver = visit(node.receiver)
2044-
arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2053+
arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
20452054

20462055
bounds(node.location)
20472056
target = on_aref_field(receiver, arguments)
@@ -2058,7 +2067,7 @@ def visit_index_operator_write_node(node)
20582067
# ^^^^^^^^^^^^^^^^
20592068
def visit_index_and_write_node(node)
20602069
receiver = visit(node.receiver)
2061-
arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2070+
arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
20622071

20632072
bounds(node.location)
20642073
target = on_aref_field(receiver, arguments)
@@ -2075,7 +2084,7 @@ def visit_index_and_write_node(node)
20752084
# ^^^^^^^^^^^^^^^^
20762085
def visit_index_or_write_node(node)
20772086
receiver = visit(node.receiver)
2078-
arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2087+
arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
20792088

20802089
bounds(node.location)
20812090
target = on_aref_field(receiver, arguments)
@@ -2092,7 +2101,7 @@ def visit_index_or_write_node(node)
20922101
# ^^^^^^^^
20932102
def visit_index_target_node(node)
20942103
receiver = visit(node.receiver)
2095-
arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2104+
arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
20962105

20972106
bounds(node.location)
20982107
on_aref_field(receiver, arguments)
@@ -3122,7 +3131,7 @@ def visit_string_node(node)
31223131
# super(foo)
31233132
# ^^^^^^^^^^
31243133
def visit_super_node(node)
3125-
arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))
3134+
arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))
31263135

31273136
if !node.lparen_loc.nil?
31283137
bounds(node.lparen_loc)
@@ -3132,11 +3141,11 @@ def visit_super_node(node)
31323141
bounds(node.location)
31333142
call = on_super(arguments)
31343143

3135-
if block.nil?
3136-
call
3137-
else
3144+
if has_ripper_block
31383145
bounds(node.block.location)
31393146
on_method_add_block(call, block)
3147+
else
3148+
call
31403149
end
31413150
end
31423151

test/prism/ruby/ripper_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,22 @@ class PrismEvents < Translation::Ripper
110110
include Events
111111
end
112112

113+
class ObjectEvents < Translation::Ripper
114+
OBJECT = BasicObject.new
115+
Prism::Translation::Ripper::PARSER_EVENTS.each do |event|
116+
define_method(:"on_#{event}") { |*args| OBJECT }
117+
end
118+
end
119+
120+
Fixture.each_for_current_ruby(except: incorrect) do |fixture|
121+
define_method("#{fixture.test_name}_events") do
122+
source = fixture.read
123+
# Similar to test/ripper/assert_parse_files.rb in CRuby
124+
object_events = ObjectEvents.new(source)
125+
assert_nothing_raised { object_events.parse }
126+
end
127+
end
128+
113129
def test_events
114130
source = "1 rescue 2"
115131
ripper = RipperEvents.new(source)

0 commit comments

Comments
 (0)