Fix a crash in preview style with assert + parenthesized string. (#3415)

The bug is in the `get_leaves_inside_matching_brackets` on the third line below:

```python
assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
    xxxxxxxxx
).xxxxxxxxxxxxxxxxxx(), (
    "xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
```

Including the invisible paren, third line is `).xxxxxxxxxxxxxxxxxx()), (`, that it has a matched pair then an unmatched closing paren afterwards. This PR ensures the returned leaves are actually matched.

Fixes #3414.
This commit is contained in:
Yilei "Dolee" Yang 2022-12-10 07:58:45 -08:00 committed by GitHub
parent 1f7f6de4ab
commit 96e62c57e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 14 deletions

View File

@ -14,6 +14,8 @@
<!-- Changes that affect Black's preview style -->
- Fix a crash in preview style with assert + parenthesized string (#3415)
### Configuration
<!-- Changes to how Black can be configured -->

View File

@ -349,26 +349,23 @@ def get_leaves_inside_matching_brackets(leaves: Sequence[Leaf]) -> Set[LeafID]:
Matching brackets are included.
"""
try:
# Only track brackets from the first opening bracket to the last closing
# bracket.
# Start with the first opening bracket and ignore closing brackets before.
start_index = next(
i for i, l in enumerate(leaves) if l.type in OPENING_BRACKETS
)
end_index = next(
len(leaves) - i
for i, l in enumerate(reversed(leaves))
if l.type in CLOSING_BRACKETS
)
except StopIteration:
return set()
bracket_stack = []
ids = set()
depth = 0
for i in range(end_index, start_index - 1, -1):
for i in range(start_index, len(leaves)):
leaf = leaves[i]
if leaf.type in CLOSING_BRACKETS:
depth += 1
if depth > 0:
ids.add(id(leaf))
if leaf.type in OPENING_BRACKETS:
depth -= 1
bracket_stack.append((BRACKET[leaf.type], i))
if leaf.type in CLOSING_BRACKETS:
if bracket_stack and leaf.type == bracket_stack[-1][0]:
_, start = bracket_stack.pop()
for j in range(start, i + 1):
ids.add(id(leaves[j]))
else:
break
return ids

View File

@ -25,6 +25,13 @@ def refresh_token(self, device_family, refresh_token, api_key):
== long_module.long_class.long_func()["some_key"].another_func(arg1)
)
# Regression test for https://github.com/psf/black/issues/3414.
assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
xxxxxxxxx
).xxxxxxxxxxxxxxxxxx(), (
"xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
# output
@ -72,3 +79,10 @@ def refresh_token(self, device_family, refresh_token, api_key):
long_module.long_class.long_func().another_func()
== long_module.long_class.long_func()["some_key"].another_func(arg1)
)
# Regression test for https://github.com/psf/black/issues/3414.
assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx(
xxxxxxxxx
).xxxxxxxxxxxxxxxxxx(), (
"xxx {xxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)