From f4978c6ae3db8a179783ce64758e0a715b382d61 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 17 Oct 2023 15:20:54 +0200 Subject: [PATCH 1/5] Insert newline after nested function or class statements --- crates/ruff_python_ast/src/node.rs | 66 +++++- .../resources/test/fixtures/ruff/newlines.py | 94 ++++++++ .../src/comments/placement.rs | 67 +----- .../src/statement/suite.rs | 58 ++++- ...patibility@simple_cases__function2.py.snap | 8 +- .../tests/snapshots/format@newlines.py.snap | 207 +++++++++++++++++- .../snapshots/format@statement__if.py.snap | 1 + .../snapshots/format@statement__try.py.snap | 1 + 8 files changed, 425 insertions(+), 77 deletions(-) diff --git a/crates/ruff_python_ast/src/node.rs b/crates/ruff_python_ast/src/node.rs index 35cfb9147cd81..17725fe0d65ae 100644 --- a/crates/ruff_python_ast/src/node.rs +++ b/crates/ruff_python_ast/src/node.rs @@ -4817,7 +4817,7 @@ pub enum AnyNodeRef<'a> { ElifElseClause(&'a ast::ElifElseClause), } -impl AnyNodeRef<'_> { +impl<'a> AnyNodeRef<'a> { pub fn as_ptr(&self) -> NonNull<()> { match self { AnyNodeRef::ModModule(node) => NonNull::from(*node).cast(), @@ -5456,9 +5456,9 @@ impl AnyNodeRef<'_> { ) } - pub fn visit_preorder<'a, V>(&'a self, visitor: &mut V) + pub fn visit_preorder<'b, V>(&'b self, visitor: &mut V) where - V: PreorderVisitor<'a> + ?Sized, + V: PreorderVisitor<'b> + ?Sized, { match self { AnyNodeRef::ModModule(node) => node.visit_preorder(visitor), @@ -5544,6 +5544,66 @@ impl AnyNodeRef<'_> { AnyNodeRef::ElifElseClause(node) => node.visit_preorder(visitor), } } + + /// The last child of the last branch, if the node has multiple branches. + pub fn last_child_in_body(&self) -> Option> { + let body = match self { + AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) + | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) + | AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) + | AnyNodeRef::MatchCase(MatchCase { body, .. }) + | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { + body, + .. + }) + | AnyNodeRef::ElifElseClause(ast::ElifElseClause { body, .. }) => body, + AnyNodeRef::StmtIf(ast::StmtIf { + body, + elif_else_clauses, + .. + }) => elif_else_clauses.last().map_or(body, |clause| &clause.body), + + AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) + | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { + if orelse.is_empty() { + body + } else { + orelse + } + } + + AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => { + return cases.last().map(AnyNodeRef::from); + } + + AnyNodeRef::StmtTry(ast::StmtTry { + body, + handlers, + orelse, + finalbody, + .. + }) => { + if finalbody.is_empty() { + if orelse.is_empty() { + if handlers.is_empty() { + body + } else { + return handlers.last().map(AnyNodeRef::from); + } + } else { + orelse + } + } else { + finalbody + } + } + + // Not a node that contains an indented child node. + _ => return None, + }; + + body.last().map(AnyNodeRef::from) + } } impl<'a> From<&'a ast::ModModule> for AnyNodeRef<'a> { diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py index 0d33408ecbf4d..9e355f3bcf1fa 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py @@ -1,6 +1,7 @@ ### # Blank lines around functions ### +import sys x = 1 @@ -159,3 +160,96 @@ def f(): # comment x = 1 + + +def f(): + if True: + + def double(s): + return s + s + print("below function") + if True: + + class A: + x = 1 + print("below class") + if True: + + def double(s): + return s + s + # + print("below comment function") + if True: + + class A: + x = 1 + # + print("below comment class") + if True: + + def double(s): + return s + s + # + print("below comment function 2") + if True: + + def double(s): + return s + s + # + def outer(): + def inner(): + pass + print("below nested functions") + +if True: + + def double(s): + return s + s +print("below function") +if True: + + class A: + x = 1 +print("below class") +def outer(): + def inner(): + pass +print("below nested functions") + + +class Path: + if sys.version_info >= (3, 11): + def joinpath(self): ... + + # The .open method comes from pathlib.pyi and should be kept in sync. + @overload + def open(self): ... + + + + +def fakehttp(): + + class FakeHTTPConnection: + if mock_close: + def close(self): + pass + FakeHTTPConnection.fakedata = fakedata + + + + + +if True: + if False: + def x(): + def y(): + pass + #comment + print() + + +# NOTE: Please keep this the last block in this file +if True: + def nested_trailing_function(): + pass \ No newline at end of file diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 88b72cdd89430..86d63a2c8cf0f 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -347,9 +347,9 @@ fn handle_end_of_line_comment_around_body<'a>( // ``` // The first earlier branch filters out ambiguities e.g. around try-except-finally. if let Some(preceding) = comment.preceding_node() { - if let Some(last_child) = last_child_in_body(preceding) { + if let Some(last_child) = preceding.last_child_in_body() { let innermost_child = - std::iter::successors(Some(last_child), |parent| last_child_in_body(*parent)) + std::iter::successors(Some(last_child), AnyNodeRef::last_child_in_body) .last() .unwrap_or(last_child); return CommentPlacement::trailing(innermost_child, comment); @@ -670,7 +670,7 @@ fn handle_own_line_comment_after_branch<'a>( preceding: AnyNodeRef<'a>, locator: &Locator, ) -> CommentPlacement<'a> { - let Some(last_child) = last_child_in_body(preceding) else { + let Some(last_child) = preceding.last_child_in_body() else { return CommentPlacement::Default(comment); }; @@ -734,7 +734,7 @@ fn handle_own_line_comment_after_branch<'a>( return CommentPlacement::trailing(last_child_in_parent, comment); } Ordering::Greater => { - if let Some(nested_child) = last_child_in_body(last_child_in_parent) { + if let Some(nested_child) = last_child_in_parent.last_child_in_body() { // The comment belongs to the inner block. parent = Some(last_child_in_parent); last_child_in_parent = nested_child; @@ -2176,65 +2176,6 @@ where right.is_some_and(|right| left.ptr_eq(right.into())) } -/// The last child of the last branch, if the node has multiple branches. -fn last_child_in_body(node: AnyNodeRef) -> Option { - let body = match node { - AnyNodeRef::StmtFunctionDef(ast::StmtFunctionDef { body, .. }) - | AnyNodeRef::StmtClassDef(ast::StmtClassDef { body, .. }) - | AnyNodeRef::StmtWith(ast::StmtWith { body, .. }) - | AnyNodeRef::MatchCase(MatchCase { body, .. }) - | AnyNodeRef::ExceptHandlerExceptHandler(ast::ExceptHandlerExceptHandler { - body, .. - }) - | AnyNodeRef::ElifElseClause(ast::ElifElseClause { body, .. }) => body, - AnyNodeRef::StmtIf(ast::StmtIf { - body, - elif_else_clauses, - .. - }) => elif_else_clauses.last().map_or(body, |clause| &clause.body), - - AnyNodeRef::StmtFor(ast::StmtFor { body, orelse, .. }) - | AnyNodeRef::StmtWhile(ast::StmtWhile { body, orelse, .. }) => { - if orelse.is_empty() { - body - } else { - orelse - } - } - - AnyNodeRef::StmtMatch(ast::StmtMatch { cases, .. }) => { - return cases.last().map(AnyNodeRef::from); - } - - AnyNodeRef::StmtTry(ast::StmtTry { - body, - handlers, - orelse, - finalbody, - .. - }) => { - if finalbody.is_empty() { - if orelse.is_empty() { - if handlers.is_empty() { - body - } else { - return handlers.last().map(AnyNodeRef::from); - } - } else { - orelse - } - } else { - finalbody - } - } - - // Not a node that contains an indented child node. - _ => return None, - }; - - body.last().map(AnyNodeRef::from) -} - /// Returns `true` if `statement` is the first statement in an alternate `body` (e.g. the else of an if statement) fn is_first_statement_in_alternate_body(statement: AnyNodeRef, has_body: AnyNodeRef) -> bool { match has_body { diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index 9575f78d86a77..c6361c53bb3f7 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -155,13 +155,63 @@ impl FormatRule> for FormatSuite { while let Some(following) = iter.next() { let following_comments = comments.leading_dangling_trailing(following); + let needs_empty_lines = if is_class_or_function_definition(following) { + // Here we insert empty lines even if the preceding has a trailing own line comment + true + } else if preceding_comments.has_trailing_own_line() { + // If there is a comment between preceding and following the empty lines were + // inserted before the comment by preceding and there are no extra empty lines after + // the comment, which also includes nested class/function definitions. + // ```python + // class Test: + // def a(self): + // pass + // # trailing comment + // + // + // # two lines before, one line after + // + // c = 30 + false + } else { + // Find nested class or function definitions that need an empty line after them. + // + // ```python + // def f(): + // if True: + // + // def double(s): + // return s + s + // + // print("below function") + // ``` + // Again, a empty lines are inserted before comments + // ```python + // if True: + // + // def double(s): + // return s + s + // + // # + // print("below comment function") + // ``` + std::iter::successors(Some(AnyNodeRef::from(preceding)), |parent| { + parent + .last_child_in_body() + .filter(|last_child| !comments.has_trailing_own_line(*last_child)) + }) + .any(|last_child| { + matches!( + last_child, + AnyNodeRef::StmtFunctionDef(_) | AnyNodeRef::StmtClassDef(_) + ) + }) + }; + // Add empty lines before and after a function or class definition. If the preceding // node is a function or class, and contains trailing comments, then the statement // itself will add the requisite empty lines when formatting its comments. - if (is_class_or_function_definition(preceding) - && !preceding_comments.has_trailing_own_line()) - || is_class_or_function_definition(following) - { + if needs_empty_lines { if source_type.is_stub() { stub_file_empty_lines( self.kind, diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap index 2570ff4de030a..2d1ed7c6ad0d6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap @@ -73,7 +73,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): elif os.name == "nt": try: import msvcrt -@@ -54,12 +53,10 @@ +@@ -54,7 +53,6 @@ class IHopeYouAreHavingALovelyDay: def __call__(self): print("i_should_be_followed_by_only_one_newline") @@ -81,11 +81,6 @@ with hmm_but_this_should_get_two_preceding_newlines(): else: def foo(): - pass -- - - with hmm_but_this_should_get_two_preceding_newlines(): - pass ``` ## Ruff Output @@ -151,6 +146,7 @@ else: def foo(): pass + with hmm_but_this_should_get_two_preceding_newlines(): pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap index 654d55dbb9789..a0873d299eafa 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap @@ -7,6 +7,7 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.p ### # Blank lines around functions ### +import sys x = 1 @@ -165,13 +166,106 @@ def f(): # comment x = 1 -``` + + +def f(): + if True: + + def double(s): + return s + s + print("below function") + if True: + + class A: + x = 1 + print("below class") + if True: + + def double(s): + return s + s + # + print("below comment function") + if True: + + class A: + x = 1 + # + print("below comment class") + if True: + + def double(s): + return s + s + # + print("below comment function 2") + if True: + + def double(s): + return s + s + # + def outer(): + def inner(): + pass + print("below nested functions") + +if True: + + def double(s): + return s + s +print("below function") +if True: + + class A: + x = 1 +print("below class") +def outer(): + def inner(): + pass +print("below nested functions") + + +class Path: + if sys.version_info >= (3, 11): + def joinpath(self): ... + + # The .open method comes from pathlib.pyi and should be kept in sync. + @overload + def open(self): ... + + + + +def fakehttp(): + + class FakeHTTPConnection: + if mock_close: + def close(self): + pass + FakeHTTPConnection.fakedata = fakedata + + + + + +if True: + if False: + def x(): + def y(): + pass + #comment + print() + + +# NOTE: Please keep this the last block in this file +if True: + def nested_trailing_function(): + pass``` ## Output ```py ### # Blank lines around functions ### +import sys x = 1 @@ -339,6 +433,117 @@ def f(): # comment x = 1 + + +def f(): + if True: + + def double(s): + return s + s + + print("below function") + if True: + + class A: + x = 1 + + print("below class") + if True: + + def double(s): + return s + s + + # + print("below comment function") + if True: + + class A: + x = 1 + + # + print("below comment class") + if True: + + def double(s): + return s + s + + # + print("below comment function 2") + if True: + + def double(s): + return s + s + # + + def outer(): + def inner(): + pass + + print("below nested functions") + + +if True: + + def double(s): + return s + s + + +print("below function") +if True: + + class A: + x = 1 + + +print("below class") + + +def outer(): + def inner(): + pass + + +print("below nested functions") + + +class Path: + if sys.version_info >= (3, 11): + + def joinpath(self): + ... + + # The .open method comes from pathlib.pyi and should be kept in sync. + @overload + def open(self): + ... + + +def fakehttp(): + class FakeHTTPConnection: + if mock_close: + + def close(self): + pass + + FakeHTTPConnection.fakedata = fakedata + + +if True: + if False: + + def x(): + def y(): + pass + + # comment + print() + + +# NOTE: Please keep this the last block in this file +if True: + + def nested_trailing_function(): + pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap index 3795d7f03922f..c72aa5423766c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__if.py.snap @@ -410,6 +410,7 @@ else: pass # 3 + if True: print("a") # 1 elif True: diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap index e4fe04e4348cb..b3facb5640191 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__try.py.snap @@ -311,6 +311,7 @@ finally: pass # d + try: pass # a except ZeroDivisionError: From 5117a41068e79f4fc39eb43a45d5fba5c281daf7 Mon Sep 17 00:00:00 2001 From: konsti Date: Wed, 18 Oct 2023 01:49:53 +0200 Subject: [PATCH 2/5] Move {AnyNodeRef, AstNode} to ruff_python_ast crate root (#8011) A quality of life improvement mostly mechanical refactoring. --- .../test/fixtures/pydocstyle/D300.py | 10 ++ .../fixtures/pylint/bad_dunder_method_name.py | 4 + crates/ruff_linter/src/fix/edits.rs | 2 +- .../rules/strip_with_multi_characters.rs | 2 +- .../flake8_pytest_style/rules/parametrize.rs | 2 +- .../flake8_simplify/rules/collapsible_if.rs | 2 +- .../flake8_simplify/rules/key_in_dict.rs | 2 +- .../ruff_linter/src/rules/pydocstyle/mod.rs | 1 + .../rules/pydocstyle/rules/triple_quotes.rs | 49 +++++-- ...__rules__pydocstyle__tests__D300_D.py.snap | 131 ++++++++++++++++-- ...ules__pydocstyle__tests__D300_D300.py.snap | 27 ++++ ...linter__rules__pydocstyle__tests__bom.snap | 7 +- .../pylint/rules/bad_dunder_method_name.rs | 2 +- .../ruff/rules/quadratic_list_summation.rs | 2 +- crates/ruff_python_ast/src/expression.rs | 2 +- crates/ruff_python_ast/src/helpers.rs | 2 +- crates/ruff_python_ast/src/lib.rs | 3 +- crates/ruff_python_ast/src/parenthesize.rs | 2 +- .../ruff_python_ast/src/visitor/preorder.rs | 2 +- crates/ruff_python_ast/tests/preorder.rs | 2 +- crates/ruff_python_ast/tests/visitor.rs | 2 +- .../src/comments/debug.rs | 2 +- .../src/comments/format.rs | 2 +- .../ruff_python_formatter/src/comments/mod.rs | 2 +- .../src/comments/node_key.rs | 4 +- .../src/comments/placement.rs | 2 +- .../src/comments/visitor.rs | 2 +- .../src/expression/expr_attribute.rs | 2 +- .../src/expression/expr_await.rs | 2 +- .../src/expression/expr_bin_op.rs | 2 +- .../src/expression/expr_bool_op.rs | 2 +- .../src/expression/expr_call.rs | 2 +- .../src/expression/expr_compare.rs | 2 +- .../src/expression/expr_constant.rs | 2 +- .../src/expression/expr_dict.rs | 2 +- .../src/expression/expr_dict_comp.rs | 2 +- .../src/expression/expr_f_string.rs | 2 +- .../src/expression/expr_formatted_value.rs | 2 +- .../src/expression/expr_generator_exp.rs | 2 +- .../src/expression/expr_if_exp.rs | 2 +- .../src/expression/expr_lambda.rs | 2 +- .../src/expression/expr_list.rs | 2 +- .../src/expression/expr_list_comp.rs | 2 +- .../src/expression/expr_name.rs | 2 +- .../src/expression/expr_named_expr.rs | 2 +- .../src/expression/expr_set.rs | 2 +- .../src/expression/expr_set_comp.rs | 2 +- .../src/expression/expr_slice.rs | 2 +- .../src/expression/expr_starred.rs | 2 +- .../src/expression/expr_subscript.rs | 2 +- .../src/expression/expr_tuple.rs | 2 +- .../src/expression/expr_unary_op.rs | 2 +- .../src/expression/expr_yield.rs | 2 +- .../src/expression/expr_yield_from.rs | 2 +- .../src/expression/mod.rs | 2 +- .../src/expression/parentheses.rs | 2 +- .../src/expression/string.rs | 2 +- crates/ruff_python_formatter/src/lib.rs | 2 +- .../src/other/match_case.rs | 2 +- .../src/other/parameters.rs | 2 +- .../ruff_python_formatter/src/pattern/mod.rs | 2 +- .../src/pattern/pattern_arguments.rs | 2 +- .../src/pattern/pattern_match_as.rs | 2 +- .../src/pattern/pattern_match_class.rs | 2 +- .../src/pattern/pattern_match_mapping.rs | 2 +- .../src/pattern/pattern_match_or.rs | 2 +- .../src/pattern/pattern_match_sequence.rs | 2 +- .../src/pattern/pattern_match_singleton.rs | 2 +- .../src/pattern/pattern_match_star.rs | 2 +- .../src/pattern/pattern_match_value.rs | 2 +- .../src/statement/clause.rs | 2 +- .../src/statement/stmt_global.rs | 2 +- .../src/statement/stmt_if.rs | 2 +- .../src/statement/stmt_import_from.rs | 2 +- .../src/statement/stmt_nonlocal.rs | 2 +- .../src/statement/stmt_while.rs | 2 +- .../src/statement/stmt_with.rs | 2 +- .../src/statement/suite.rs | 2 +- .../src/type_param/type_params.rs | 2 +- crates/ruff_python_formatter/src/verbatim.rs | 2 +- crates/ruff_python_semantic/src/nodes.rs | 6 +- crates/ruff_workspace/src/options.rs | 2 +- docs/editor-integrations.md | 4 +- ruff.schema.json | 2 +- 84 files changed, 291 insertions(+), 101 deletions(-) create mode 100644 crates/ruff_linter/resources/test/fixtures/pydocstyle/D300.py create mode 100644 crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D300.py.snap diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/D300.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/D300.py new file mode 100644 index 0000000000000..eb9b4c57307da --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/D300.py @@ -0,0 +1,10 @@ +def with_backslash(): + """Sum\\mary.""" + + +def ends_in_quote(): + 'Sum\\mary."' + + +def contains_quote(): + 'Sum"\\mary.' diff --git a/crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py b/crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py index 468e86f2f3c28..86c9081b475b4 100644 --- a/crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py +++ b/crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py @@ -68,6 +68,10 @@ def __html__(self): def _missing_(cls, value): pass + # Allow anonymous functions. + def _(self): + pass + def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule ... diff --git a/crates/ruff_linter/src/fix/edits.rs b/crates/ruff_linter/src/fix/edits.rs index e31fce4b81b1f..0a23555497faa 100644 --- a/crates/ruff_linter/src/fix/edits.rs +++ b/crates/ruff_linter/src/fix/edits.rs @@ -3,7 +3,7 @@ use anyhow::{Context, Result}; use ruff_diagnostics::Edit; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Stmt}; use ruff_python_codegen::Stylist; use ruff_python_index::Indexer; diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs index ae50f8ff2f798..3fd3dacdaab9b 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/strip_with_multi_characters.rs @@ -34,7 +34,7 @@ use crate::checkers::ast::Checker; /// /// ## Example /// ```python -/// "text.txt".strip(".txt") # "ex" +/// "text.txt".strip(".txt") # "e" /// ``` /// /// Use instead: diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs index bdf63cdef983a..4ab938ffef5cc 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -5,8 +5,8 @@ use rustc_hash::FxHashMap; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; -use ruff_python_ast::node::AstNode; use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::AstNode; use ruff_python_ast::{self as ast, Arguments, Constant, Decorator, Expr, ExprContext}; use ruff_python_codegen::Generator; use ruff_python_trivia::CommentRanges; diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs index 5433a6b98afaa..7f9cde0604edf 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs @@ -6,7 +6,7 @@ use log::error; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, whitespace, Constant, ElifElseClause, Expr, Stmt}; use ruff_python_codegen::Stylist; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs index 32872db72b24c..36592a3874cdf 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -1,8 +1,8 @@ use ruff_diagnostics::Edit; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, Arguments, CmpOp, Comprehension, Expr}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_linter/src/rules/pydocstyle/mod.rs b/crates/ruff_linter/src/rules/pydocstyle/mod.rs index e3e51c00c6387..59931647d9e9b 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/mod.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/mod.rs @@ -87,6 +87,7 @@ mod tests { #[test_case(Rule::EscapeSequenceInDocstring, Path::new("D.py"))] #[test_case(Rule::EscapeSequenceInDocstring, Path::new("D301.py"))] #[test_case(Rule::TripleSingleQuotes, Path::new("D.py"))] + #[test_case(Rule::TripleSingleQuotes, Path::new("D300.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/triple_quotes.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/triple_quotes.rs index c8b7d6208a80c..9ec1dd66d9ebc 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/triple_quotes.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/triple_quotes.rs @@ -1,4 +1,4 @@ -use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_codegen::Quote; use ruff_text_size::Ranged; @@ -37,6 +37,8 @@ pub struct TripleSingleQuotes { } impl Violation for TripleSingleQuotes { + const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; + #[derive_message_formats] fn message(&self) -> String { let TripleSingleQuotes { expected_quote } = self; @@ -45,12 +47,25 @@ impl Violation for TripleSingleQuotes { Quote::Single => format!(r#"Use triple single quotes `'''`"#), } } + + fn fix_title(&self) -> Option { + let TripleSingleQuotes { expected_quote } = self; + Some(match expected_quote { + Quote::Double => format!("Convert to triple double quotes"), + Quote::Single => format!("Convert to triple single quotes"), + }) + } } /// D300 pub(crate) fn triple_quotes(checker: &mut Checker, docstring: &Docstring) { let leading_quote = docstring.leading_quote(); + let prefixes = docstring + .leading_quote() + .trim_end_matches(|c| c == '\'' || c == '"') + .to_owned(); + let expected_quote = if docstring.body().contains("\"\"\"") { Quote::Single } else { @@ -60,18 +75,34 @@ pub(crate) fn triple_quotes(checker: &mut Checker, docstring: &Docstring) { match expected_quote { Quote::Single => { if !leading_quote.ends_with("'''") { - checker.diagnostics.push(Diagnostic::new( - TripleSingleQuotes { expected_quote }, - docstring.range(), - )); + let mut diagnostic = + Diagnostic::new(TripleSingleQuotes { expected_quote }, docstring.range()); + + let body = docstring.body().as_str(); + if !body.ends_with('\'') { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("{prefixes}'''{body}'''"), + docstring.range(), + ))); + } + + checker.diagnostics.push(diagnostic); } } Quote::Double => { if !leading_quote.ends_with("\"\"\"") { - checker.diagnostics.push(Diagnostic::new( - TripleSingleQuotes { expected_quote }, - docstring.range(), - )); + let mut diagnostic = + Diagnostic::new(TripleSingleQuotes { expected_quote }, docstring.range()); + + let body = docstring.body().as_str(); + if !body.ends_with('"') { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("{prefixes}\"\"\"{body}\"\"\""), + docstring.range(), + ))); + } + + checker.diagnostics.push(diagnostic); } } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D.py.snap index dbf703c165317..419c4e237ae64 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D.py.snap @@ -1,47 +1,102 @@ --- source: crates/ruff_linter/src/rules/pydocstyle/mod.rs --- -D.py:307:5: D300 Use triple double quotes `"""` +D.py:307:5: D300 [*] Use triple double quotes `"""` | 305 | @expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)') 306 | def triple_single_quotes_raw(): 307 | r'''Summary.''' | ^^^^^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes -D.py:312:5: D300 Use triple double quotes `"""` +ℹ Fix +304 304 | +305 305 | @expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)') +306 306 | def triple_single_quotes_raw(): +307 |- r'''Summary.''' + 307 |+ r"""Summary.""" +308 308 | +309 309 | +310 310 | @expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)') + +D.py:312:5: D300 [*] Use triple double quotes `"""` | 310 | @expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)') 311 | def triple_single_quotes_raw_uppercase(): 312 | R'''Summary.''' | ^^^^^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +309 309 | +310 310 | @expect('D300: Use """triple double quotes""" (found \'\'\'-quotes)') +311 311 | def triple_single_quotes_raw_uppercase(): +312 |- R'''Summary.''' + 312 |+ R"""Summary.""" +313 313 | +314 314 | +315 315 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') -D.py:317:5: D300 Use triple double quotes `"""` +D.py:317:5: D300 [*] Use triple double quotes `"""` | 315 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') 316 | def single_quotes_raw(): 317 | r'Summary.' | ^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +314 314 | +315 315 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') +316 316 | def single_quotes_raw(): +317 |- r'Summary.' + 317 |+ r"""Summary.""" +318 318 | +319 319 | +320 320 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') -D.py:322:5: D300 Use triple double quotes `"""` +D.py:322:5: D300 [*] Use triple double quotes `"""` | 320 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') 321 | def single_quotes_raw_uppercase(): 322 | R'Summary.' | ^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes -D.py:328:5: D300 Use triple double quotes `"""` +ℹ Fix +319 319 | +320 320 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') +321 321 | def single_quotes_raw_uppercase(): +322 |- R'Summary.' + 322 |+ R"""Summary.""" +323 323 | +324 324 | +325 325 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') + +D.py:328:5: D300 [*] Use triple double quotes `"""` | 326 | @expect('D301: Use r""" if any backslashes in a docstring') 327 | def single_quotes_raw_uppercase_backslash(): 328 | R'Sum\mary.' | ^^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +325 325 | @expect('D300: Use """triple double quotes""" (found \'-quotes)') +326 326 | @expect('D301: Use r""" if any backslashes in a docstring') +327 327 | def single_quotes_raw_uppercase_backslash(): +328 |- R'Sum\mary.' + 328 |+ R"""Sum\mary.""" +329 329 | +330 330 | +331 331 | @expect('D301: Use r""" if any backslashes in a docstring') -D.py:645:5: D300 Use triple double quotes `"""` +D.py:645:5: D300 [*] Use triple double quotes `"""` | 644 | def single_line_docstring_with_an_escaped_backslash(): 645 | "\ @@ -51,8 +106,21 @@ D.py:645:5: D300 Use triple double quotes `"""` 647 | 648 | class StatementOnSameLineAsDocstring: | + = help: Convert to triple double quotes -D.py:649:5: D300 Use triple double quotes `"""` +ℹ Fix +642 642 | +643 643 | +644 644 | def single_line_docstring_with_an_escaped_backslash(): +645 |- "\ +646 |- " + 645 |+ """\ + 646 |+ """ +647 647 | +648 648 | class StatementOnSameLineAsDocstring: +649 649 | "After this docstring there's another statement on the same line separated by a semicolon." ; priorities=1 + +D.py:649:5: D300 [*] Use triple double quotes `"""` | 648 | class StatementOnSameLineAsDocstring: 649 | "After this docstring there's another statement on the same line separated by a semicolon." ; priorities=1 @@ -60,15 +128,37 @@ D.py:649:5: D300 Use triple double quotes `"""` 650 | def sort_services(self): 651 | pass | + = help: Convert to triple double quotes + +ℹ Fix +646 646 | " +647 647 | +648 648 | class StatementOnSameLineAsDocstring: +649 |- "After this docstring there's another statement on the same line separated by a semicolon." ; priorities=1 + 649 |+ """After this docstring there's another statement on the same line separated by a semicolon.""" ; priorities=1 +650 650 | def sort_services(self): +651 651 | pass +652 652 | -D.py:654:5: D300 Use triple double quotes `"""` +D.py:654:5: D300 [*] Use triple double quotes `"""` | 653 | class StatementOnSameLineAsDocstring: 654 | "After this docstring there's another statement on the same line separated by a semicolon."; priorities=1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +651 651 | pass +652 652 | +653 653 | class StatementOnSameLineAsDocstring: +654 |- "After this docstring there's another statement on the same line separated by a semicolon."; priorities=1 + 654 |+ """After this docstring there's another statement on the same line separated by a semicolon."""; priorities=1 +655 655 | +656 656 | +657 657 | class CommentAfterDocstring: -D.py:658:5: D300 Use triple double quotes `"""` +D.py:658:5: D300 [*] Use triple double quotes `"""` | 657 | class CommentAfterDocstring: 658 | "After this docstring there's a comment." # priorities=1 @@ -76,8 +166,19 @@ D.py:658:5: D300 Use triple double quotes `"""` 659 | def sort_services(self): 660 | pass | + = help: Convert to triple double quotes -D.py:664:5: D300 Use triple double quotes `"""` +ℹ Fix +655 655 | +656 656 | +657 657 | class CommentAfterDocstring: +658 |- "After this docstring there's a comment." # priorities=1 + 658 |+ """After this docstring there's a comment.""" # priorities=1 +659 659 | def sort_services(self): +660 660 | pass +661 661 | + +D.py:664:5: D300 [*] Use triple double quotes `"""` | 663 | def newline_after_closing_quote(self): 664 | "We enforce a newline after the closing quote for a multi-line docstring \ @@ -85,5 +186,15 @@ D.py:664:5: D300 Use triple double quotes `"""` 665 | | but continuations shouldn't be considered multi-line" | |_________________________________________________________^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +661 661 | +662 662 | +663 663 | def newline_after_closing_quote(self): +664 |- "We enforce a newline after the closing quote for a multi-line docstring \ +665 |- but continuations shouldn't be considered multi-line" + 664 |+ """We enforce a newline after the closing quote for a multi-line docstring \ + 665 |+ but continuations shouldn't be considered multi-line""" diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D300.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D300.py.snap new file mode 100644 index 0000000000000..3b1b637e90a4c --- /dev/null +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D300_D300.py.snap @@ -0,0 +1,27 @@ +--- +source: crates/ruff_linter/src/rules/pydocstyle/mod.rs +--- +D300.py:6:5: D300 Use triple double quotes `"""` + | +5 | def ends_in_quote(): +6 | 'Sum\\mary."' + | ^^^^^^^^^^^^^ D300 + | + = help: Convert to triple double quotes + +D300.py:10:5: D300 [*] Use triple double quotes `"""` + | + 9 | def contains_quote(): +10 | 'Sum"\\mary.' + | ^^^^^^^^^^^^^ D300 + | + = help: Convert to triple double quotes + +ℹ Fix +7 7 | +8 8 | +9 9 | def contains_quote(): +10 |- 'Sum"\\mary.' + 10 |+ """Sum"\\mary.""" + + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__bom.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__bom.snap index 1c7757d4b4b3e..53d779dfaf713 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__bom.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__bom.snap @@ -1,10 +1,15 @@ --- source: crates/ruff_linter/src/rules/pydocstyle/mod.rs --- -bom.py:1:1: D300 Use triple double quotes `"""` +bom.py:1:1: D300 [*] Use triple double quotes `"""` | 1 | ''' SAM macro definitions ''' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D300 | + = help: Convert to triple double quotes + +ℹ Fix +1 |-''' SAM macro definitions ''' + 1 |+""" SAM macro definitions """ diff --git a/crates/ruff_linter/src/rules/pylint/rules/bad_dunder_method_name.rs b/crates/ruff_linter/src/rules/pylint/rules/bad_dunder_method_name.rs index 98c05d6554b9b..0ea5001d54053 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/bad_dunder_method_name.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/bad_dunder_method_name.rs @@ -54,7 +54,7 @@ pub(crate) fn bad_dunder_method_name(checker: &mut Checker, class_body: &[Stmt]) .iter() .filter_map(ruff_python_ast::Stmt::as_function_def_stmt) .filter(|method| { - if is_known_dunder_method(&method.name) { + if is_known_dunder_method(&method.name) || matches!(method.name.as_str(), "_") { return false; } method.name.starts_with('_') && method.name.ends_with('_') diff --git a/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs b/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs index 9fe896d28da62..67de3f48eeff5 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs @@ -3,8 +3,8 @@ use itertools::Itertools; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::node::AstNode; use ruff_python_ast::parenthesize::parenthesized_range; +use ruff_python_ast::AstNode; use ruff_python_ast::{self as ast, Arguments, Expr}; use ruff_python_semantic::SemanticModel; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_ast/src/expression.rs b/crates/ruff_python_ast/src/expression.rs index 562c68495281d..041c0a0e4ea05 100644 --- a/crates/ruff_python_ast/src/expression.rs +++ b/crates/ruff_python_ast/src/expression.rs @@ -1,6 +1,6 @@ use ruff_text_size::{Ranged, TextRange}; -use crate::node::AnyNodeRef; +use crate::AnyNodeRef; use crate::{self as ast, Expr}; /// Unowned pendant to [`ast::Expr`] that stores a reference instead of a owned value. diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index 598fb4b5ac3ee..4bd66427f8311 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -8,9 +8,9 @@ use smallvec::SmallVec; use ruff_text_size::{Ranged, TextRange}; use crate::call_path::CallPath; -use crate::node::AnyNodeRef; use crate::parenthesize::parenthesized_range; use crate::statement_visitor::{walk_body, walk_stmt, StatementVisitor}; +use crate::AnyNodeRef; use crate::{ self as ast, Arguments, CmpOp, Constant, ExceptHandler, Expr, MatchCase, Pattern, Stmt, TypeParam, diff --git a/crates/ruff_python_ast/src/lib.rs b/crates/ruff_python_ast/src/lib.rs index 1c3f182921976..210e287eed372 100644 --- a/crates/ruff_python_ast/src/lib.rs +++ b/crates/ruff_python_ast/src/lib.rs @@ -2,6 +2,7 @@ use std::path::Path; pub use expression::*; pub use int::*; +pub use node::{AnyNode, AnyNodeRef, AstNode, NodeKind}; pub use nodes::*; pub mod all; @@ -14,7 +15,7 @@ pub mod helpers; pub mod identifier; pub mod imports; mod int; -pub mod node; +mod node; mod nodes; pub mod parenthesize; pub mod relocate; diff --git a/crates/ruff_python_ast/src/parenthesize.rs b/crates/ruff_python_ast/src/parenthesize.rs index 8c6b441a989a4..0cf8e57a7e6a2 100644 --- a/crates/ruff_python_ast/src/parenthesize.rs +++ b/crates/ruff_python_ast/src/parenthesize.rs @@ -1,7 +1,7 @@ use ruff_python_trivia::{BackwardsTokenizer, CommentRanges, SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextLen, TextRange}; -use crate::node::AnyNodeRef; +use crate::AnyNodeRef; use crate::ExpressionRef; /// Returns the [`TextRange`] of a given expression including parentheses, if the expression is diff --git a/crates/ruff_python_ast/src/visitor/preorder.rs b/crates/ruff_python_ast/src/visitor/preorder.rs index 6a64d1daa3a87..9f69e219ed376 100644 --- a/crates/ruff_python_ast/src/visitor/preorder.rs +++ b/crates/ruff_python_ast/src/visitor/preorder.rs @@ -1,10 +1,10 @@ -use crate::node::{AnyNodeRef, AstNode}; use crate::{ Alias, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, ElifElseClause, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Parameter, ParameterWithDefault, Parameters, Pattern, PatternArguments, PatternKeyword, Stmt, TypeParam, TypeParams, UnaryOp, WithItem, }; +use crate::{AnyNodeRef, AstNode}; /// Visitor that traverses all nodes recursively in pre-order. pub trait PreorderVisitor<'a> { diff --git a/crates/ruff_python_ast/tests/preorder.rs b/crates/ruff_python_ast/tests/preorder.rs index c5de87e9fd98c..0f41fa1e27994 100644 --- a/crates/ruff_python_ast/tests/preorder.rs +++ b/crates/ruff_python_ast/tests/preorder.rs @@ -2,12 +2,12 @@ use std::fmt::{Debug, Write}; use insta::assert_snapshot; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::preorder::{ walk_alias, walk_comprehension, walk_except_handler, walk_expr, walk_keyword, walk_match_case, walk_module, walk_parameter, walk_parameters, walk_pattern, walk_stmt, walk_type_param, walk_with_item, PreorderVisitor, }; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{ Alias, BoolOp, CmpOp, Comprehension, Constant, ExceptHandler, Expr, Keyword, MatchCase, Mod, Operator, Parameter, Parameters, Pattern, Stmt, TypeParam, UnaryOp, WithItem, diff --git a/crates/ruff_python_ast/tests/visitor.rs b/crates/ruff_python_ast/tests/visitor.rs index 599b7b4cfd909..0765f5e7d63b5 100644 --- a/crates/ruff_python_ast/tests/visitor.rs +++ b/crates/ruff_python_ast/tests/visitor.rs @@ -5,12 +5,12 @@ use ruff_python_ast as ast; use ruff_python_parser::lexer::lex; use ruff_python_parser::{parse_tokens, Mode}; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::{ walk_alias, walk_comprehension, walk_except_handler, walk_expr, walk_keyword, walk_match_case, walk_parameter, walk_parameters, walk_pattern, walk_stmt, walk_type_param, walk_with_item, Visitor, }; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{ Alias, BoolOp, CmpOp, Comprehension, ExceptHandler, Expr, Keyword, MatchCase, Operator, Parameter, Parameters, Pattern, Stmt, TypeParam, UnaryOp, WithItem, diff --git a/crates/ruff_python_formatter/src/comments/debug.rs b/crates/ruff_python_formatter/src/comments/debug.rs index 0d9057b85a9c0..6f12bf690c2ee 100644 --- a/crates/ruff_python_formatter/src/comments/debug.rs +++ b/crates/ruff_python_formatter/src/comments/debug.rs @@ -180,7 +180,7 @@ mod tests { use insta::assert_debug_snapshot; use ruff_formatter::SourceCode; - use ruff_python_ast::node::AnyNode; + use ruff_python_ast::AnyNode; use ruff_python_ast::{StmtBreak, StmtContinue}; use ruff_python_trivia::CommentRanges; use ruff_text_size::{TextRange, TextSize}; diff --git a/crates/ruff_python_formatter/src/comments/format.rs b/crates/ruff_python_formatter/src/comments/format.rs index cba0a4e7c7848..06bc334262fa9 100644 --- a/crates/ruff_python_formatter/src/comments/format.rs +++ b/crates/ruff_python_formatter/src/comments/format.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use ruff_formatter::{format_args, write, FormatError, FormatOptions, SourceCode}; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; use ruff_python_ast::PySourceType; +use ruff_python_ast::{AnyNodeRef, AstNode}; use ruff_python_trivia::{ is_pragma_comment, lines_after, lines_after_ignoring_trivia, lines_before, }; diff --git a/crates/ruff_python_formatter/src/comments/mod.rs b/crates/ruff_python_formatter/src/comments/mod.rs index e1f2a0ba6b1bd..cf51a37d43578 100644 --- a/crates/ruff_python_formatter/src/comments/mod.rs +++ b/crates/ruff_python_formatter/src/comments/mod.rs @@ -96,8 +96,8 @@ pub(crate) use format::{ leading_alternate_branch_comments, leading_comments, leading_node_comments, trailing_comments, }; use ruff_formatter::{SourceCode, SourceCodeSlice}; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::preorder::{PreorderVisitor, TraversalSignal}; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::Mod; use ruff_python_trivia::{CommentRanges, PythonWhitespace}; use ruff_source_file::Locator; diff --git a/crates/ruff_python_formatter/src/comments/node_key.rs b/crates/ruff_python_formatter/src/comments/node_key.rs index eb026ca82d42c..5c38ac10e5f9f 100644 --- a/crates/ruff_python_formatter/src/comments/node_key.rs +++ b/crates/ruff_python_formatter/src/comments/node_key.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use std::fmt::{Debug, Formatter}; use std::hash::{Hash, Hasher}; @@ -52,7 +52,7 @@ impl<'a> From> for NodeRefEqualityKey<'a> { #[cfg(test)] mod tests { use crate::comments::node_key::NodeRefEqualityKey; - use ruff_python_ast::node::AnyNodeRef; + use ruff_python_ast::AnyNodeRef; use ruff_python_ast::StmtContinue; use ruff_text_size::TextRange; use std::collections::hash_map::DefaultHasher; diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 86d63a2c8cf0f..e45312a1532ed 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::whitespace::indentation; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, Comprehension, Expr, MatchCase, ModModule, Parameters}; use ruff_python_trivia::{ find_only_token_in_range, indentation_at_offset, BackwardsTokenizer, CommentRanges, diff --git a/crates/ruff_python_formatter/src/comments/visitor.rs b/crates/ruff_python_formatter/src/comments/visitor.rs index 91819acc391d3..b9788be8d23e4 100644 --- a/crates/ruff_python_formatter/src/comments/visitor.rs +++ b/crates/ruff_python_formatter/src/comments/visitor.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use std::iter::Peekable; use ruff_formatter::{SourceCode, SourceCodeSlice}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Mod, Stmt}; // The interface is designed to only export the members relevant for iterating nodes in // pre-order. diff --git a/crates/ruff_python_formatter/src/expression/expr_attribute.rs b/crates/ruff_python_formatter/src/expression/expr_attribute.rs index c9cc463beaf9b..16d3956b26cbc 100644 --- a/crates/ruff_python_formatter/src/expression/expr_attribute.rs +++ b/crates/ruff_python_formatter/src/expression/expr_attribute.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Constant, Expr, ExprAttribute, ExprConstant}; use ruff_python_trivia::{find_only_token_in_range, SimpleTokenKind}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_await.rs b/crates/ruff_python_formatter/src/expression/expr_await.rs index 91627848befdd..da408023106e6 100644 --- a/crates/ruff_python_formatter/src/expression/expr_await.rs +++ b/crates/ruff_python_formatter/src/expression/expr_await.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprAwait; use crate::expression::maybe_parenthesize_expression; diff --git a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs index 5402b3e5f52be..4d5ea27354ae5 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Expr, ExprBinOp}; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs index 674cfa933436c..63c0b4e3e0640 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs @@ -1,5 +1,5 @@ use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{BoolOp, ExprBoolOp}; use crate::expression::binary_like::BinaryLike; diff --git a/crates/ruff_python_formatter/src/expression/expr_call.rs b/crates/ruff_python_formatter/src/expression/expr_call.rs index 842d59062c2d4..47cd6502558e0 100644 --- a/crates/ruff_python_formatter/src/expression/expr_call.rs +++ b/crates/ruff_python_formatter/src/expression/expr_call.rs @@ -1,5 +1,5 @@ use ruff_formatter::FormatRuleWithOptions; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Expr, ExprCall}; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/expression/expr_compare.rs b/crates/ruff_python_formatter/src/expression/expr_compare.rs index ae4e4d9b492bc..e4f638831cc3e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_compare.rs +++ b/crates/ruff_python_formatter/src/expression/expr_compare.rs @@ -1,5 +1,5 @@ use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{CmpOp, Expr, ExprCompare}; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_constant.rs b/crates/ruff_python_formatter/src/expression/expr_constant.rs index 580c63d773754..f9dda6c555f62 100644 --- a/crates/ruff_python_formatter/src/expression/expr_constant.rs +++ b/crates/ruff_python_formatter/src/expression/expr_constant.rs @@ -1,5 +1,5 @@ use ruff_formatter::FormatRuleWithOptions; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Constant, ExprConstant}; use ruff_text_size::{Ranged, TextLen, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_dict.rs b/crates/ruff_python_formatter/src/expression/expr_dict.rs index 351505fe3ab4c..43ff4830beea2 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Expr, ExprDict}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs index fa3566809a214..605f6f5d34009 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprDictComp; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/expression/expr_f_string.rs b/crates/ruff_python_formatter/src/expression/expr_f_string.rs index 5a9612f39f78e..51beb4dbb8f4a 100644 --- a/crates/ruff_python_formatter/src/expression/expr_f_string.rs +++ b/crates/ruff_python_formatter/src/expression/expr_f_string.rs @@ -2,7 +2,7 @@ use memchr::memchr2; use crate::comments::SourceComment; use ruff_formatter::FormatResult; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprFString; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; diff --git a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs index 5133cb86e5845..a1939891a30a1 100644 --- a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs +++ b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprFormattedValue; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; diff --git a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs index 5ac878a1876ac..4d3de0402e907 100644 --- a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprGeneratorExp; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs index 78853d40d33dc..5244e18d49f6b 100644 --- a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Expr, ExprIfExp}; use crate::comments::leading_comments; diff --git a/crates/ruff_python_formatter/src/expression/expr_lambda.rs b/crates/ruff_python_formatter/src/expression/expr_lambda.rs index 9e1e7f94020d0..f2487fd6a488a 100644 --- a/crates/ruff_python_formatter/src/expression/expr_lambda.rs +++ b/crates/ruff_python_formatter/src/expression/expr_lambda.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprLambda; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/expression/expr_list.rs b/crates/ruff_python_formatter/src/expression/expr_list.rs index e7e522a84c2bf..6f5d70e81294e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list.rs @@ -1,5 +1,5 @@ use ruff_formatter::prelude::format_with; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprList; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs index 48aa12d0be66c..3b2d709607640 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprListComp; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_name.rs b/crates/ruff_python_formatter/src/expression/expr_name.rs index 7a49de08945e3..afe165e07acad 100644 --- a/crates/ruff_python_formatter/src/expression/expr_name.rs +++ b/crates/ruff_python_formatter/src/expression/expr_name.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, FormatContext}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprName; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs index 1b0cd194e8608..3fe831c3a0b9a 100644 --- a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs +++ b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprNamedExpr; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/expression/expr_set.rs b/crates/ruff_python_formatter/src/expression/expr_set.rs index 109227c5d1a4f..db5e25a0540ea 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprSet; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs index 6d91be7115059..0a09c60377ae2 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write, Buffer, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprSetComp; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_slice.rs b/crates/ruff_python_formatter/src/expression/expr_slice.rs index 85d3822029c9e..5837a22605aeb 100644 --- a/crates/ruff_python_formatter/src/expression/expr_slice.rs +++ b/crates/ruff_python_formatter/src/expression/expr_slice.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, FormatError}; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; +use ruff_python_ast::{AnyNodeRef, AstNode}; use ruff_python_ast::{Expr, ExprSlice, ExprUnaryOp, UnaryOp}; use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_starred.rs b/crates/ruff_python_formatter/src/expression/expr_starred.rs index da3e5e208caec..16136417f3a12 100644 --- a/crates/ruff_python_formatter/src/expression/expr_starred.rs +++ b/crates/ruff_python_formatter/src/expression/expr_starred.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprStarred; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/expression/expr_subscript.rs b/crates/ruff_python_formatter/src/expression/expr_subscript.rs index 1397973d1be57..75a7b16f6e3e0 100644 --- a/crates/ruff_python_formatter/src/expression/expr_subscript.rs +++ b/crates/ruff_python_formatter/src/expression/expr_subscript.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, FormatRuleWithOptions}; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; +use ruff_python_ast::{AnyNodeRef, AstNode}; use ruff_python_ast::{Expr, ExprSubscript}; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/expression/expr_tuple.rs b/crates/ruff_python_formatter/src/expression/expr_tuple.rs index abddb2ac35519..5d7e23a3dad0f 100644 --- a/crates/ruff_python_formatter/src/expression/expr_tuple.rs +++ b/crates/ruff_python_formatter/src/expression/expr_tuple.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprTuple; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs index cd5d30e97bea1..b81b2f7cb65a5 100644 --- a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprUnaryOp; use ruff_python_ast::UnaryOp; diff --git a/crates/ruff_python_formatter/src/expression/expr_yield.rs b/crates/ruff_python_formatter/src/expression/expr_yield.rs index 11765d6184bf0..20e274ec21d92 100644 --- a/crates/ruff_python_formatter/src/expression/expr_yield.rs +++ b/crates/ruff_python_formatter/src/expression/expr_yield.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Expr, ExprYield, ExprYieldFrom}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/expression/expr_yield_from.rs b/crates/ruff_python_formatter/src/expression/expr_yield_from.rs index b3194a58a7ab3..d459617f7e2ed 100644 --- a/crates/ruff_python_formatter/src/expression/expr_yield_from.rs +++ b/crates/ruff_python_formatter/src/expression/expr_yield_from.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExprYieldFrom; use crate::expression::expr_yield::AnyExpressionYield; diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index 4a8f01f6a2d1c..bc1bd2050ab8f 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -6,8 +6,8 @@ use ruff_formatter::{ write, FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions, }; use ruff_python_ast as ast; -use ruff_python_ast::node::AnyNodeRef; use ruff_python_ast::visitor::preorder::{walk_expr, PreorderVisitor}; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Constant, Expr, ExpressionRef, Operator}; use ruff_python_trivia::CommentRanges; diff --git a/crates/ruff_python_formatter/src/expression/parentheses.rs b/crates/ruff_python_formatter/src/expression/parentheses.rs index 005b3efa052c5..e68a5a473e9a2 100644 --- a/crates/ruff_python_formatter/src/expression/parentheses.rs +++ b/crates/ruff_python_formatter/src/expression/parentheses.rs @@ -1,6 +1,6 @@ use ruff_formatter::prelude::tag::Condition; use ruff_formatter::{format_args, write, Argument, Arguments}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::ExpressionRef; use ruff_python_trivia::CommentRanges; use ruff_python_trivia::{ diff --git a/crates/ruff_python_formatter/src/expression/string.rs b/crates/ruff_python_formatter/src/expression/string.rs index 7e0b0cb06b575..b6f7da74554bb 100644 --- a/crates/ruff_python_formatter/src/expression/string.rs +++ b/crates/ruff_python_formatter/src/expression/string.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use bitflags::bitflags; use ruff_formatter::{format_args, write, FormatError}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, Constant, ExprConstant, ExprFString, ExpressionRef}; use ruff_python_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType}; use ruff_python_parser::{Mode, Tok}; diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index 3bd8ae3f4daef..e92ec0028b3a2 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -3,7 +3,7 @@ use tracing::Level; use ruff_formatter::prelude::*; use ruff_formatter::{format, FormatError, Formatted, PrintError, Printed, SourceCode}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::Mod; use ruff_python_index::tokens_and_ranges; use ruff_python_parser::lexer::LexicalError; diff --git a/crates/ruff_python_formatter/src/other/match_case.rs b/crates/ruff_python_formatter/src/other/match_case.rs index 0b965583d5e3d..785ab73f502b1 100644 --- a/crates/ruff_python_formatter/src/other/match_case.rs +++ b/crates/ruff_python_formatter/src/other/match_case.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::MatchCase; use crate::builders::parenthesize_if_expands; diff --git a/crates/ruff_python_formatter/src/other/parameters.rs b/crates/ruff_python_formatter/src/other/parameters.rs index 2194a579f4d26..5e67e579de728 100644 --- a/crates/ruff_python_formatter/src/other/parameters.rs +++ b/crates/ruff_python_formatter/src/other/parameters.rs @@ -1,8 +1,8 @@ use std::usize; use ruff_formatter::{format_args, write, FormatRuleWithOptions}; -use ruff_python_ast::node::{AnyNodeRef, AstNode}; use ruff_python_ast::Parameters; +use ruff_python_ast::{AnyNodeRef, AstNode}; use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange, TextSize}; diff --git a/crates/ruff_python_formatter/src/pattern/mod.rs b/crates/ruff_python_formatter/src/pattern/mod.rs index 50d1f99fb24d5..36d927be2a594 100644 --- a/crates/ruff_python_formatter/src/pattern/mod.rs +++ b/crates/ruff_python_formatter/src/pattern/mod.rs @@ -1,5 +1,5 @@ use ruff_formatter::{FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::Pattern; use ruff_python_trivia::CommentRanges; use ruff_python_trivia::{ diff --git a/crates/ruff_python_formatter/src/pattern/pattern_arguments.rs b/crates/ruff_python_formatter/src/pattern/pattern_arguments.rs index 8dd05a91f50b5..cdcb482943ea0 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_arguments.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_arguments.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::{Pattern, PatternArguments}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange, TextSize}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs index 921e548ac0b07..d9db505418e1d 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_as.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchAs; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs index 69cbf4e774781..c6253e96c3e60 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_class.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchClass; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs index 1145f64bdd532..1cd449c4e6825 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_mapping.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchMapping; use ruff_python_ast::{Expr, Identifier, Pattern}; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs index 4de2af6c3ebe9..91e141dcc790a 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_or.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchOr; use crate::comments::leading_comments; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs index 8f5f10ce523ec..56e9d1c8a76ff 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_sequence.rs @@ -1,6 +1,6 @@ use crate::comments::SourceComment; use ruff_formatter::{format_args, Format, FormatResult}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchSequence; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs index f1aabfddc33f4..0fa9a8af6800a 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_singleton.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{Constant, PatternMatchSingleton}; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs index c8a88fe77353e..e608e65c14e98 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_star.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchStar; use crate::comments::{dangling_comments, SourceComment}; diff --git a/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs b/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs index e513ef2fcfe6c..0e9db27b15877 100644 --- a/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs +++ b/crates/ruff_python_formatter/src/pattern/pattern_match_value.rs @@ -1,4 +1,4 @@ -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::PatternMatchValue; use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses}; diff --git a/crates/ruff_python_formatter/src/statement/clause.rs b/crates/ruff_python_formatter/src/statement/clause.rs index b8138df503773..d7725bca77e29 100644 --- a/crates/ruff_python_formatter/src/statement/clause.rs +++ b/crates/ruff_python_formatter/src/statement/clause.rs @@ -1,5 +1,5 @@ use ruff_formatter::{write, Argument, Arguments, FormatError}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{ ElifElseClause, ExceptHandlerExceptHandler, MatchCase, StmtClassDef, StmtFor, StmtFunctionDef, StmtIf, StmtMatch, StmtTry, StmtWhile, StmtWith, Suite, diff --git a/crates/ruff_python_formatter/src/statement/stmt_global.rs b/crates/ruff_python_formatter/src/statement/stmt_global.rs index 731630a3d8e00..dac5c0b520c0d 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_global.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_global.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::StmtGlobal; use crate::comments::{SourceComment, SuppressionKind}; diff --git a/crates/ruff_python_formatter/src/statement/stmt_if.rs b/crates/ruff_python_formatter/src/statement/stmt_if.rs index e5852db8d0dc5..5c6fabea10edd 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_if.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_if.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{ElifElseClause, StmtIf}; use crate::comments::SourceComment; diff --git a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs index 29c1738d04866..e0535268a002e 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs @@ -1,5 +1,5 @@ use ruff_formatter::write; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::StmtImportFrom; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs b/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs index 5be0c7c9eb17d..e39965e5b1c12 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_nonlocal.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::StmtNonlocal; use crate::comments::{SourceComment, SuppressionKind}; diff --git a/crates/ruff_python_formatter/src/statement/stmt_while.rs b/crates/ruff_python_formatter/src/statement/stmt_while.rs index 88a9af9831fdc..8372cd6062e36 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_while.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_while.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::{Stmt, StmtWhile}; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/statement/stmt_with.rs b/crates/ruff_python_formatter/src/statement/stmt_with.rs index a71f73e6b2fbe..af2389279b559 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_with.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_with.rs @@ -1,5 +1,5 @@ use ruff_formatter::{format_args, write, FormatError}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::StmtWith; use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index c6361c53bb3f7..a818abcf6cd98 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -1,6 +1,6 @@ use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; use ruff_python_ast::helpers::is_compound_statement; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::{self as ast, Constant, Expr, ExprConstant, PySourceType, Stmt, Suite}; use ruff_python_trivia::{lines_after, lines_after_ignoring_end_of_line_trivia, lines_before}; use ruff_text_size::{Ranged, TextRange}; diff --git a/crates/ruff_python_formatter/src/type_param/type_params.rs b/crates/ruff_python_formatter/src/type_param/type_params.rs index cac5b8b33f577..c99020cc249ef 100644 --- a/crates/ruff_python_formatter/src/type_param/type_params.rs +++ b/crates/ruff_python_formatter/src/type_param/type_params.rs @@ -1,6 +1,6 @@ use ruff_formatter::write; use ruff_formatter::FormatResult; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::AstNode; use ruff_python_ast::TypeParams; use ruff_text_size::Ranged; diff --git a/crates/ruff_python_formatter/src/verbatim.rs b/crates/ruff_python_formatter/src/verbatim.rs index deaa8cf4c5a0e..a9657c097a82c 100644 --- a/crates/ruff_python_formatter/src/verbatim.rs +++ b/crates/ruff_python_formatter/src/verbatim.rs @@ -4,7 +4,7 @@ use std::iter::FusedIterator; use unicode_width::UnicodeWidthStr; use ruff_formatter::{write, FormatError}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::AnyNodeRef; use ruff_python_ast::Stmt; use ruff_python_parser::lexer::{lex_starts_at, LexResult}; use ruff_python_parser::{Mode, Tok}; diff --git a/crates/ruff_python_semantic/src/nodes.rs b/crates/ruff_python_semantic/src/nodes.rs index 3a95b2e8e2c3c..37bd797442eb0 100644 --- a/crates/ruff_python_semantic/src/nodes.rs +++ b/crates/ruff_python_semantic/src/nodes.rs @@ -74,11 +74,11 @@ impl<'a> Index for Nodes<'a> { } } -/// A reference to an AST node. Like [`ruff_python_ast::node::AnyNodeRef`], but wraps the node +/// A reference to an AST node. Like [`ruff_python_ast::AnyNodeRef`], but wraps the node /// itself (like [`Stmt`]) rather than the narrowed type (like [`ruff_python_ast::StmtAssign`]). /// -/// TODO(charlie): Replace with [`ruff_python_ast::node::AnyNodeRef`]. This requires migrating -/// the rest of the codebase to use [`ruff_python_ast::node::AnyNodeRef`] and related abstractions, +/// TODO(charlie): Replace with [`ruff_python_ast::AnyNodeRef`]. This requires migrating +/// the rest of the codebase to use [`ruff_python_ast::AnyNodeRef`] and related abstractions, /// like [`ruff_python_ast::ExpressionRef`] instead of [`Expr`]. #[derive(Copy, Clone, Debug, PartialEq)] pub enum NodeRef<'a> { diff --git a/crates/ruff_workspace/src/options.rs b/crates/ruff_workspace/src/options.rs index eaf1cd22fe058..9250f4c166683 100644 --- a/crates/ruff_workspace/src/options.rs +++ b/crates/ruff_workspace/src/options.rs @@ -2509,7 +2509,7 @@ pub struct FormatOptions { /// ``` /// /// Ruff will change `a` to use single quotes when using `quote-style = "single"`. However, - /// `a` will be unchanged, as converting to single quotes would require the inner `'` to be + /// `b` will be unchanged, as converting to single quotes would require the inner `'` to be /// escaped, which leads to less readable code: `'It\'s monday morning'`. #[option( default = r#"double"#, diff --git a/docs/editor-integrations.md b/docs/editor-integrations.md index ce76e01fa3986..685b2df09fee3 100644 --- a/docs/editor-integrations.md +++ b/docs/editor-integrations.md @@ -292,7 +292,7 @@ jobs: run: | python -m pip install --upgrade pip pip install ruff - # Include `--format=github` to enable automatic inline annotations. + # Update output format to enable automatic inline annotations. - name: Run Ruff - run: ruff check --format=github . + run: ruff check --output-format=github . ``` diff --git a/ruff.schema.json b/ruff.schema.json index 1c49b5838559d..9752f750363cb 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -1239,7 +1239,7 @@ ] }, "quote-style": { - "description": "Whether to prefer single `'` or double `\"` quotes for strings. Defaults to double quotes.\n\nIn compliance with [PEP 8](https://peps.python.org/pep-0008/) and [PEP 257](https://peps.python.org/pep-0257/), Ruff prefers double quotes for multiline strings and docstrings, regardless of the configured quote style.\n\nRuff may also deviate from this option if using the configured quotes would require escaping quote characters within the string. For example, given:\n\n```python a = \"a string without any quotes\" b = \"It's monday morning\" ```\n\nRuff will change `a` to use single quotes when using `quote-style = \"single\"`. However, `a` will be unchanged, as converting to single quotes would require the inner `'` to be escaped, which leads to less readable code: `'It\\'s monday morning'`.", + "description": "Whether to prefer single `'` or double `\"` quotes for strings. Defaults to double quotes.\n\nIn compliance with [PEP 8](https://peps.python.org/pep-0008/) and [PEP 257](https://peps.python.org/pep-0257/), Ruff prefers double quotes for multiline strings and docstrings, regardless of the configured quote style.\n\nRuff may also deviate from this option if using the configured quotes would require escaping quote characters within the string. For example, given:\n\n```python a = \"a string without any quotes\" b = \"It's monday morning\" ```\n\nRuff will change `a` to use single quotes when using `quote-style = \"single\"`. However, `b` will be unchanged, as converting to single quotes would require the inner `'` to be escaped, which leads to less readable code: `'It\\'s monday morning'`.", "anyOf": [ { "$ref": "#/definitions/QuoteStyle" From 728bce52563f7a34de01dc8cc6d050ef005ae4fa Mon Sep 17 00:00:00 2001 From: konstin Date: Wed, 18 Oct 2023 11:22:33 +0200 Subject: [PATCH 3/5] Make the comment clearer --- .../src/statement/suite.rs | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index a818abcf6cd98..ea48cdf4088c7 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -158,21 +158,6 @@ impl FormatRule> for FormatSuite { let needs_empty_lines = if is_class_or_function_definition(following) { // Here we insert empty lines even if the preceding has a trailing own line comment true - } else if preceding_comments.has_trailing_own_line() { - // If there is a comment between preceding and following the empty lines were - // inserted before the comment by preceding and there are no extra empty lines after - // the comment, which also includes nested class/function definitions. - // ```python - // class Test: - // def a(self): - // pass - // # trailing comment - // - // - // # two lines before, one line after - // - // c = 30 - false } else { // Find nested class or function definitions that need an empty line after them. // @@ -185,21 +170,38 @@ impl FormatRule> for FormatSuite { // // print("below function") // ``` - // Again, a empty lines are inserted before comments - // ```python - // if True: - // - // def double(s): - // return s + s - // - // # - // print("below comment function") - // ``` - std::iter::successors(Some(AnyNodeRef::from(preceding)), |parent| { - parent - .last_child_in_body() - .filter(|last_child| !comments.has_trailing_own_line(*last_child)) - }) + std::iter::successors( + Some(AnyNodeRef::from(preceding)), + AnyNodeRef::last_child_in_body, + ) + .take_while(|last_child| + // If there is a comment between preceding and following the empty lines were + // inserted before the comment by preceding and there are no extra empty lines + // after the comment. + // ```python + // class Test: + // def a(self): + // pass + // # trailing comment + // + // + // # two lines before, one line after + // + // c = 30 + // ```` + // This also includes nested class/function definitions, so we stop recursing + // once we see a node with a trailing own line comment: + // ```python + // def f(): + // if True: + // + // def double(s): + // return s + s + // + // # nested trailing own line comment + // print("below function with trailing own line comment") + // ``` + !comments.has_trailing_own_line(*last_child)) .any(|last_child| { matches!( last_child, From ddaaba64c4cc6e9d6e29fd9ff8128b0d5f139231 Mon Sep 17 00:00:00 2001 From: konstin Date: Wed, 18 Oct 2023 11:27:31 +0200 Subject: [PATCH 4/5] Make another comment clearer --- .../resources/test/fixtures/ruff/newlines.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py index 9e355f3bcf1fa..26b1867465e3b 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py @@ -249,7 +249,8 @@ def y(): print() -# NOTE: Please keep this the last block in this file +# NOTE: Please keep this the last block in this file. This tests that we don't insert empty line at the end of the file +# due to nested functions if True: def nested_trailing_function(): pass \ No newline at end of file From 535f3541c58a8e8d7ba50899a13515bca28d0f21 Mon Sep 17 00:00:00 2001 From: konstin Date: Wed, 18 Oct 2023 11:34:38 +0200 Subject: [PATCH 5/5] Update fixture comment --- .../resources/test/fixtures/ruff/newlines.py | 4 ++-- .../tests/snapshots/format@newlines.py.snap | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py index 26b1867465e3b..e684befc4bb3d 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/newlines.py @@ -249,8 +249,8 @@ def y(): print() -# NOTE: Please keep this the last block in this file. This tests that we don't insert empty line at the end of the file -# due to nested functions +# NOTE: Please keep this the last block in this file. This tests that we don't insert +# empty line(s) at the end of the file due to nested function if True: def nested_trailing_function(): pass \ No newline at end of file diff --git a/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap index a0873d299eafa..68f3674034ec5 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@newlines.py.snap @@ -255,7 +255,8 @@ if True: print() -# NOTE: Please keep this the last block in this file +# NOTE: Please keep this the last block in this file. This tests that we don't insert +# empty line(s) at the end of the file due to nested function if True: def nested_trailing_function(): pass``` @@ -539,7 +540,8 @@ if True: print() -# NOTE: Please keep this the last block in this file +# NOTE: Please keep this the last block in this file. This tests that we don't insert +# empty line(s) at the end of the file due to nested function if True: def nested_trailing_function():