Skip to content

Commit 5f93e07

Browse files
authored
Merge pull request #1031 from dart-lang/837-block-comment-splits
Don't unnecessarily split argument lists with block comments.
2 parents b13403c + f9a4f47 commit 5f93e07

File tree

13 files changed

+201
-41
lines changed

13 files changed

+201
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 2.0.2-dev
2+
3+
* Don't unnecessarily split argument lists with `/* */` comments (#837).
4+
15
# 2.0.1
26

37
* Support triple-shift `>>>` and `>>>=` operators (#992).

lib/src/chunk.dart

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,32 +384,43 @@ class Span extends FastHash {
384384
String toString() => '$id\$$cost';
385385
}
386386

387+
enum CommentType {
388+
/// A `///` or `/**` doc comment.
389+
doc,
390+
391+
/// A non-doc line comment.
392+
line,
393+
394+
/// A `/* ... */` comment that should be on its own line.
395+
block,
396+
397+
/// A `/* ... */` comment that can share a line with other code.
398+
inlineBlock,
399+
}
400+
387401
/// A comment in the source, with a bit of information about the surrounding
388402
/// whitespace.
389403
class SourceComment extends Selection {
390404
/// The text of the comment, including `//`, `/*`, and `*/`.
391405
@override
392406
final String text;
393407

408+
/// What kind of comment this is.
409+
final CommentType type;
410+
394411
/// The number of newlines between the comment or token preceding this comment
395412
/// and the beginning of this one.
396413
///
397414
/// Will be zero if the comment is a trailing one.
398415
int linesBefore;
399416

400-
/// Whether this comment is a line comment.
401-
final bool isLineComment;
402-
403417
/// Whether this comment starts at column one in the source.
404418
///
405419
/// Comments that start at the start of the line will not be indented in the
406420
/// output. This way, commented out chunks of code do not get erroneously
407421
/// re-indented.
408422
final bool flushLeft;
409423

410-
/// Whether this comment is an inline block comment.
411-
bool get isInline => linesBefore == 0 && !isLineComment;
412-
413-
SourceComment(this.text, this.linesBefore,
414-
{required this.isLineComment, required this.flushLeft});
424+
SourceComment(this.text, this.type, this.linesBefore,
425+
{required this.flushLeft});
415426
}

lib/src/chunk_builder.dart

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -253,22 +253,19 @@ class ChunkBuilder {
253253
// Edge case: if the comments are completely inline (i.e. just a series of
254254
// block comments with no newlines before, after, or between them), then
255255
// they will eat any pending newlines. Make sure that doesn't happen by
256-
// putting the pending whitespace before the first comment and moving them
257-
// to their own line. Turns this:
256+
// putting the pending whitespace before the first comment. Turns this:
258257
//
259258
// library foo; /* a */ /* b */ import 'a.dart';
260259
//
261260
// into:
262261
//
263262
// library foo;
264263
//
265-
// /* a */ /* b */
266-
// import 'a.dart';
264+
// /* a */ /* b */ import 'a.dart';
267265
if (linesBeforeToken == 0 &&
268-
comments.every((comment) => comment.isInline) &&
269-
_pendingWhitespace.minimumLines > 0) {
266+
_pendingWhitespace.minimumLines > comments.first.linesBefore &&
267+
comments.every((comment) => comment.type == CommentType.inlineBlock)) {
270268
comments.first.linesBefore = _pendingWhitespace.minimumLines;
271-
linesBeforeToken = 1;
272269
}
273270

274271
// Write each comment and the whitespace between them.
@@ -284,18 +281,19 @@ class ChunkBuilder {
284281
}
285282
_emitPendingWhitespace();
286283

287-
if (comment.linesBefore == 0) {
284+
// See if the comment should follow text on the current line.
285+
if (comment.linesBefore == 0 || comment.type == CommentType.inlineBlock) {
288286
// If we're sitting on a split, move the comment before it to adhere it
289287
// to the preceding text.
290-
if (_shouldMoveCommentBeforeSplit(comment.text)) {
288+
if (_shouldMoveCommentBeforeSplit(comment)) {
291289
_chunks.last.allowText();
292290
}
293291

294292
// The comment follows other text, so we need to decide if it gets a
295293
// space before it or not.
296294
if (_needsSpaceBeforeComment(comment)) _writeText(' ');
297295
} else {
298-
// The comment starts a line, so make sure it stays on its own line.
296+
// The comment is not inline, so start a new line.
299297
_writeHardSplit(
300298
flushLeft: comment.flushLeft,
301299
isDouble: comment.linesBefore > 1,
@@ -743,17 +741,23 @@ class ChunkBuilder {
743741

744742
/// Returns `true` if the last chunk is a split that should be moved after the
745743
/// comment that is about to be written.
746-
bool _shouldMoveCommentBeforeSplit(String comment) {
744+
bool _shouldMoveCommentBeforeSplit(SourceComment comment) {
747745
// Not if there is nothing before it.
748746
if (_chunks.isEmpty) return false;
749747

748+
// Don't move a comment to a preceding line.
749+
if (comment.linesBefore != 0) return false;
750+
750751
// Multi-line comments are always pushed to the next line.
751-
if (comment.contains('\n')) return false;
752+
if (comment.type == CommentType.doc) return false;
753+
if (comment.type == CommentType.block) return false;
752754

753755
var text = _chunks.last.text;
754756

755757
// A block comment following a comma probably refers to the following item.
756-
if (text.endsWith(',') && comment.startsWith('/*')) return false;
758+
if (text.endsWith(',') && comment.type == CommentType.inlineBlock) {
759+
return false;
760+
}
757761

758762
// If the text before the split is an open grouping character, it looks
759763
// better to keep it with the elements than with the bracket itself.
@@ -788,13 +792,11 @@ class ChunkBuilder {
788792
// Not at the start of a line.
789793
if (!_chunks.last.canAddText) return false;
790794

791-
var text = _chunks.last.text;
792-
if (text.endsWith('\n')) return false;
793-
794795
// Always put a space before line comments.
795-
if (comment.isLineComment) return true;
796+
if (comment.type == CommentType.line) return true;
796797

797798
// Magic generic method comments like "Foo/*<T>*/" don't get spaces.
799+
var text = _chunks.last.text;
798800
if (_isGenericMethodComment(comment) &&
799801
_trailingIdentifierChar.hasMatch(text)) {
800802
return false;

lib/src/source_visitor.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,9 +3770,18 @@ class SourceVisitor extends ThrowingAstVisitor {
37703770
if (comment == token.precedingComments) linesBefore = 2;
37713771
}
37723772

3773-
var sourceComment = SourceComment(text, linesBefore,
3774-
isLineComment: comment.type == TokenType.SINGLE_LINE_COMMENT,
3775-
flushLeft: flushLeft);
3773+
var type = CommentType.block;
3774+
if (text.startsWith('///') && !text.startsWith('////') ||
3775+
text.startsWith('/**')) {
3776+
type = CommentType.doc;
3777+
} else if (comment.type == TokenType.SINGLE_LINE_COMMENT) {
3778+
type = CommentType.line;
3779+
} else if (commentLine == previousLine || commentLine == tokenLine) {
3780+
type = CommentType.inlineBlock;
3781+
}
3782+
3783+
var sourceComment =
3784+
SourceComment(text, type, linesBefore, flushLeft: flushLeft);
37763785

37773786
// If this comment contains either of the selection endpoints, mark them
37783787
// in the comment.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: dart_style
22
# Note: See tool/grind.dart for how to bump the version.
3-
version: 2.0.1
3+
version: 2.0.2-dev
44
description: >-
55
Opinionated, automatic Dart source code formatter.
66
Provides an API and a CLI tool.

test/comments/classes.unit

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ class A {
3333
class A {
3434
/* comment */}
3535
<<<
36-
class A {
37-
/* comment */
38-
}
36+
class A {/* comment */}
3937
>>> inline block comment
4038
class A { /* comment */ }
4139
<<<

test/comments/extensions.unit

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ extension A on B {
3333
extension A on B {
3434
/* comment */}
3535
<<<
36-
extension A on B {
37-
/* comment */
38-
}
36+
extension A on B {/* comment */}
3937
>>> inline block comment
4038
extension A on B { /* comment */ }
4139
<<<

test/comments/functions.unit

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,36 @@ function([
143143
parameter,
144144
] /* c */) {
145145
;
146+
}
147+
>>>
148+
function(
149+
/* comment */ int a, int b, int c,
150+
[direction]) {
151+
;
152+
}
153+
<<<
154+
function(
155+
/* comment */ int a, int b, int c,
156+
[direction]) {
157+
;
158+
}
159+
>>>
160+
function(
161+
/* comment */ int a, int b, int c) {
162+
;
163+
}
164+
<<<
165+
function(
166+
/* comment */ int a, int b, int c) {
167+
;
168+
}
169+
>>>
170+
function(
171+
/* comment */ int a, int b, int c, int d) {
172+
;
173+
}
174+
<<<
175+
function(/* comment */ int a, int b,
176+
int c, int d) {
177+
;
146178
}

test/comments/statements.stmt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,33 @@ while (true) {
5454
<<<
5555
while (true) {
5656
// comment
57+
}
58+
>>>
59+
main() {
60+
/* comment */ statement;
61+
}
62+
<<<
63+
main() {
64+
/* comment */ statement;
65+
}
66+
>>>
67+
main() {
68+
code;
69+
70+
/* comment */ statement;
71+
}
72+
<<<
73+
main() {
74+
code;
75+
76+
/* comment */ statement;
77+
}
78+
>>>
79+
main() {
80+
while (b)
81+
/*unreachable*/ {}
82+
}
83+
<<<
84+
main() {
85+
while (b) /*unreachable*/ {}
5786
}

test/comments/top_level.unit

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,12 @@ library a; /* comment */ import 'b.dart';
190190
<<<
191191
library a;
192192

193-
/* comment */
194-
import 'b.dart';
193+
/* comment */ import 'b.dart';
195194
>>> inline block comment between directives
196195
import 'a.dart'; /* comment */ import 'b.dart';
197196
<<<
198197
import 'a.dart';
199-
/* comment */
200-
import 'b.dart';
198+
/* comment */ import 'b.dart';
201199
>>> block comment between directives
202200
import 'a.dart'; /* comment */
203201
import 'b.dart';

0 commit comments

Comments
 (0)