Handle pattern parentheses in FormatPattern (#6800)

## Summary

This PR fixes the duplicate-parenthesis problem that's visible in the
tests from https://github.com/astral-sh/ruff/pull/6799. The issue is
that we might have parentheses around the entire match-case pattern,
like in `(1)` here:

```python
match foo:
    case (1):
        y = 0
```

In this case, the inner expression (`1`) will _think_ it's
parenthesized, but we'll _also_ detect the parentheses at the case level
-- so they get rendered by the case, then again by the expression.
Instead, if we detect parentheses at the case level, we can force-off
the parentheses for the pattern using a design similar to the way we
handle parentheses on expressions.

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

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-08-24 23:45:49 -04:00 committed by GitHub
parent 281ce56dc1
commit 6f23469e00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 406 additions and 124 deletions

View file

@ -231,7 +231,7 @@ match bar1:
pass
- case 4 as d, (5 as e), (6 | 7 as g), *h:
+ case 4 as d, 5 as e, NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g, *h:
+ case 4 as d, (5 as e), (NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g), *h:
pass
@ -358,7 +358,7 @@ match something:
case 2 as b, 3 as c:
pass
case 4 as d, 5 as e, NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g, *h:
case 4 as d, (5 as e), (NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as g), *h:
pass

View file

@ -117,13 +117,13 @@ def where_is(point):
match command.split():
- case ["go", ("north" | "south" | "east" | "west")]:
+ case ["go", NOT_YET_IMPLEMENTED_PatternMatchOf | (y)]:
+ case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y))]:
current_room = current_room.neighbor(...)
# how do I know which direction to go?
match command.split():
- case ["go", ("north" | "south" | "east" | "west") as direction]:
+ case ["go", NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as direction]:
+ case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y)) as direction]:
current_room = current_room.neighbor(direction)
match command.split():
@ -223,12 +223,12 @@ match command.split():
... # Code for picking up the given object
match command.split():
case ["go", NOT_YET_IMPLEMENTED_PatternMatchOf | (y)]:
case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y))]:
current_room = current_room.neighbor(...)
# how do I know which direction to go?
match command.split():
case ["go", NOT_YET_IMPLEMENTED_PatternMatchOf | (y) as direction]:
case ["go", (NOT_YET_IMPLEMENTED_PatternMatchOf | (y)) as direction]:
current_room = current_room.neighbor(direction)
match command.split():

View file

@ -269,6 +269,7 @@ match foo:
):
y = 1
match foo:
case [1, 2, *rest]:
pass
@ -305,6 +306,50 @@ match foo:
_, 1, 2]:
pass
match foo:
case (1):
pass
case ((1)):
pass
case [(1), 2]:
pass
case [( # comment
1
), 2]:
pass
case [ # outer
( # inner
1
), 2]:
pass
case [
( # outer
[ # inner
1,
]
)
]:
pass
case [ # outer
( # inner outer
[ # inner
1,
]
)
]:
pass
case [ # outer
# own line
( # inner outer
[ # inner
1,
]
)
]:
pass
case [(*rest), (a as b)]:
pass
```
## Output
@ -440,7 +485,7 @@ match pattern_comments:
match pattern_comments:
case (no_comments):
case no_comments:
pass
@ -504,9 +549,7 @@ match pattern_singleton:
# trailing own 2
):
pass
case (
True # trailing
):
case True: # trailing
...
case False:
...
@ -524,7 +567,7 @@ match foo:
pass
case ["a", "b"]:
pass
case (["a", "b"]):
case ["a", "b"]:
pass
@ -545,29 +588,28 @@ match foo:
match foo:
case 1:
y = 0
case ((1)):
case 1:
y = 1
case (("a")):
case "a":
y = 1
case ( # comment
(1)
1
):
y = 1
case (
# comment
(1)
1
):
y = 1
case (
(1) # comment
):
case 1: # comment
y = 1
case (
(1)
1
# comment
):
y = 1
match foo:
case [1, 2, *rest]:
pass
@ -627,6 +669,62 @@ match foo:
2,
]:
pass
match foo:
case 1:
pass
case 1:
pass
case [(1), 2]:
pass
case [
( # comment
1
),
2,
]:
pass
case [
( # outer
# inner
1
),
2,
]:
pass
case [
( # outer
[
# inner
1,
]
)
]:
pass
case [
( # outer
# inner outer
[
# inner
1,
]
)
]:
pass
case [
( # outer
# own line
# inner outer
[
# inner
1,
]
)
]:
pass
case [(*rest), (a as b)]:
pass
```