Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comments outside expression parentheses #7873

Merged
merged 10 commits into from
Oct 19, 2023

Conversation

konstin
Copy link
Member

@konstin konstin commented Oct 9, 2023

Summary

Fixes #7448
Fixes #7892

I've removed automatic dangling comment formatting, we're doing manual dangling comment formatting everywhere anyway (the assert-all-comments-formatted ensures this) and dangling comments would break the formatting there.

main:

project similarity index total files changed files
cpython 0.75803 1799 1647
django 0.99983 2772 35
home-assistant 0.99953 10596 189
poetry 0.99891 317 17
transformers 0.99963 2657 332
twine 1.00000 33 0
typeshed 0.99978 3669 20
warehouse 0.99969 654 15
zulip 0.99970 1459 22

PR:

project similarity index total files changed files
cpython 0.75803 1799 1647
django 0.99983 2772 34
home-assistant 0.99953 10596 186
poetry 0.99891 317 17
transformers 0.99966 2657 330
twine 1.00000 33 0
typeshed 0.99978 3669 20
warehouse 0.99977 654 13
zulip 0.99970 1459 22

Test Plan

New test file.

@konstin konstin force-pushed the Comments-outside-expression-parentheses branch from 2a1fa16 to 55b2da1 Compare October 10, 2023 14:28
@konstin konstin added the formatter Related to the formatter label Oct 10, 2023
@konstin konstin requested a review from MichaReiser October 11, 2023 14:02
@konstin
Copy link
Member Author

konstin commented Oct 12, 2023

An alternative we could explore is storing the parentheses range on OptionalParentheses through needs_parentheses

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work for expressions where we use maybe_parenthesize with a layout that doesn't preserve parentheses and a trailing (non-own line) comment?

crates/ruff_python_formatter/src/expression/mod.rs Outdated Show resolved Hide resolved
crates/ruff_python_formatter/src/expression/mod.rs Outdated Show resolved Hide resolved
Comment on lines +274 to +283
Expr::BoolOp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::NamedExpr(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::BinOp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::UnaryOp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Lambda(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::IfExp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Dict(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Set(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::ListComp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::SetComp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::DictComp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::GeneratorExp(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Await(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Yield(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::YieldFrom(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Compare(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Call(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::FormattedValue(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::FString(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Constant(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Attribute(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Subscript(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Starred(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Name(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::List(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Tuple(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::Slice(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Expr::IpyEscapeCommand(expr) => FormatNodeRule::fmt_fields(expr.format().rule(), expr, f),
Copy link
Member

@MichaReiser MichaReiser Oct 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The main benefit of FormatRuleWith is that it wraps the object to format with how it gets formatted. I would probably lean towards calling the relevant format rules directly (fewer abstractions, easier to understand)

Expr::Call => FormatExprCall::default().fmt_fields(expr, f)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this one for avoiding repeating the -> Format association.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair and up to you. It just requires a few more brain cycles to resolve FormatNodeRule::fmt_fields(expr.format().rule(), expr, f) to FormatExprFString::default().fmt_fields(expr, f)

@konstin konstin force-pushed the Comments-outside-expression-parentheses branch from 9addbb3 to 504c7af Compare October 17, 2023 10:16
@konstin konstin marked this pull request as ready for review October 17, 2023 10:49
) -> FormatResult<()> {
// First part: Split the comments

// TODO(konstin): This is copied from `parenthesized_range`, except that we don't have the
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure what to do about this, otherwise this PR is ready

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind the duplication. We could implement a helper that returns an Iterator over the parentheses (opening and closing) and reuse it in parenthesized_range and here.

@konstin konstin requested a review from MichaReiser October 18, 2023 19:34
@MichaReiser
Copy link
Member

Could you update the test plan with the similarity index table to see if there are any changes.

) -> FormatResult<()> {
// First part: Split the comments

// TODO(konstin): This is copied from `parenthesized_range`, except that we don't have the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind the duplication. We could implement a helper that returns an Iterator over the parentheses (opening and closing) and reuse it in parenthesized_range and here.

) -> FormatResult<()> {
// First part: Split the comments

// TODO(konstin): This is copied from `parenthesized_range`, except that we don't have the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parenthesized_range has a special case for call expressions like call(a) to avoid counting the ( and ) as the parentheses of this node. Is it safe to not special-tread call expressions here and if so why?

(
	call # sneaky
		( # comments
			a
	) # more	
)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the expression would be a but a doesn't know its parent

crates/ruff_python_formatter/src/expression/mod.rs Outdated Show resolved Hide resolved
// * the closing parenthesis
// * outer trailing comments

let fmt_fields = format_with(|f| match expression {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It could make sense to extract this into it's own struct FormatExprFields to not make this function longer than absolutely necessary (It kind of breaks the reading flow, there's the comment above explaining what is happening, but it is then followed by this somewhat unrelated boilerplate)

Comment on lines 89 to 92
with (a # trailing same line comment
# trailing own line comment
) as b: ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for removing this test case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a duplicate, sorry should have added a PR comment

@konstin konstin force-pushed the Comments-outside-expression-parentheses branch from a40819c to d61caea Compare October 19, 2023 09:08
@konstin konstin enabled auto-merge (squash) October 19, 2023 09:08
@konstin konstin force-pushed the Comments-outside-expression-parentheses branch from d61caea to e4ef5b0 Compare October 19, 2023 09:15
@konstin
Copy link
Member Author

konstin commented Oct 19, 2023

Added the similarity index table to the description, this had more impact than i had expected

@konstin konstin merged commit 8f9753f into main Oct 19, 2023
15 checks passed
@konstin konstin deleted the Comments-outside-expression-parentheses branch October 19, 2023 09:24
@github-actions
Copy link
Contributor

PR Check Results

Ecosystem

✅ ecosystem check detected no changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
formatter Related to the formatter
Projects
None yet
2 participants