Skip to content

Collection for #784

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

Merged
merged 3 commits into from
Mar 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.2.5

* Add support for spreads inside collections (#778).
* Add support for `if` and `for` elements inside collections (#779).

# 1.2.4

* Update to latest analyzer package AST API.
Expand Down
77 changes: 60 additions & 17 deletions lib/src/source_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,45 @@ class SourceVisitor extends ThrowingAstVisitor {
if (nestExpression) builder.unnest();
}

void visitForElement(ForElement node) {
// Treat a spread of a collection literal like a block in a for statement
// and don't split after the for parts.
var isSpreadBody = _isSpreadCollection(node.body);

builder.nestExpression();
token(node.awaitKeyword, after: space);
token(node.forKeyword);
space();
token(node.leftParenthesis);

// Start the body rule so that if the parts split, the body does too.
builder.startRule();

// The rule for the parts.
builder.startRule();
visit(node.forLoopParts);
token(node.rightParenthesis);
builder.endRule();
builder.unnest();

builder.nestExpression(indent: 2, now: true);

if (isSpreadBody) {
space();
} else {
split();

// If the body is a non-spread collection or lambda, indent it.
builder.startBlockArgumentNesting();
}

visit(node.body);

if (!isSpreadBody) builder.endBlockArgumentNesting();
builder.unnest();
builder.endRule();
}

visitForStatement2(ForStatement2 node) {
builder.nestExpression();
token(node.awaitKeyword, after: space);
Expand Down Expand Up @@ -1490,23 +1529,6 @@ class SourceVisitor extends ThrowingAstVisitor {
builder.endRule();
}

/// If [node] is a spread of a collection literal, then this returns the
/// token for the opening bracket of the collection, as in:
///
/// [ ...[a, list] ]
/// // ^
///
/// Otherwise, returns `null`.
Token _findSpreadCollectionBracket(AstNode node) {
if (node is SpreadElement) {
var expression = node.expression;
if (expression is ListLiteral) return expression.leftBracket;
if (expression is SetOrMapLiteral) return expression.leftBracket;
}

return null;
}

visitIfStatement(IfStatement node) {
builder.nestExpression();
token(node.ifKeyword);
Expand Down Expand Up @@ -2802,6 +2824,27 @@ class SourceVisitor extends ThrowingAstVisitor {
builder.endRule();
}

/// Whether [node] is a spread of a collection literal.
bool _isSpreadCollection(AstNode node) =>
_findSpreadCollectionBracket(node) != null;

/// If [node] is a spread of a collection literal, then this returns the
/// token for the opening bracket of the collection, as in:
///
/// [ ...[a, list] ]
/// // ^
///
/// Otherwise, returns `null`.
Token _findSpreadCollectionBracket(AstNode node) {
if (node is SpreadElement) {
var expression = node.expression;
if (expression is ListLiteral) return expression.leftBracket;
if (expression is SetOrMapLiteral) return expression.leftBracket;
}

return null;
}

/// Gets the cost to split at an assignment (or `:` in the case of a named
/// default value) with the given [rightHandSide].
///
Expand Down
43 changes: 4 additions & 39 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ packages:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.35.3"
version: "0.35.4"
args:
dependency: "direct main"
description:
Expand All @@ -21,7 +21,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.1.0"
boolean_selector:
dependency: transitive
description:
Expand Down Expand Up @@ -64,20 +64,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.6"
front_end:
dependency: transitive
description:
name: front_end
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.13"
version: "0.1.14"
glob:
dependency: transitive
description:
Expand All @@ -92,13 +85,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.3"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.4+1"
http:
dependency: transitive
description:
Expand Down Expand Up @@ -147,14 +133,7 @@ packages:
name: kernel
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.13"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.3+2"
version: "0.3.14"
matcher:
dependency: transitive
description:
Expand Down Expand Up @@ -218,13 +197,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
plugin:
dependency: transitive
description:
name: plugin
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+3"
pool:
dependency: transitive
description:
Expand Down Expand Up @@ -358,13 +330,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
utf:
dependency: transitive
description:
name: utf
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0+5"
vm_service_client:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dart_style
# Note: See tool/grind.dart for how to bump the version.
version: 1.2.4
version: 1.2.5-dev
author: Dart Team <[email protected]>
description: Opinionated, automatic Dart source code formatter.
homepage: https://github.com/dart-lang/dart_style
Expand Down
147 changes: 147 additions & 0 deletions test/splitting/list_collection_for.stmt
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
40 columns |
>>> split collection before for
var list = [for (a in b) somewhatLongThingHere];
<<<
var list = [
for (a in b) somewhatLongThingHere
];
>>> one line in multi-line
var list = [veryLongThingThatForcesASplit, for (a in b) 2, 3];
<<<
var list = [
veryLongThingThatForcesASplit,
for (a in b) 2,
3
];
>>> long body forces split
var list = [1, for (a in b) veryLongThingThatForcesASplit, 3];
<<<
var list = [
1,
for (a in b)
veryLongThingThatForcesASplit,
3
];
>>> split inside body
var list = [1, for (a in b) veryLongThingThatForcesASplit + anotherLongThing, 3];
<<<
var list = [
1,
for (a in b)
veryLongThingThatForcesASplit +
anotherLongThing,
3
];
>>> trailing comma
var list = [for (a in b) 2,];
<<<
var list = [
for (a in b) 2,
];
>>> spread list inside for stays on one line if it fits
var list = [for (a in b) ...[1, 2]];
<<<
var list = [
for (a in b) ...[1, 2]
];
>>> spread list inside for formats like block if it splits
var list = [for (a in b) ...[1, 2,]];
<<<
var list = [
for (a in b) ...[
1,
2,
]
];
>>> a split collection that isn't spread wraps and indents
var list = [for (a in b) [1,2,]];
<<<
var list = [
for (a in b)
[
1,
2,
]
];
>>> lambda inside body
var list = [for (a in b) () { body; }];
<<<
var list = [
for (a in b)
() {
body;
}
];
>>> nested for doesn't split if it fits
var l = [for (a in b) for (c in d) t];
<<<
var l = [for (a in b) for (c in d) t];
>>> split collection before nested for
var list = [for (a in b) for (c in d) longThing];
<<<
var list = [
for (a in b) for (c in d) longThing
];
>>> just split outer for
var list = [for (a in b) for (c in d) longThingThatIsLong];
<<<
var list = [
for (a in b)
for (c in d) longThingThatIsLong
];
>>> split in for-in type
var list = [for (LongGenericTypeName<TypeArg, AnotherTypeArgument> a in b) body];
<<<
var list = [
for (LongGenericTypeName<TypeArg,
AnotherTypeArgument> a in b)
body
];
>>> split in for-in expression
var list = [for (a in sequenceExpression + thatDoesNotFit) body];
<<<
var list = [
for (a in sequenceExpression +
thatDoesNotFit)
body
];
>>> split in for var type
var list = [for (LongGenericTypeName<TypeArg, AnotherTypeArgument> a = 0; a < 1; a++) body];
<<<
var list = [
for (LongGenericTypeName<TypeArg,
AnotherTypeArgument> a = 0;
a < 1;
a++)
body
];
>>> split in for initializer
var list = [for (a = initializerExpression + thatDoesNotFit; a < 1; a++) body];
<<<
var list = [
for (a = initializerExpression +
thatDoesNotFit;
a < 1;
a++)
body
];
>>> split in for condition
var list = [for (a = b; conditionExpression + thatDoesNotFit; a++) body];
<<<
var list = [
for (a = b;
conditionExpression +
thatDoesNotFit;
a++)
body
];
>>> split in for increment
var list = [for (a = b; a < 1; incrementExpression + thatDoesNotFit) body];
<<<
var list = [
for (a = b;
a < 1;
incrementExpression +
thatDoesNotFit)
body
];
Loading