Skip to content

Commit 7e7516d

Browse files
authored
Add style fix to remove "new" keyword. (flutter#695)
1 parent 9eb5c5d commit 7e7516d

8 files changed

+136
-14
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# 1.1.0-dev
22

33
* Add support for "style fixes", opt-in non-whitespace changes.
4-
* Add fix to convert ":" to "=" as the named parameter default value separator.
4+
* Add fix to convert `:` to `=` as the named parameter default value separator.
5+
* Add fix to remove `new` keywords.
56

67
# 1.0.14
78

lib/src/chunk_builder.dart

+22-5
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,24 @@ class ChunkBuilder {
200200
}
201201
}
202202

203+
// Edge case: if the previous output was also from a call to
204+
// [writeComments()] which ended with a line comment, force a newline.
205+
// Normally, comments are strictly interleaved with tokens and you never
206+
// get two sequences of comments in a row. However, when applying a fix
207+
// that removes a token (like `new`), it's possible to get two sets of
208+
// comments in a row, as in:
209+
//
210+
// // a
211+
// new // b
212+
// Foo();
213+
//
214+
// When that happens, we need to make sure the preserve the split at the
215+
// end of the first sequence of comments if there is one.
216+
if (_pendingWhitespace == null) {
217+
comments.first.linesBefore = 1;
218+
_pendingWhitespace = Whitespace.none;
219+
}
220+
203221
// Edge case: if the comments are completely inline (i.e. just a series of
204222
// block comments with no newlines before, after, or between them), then
205223
// they will eat any pending newlines. Make sure that doesn't happen by
@@ -215,11 +233,10 @@ class ChunkBuilder {
215233
// /* a */ /* b */
216234
// import 'a.dart';
217235
if (linesBeforeToken == 0 &&
218-
comments.every((comment) => comment.isInline)) {
219-
if (_pendingWhitespace.minimumLines > 0) {
220-
comments.first.linesBefore = _pendingWhitespace.minimumLines;
221-
linesBeforeToken = 1;
222-
}
236+
comments.every((comment) => comment.isInline) &&
237+
_pendingWhitespace.minimumLines > 0) {
238+
comments.first.linesBefore = _pendingWhitespace.minimumLines;
239+
linesBeforeToken = 1;
223240
}
224241

225242
// Write each comment and the whitespace between them.

lib/src/source_visitor.dart

+17-1
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,23 @@ class SourceVisitor extends ThrowingAstVisitor {
14431443

14441444
visitInstanceCreationExpression(InstanceCreationExpression node) {
14451445
builder.startSpan();
1446-
token(node.keyword, after: space);
1446+
1447+
var includeKeyword = true;
1448+
1449+
if (node.keyword != null) {
1450+
if (node.keyword.keyword == Keyword.NEW &&
1451+
_formatter.fixes.contains(StyleFix.optionalNew)) {
1452+
includeKeyword = false;
1453+
}
1454+
}
1455+
1456+
if (includeKeyword) {
1457+
token(node.keyword, after: space);
1458+
} else {
1459+
// Don't lose comments before the discarded keyword, if any.
1460+
writePrecedingCommentsAndNewlines(node.keyword);
1461+
}
1462+
14471463
builder.startSpan(Cost.constructorName);
14481464

14491465
// Start the expression nesting for the argument list here, in case this

lib/src/style_fix.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ class StyleFix {
99
"named-default-separator",
1010
'Use "=" as the separator before named parameter default values.');
1111

12-
static const all = const [namedDefaultSeparator];
12+
static const optionalNew =
13+
const StyleFix._("optional-new", 'Remove "new" keyword.');
14+
15+
static const all = const [namedDefaultSeparator, optionalNew];
1316

1417
final String name;
1518
final String description;

pubspec.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,4 @@ packages:
366366
source: hosted
367367
version: "2.1.13"
368368
sdks:
369-
dart: ">=2.0.0-dev.54.0 <=2.0.0-edge.ba342a94ecd08c183b6ea0b4dab33e47bb8dadd5"
369+
dart: ">=2.0.0-dev.54.0 <=2.0.0-edge.9ff283218499ccc46fe7bb59f6aa4a40f31331c0"

test/command_line_test.dart

+22-5
Original file line numberDiff line numberDiff line change
@@ -234,22 +234,39 @@ void main() {
234234
});
235235

236236
group("fix", () {
237-
// TODO(rnystrom): This will get more useful when other fixes are supported.
238237
test("--fix applies all fixes", () async {
239238
var process = await runFormatter(["--fix"]);
240-
process.stdin.writeln("foo({a:1}) {}");
239+
process.stdin.writeln("foo({a:1}) {");
240+
process.stdin.writeln(" new Bar();}");
241241
await process.stdin.close();
242242

243-
expect(await process.stdout.next, "foo({a = 1}) {}");
243+
expect(await process.stdout.next, "foo({a = 1}) {");
244+
expect(await process.stdout.next, " Bar();");
245+
expect(await process.stdout.next, "}");
244246
await process.shouldExit(0);
245247
});
246248

247249
test("--fix-named-default-separator", () async {
248250
var process = await runFormatter(["--fix-named-default-separator"]);
249-
process.stdin.writeln("foo({a:1}) {}");
251+
process.stdin.writeln("foo({a:1}) {");
252+
process.stdin.writeln(" new Bar();}");
250253
await process.stdin.close();
251254

252-
expect(await process.stdout.next, "foo({a = 1}) {}");
255+
expect(await process.stdout.next, "foo({a = 1}) {");
256+
expect(await process.stdout.next, " new Bar();");
257+
expect(await process.stdout.next, "}");
258+
await process.shouldExit(0);
259+
});
260+
261+
test("--fix-optional-new", () async {
262+
var process = await runFormatter(["--fix-optional-new"]);
263+
process.stdin.writeln("foo({a:1}) {");
264+
process.stdin.writeln(" new Bar();}");
265+
await process.stdin.close();
266+
267+
expect(await process.stdout.next, "foo({a: 1}) {");
268+
expect(await process.stdout.next, " Bar();");
269+
expect(await process.stdout.next, "}");
253270
await process.shouldExit(0);
254271
});
255272

test/fix_test.dart

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ import 'utils.dart';
1414
void main() {
1515
testFile(
1616
"fixes/named_default_separator.unit", [StyleFix.namedDefaultSeparator]);
17+
testFile("fixes/optional_new.stmt", [StyleFix.optionalNew]);
1718
}

test/fixes/optional_new.stmt

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
40 columns |
2+
>>>
3+
{
4+
new A(new A.named());
5+
new A<int>(new A<int>.named());
6+
// Don't touch const.
7+
const A();
8+
const A.named();
9+
}
10+
<<<
11+
{
12+
A(A.named());
13+
A<int>(A<int>.named());
14+
// Don't touch const.
15+
const A();
16+
const A.named();
17+
}
18+
>>> preserves block comments before
19+
/* a */ /* b */ new A();
20+
<<<
21+
/* a */ /* b */ A();
22+
>>> preserves block comments after
23+
new /* a */ /* b */A();
24+
<<<
25+
/* a */ /* b */ A();
26+
>>> preserves line comments before
27+
// a
28+
// b
29+
new A();
30+
<<<
31+
// a
32+
// b
33+
A();
34+
>>> preserves line comments after
35+
new // a
36+
// b
37+
A();
38+
<<<
39+
// a
40+
// b
41+
A();
42+
>>> merge surrounding comments
43+
{
44+
/* a */ new /* b */ A();
45+
/* a */ new // b
46+
A();
47+
// a
48+
new /* b */ A();
49+
// a
50+
new // b
51+
A();
52+
}
53+
<<<
54+
{
55+
/* a */ /* b */ A();
56+
/* a */ // b
57+
A();
58+
// a
59+
/* b */ A();
60+
// a
61+
// b
62+
A();
63+
}
64+
>>> handle already-removed keyword
65+
A<int>(A<int>.named());
66+
<<<
67+
A<int>(A<int>.named());

0 commit comments

Comments
 (0)