Add support for PatternMatchMapping formatting (#6836)

<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Adds support for `PatternMatchMapping` -- i.e., cases like:

```python
match foo:
    case {"a": 1, "b": 2, **rest}:
        pass
```

Unfortunately, this node has _three_ kinds of dangling comments:

```python
{  # "open parenthesis comment"
   key: pattern,
   **  # end-of-line "double star comment"
   # own-line "double star comment"
   rest  # end-of-line "after rest comment"
   # own-line "after rest comment"
}
```

Some of the complexity comes from the fact that in `**rest`, `rest` is
an _identifier_, not a node, so we have to handle comments _after_ it as
dangling on the enclosing node, rather than trailing on `**rest`. (We
could change the AST to use `PatternMatchAs` there, which would be more
permissive than the grammar but not totally crazy -- `PatternMatchAs` is
used elsewhere to mean "a single identifier".)

Closes https://github.com/astral-sh/ruff/issues/6644.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-08-25 00:33:34 -04:00 committed by GitHub
parent 813d7da7ec
commit 1044d66c1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 407 additions and 73 deletions

View file

@ -165,7 +165,7 @@ match x:
y = 0
# case black_test_patma_073
match x:
@@ -16,23 +16,23 @@
@@ -16,11 +16,11 @@
y = 1
# case black_test_patma_006
match 3:
@ -179,15 +179,9 @@ match x:
y = 0
# case black_check_sequence_then_mapping
match x:
case [*_]:
return "seq"
- case {}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
return "map"
# case black_test_patma_035
@@ -32,7 +32,7 @@
match x:
- case {0: [1, 2, {}]}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {0: [1, 2, {}]}:
y = 0
- case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
+ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y):
@ -203,30 +197,6 @@ match x:
x = True
# case black_test_patma_154
match x:
@@ -54,11 +54,11 @@
y = 0
# case black_test_patma_134
match x:
- case {1: 0}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
y = 0
- case {0: 0}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
y = 1
- case {**z}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
y = 2
# case black_test_patma_185
match Seq():
@@ -72,7 +72,7 @@
y = 1
# case black_test_patma_248
match x:
- case {"foo": bar}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
y = bar
# case black_test_patma_019
match (0, 1, 2):
@@ -132,13 +132,13 @@
z = 0
# case black_test_patma_042
@ -236,8 +206,7 @@ match x:
y = 0
# case black_test_patma_034
match x:
- case {0: [1, 2, {}]}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {0: [1, 2, {}]}:
y = 0
- case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
+ case NOT_YET_IMPLEMENTED_PatternMatchOf | (y):
@ -277,11 +246,11 @@ match x:
match x:
case [*_]:
return "seq"
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {}:
return "map"
# case black_test_patma_035
match x:
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {0: [1, 2, {}]}:
y = 0
case NOT_YET_IMPLEMENTED_PatternMatchOf | (y):
y = 1
@ -305,11 +274,11 @@ match x:
y = 0
# case black_test_patma_134
match x:
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {1: 0}:
y = 0
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {0: 0}:
y = 1
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {**z}:
y = 2
# case black_test_patma_185
match Seq():
@ -323,7 +292,7 @@ match x:
y = 1
# case black_test_patma_248
match x:
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {"foo": bar}:
y = bar
# case black_test_patma_019
match (0, 1, 2):
@ -387,7 +356,7 @@ match x:
y = 0
# case black_test_patma_034
match x:
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {0: [1, 2, {}]}:
y = 0
case NOT_YET_IMPLEMENTED_PatternMatchOf | (y):
y = 1

View file

@ -188,15 +188,6 @@ match bar1:
pass
case _:
pass
@@ -48,7 +57,7 @@
match a, *b, c:
case [*_]:
assert "seq" == _
- case {}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
assert "map" == b
@@ -59,12 +68,7 @@
),
case,
@ -211,22 +202,20 @@ match bar1:
pass
case [a as match]:
@@ -85,12 +89,9 @@
@@ -87,10 +91,10 @@
match something:
- case {
- "key": key as key_1,
case {
"key": key as key_1,
- "password": PASS.ONE | PASS.TWO | PASS.THREE as password,
- }:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
+ "password": NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as password,
}:
pass
- case {"maybe": something(complicated as this) as that}:
+ case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
+ case {"maybe": NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0) as that}:
pass
@@ -101,19 +102,17 @@
@@ -101,19 +105,17 @@
case 2 as b, 3 as c:
pass
@ -313,7 +302,7 @@ match (
match a, *b, c:
case [*_]:
assert "seq" == _
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {}:
assert "map" == b
@ -345,9 +334,12 @@ match a, *b(), c:
match something:
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {
"key": key as key_1,
"password": NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as password,
}:
pass
case {"NOT_YET_IMPLEMENTED_PatternMatchMapping": _, 2: _}:
case {"maybe": NOT_YET_IMPLEMENTED_PatternMatchClass(0, 0) as that}:
pass

View file

@ -350,6 +350,61 @@ match foo:
pass
case [(*rest), (a as b)]:
pass
match foo:
case {"a": 1, "b": 2}:
pass
case {
# own line
"a": 1, # end-of-line
# own line
"b": 2,
}:
pass
case { # open
1 # key
: # colon
value # value
}:
pass
case {**d}:
pass
case {
** # middle with single item
b
}:
pass
case {
# before
** # between
b,
}:
pass
case {
1: x,
# foo
** # bop
# before
b, # boo
# baz
}:
pass
case {
1: x
# foo
,
**
b,
}:
pass
```
## Output
@ -719,6 +774,57 @@ match foo:
pass
case [(*rest), (a as b)]:
pass
match foo:
case {"a": 1, "b": 2}:
pass
case {
# own line
"a": 1, # end-of-line
# own line
"b": 2,
}:
pass
case { # open
1: value # key # colon # value
}:
pass
case {**d}:
pass
case {
# middle with single item
**b
}:
pass
case {
# before
# between
**b,
}:
pass
case {
1: x,
# foo
# bop
# before
**b, # boo
# baz
}:
pass
case {
1: x,
# foo
**b,
}:
pass
```