Skip to content

Commit

Permalink
Fix bug where # fmt: skip is not being respect with one-liner functio…
Browse files Browse the repository at this point in the history
…ns (#4535)
  • Loading branch information
Pedro-Muller29 committed Jan 18, 2025
1 parent 584d033 commit a94a78c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
- Fix crash when formatting `with` statements containing tuple generators/unpacking
(#4538)

- Fix a bug where one-liner functions marked with `# fmt: skip` would still be
formatted (#)

### Preview style

<!-- Changes that affect Black's preview style -->
Expand Down
41 changes: 35 additions & 6 deletions src/black/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,26 +318,55 @@ def _generate_ignored_nodes_from_fmt_skip(
"""Generate all leaves that should be ignored by the `# fmt: skip` from `leaf`."""
prev_sibling = leaf.prev_sibling
parent = leaf.parent
ignored_nodes: list[LN] = []
# Need to properly format the leaf prefix to compare it to comment.value,
# which is also formatted
comments = list_comments(leaf.prefix, is_endmarker=False)
if not comments or comment.value != comments[0].value:
return
if prev_sibling is not None:
# Generates the nodes to be ignored by `fmt: skip`.

# Nodes to ignore are those on the same line as the `# fmt: skip` comment,
# excluding the `# fmt: skip` node itself.

# Traversal process (starting at the `# fmt: skip` node):
# 1. Move to the `prev_sibling` of the current node.
# 2. If `prev_sibling` has children, go to its rightmost leaf.
# 3. If there’s no `prev_sibling`, move up to the parent node and repeat.
# 4. Continue until:
# a. You encounter an `INDENT` or `NEWLINE` node (indicates
# start of the line).
# b. You reach the root node.

# Include all visited LEAVES in the ignored list, except INDENT
# or NEWLINE leaves.

leaf.prefix = ""
siblings = [prev_sibling]
while "\n" not in prev_sibling.prefix and prev_sibling.prev_sibling is not None:
prev_sibling = prev_sibling.prev_sibling
siblings.insert(0, prev_sibling)
yield from siblings
current_node = prev_sibling
ignored_nodes = [current_node]
if current_node.prev_sibling is None and current_node.parent is not None:
current_node = current_node.parent
while "\n" not in current_node.prefix and current_node.prev_sibling is not None:
leaf_nodes = list(current_node.prev_sibling.leaves())
current_node = leaf_nodes[-1] if leaf_nodes else current_node

if current_node.type in (token.NEWLINE, token.INDENT):
current_node.prefix = ""
break

ignored_nodes.insert(0, current_node)

if current_node.prev_sibling is None and current_node.parent is not None:
current_node = current_node.parent
yield from ignored_nodes
elif (
parent is not None and parent.type == syms.suite and leaf.type == token.NEWLINE
):
# The `# fmt: skip` is on the colon line of the if/while/def/class/...
# statements. The ignored nodes should be previous siblings of the
# parent suite node.
leaf.prefix = ""
ignored_nodes: list[LN] = []
parent_sibling = parent.prev_sibling
while parent_sibling is not None and parent_sibling.type != syms.suite:
ignored_nodes.insert(0, parent_sibling)
Expand Down
1 change: 1 addition & 0 deletions tests/data/cases/fmtskip10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
def foo(): return "mock" # fmt: skip

0 comments on commit a94a78c

Please sign in to comment.