diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_deep_nested_trailing_comment.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_deep_nested_trailing_comment.py new file mode 100644 index 0000000000000..5072697b47331 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_deep_nested_trailing_comment.py @@ -0,0 +1,8 @@ +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +if True: + if False: + x: int # Optional[int] diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_trailing_comment.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_trailing_comment.py new file mode 100644 index 0000000000000..44d0bb09f73f8 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_trailing_comment.py @@ -0,0 +1,8 @@ +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +@dataclass +class A: + x: int # Optional[int] diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index ea48cdf4088c7..c31de9f0f071f 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -536,7 +536,7 @@ impl<'ast> IntoFormat> for Suite { } /// A statement representing a docstring. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) struct DocstringStmt<'a>(&'a Stmt); impl<'a> DocstringStmt<'a> { @@ -589,7 +589,7 @@ impl Format> for DocstringStmt<'_> { } /// A Child of a suite. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum SuiteChildStatement<'a> { /// A docstring documenting a class or function definition. Docstring(DocstringStmt<'a>), diff --git a/crates/ruff_python_formatter/src/verbatim.rs b/crates/ruff_python_formatter/src/verbatim.rs index a9657c097a82c..4e2a532ce0f07 100644 --- a/crates/ruff_python_formatter/src/verbatim.rs +++ b/crates/ruff_python_formatter/src/verbatim.rs @@ -327,7 +327,7 @@ fn write_suppressed_statements<'a>( for range in CommentRangeIter::in_suppression(comments.trailing(statement), source) { match range { - // All leading comments are suppressed + // All trailing comments are suppressed // ```python // statement // # suppressed @@ -394,10 +394,14 @@ fn write_suppressed_statements<'a>( statement = SuiteChildStatement::Other(next_statement); leading_node_comments = comments.leading(next_statement); } else { - let end = comments - .trailing(statement) - .last() - .map_or(statement.end(), Ranged::end); + let mut nodes = + std::iter::successors(Some(AnyNodeRef::from(statement.statement())), |statement| { + statement.last_child_in_body() + }); + + let end = nodes + .find_map(|statement| comments.trailing(statement).last().map(Ranged::end)) + .unwrap_or(statement.end()); FormatVerbatimStatementRange { verbatim_range: TextRange::new(format_off_comment.end(), end), diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_deep_nested_trailing_comment.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_deep_nested_trailing_comment.py.snap new file mode 100644 index 0000000000000..081eb523828fd --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_deep_nested_trailing_comment.py.snap @@ -0,0 +1,30 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_deep_nested_trailing_comment.py +--- +## Input +```py +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +if True: + if False: + x: int # Optional[int] +``` + +## Output +```py +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +if True: + if False: + x: int # Optional[int] +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_trailing_comment.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_trailing_comment.py.snap new file mode 100644 index 0000000000000..14cf588e95ccb --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@fmt_on_off__fmt_off_unclosed_trailing_comment.py.snap @@ -0,0 +1,30 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off/fmt_off_unclosed_trailing_comment.py +--- +## Input +```py +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +@dataclass +class A: + x: int # Optional[int] +``` + +## Output +```py +# Regression test for https://github.com/astral-sh/ruff/issues/8211 + +# fmt: off +from dataclasses import dataclass + +@dataclass +class A: + x: int # Optional[int] +``` + + +