Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@

<!-- Changes to the parser or to version autodetection -->

- Fix `# fmt: skip` crashing with `Cannot parse` on multiline `case` statements that use
backslash line continuation (e.g. `case A \ | B: # fmt: skip`) (#5123)

### Performance

<!-- Changes that improve Black's performance. -->
Expand Down
18 changes: 17 additions & 1 deletion src/black/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,19 @@ def _get_compound_statement_header(
return header_leaves


def _prefix_has_real_newline(prefix: str) -> bool:
"""Return True if prefix contains a newline that is NOT a line continuation.

A backslash immediately before a newline (``\\\n``) is a line continuation
and should not be treated as a logical line boundary when collecting nodes
to skip via ``# fmt: skip``.
"""
for i, ch in enumerate(prefix):
if ch == "\n" and (i == 0 or prefix[i - 1] != "\\"):
return True
return False


def _generate_ignored_nodes_from_fmt_skip(
leaf: Leaf, comment: ProtoComment, mode: Mode
) -> Iterator[LN]:
Expand Down Expand Up @@ -676,7 +689,10 @@ def _generate_ignored_nodes_from_fmt_skip(
# Track seen nodes to detect cycles that can occur after tree modifications
seen_nodes = {id(current_node)}

while "\n" not in current_node.prefix and current_node.prev_sibling is not None:
while (
not _prefix_has_real_newline(current_node.prefix)
and current_node.prev_sibling is not None
):
leaf_nodes = list(current_node.prev_sibling.leaves())
next_node = leaf_nodes[-1] if leaf_nodes else current_node

Expand Down
19 changes: 19 additions & 0 deletions tests/data/cases/fmtskip14.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# flags: --minimum-version=3.10
# Test fmt: skip on multiline case statements with backslash line continuation
# See https://github.com/psf/black/issues/5122

match (method, *path.split("/")):

case ("GET", "parent", _, "resource", resource_id) \
| ("GET", "resource", resource_id): # fmt: skip
pass

case _:
pass


match x:
case a \
| b \
| c: # fmt: skip
pass
Loading