mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-19 20:24:27 +00:00
Fix syntax error false positive on nested alternative patterns (#21104)
## Summary Fixes #21101 by storing the child visitor's names in the parent visitor. This makes sure that `visitor.names` on line 1818 isn't empty after we visit a nested OR pattern. ## Test Plan New inline test cases derived from the issue, [playground](https://play.ruff.rs/7b6439ac-ee8f-4593-9a3e-c2aa34a595d0)
This commit is contained in:
parent
10bda3df00
commit
f0fe6d62fb
3 changed files with 512 additions and 0 deletions
|
|
@ -0,0 +1,7 @@
|
|||
match ruff:
|
||||
case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}:
|
||||
...
|
||||
match 42:
|
||||
case [[x] | [x]] | x: ...
|
||||
match 42:
|
||||
case [[x | x] | [x]] | x: ...
|
||||
|
|
@ -1841,6 +1841,15 @@ impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> {
|
|||
// case (x, (y | y)): ...
|
||||
// case [a, _] | [a, _]: ...
|
||||
// case [a] | [C(a)]: ...
|
||||
|
||||
// test_ok nested_alternative_patterns
|
||||
// match ruff:
|
||||
// case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}:
|
||||
// ...
|
||||
// match 42:
|
||||
// case [[x] | [x]] | x: ...
|
||||
// match 42:
|
||||
// case [[x | x] | [x]] | x: ...
|
||||
SemanticSyntaxChecker::add_error(
|
||||
self.ctx,
|
||||
SemanticSyntaxErrorKind::DifferentMatchPatternBindings,
|
||||
|
|
@ -1848,6 +1857,7 @@ impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> {
|
|||
);
|
||||
break;
|
||||
}
|
||||
self.names = visitor.names;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,495 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/inline/ok/nested_alternative_patterns.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
node_index: NodeIndex(None),
|
||||
range: 0..181,
|
||||
body: [
|
||||
Match(
|
||||
StmtMatch {
|
||||
node_index: NodeIndex(None),
|
||||
range: 0..96,
|
||||
subject: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 6..10,
|
||||
id: Name("ruff"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
cases: [
|
||||
MatchCase {
|
||||
range: 16..96,
|
||||
node_index: NodeIndex(None),
|
||||
pattern: MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 21..83,
|
||||
patterns: [
|
||||
MatchMapping(
|
||||
PatternMatchMapping {
|
||||
node_index: NodeIndex(None),
|
||||
range: 21..67,
|
||||
keys: [
|
||||
StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 22..28,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 22..28,
|
||||
node_index: NodeIndex(None),
|
||||
value: "lint",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
unclosed: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
patterns: [
|
||||
MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 30..66,
|
||||
patterns: [
|
||||
MatchMapping(
|
||||
PatternMatchMapping {
|
||||
node_index: NodeIndex(None),
|
||||
range: 30..43,
|
||||
keys: [
|
||||
StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 31..39,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 31..39,
|
||||
node_index: NodeIndex(None),
|
||||
value: "select",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
unclosed: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 41..42,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 41..42,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
rest: None,
|
||||
},
|
||||
),
|
||||
MatchMapping(
|
||||
PatternMatchMapping {
|
||||
node_index: NodeIndex(None),
|
||||
range: 46..66,
|
||||
keys: [
|
||||
StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 47..62,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 47..62,
|
||||
node_index: NodeIndex(None),
|
||||
value: "extend-select",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
unclosed: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 64..65,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 64..65,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
rest: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
rest: None,
|
||||
},
|
||||
),
|
||||
MatchMapping(
|
||||
PatternMatchMapping {
|
||||
node_index: NodeIndex(None),
|
||||
range: 70..83,
|
||||
keys: [
|
||||
StringLiteral(
|
||||
ExprStringLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 71..79,
|
||||
value: StringLiteralValue {
|
||||
inner: Single(
|
||||
StringLiteral {
|
||||
range: 71..79,
|
||||
node_index: NodeIndex(None),
|
||||
value: "select",
|
||||
flags: StringLiteralFlags {
|
||||
quote_style: Double,
|
||||
prefix: Empty,
|
||||
triple_quoted: false,
|
||||
unclosed: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 81..82,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 81..82,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
rest: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
guard: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 93..96,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 93..96,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
Match(
|
||||
StmtMatch {
|
||||
node_index: NodeIndex(None),
|
||||
range: 97..136,
|
||||
subject: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 103..105,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
cases: [
|
||||
MatchCase {
|
||||
range: 111..136,
|
||||
node_index: NodeIndex(None),
|
||||
pattern: MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 116..131,
|
||||
patterns: [
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 116..127,
|
||||
patterns: [
|
||||
MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 117..126,
|
||||
patterns: [
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 117..120,
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 118..119,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 118..119,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 123..126,
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 124..125,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 124..125,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 130..131,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 130..131,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
guard: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 133..136,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 133..136,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
Match(
|
||||
StmtMatch {
|
||||
node_index: NodeIndex(None),
|
||||
range: 137..180,
|
||||
subject: NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 143..145,
|
||||
value: Int(
|
||||
42,
|
||||
),
|
||||
},
|
||||
),
|
||||
cases: [
|
||||
MatchCase {
|
||||
range: 151..180,
|
||||
node_index: NodeIndex(None),
|
||||
pattern: MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 156..175,
|
||||
patterns: [
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 156..171,
|
||||
patterns: [
|
||||
MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 157..170,
|
||||
patterns: [
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 157..164,
|
||||
patterns: [
|
||||
MatchOr(
|
||||
PatternMatchOr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 158..163,
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 158..159,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 158..159,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 162..163,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 162..163,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
MatchSequence(
|
||||
PatternMatchSequence {
|
||||
node_index: NodeIndex(None),
|
||||
range: 167..170,
|
||||
patterns: [
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 168..169,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 168..169,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
MatchAs(
|
||||
PatternMatchAs {
|
||||
node_index: NodeIndex(None),
|
||||
range: 174..175,
|
||||
pattern: None,
|
||||
name: Some(
|
||||
Identifier {
|
||||
id: Name("x"),
|
||||
range: 174..175,
|
||||
node_index: NodeIndex(None),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
guard: None,
|
||||
body: [
|
||||
Expr(
|
||||
StmtExpr {
|
||||
node_index: NodeIndex(None),
|
||||
range: 177..180,
|
||||
value: EllipsisLiteral(
|
||||
ExprEllipsisLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 177..180,
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue