Skip to content

Commit 503da82

Browse files
committed
Only allow the comment at the top of the formatted code.
1 parent 6d60708 commit 503da82

File tree

5 files changed

+59
-61
lines changed

5 files changed

+59
-61
lines changed

lib/src/dart_formatter.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import 'short/source_visitor.dart';
2121
import 'source_code.dart';
2222
import 'string_compare.dart' as string_compare;
2323

24+
/// Regular expression that matches a format width comment like:
25+
///
26+
/// // dart format width=123
27+
final RegExp _widthCommentPattern = RegExp(r'^// dart format width=(\d+)$');
28+
2429
/// Dart source code formatter.
2530
class DartFormatter {
2631
/// The latest Dart language version that can be parsed and formatted by this
@@ -178,8 +183,21 @@ class DartFormatter {
178183

179184
SourceCode output;
180185
if (experimentFlags.contains(tallStyleExperimentFlag)) {
186+
// Look for a page width comment before the code.
187+
int? pageWidthFromComment;
188+
for (Token? comment = node.beginToken.precedingComments;
189+
comment != null;
190+
comment = comment.next) {
191+
if (_widthCommentPattern.firstMatch(comment.lexeme) case var match?) {
192+
// If integer parsing fails for some reason, the returned `null`
193+
// means we correctly ignore the comment.
194+
pageWidthFromComment = int.tryParse(match[1]!);
195+
break;
196+
}
197+
}
198+
181199
var visitor = AstNodeVisitor(this, lineInfo, unitSourceCode);
182-
output = visitor.run(unitSourceCode, node);
200+
output = visitor.run(unitSourceCode, node, pageWidthFromComment);
183201
} else {
184202
var visitor = SourceVisitor(this, lineInfo, unitSourceCode);
185203
output = visitor.run(node);

lib/src/front_end/ast_node_visitor.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
6666
///
6767
/// This is the only method that should be called externally. Everything else
6868
/// is effectively private.
69-
SourceCode run(SourceCode source, AstNode node) {
69+
///
70+
/// If there is a `// dart format width=123` comment before the formatted
71+
/// code, then [pageWidthFromComment] is that width.
72+
SourceCode run(SourceCode source, AstNode node, int? pageWidthFromComment) {
7073
Profile.begin('AstNodeVisitor.run()');
7174

7275
Profile.begin('AstNodeVisitor build Piece tree');
@@ -123,7 +126,7 @@ class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
123126
Profile.end('AstNodeVisitor build Piece tree');
124127

125128
// Finish writing and return the complete result.
126-
var result = pieces.finish(source, unitPiece);
129+
var result = pieces.finish(source, unitPiece, pageWidthFromComment);
127130

128131
Profile.end('AstNodeVisitor.run()');
129132

lib/src/front_end/comment_writer.dart

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,12 @@ import '../comment_type.dart';
4242
/// written. When that [TextPiece] is output later, it will include the comments
4343
/// as well.
4444
class CommentWriter {
45-
/// Regular expression that matches a format width comment like:
46-
///
47-
/// // dart format width=123
48-
static final RegExp _widthCommentPattern =
49-
RegExp(r'^// dart format width=(\d+)$');
50-
5145
final LineInfo _lineInfo;
5246

5347
/// The tokens whose preceding comments have already been taken by calls to
5448
/// [takeCommentsBefore()].
5549
final Set<Token> _takenTokens = {};
5650

57-
/// If we have encountered a comment that sets an explicit page width, that
58-
/// width, otherwise `null`.
59-
///
60-
/// The comment looks like:
61-
///
62-
/// // dart format width=123
63-
///
64-
/// If there are multiple of these comments, the first one wins.
65-
int? get pageWidthFromComment => _pageWidthFromComment;
66-
int? _pageWidthFromComment;
67-
6851
CommentWriter(this._lineInfo);
6952

7053
/// Returns the comments that appear before [token].
@@ -123,14 +106,6 @@ class CommentWriter {
123106
if (comment == token.precedingComments) linesBefore = 2;
124107
}
125108

126-
// If this comment configures the page width, remember it.
127-
if (_widthCommentPattern.firstMatch(text) case var match?
128-
when _pageWidthFromComment == null) {
129-
// If integer parsing fails for some reason, the returned `null`
130-
// means we correctly ignore the comment.
131-
_pageWidthFromComment = int.tryParse(match[1]!);
132-
}
133-
134109
CommentType type;
135110
if (text.startsWith('///') && !text.startsWith('////') ||
136111
text.startsWith('/**') && text != '/**/') {

lib/src/front_end/piece_writer.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,11 @@ class PieceWriter {
390390

391391
/// Finishes writing and returns a [SourceCode] containing the final output
392392
/// and updated selection, if any.
393-
SourceCode finish(SourceCode source, Piece rootPiece) {
393+
///
394+
/// If there is a `// dart format width=123` comment before the formatted
395+
/// code, then [pageWidthFromComment] is that width.
396+
SourceCode finish(
397+
SourceCode source, Piece rootPiece, int? pageWidthFromComment) {
394398
if (debug.tracePieceBuilder) {
395399
debug.log(debug.pieceTree(rootPiece));
396400
}
@@ -399,7 +403,7 @@ class PieceWriter {
399403

400404
var cache = SolutionCache();
401405
var solver = Solver(cache,
402-
pageWidth: _comments.pageWidthFromComment ?? _formatter.pageWidth,
406+
pageWidth: pageWidthFromComment ?? _formatter.pageWidth,
403407
leadingIndent: _formatter.indent);
404408
var solution = solver.format(rootPiece);
405409
var output = solution.code.build(source, _formatter.lineEnding);

test/tall/other/format_width.unit

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,116 @@
11
40 columns |
22
### Tests for the comment to set formatting width.
33
>>> Comment sets page width.
4+
// dart format width=30
45
main() {
5-
// dart format width=30
66
fitsUnsplitAt40 + butNotAt30;
77
}
88
<<<
9+
// dart format width=30
910
main() {
10-
// dart format width=30
1111
fitsUnsplitAt40 +
1212
butNotAt30;
1313
}
14-
>>> Comment anywhere affects all code.
14+
>>> Comment only takes effect if it appears before code.
1515
main() {
16+
// dart format width=30
1617
fitsUnsplitAt40 + butNotAt30;
1718
}
18-
// dart format width=30
1919
<<<
2020
main() {
21-
fitsUnsplitAt40 +
22-
butNotAt30;
21+
// dart format width=30
22+
fitsUnsplitAt40 + butNotAt30;
2323
}
24-
24+
>>> If there are multiple comments, first one wins.
2525
// dart format width=30
26-
>>> If multiple comments, first one wins.
26+
// dart format width=60
2727
main() {
28-
// dart format width=30
29-
// dart format width=60
3028
fitsUnsplitAt40 + butNotAt30;
3129
}
3230
<<<
31+
// dart format width=30
32+
// dart format width=60
3333
main() {
34-
// dart format width=30
35-
// dart format width=60
3634
fitsUnsplitAt40 +
3735
butNotAt30;
3836
}
3937
>>> Does nothing if width is not an integer.
38+
// dart format width=wat
4039
main() {
41-
// dart format width=wat
4240
fitsUnsplitAt40 + butNotAt30;
4341
}
4442
<<<
43+
// dart format width=wat
4544
main() {
46-
// dart format width=wat
4745
fitsUnsplitAt40 + butNotAt30;
4846
}
4947
>>> Can't have trailing text.
48+
// dart format width=30 some more text
5049
main() {
51-
// dart format width=30 some more text
5250
fitsUnsplitAt40 + butNotAt30;
5351
}
5452
<<<
53+
// dart format width=30 some more text
5554
main() {
56-
// dart format width=30 some more text
5755
fitsUnsplitAt40 + butNotAt30;
5856
}
5957
>>> Whitespace must match exactly.
58+
//dart format width=30
6059
main() {
61-
//dart format width=30
6260
fitsUnsplitAt40 + butNotAt30;
6361
}
6462
<<<
63+
//dart format width=30
6564
main() {
66-
//dart format width=30
6765
fitsUnsplitAt40 + butNotAt30;
6866
}
6967
>>> Whitespace must match exactly.
68+
// dart format width=30
7069
main() {
71-
// dart format width=30
7270
fitsUnsplitAt40 + butNotAt30;
7371
}
7472
<<<
73+
// dart format width=30
7574
main() {
76-
// dart format width=30
7775
fitsUnsplitAt40 + butNotAt30;
7876
}
7977
>>> Whitespace must match exactly.
78+
// dart format width = 30
8079
main() {
81-
// dart format width = 30
8280
fitsUnsplitAt40 + butNotAt30;
8381
}
8482
<<<
83+
// dart format width = 30
8584
main() {
86-
// dart format width = 30
8785
fitsUnsplitAt40 + butNotAt30;
8886
}
89-
>>> Can't be doc comment.
87+
>>> Can't be a doc comment.
88+
/// dart format width=30
9089
main() {
91-
/// dart format width=30
9290
fitsUnsplitAt40 + butNotAt30;
9391
}
9492
<<<
93+
/// dart format width=30
9594
main() {
96-
/// dart format width=30
9795
fitsUnsplitAt40 + butNotAt30;
9896
}
99-
>>> Can't be nested inside other comment.
97+
>>> Can't be nested inside another comment.
98+
/* // dart format width=30 */
10099
main() {
101-
/* // dart format width=30 */
102100
fitsUnsplitAt40 + butNotAt30;
103101
}
104102
<<<
103+
/* // dart format width=30 */
105104
main() {
106-
/* // dart format width=30 */
107105
fitsUnsplitAt40 + butNotAt30;
108106
}
109-
>>> Can't be inside string literal.
107+
>>> Can't be inside a string literal.
108+
var c = '// dart format width=30';
110109
main() {
111-
var c = '// dart format width=30';
112110
fitsUnsplitAt40 + butNotAt30;
113111
}
114112
<<<
113+
var c = '// dart format width=30';
115114
main() {
116-
var c = '// dart format width=30';
117115
fitsUnsplitAt40 + butNotAt30;
118116
}

0 commit comments

Comments
 (0)