diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py index 6f5a7ac1a6..a760491b3d 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/attribute.py @@ -169,3 +169,53 @@ result = ( # dangling before dot .b # trailing end-of-line ) + +# Regression test for https://github.com/astral-sh/ruff/issues/19350 +variable = ( + (something) # a comment + .first_method("some string") +) + +variable = ( + something # a commentdddddddddddddddddddddddddddddd + .first_method("some string") +) + +if ( + (something) # a commentdddddddddddddddddddddddddddddd + .first_method("some string") +): pass + +variable = ( + (something # a comment + ).first_method("some string") +) + +if ( + (something # a comment + ).first_method("some string") # second comment +): pass + +variable = ( # 1 + # 2 + (something) # 3 + # 4 + .first_method("some string") # 5 + # 6 +) # 7 + + +if ( + (something + # trailing own line on value + ) + .first_method("some string") +): ... + +variable = ( + (something + # 1 + ) # 2 + .first_method("some string") +) + diff --git a/crates/ruff_python_formatter/src/expression/expr_attribute.rs b/crates/ruff_python_formatter/src/expression/expr_attribute.rs index ebb0093ccb..781b8b4601 100644 --- a/crates/ruff_python_formatter/src/expression/expr_attribute.rs +++ b/crates/ruff_python_formatter/src/expression/expr_attribute.rs @@ -179,7 +179,22 @@ impl NeedsParentheses for ExprAttribute { context.comments().ranges(), context.source(), ) { - OptionalParentheses::Never + // We have to avoid creating syntax errors like + // ```python + // variable = (something) # trailing + // .my_attribute + // ``` + // See https://github.com/astral-sh/ruff/issues/19350 + if context + .comments() + .trailing(self.value.as_ref()) + .iter() + .any(|comment| comment.line_position().is_end_of_line()) + { + OptionalParentheses::Multiline + } else { + OptionalParentheses::Never + } } else { self.value.needs_parentheses(self.into(), context) } diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap index 89ce7d237b..4677ca06de 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap @@ -175,6 +175,56 @@ result = ( # dangling before dot .b # trailing end-of-line ) + +# Regression test for https://github.com/astral-sh/ruff/issues/19350 +variable = ( + (something) # a comment + .first_method("some string") +) + +variable = ( + something # a commentdddddddddddddddddddddddddddddd + .first_method("some string") +) + +if ( + (something) # a commentdddddddddddddddddddddddddddddd + .first_method("some string") +): pass + +variable = ( + (something # a comment + ).first_method("some string") +) + +if ( + (something # a comment + ).first_method("some string") # second comment +): pass + +variable = ( # 1 + # 2 + (something) # 3 + # 4 + .first_method("some string") # 5 + # 6 +) # 7 + + +if ( + (something + # trailing own line on value + ) + .first_method("some string") +): ... + +variable = ( + (something + # 1 + ) # 2 + .first_method("some string") +) + ``` ## Output @@ -328,4 +378,54 @@ result = ( # dangling before dot .b # trailing end-of-line ) + +# Regression test for https://github.com/astral-sh/ruff/issues/19350 +variable = ( + (something) # a comment + .first_method("some string") +) + +variable = something.first_method( # a commentdddddddddddddddddddddddddddddd + "some string" +) + +if ( + (something) # a commentdddddddddddddddddddddddddddddd + .first_method("some string") +): + pass + +variable = ( + something # a comment +).first_method("some string") + +if ( + ( + something # a comment + ).first_method("some string") # second comment +): + pass + +variable = ( # 1 + # 2 + (something) # 3 + # 4 + .first_method("some string") # 5 + # 6 +) # 7 + + +if ( + something + # trailing own line on value +).first_method("some string"): + ... + +variable = ( + ( + something + # 1 + ) # 2 + .first_method("some string") +) ```