Skip to content

Commit a9658b6

Browse files
kddnewtonmatzbot
authored andcommitted
[ruby/prism] Do not track locals starting with _
ruby/prism@0d5a6d936a
1 parent ec879e7 commit a9658b6

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

prism/prism.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14605,6 +14605,9 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pat
1460514605
*/
1460614606
static void
1460714607
parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_constant_id_t capture, const pm_location_t *location) {
14608+
// Skip this capture if it starts with an underscore.
14609+
if (*location->start == '_') return;
14610+
1460814611
if (pm_constant_id_list_includes(captures, capture)) {
1460914612
pm_parser_err(parser, location->start, location->end, PM_ERR_PATTERN_CAPTURE_DUPLICATE);
1461014613
} else {
@@ -14828,6 +14831,10 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *ca
1482814831
return (pm_node_t *) pm_implicit_node_create(parser, (pm_node_t *) target);
1482914832
}
1483014833

14834+
/**
14835+
* Add a node to the list of keys for a hash pattern, and if it is a duplicate
14836+
* then add an error to the parser.
14837+
*/
1483114838
static void
1483214839
parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_t *node) {
1483314840
if (pm_static_literals_add(parser, keys, node) != NULL) {

test/prism/errors_test.rb

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,7 +2075,7 @@ def test_it_with_ordinary_parameter
20752075
source = "proc { || it }"
20762076
errors = [["`it` is not allowed when an ordinary parameter is defined", 10..12]]
20772077

2078-
assert_errors expression(source), source, errors
2078+
assert_errors expression(source), source, errors, check_valid_syntax: RUBY_VERSION >= "3.4.0"
20792079
end
20802080

20812081
def test_regular_expression_with_unknown_regexp_options
@@ -2170,47 +2170,56 @@ def test_assignment_to_literal_in_conditionals
21702170

21712171
def test_duplicate_pattern_capture
21722172
source = <<~RUBY
2173-
() => [a, a]
2174-
() => [a, *a]
2175-
() => {a: a, b: a}
2176-
() => {a: a, **a}
2177-
() => [a, {a:}]
2178-
() => [a, {a: {a: {a: [a]}}}]
2179-
() => a => a
2180-
() => [A => a, {a: b => a}]
2173+
case (); in [a, a]; end
2174+
case (); in [a, *a]; end
2175+
case (); in {a: a, b: a}; end
2176+
case (); in {a: a, **a}; end
2177+
case (); in [a, {a:}]; end
2178+
case (); in [a, {a: {a: {a: [a]}}}]; end
2179+
case (); in a => a; end
2180+
case (); in [A => a, {a: b => a}]; end
21812181
RUBY
21822182

21832183
assert_error_messages source, Array.new(source.lines.length, "duplicated variable name")
2184+
refute_error_messages "case (); in [_a, _a]; end"
21842185
end
21852186

21862187
def test_duplicate_pattern_hash_key
2187-
assert_error_messages "() => {a:, a:}", ["duplicated key name", "duplicated variable name"]
2188-
assert_error_messages "() => {a:1, a:2}", ["duplicated key name"]
2188+
assert_error_messages "case (); in {a:, a:}; end", ["duplicated key name", "duplicated variable name"]
2189+
assert_error_messages "case (); in {a:1, a:2}; end", ["duplicated key name"]
21892190
refute_error_messages "case (); in [{a:1}, {a:2}]; end"
21902191
end
21912192

21922193
private
21932194

2194-
def check_syntax(source)
2195-
$VERBOSE, previous = nil, $VERBOSE
2195+
if RUBY_ENGINE == "ruby"
2196+
def check_syntax(source)
2197+
$VERBOSE, previous = nil, $VERBOSE
21962198

2197-
begin
2198-
RubyVM::InstructionSequence.compile(source)
2199-
ensure
2200-
$VERBOSE = previous
2199+
begin
2200+
RubyVM::InstructionSequence.compile(source)
2201+
ensure
2202+
$VERBOSE = previous
2203+
end
22012204
end
2202-
end
22032205

2204-
def assert_valid_syntax(source)
2205-
check_syntax(source)
2206-
end
2206+
def assert_valid_syntax(source)
2207+
check_syntax(source)
2208+
end
22072209

2208-
def refute_valid_syntax(source)
2209-
assert_raise(SyntaxError) { check_syntax(source) }
2210+
def refute_valid_syntax(source)
2211+
assert_raise(SyntaxError) { check_syntax(source) }
2212+
end
2213+
else
2214+
def assert_valid_syntax(source)
2215+
end
2216+
2217+
def refute_valid_syntax(source)
2218+
end
22102219
end
22112220

2212-
def assert_errors(expected, source, errors)
2213-
refute_valid_syntax(source) if RUBY_ENGINE == "ruby"
2221+
def assert_errors(expected, source, errors, check_valid_syntax: true)
2222+
refute_valid_syntax(source) if check_valid_syntax
22142223

22152224
result = Prism.parse(source)
22162225
node = result.value.statements.body.last
@@ -2220,13 +2229,13 @@ def assert_errors(expected, source, errors)
22202229
end
22212230

22222231
def assert_error_messages(source, errors)
2223-
refute_valid_syntax(source) if RUBY_ENGINE == "ruby"
2232+
refute_valid_syntax(source)
22242233
result = Prism.parse(source)
22252234
assert_equal(errors, result.errors.map(&:message))
22262235
end
22272236

22282237
def refute_error_messages(source)
2229-
assert_valid_syntax(source) if RUBY_ENGINE == "ruby"
2238+
assert_valid_syntax(source)
22302239
assert Prism.parse_success?(source)
22312240
end
22322241

0 commit comments

Comments
 (0)