diff --git a/CHANGES.md b/CHANGES.md index fda755cd3d9..2712e1c6e4f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,8 @@ - Remove support for pre-python 3.7 `await/async` as soft keywords/variable names (#4676) - Fix crash on parenthesized expression inside a type parameter bound (#4684) +- Fix crash when using line ranges excluding indented single line decorated items + (#4670) ### Preview style diff --git a/src/black/ranges.py b/src/black/ranges.py index 92e1c93aaf7..26407cc7cfd 100644 --- a/src/black/ranges.py +++ b/src/black/ranges.py @@ -330,6 +330,19 @@ def _convert_node_to_standalone_comment(node: LN) -> None: first.prefix = "" index = node.remove() if index is not None: + # Because of the special handling of multiple decorators, if the decorated + # item is a single line then there will be a missing newline between the + # decorator and item, so add it back. This doesn't affect any other case + # since a decorated item with a newline would hit the earlier suite case + # in _convert_unchanged_line_by_line that correctly handles the newlines. + if node.type == syms.decorated: + # A leaf of type decorated wouldn't make sense, since it should always + # have at least the decorator + the decorated item, so if this assert + # hits that means there's a problem in the parser. + assert isinstance(node, Node) + # 1 will always be the correct index since before this function is + # called all the decorators are collapsed into a single leaf + node.insert_child(1, Leaf(NEWLINE, "\n")) # Remove the '\n', as STANDALONE_COMMENT will have '\n' appended when # generating the formatted code. value = str(node)[:-1] diff --git a/tests/data/cases/line_ranges_decorator_edge_case.py b/tests/data/cases/line_ranges_decorator_edge_case.py new file mode 100644 index 00000000000..483fbe8c57d --- /dev/null +++ b/tests/data/cases/line_ranges_decorator_edge_case.py @@ -0,0 +1,8 @@ +# flags: --line-ranges=6-7 +class Foo: + + @overload + def foo(): ... + + def fox(self): + print()