-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid gratuitous splits after
=
. (#1554)
This makes two changes that improve how assignments are formatted: 1. If a comment is before a cascade setter, don't force the setter to split. Prior to this change, if you had: ```dart target // Comment ..setter = value; ``` The formatter would give you: ```dart target // Comment ..setter = value; ``` It attached the comment to the `..setter`, which was the LHS of the assignment. Then, because there was a newline inside the LHS, it forced a split at the `=`. Instead, we hoist those leading comments out, similar to how we handle binary operators. In fact, I did some refactoring to get rid of duplicate code in InfixPiece that handled leading comments. 2. If the LHS of an assignment is a call chain, don't force the assignment to split if the chain does. In the process of fixing 1, I ran into a similar problem. If you had: ```dart target // Comment .setter = value; ``` The formatter would give you: ```dart target // Comment .setter = value; ``` However, the solution is different in this case. With cascade setters, the target of the `=` is just the `..setter`. With a non-cascade setter, the target is the entire `target // Comment \n.setter` part. That *does* contain a newline, and we can't hoist the comment out of the assignment because the target really is the entire `target // Comment \n.setter` expression. Instead, we treat call chains on the LHS of assignments as "block formattable". "Block" is kind of a misnomer here because what it really means is "allow a newline without splitting at the `=` or increasing indentation". I can't think of a good term for that. That change fixes the above example, but also generally improves how setter calls are formatted when the target is a large call chain expression like: ```dart // Before this PR: target.method( argument, ).setter = value; // After: target.method(argument) .setter = value; ``` This second change isn't entirely... principled? But I tested on a giant corpus and when it kicks in, it invariably produces nicer output. Fix #1429.
- Loading branch information
1 parent
d3b5aed
commit 7276774
Showing
9 changed files
with
244 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
import '../back_end/code_writer.dart'; | ||
import 'piece.dart'; | ||
|
||
/// A piece for a series of leading comments preceding some other piece. | ||
/// | ||
/// We use this and hoist comments out from the inner piece so that a newline | ||
/// in the comments doesn't erroneously force the inner piece to split. For | ||
/// example, if comments preceding an infix operator's left operand: | ||
/// | ||
/// value = | ||
/// // comment | ||
/// a + b; | ||
/// | ||
/// Here, the `// comment` will be hoisted out and stored in a | ||
/// [LeadingCommentPiece] instead of being a leading comment in the [CodePiece] | ||
/// for `a`. If we left the comment in `a`, then the newline after the line | ||
/// comment would force the `+` operator to split yielding: | ||
/// | ||
/// value = | ||
/// // comment | ||
/// a + | ||
/// b; | ||
class LeadingCommentPiece extends Piece { | ||
final List<Piece> _comments; | ||
final Piece _piece; | ||
|
||
LeadingCommentPiece(this._comments, this._piece); | ||
|
||
@override | ||
void format(CodeWriter writer, State state) { | ||
for (var comment in _comments) { | ||
writer.format(comment); | ||
} | ||
|
||
writer.format(_piece); | ||
} | ||
|
||
@override | ||
void forEachChild(void Function(Piece piece) callback) { | ||
_comments.forEach(callback); | ||
callback(_piece); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.