diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py index b8c95cb46a2a9..518d0819042e6 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py @@ -143,6 +143,35 @@ def foo(): pass +match pattern_comments: + case ( + # 1 + pattern # 2 + # 3 + as # 4 + # 5 + name # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as # 2 + # 3 + name #4 + # 5 + ): + pass + + +match x: + case (a as b) as c: + pass + match pattern_singleton: case ( # leading 1 diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs index 74a02a98e1d07..b6785bc279b21 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs @@ -1,19 +1,42 @@ use ruff_formatter::{write, Buffer, FormatResult}; -use ruff_python_ast::PatternMatchAs; +use ruff_python_ast::{Pattern, PatternMatchAs}; -use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; +use crate::expression::parentheses::parenthesized; +use crate::prelude::*; +use crate::{FormatNodeRule, PyFormatter}; #[derive(Default)] pub struct FormatPatternMatchAs; impl FormatNodeRule for FormatPatternMatchAs { fn fmt_fields(&self, item: &PatternMatchAs, f: &mut PyFormatter) -> FormatResult<()> { - write!( - f, - [not_yet_implemented_custom_text( - "x as NOT_YET_IMPLEMENTED_PatternMatchAs", - item - )] - ) + let PatternMatchAs { + range: _, + pattern, + name, + } = item; + + if let Some(name) = name { + if let Some(pattern) = pattern { + // Parenthesize nested `PatternMatchAs` like `(a as b) as c`. + if matches!( + pattern.as_ref(), + Pattern::MatchAs(PatternMatchAs { + pattern: Some(_), + .. + }) + ) { + parenthesized("(", &pattern.format(), ")").fmt(f)?; + } else { + pattern.format().fmt(f)?; + } + + write!(f, [space(), text("as"), space()])?; + } + name.format().fmt(f) + } else { + debug_assert!(pattern.is_none()); + text("_").fmt(f) + } } } diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap index 2fbba6dfef540..0bfe67727aafd 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_complex.py.snap @@ -301,7 +301,7 @@ match x: y = 0 # case black_test_patma_233 match x: -@@ -116,29 +116,29 @@ +@@ -116,11 +116,11 @@ y = 0 # case black_test_patma_078 match x: @@ -316,8 +316,7 @@ match x: y = 2 # case black_test_patma_156 match x: -- case z: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: +@@ -128,17 +128,17 @@ y = 0 # case black_test_patma_189 match w: @@ -471,7 +470,7 @@ match x: y = 2 # case black_test_patma_156 match x: - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case z: y = 0 # case black_test_patma_189 match w: diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap index 942764211b400..8bcbd65ca1fbb 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap @@ -149,25 +149,23 @@ match bar1: print(x, y) -@@ -15,40 +15,43 @@ +@@ -15,7 +15,7 @@ case: int = re.match(something) match re.match(case): - case type("match", match): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): pass -- case match: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case match: pass - +@@ -23,32 +23,35 @@ def func(match: case, case: match) -> case: match Something(): - case func(match, case): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): ... -- case another: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case another: ... @@ -191,8 +189,7 @@ match bar1: - case [[5], (6)], [7],: + case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: pass -- case _: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: pass @@ -205,7 +202,7 @@ match bar1: assert "map" == b -@@ -59,61 +62,51 @@ +@@ -59,15 +62,10 @@ ), case, ): @@ -222,15 +219,8 @@ match bar1: + case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: pass -- case case: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: - pass - - - match match: -- case case: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: - pass + case case: +@@ -80,40 +78,35 @@ match a, *b(), c: @@ -253,7 +243,7 @@ match bar1: match something: - case 1 as a: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: ++ case "NOT_YET_IMPLEMENTED_PatternMatchValue" as a: pass - case 2 as b, 3 as c: @@ -269,8 +259,7 @@ match bar1: - case Foo(aa=Callable() as aa, bb=int()): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print(bar1.aa, bar1.bb) -- case _: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("no match", "\n") @@ -304,7 +293,7 @@ case: int = re.match(something) match re.match(case): case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): pass - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case match: pass @@ -312,7 +301,7 @@ def func(match: case, case: match) -> case: match Something(): case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): ... - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case another: ... @@ -331,7 +320,7 @@ match ( pass case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: pass - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: pass @@ -355,12 +344,12 @@ match match( case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: pass - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case case: pass match match: - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case case: pass @@ -377,7 +366,7 @@ match something: match something: - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case "NOT_YET_IMPLEMENTED_PatternMatchValue" as a: pass case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: @@ -390,7 +379,7 @@ match something: match bar1: case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print(bar1.aa, bar1.bb) - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("no match", "\n") diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap index 5783c75da65ac..d7e3f098799ab 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_generic.py.snap @@ -119,18 +119,6 @@ with match() as match: ```diff --- Black +++ Ruff -@@ -24,9 +24,9 @@ - ] - - match match: -- case case: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: - match match: -- case case: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: - pass - - if all(version.is_python2() for version in target_versions): @@ -46,7 +46,7 @@ def test_patma_139(self): x = False @@ -188,9 +176,9 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: ] match match: - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case case: match match: - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case case: pass if all(version.is_python2() for version in target_versions): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap index 522535bd2519e..bf02fd3fe4a70 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_simple.py.snap @@ -153,8 +153,7 @@ def where_is(point): - case ["drop", *objects]: + case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: print("Dropping: ", *objects) -- case _: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print(f"Sorry, I couldn't understand {command!r}") match command.split(): @@ -197,8 +196,7 @@ def where_is(point): - case KeyPress(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): pass # Ignore other keystrokes -- case other_event: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case other_event: raise ValueError(f"Unrecognized event: {other_event}") match event.get(): @@ -224,8 +222,7 @@ def where_is(point): - case Point(): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print("Somewhere else") -- case _: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("Not a point") ``` @@ -269,7 +266,7 @@ match command.split(): print("Going:", direction) case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: print("Dropping: ", *objects) - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print(f"Sorry, I couldn't understand {command!r}") match command.split(): @@ -302,7 +299,7 @@ match event.get(): game.go_north() case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): pass # Ignore other keystrokes - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case other_event: raise ValueError(f"Unrecognized event: {other_event}") match event.get(): @@ -322,7 +319,7 @@ def where_is(point): print(f"X={x}") case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print("Somewhere else") - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("Not a point") ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap index 74b37542aec8c..3f8e3b8febe2e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_style.py.snap @@ -81,8 +81,7 @@ match match( - ): + case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print(2) -- case a: -+ case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case a: pass -match(arg) # comment @@ -127,7 +126,7 @@ match something: print(1) case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print(2) - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case a: pass match( diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap index 0e6f84da78b74..39466e5247f4e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_skip__match.py.snap @@ -89,7 +89,7 @@ def http_error(status): return "Not found" case "NOT_YET_IMPLEMENTED_PatternMatchValue": return "I'm a teapot" - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: return "Something's wrong with the internet" @@ -103,7 +103,7 @@ match point: print(f"X={x}") case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: print(f"X={x}, Y={y}") - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: raise ValueError("Not a point") @@ -122,7 +122,7 @@ def location(point): print(f"X={x} and the point is on the x-axis.") case NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0): print("The point is located somewhere else on the plane.") - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("Not a point") @@ -137,7 +137,7 @@ match points: print(f"A single point {x}, {y} is in the list.") case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: print(f"Two points on the Y axis at {y1}, {y2} are in the list.") - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: print("Something else is found in the list.") diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap index 4a16d601bb664..69ba4add15449 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_empty.py.snap @@ -139,7 +139,7 @@ with ( # d 1 pass match ( # d 2 ): - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case d2: pass match d3: case [NOT_YET_IMPLEMENTED_PatternMatchSequence, 2]: diff --git a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap index bf8a4b4478473..706b92f950ee7 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@parentheses__opening_parentheses_comment_value.py.snap @@ -219,12 +219,12 @@ with ( # d 1 match ( # d 2 x ): - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case d2: pass match d3: case ( # d 3 - x as NOT_YET_IMPLEMENTED_PatternMatchAs + x ): pass while ( # d 4 diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap index 39bde6ad75eb6..b01406571859e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap @@ -149,6 +149,35 @@ match pattern_comments: pass +match pattern_comments: + case ( + # 1 + pattern # 2 + # 3 + as # 4 + # 5 + name # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern + # 1 + as # 2 + # 3 + name #4 + # 5 + ): + pass + + +match x: + case (a as b) as c: + pass + match pattern_singleton: case ( # leading 1 @@ -247,7 +276,7 @@ match newlines: case "NOT_YET_IMPLEMENTED_PatternMatchValue": pass - case x as NOT_YET_IMPLEMENTED_PatternMatchAs: + case _: pass @@ -274,7 +303,7 @@ match long_lines: match pattern_comments: case ( - x as NOT_YET_IMPLEMENTED_PatternMatchAs # trailing 1 + only_trailing # trailing 1 # trailing 2 # trailing 3 ): @@ -284,7 +313,7 @@ match pattern_comments: match pattern_comments: case ( # leading - x as NOT_YET_IMPLEMENTED_PatternMatchAs + only_leading ): pass @@ -292,7 +321,7 @@ match pattern_comments: match pattern_comments: case ( # leading - x as NOT_YET_IMPLEMENTED_PatternMatchAs # trailing 1 + leading_and_trailing # trailing 1 # trailing 2 # trailing 3 ): @@ -300,10 +329,37 @@ match pattern_comments: match pattern_comments: - case (x as NOT_YET_IMPLEMENTED_PatternMatchAs): + case (no_comments): pass +match pattern_comments: + case ( + # 1 + pattern as name # 2 + # 3 + # 4 + # 5 # 6 + # 7 + ): + pass + + +match pattern_comments: + case ( + pattern as name + # 1 + # 2 + # 3 # 4 + # 5 + ): + pass + + +match x: + case (a as b) as c: + pass + match pattern_singleton: case ( # leading 1