diff --git a/crates/ruff_python_parser/resources/inline/err/multiple_assignment_in_case_pattern.py b/crates/ruff_python_parser/resources/inline/err/multiple_assignment_in_case_pattern.py index 45323edd66..b5e00fba2e 100644 --- a/crates/ruff_python_parser/resources/inline/err/multiple_assignment_in_case_pattern.py +++ b/crates/ruff_python_parser/resources/inline/err/multiple_assignment_in_case_pattern.py @@ -5,6 +5,6 @@ match 2: case {1: x, 2: x}: ... # MatchMapping duplicate pattern case {1: x, **x}: ... # MatchMapping duplicate in **rest case Class(x, x): ... # MatchClass positional - case Class(x=1, x=2): ... # MatchClass keyword - case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr + case Class(y=x, z=x): ... # MatchClass keyword + case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr case x as x: ... # MatchAs diff --git a/crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py b/crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py new file mode 100644 index 0000000000..2852450d58 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py @@ -0,0 +1,2 @@ +match 2: + case Class(x=x): ... diff --git a/crates/ruff_python_parser/src/semantic_errors.rs b/crates/ruff_python_parser/src/semantic_errors.rs index fba092d52c..2687eca82e 100644 --- a/crates/ruff_python_parser/src/semantic_errors.rs +++ b/crates/ruff_python_parser/src/semantic_errors.rs @@ -794,6 +794,10 @@ struct MultipleCaseAssignmentVisitor<'a, Ctx> { impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> { fn visit_pattern(&mut self, pattern: &'a Pattern) { + // test_ok class_keyword_in_case_pattern + // match 2: + // case Class(x=x): ... + // test_err multiple_assignment_in_case_pattern // match 2: // case [y, z, y]: ... # MatchSequence @@ -802,8 +806,8 @@ impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> { // case {1: x, 2: x}: ... # MatchMapping duplicate pattern // case {1: x, **x}: ... # MatchMapping duplicate in **rest // case Class(x, x): ... # MatchClass positional - // case Class(x=1, x=2): ... # MatchClass keyword - // case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr + // case Class(y=x, z=x): ... # MatchClass keyword + // case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr // case x as x: ... # MatchAs match pattern { Pattern::MatchValue(_) | Pattern::MatchSingleton(_) => {} @@ -830,7 +834,6 @@ impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> { self.visit_pattern(pattern); } for keyword in &arguments.keywords { - self.insert(&keyword.attr); self.visit_pattern(&keyword.pattern); } } diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@multiple_assignment_in_case_pattern.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@multiple_assignment_in_case_pattern.py.snap index 3484caa037..c47d0febba 100644 --- a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@multiple_assignment_in_case_pattern.py.snap +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@multiple_assignment_in_case_pattern.py.snap @@ -391,18 +391,17 @@ Module( PatternKeyword { range: 331..334, attr: Identifier { - id: Name("x"), + id: Name("y"), range: 331..332, }, - pattern: MatchValue( - PatternMatchValue { + pattern: MatchAs( + PatternMatchAs { range: 333..334, - value: NumberLiteral( - ExprNumberLiteral { + pattern: None, + name: Some( + Identifier { + id: Name("x"), range: 333..334, - value: Int( - 1, - ), }, ), }, @@ -411,18 +410,17 @@ Module( PatternKeyword { range: 336..339, attr: Identifier { - id: Name("x"), + id: Name("z"), range: 336..337, }, - pattern: MatchValue( - PatternMatchValue { + pattern: MatchAs( + PatternMatchAs { range: 338..339, - value: NumberLiteral( - ExprNumberLiteral { + pattern: None, + name: Some( + Identifier { + id: Name("x"), range: 338..339, - value: Int( - 2, - ), }, ), }, @@ -518,18 +516,17 @@ Module( PatternKeyword { range: 398..401, attr: Identifier { - id: Name("x"), + id: Name("y"), range: 398..399, }, - pattern: MatchValue( - PatternMatchValue { + pattern: MatchAs( + PatternMatchAs { range: 400..401, - value: NumberLiteral( - ExprNumberLiteral { + pattern: None, + name: Some( + Identifier { + id: Name("x"), range: 400..401, - value: Int( - 1, - ), }, ), }, @@ -538,18 +535,17 @@ Module( PatternKeyword { range: 403..406, attr: Identifier { - id: Name("x"), + id: Name("z"), range: 403..404, }, - pattern: MatchValue( - PatternMatchValue { + pattern: MatchAs( + PatternMatchAs { range: 405..406, - value: NumberLiteral( - ExprNumberLiteral { + pattern: None, + name: Some( + Identifier { + id: Name("x"), range: 405..406, - value: Int( - 2, - ), }, ), }, @@ -681,7 +677,7 @@ Module( 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest | ^ Syntax Error: multiple assignments to name `x` in pattern 7 | case Class(x, x): ... # MatchClass positional -8 | case Class(x=1, x=2): ... # MatchClass keyword +8 | case Class(y=x, z=x): ... # MatchClass keyword | @@ -690,33 +686,33 @@ Module( 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest 7 | case Class(x, x): ... # MatchClass positional | ^ Syntax Error: multiple assignments to name `x` in pattern -8 | case Class(x=1, x=2): ... # MatchClass keyword -9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr +8 | case Class(y=x, z=x): ... # MatchClass keyword +9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr | | 6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest 7 | case Class(x, x): ... # MatchClass positional - 8 | case Class(x=1, x=2): ... # MatchClass keyword - | ^ Syntax Error: multiple assignments to name `x` in pattern - 9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr + 8 | case Class(y=x, z=x): ... # MatchClass keyword + | ^ Syntax Error: multiple assignments to name `x` in pattern + 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr 10 | case x as x: ... # MatchAs | | 7 | case Class(x, x): ... # MatchClass positional - 8 | case Class(x=1, x=2): ... # MatchClass keyword - 9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr - | ^ Syntax Error: multiple assignments to name `x` in pattern + 8 | case Class(y=x, z=x): ... # MatchClass keyword + 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr + | ^ Syntax Error: multiple assignments to name `x` in pattern 10 | case x as x: ... # MatchAs | | - 8 | case Class(x=1, x=2): ... # MatchClass keyword - 9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr + 8 | case Class(y=x, z=x): ... # MatchClass keyword + 9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr 10 | case x as x: ... # MatchAs | ^ Syntax Error: multiple assignments to name `x` in pattern | diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@class_keyword_in_case_pattern.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@class_keyword_in_case_pattern.py.snap new file mode 100644 index 0000000000..99fc05f67b --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@class_keyword_in_case_pattern.py.snap @@ -0,0 +1,83 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py +--- +## AST + +``` +Module( + ModModule { + range: 0..34, + body: [ + Match( + StmtMatch { + range: 0..33, + subject: NumberLiteral( + ExprNumberLiteral { + range: 6..7, + value: Int( + 2, + ), + }, + ), + cases: [ + MatchCase { + range: 13..33, + pattern: MatchClass( + PatternMatchClass { + range: 18..28, + cls: Name( + ExprName { + range: 18..23, + id: Name("Class"), + ctx: Load, + }, + ), + arguments: PatternArguments { + range: 23..28, + patterns: [], + keywords: [ + PatternKeyword { + range: 24..27, + attr: Identifier { + id: Name("x"), + range: 24..25, + }, + pattern: MatchAs( + PatternMatchAs { + range: 26..27, + pattern: None, + name: Some( + Identifier { + id: Name("x"), + range: 26..27, + }, + ), + }, + ), + }, + ], + }, + }, + ), + guard: None, + body: [ + Expr( + StmtExpr { + range: 30..33, + value: EllipsisLiteral( + ExprEllipsisLiteral { + range: 30..33, + }, + ), + }, + ), + ], + }, + ], + }, + ), + ], + }, +) +```