diff --git a/lib/src/argument_list_visitor.dart b/lib/src/argument_list_visitor.dart index c71b9f06..c17264cf 100644 --- a/lib/src/argument_list_visitor.dart +++ b/lib/src/argument_list_visitor.dart @@ -453,7 +453,7 @@ class ArgumentSublist { rule.disableSplitOnInnerRules(); // Tell it to use the rule we've already created. - visitor.beforeBlock(_blocks[argument], this); + visitor.beforeBlock(_blocks[argument], blockRule, previousSplit); } else if (_allArguments.length > 1) { // Edge case: Only bump the nesting if there are multiple arguments. This // lets us avoid spurious indentation in cases like: diff --git a/lib/src/dart_formatter.dart b/lib/src/dart_formatter.dart index afd06268..4a3950cb 100644 --- a/lib/src/dart_formatter.dart +++ b/lib/src/dart_formatter.dart @@ -114,6 +114,9 @@ class DartFormatter { // Parse it. var parser = new Parser(stringSource, errorListener); parser.enableOptionalNewAndConst = true; + parser.enableSetLiterals = true; + parser.enableSpreadCollections = true; + parser.enableControlFlowCollections = true; AstNode node; if (source.isCompilationUnit) { diff --git a/lib/src/nesting_builder.dart b/lib/src/nesting_builder.dart index 2efebb37..544ab57c 100644 --- a/lib/src/nesting_builder.dart +++ b/lib/src/nesting_builder.dart @@ -64,22 +64,11 @@ class NestingBuilder { NestingLevel get currentNesting => _pendingNesting != null ? _pendingNesting : _nesting; - /// The top "nesting level" that represents no expression nesting for the - /// current block. - NestingLevel get blockNesting { - // Walk the nesting levels until we bottom out. - var result = _nesting; - while (result.parent != null) { - result = result.parent; - } - return result; - } - /// Creates a new indentation level [spaces] deeper than the current one. /// /// If omitted, [spaces] defaults to [Indent.block]. void indent([int spaces]) { - if (spaces == null) spaces = Indent.block; + spaces ??= Indent.block; // Indentation should only change outside of nesting. assert(_pendingNesting == null); diff --git a/lib/src/source_visitor.dart b/lib/src/source_visitor.dart index 6aa452a1..85c02e12 100644 --- a/lib/src/source_visitor.dart +++ b/lib/src/source_visitor.dart @@ -153,7 +153,12 @@ class SourceVisitor extends ThrowingAstVisitor { /// Before a block argument is visited, [ArgumentSublist] binds itself to the /// beginning token of each block it controls. When we later visit that /// literal, we use the token to find that association. - final Map _blockArgumentLists = {}; + /// + /// This mapping is also used for spread collection literals that appear + /// inside control flow elements to ensure that when a "then" collection + /// splits, the corresponding "else" one does too. + final Map _blockRules = {}; + final Map _blockPreviousChunks = {}; /// Initialize a newly created visitor to write source code representing /// the visited nodes to the given [writer]. @@ -1387,6 +1392,121 @@ class SourceVisitor extends ThrowingAstVisitor { _visitCombinator(node.keyword, node.hiddenNames); } + void visitIfElement(IfElement node) { + // Wrap the whole thing in a single rule. If a split happens inside the + // condition or the then clause, we want the then and else clauses to split. + builder.startRule(); + + token(node.ifKeyword); + space(); + token(node.leftParenthesis); + visit(node.condition); + token(node.rightParenthesis); + + // If the body of the then or else branch is a spread of a collection + // literal, then we want to format those collections more like blocks than + // like standalone objects. In particular, if both the then and else branch + // are spread collection literals, we want to ensure that they both split + // if either splits. So this: + // + // [ + // if (condition) ...[ + // thenClause + // ] else ...[ + // elseClause + // ] + // ] + // + // And not something like this: + // + // [ + // if (condition) ...[ + // thenClause + // ] else ...[elseClause] + // ] + // + // To do that, if we see that either clause is a spread collection, we + // create a single rule and force both collections to use it. + var thenSpreadBracket = _findSpreadCollectionBracket(node.thenElement); + var elseSpreadBracket = _findSpreadCollectionBracket(node.elseElement); + + if (thenSpreadBracket != null || elseSpreadBracket != null) { + var spreadRule = Rule(); + if (thenSpreadBracket != null) { + beforeBlock(thenSpreadBracket, spreadRule, null); + } + + if (elseSpreadBracket != null) { + beforeBlock(elseSpreadBracket, spreadRule, null); + } + } + + builder.nestExpression(indent: 2, now: true); + + // Treat a spread of a collection literal like a block in an if statement + // and don't split after the "else". + if (thenSpreadBracket != null) { + space(); + } else { + split(); + + // If the then clause is a non-spread collection or lambda, make sure the + // body is indented. + builder.startBlockArgumentNesting(); + } + + visit(node.thenElement); + + if (thenSpreadBracket == null) builder.endBlockArgumentNesting(); + builder.unnest(); + + if (node.elseElement != null) { + if (thenSpreadBracket != null) { + space(); + } else { + split(); + } + + token(node.elseKeyword); + + builder.nestExpression(indent: 2, now: true); + + if (elseSpreadBracket != null) { + space(); + } else { + split(); + + // If the else clause is a non-spread collection or lambda, make sure + // the body is indented. + builder.startBlockArgumentNesting(); + } + + visit(node.elseElement); + + if (elseSpreadBracket == null) builder.endBlockArgumentNesting(); + builder.unnest(); + } + + 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); @@ -1611,10 +1731,12 @@ class SourceVisitor extends ThrowingAstVisitor { } visitMapLiteralEntry(MapLiteralEntry node) { + builder.nestExpression(); visit(node.key); token(node.separator); soloSplit(); visit(node.value); + builder.unnest(); } visitMethodDeclaration(MethodDeclaration node) { @@ -1882,6 +2004,11 @@ class SourceVisitor extends ThrowingAstVisitor { _writeStringLiteral(node.literal); } + visitSpreadElement(SpreadElement node) { + token(node.spreadOperator); + visit(node.expression); + } + visitStringInterpolation(StringInterpolation node) { for (var element in node.elements) { visit(element); @@ -2511,15 +2638,12 @@ class SourceVisitor extends ThrowingAstVisitor { } } - builder.nestExpression(); visit(element); // The comma after the element. if (element.endToken.next.type == TokenType.COMMA) { token(element.endToken.next); } - - builder.unnest(); } builder.endRule(); @@ -2741,14 +2865,17 @@ class SourceVisitor extends ThrowingAstVisitor { void _startLiteralBody(Token leftBracket) { token(leftBracket); - // See if this literal is associated with an argument list that wants to - // handle splitting and indenting it. If not, we'll use a default rule. - var rule; - var argumentChunk; - if (_blockArgumentLists.containsKey(leftBracket)) { - var argumentList = _blockArgumentLists[leftBracket]; - rule = argumentList.blockRule; - argumentChunk = argumentList.previousSplit; + // See if this literal is associated with an argument list or if element + // that wants to handle splitting and indenting it. If not, we'll use a + // default rule. + Rule rule; + if (_blockRules.containsKey(leftBracket)) { + rule = _blockRules[leftBracket]; + } + + Chunk argumentChunk; + if (_blockPreviousChunks.containsKey(leftBracket)) { + argumentChunk = _blockPreviousChunks[leftBracket]; } // Create a rule for whether or not to split the block contents. @@ -2844,12 +2971,15 @@ class SourceVisitor extends ThrowingAstVisitor { } /// Marks the block that starts with [token] as being controlled by - /// [argumentList]. + /// [rule] and following [previousChunk]. /// - /// When the block is visited, [argumentList] will determine the - /// indentation and splitting rule for the block. - void beforeBlock(Token token, ArgumentSublist argumentList) { - _blockArgumentLists[token] = argumentList; + /// When the block is visited, these will determine the indentation and + /// splitting rule for the block. These are used for handling block-like + /// expressions inside argument lists and spread collections inside if + /// elements. + void beforeBlock(Token token, Rule rule, [Chunk previousChunk]) { + _blockRules[token] = rule; + if (previousChunk != null) _blockPreviousChunks[token] = previousChunk; } /// Writes the beginning of a brace-delimited body and handles indenting and diff --git a/test/splitting/list_collection_if.stmt b/test/splitting/list_collection_if.stmt new file mode 100644 index 00000000..7f272a7f --- /dev/null +++ b/test/splitting/list_collection_if.stmt @@ -0,0 +1,217 @@ +40 columns | +>>> split in condition +var list = [1, if (veryLongConditionExpression || anotherPart) 2]; +<<< +var list = [ + 1, + if (veryLongConditionExpression || + anotherPart) + 2 +]; +>>> without else on one line +var list = [1, if (c) 2, 3]; +<<< +var list = [1, if (c) 2, 3]; +>>> with else on one line +var list = [1, if (c) 2 else 2, 3]; +<<< +var list = [1, if (c) 2 else 2, 3]; +>>> split collection before if +var list = [if (c) somewhatLongThingHere]; +<<< +var list = [ + if (c) somewhatLongThingHere +]; +>>> one line in multi-line +var list = [veryLongThingThatForcesASplit, if (c) 2, 3]; +<<< +var list = [ + veryLongThingThatForcesASplit, + if (c) 2, + 3 +]; +>>> one line in multi-line with else +var list = [veryLongThingThatForcesASplit, if (c) 2 else 2, 3]; +<<< +var list = [ + veryLongThingThatForcesASplit, + if (c) 2 else 2, + 3 +]; +>>> long then branch forces split +var list = [1, if (condition) veryLongThingThatForcesASplit, 3]; +<<< +var list = [ + 1, + if (condition) + veryLongThingThatForcesASplit, + 3 +]; +>>> long then branch forces both to split +var list = [1, if (condition) veryLongThingThatForcesASplit else 2, 3]; +<<< +var list = [ + 1, + if (condition) + veryLongThingThatForcesASplit + else + 2, + 3 +]; +>>> long else branch forces both to split +var list = [1, if (condition) 2 else veryLongThingThatForcesASplit, 3]; +<<< +var list = [ + 1, + if (condition) + 2 + else + veryLongThingThatForcesASplit, + 3 +]; +>>> split inside then +var list = [1, if (condition) veryLongThingThatForcesASplit + anotherLongThing, 3]; +<<< +var list = [ + 1, + if (condition) + veryLongThingThatForcesASplit + + anotherLongThing, + 3 +]; +>>> split inside else +var list = [1, if (condition) ok else veryLongThingThatForcesASplit + anotherLongThing, 3]; +<<< +var list = [ + 1, + if (condition) + ok + else + veryLongThingThatForcesASplit + + anotherLongThing, + 3 +]; +>>> trailing comma +var list = [if (c) 2,]; +<<< +var list = [ + if (c) 2, +]; +>>> spread list inside if stays on one line if it fits +var list = [if (c) ...[1, 2]]; +<<< +var list = [ + if (c) ...[1, 2] +]; +>>> spread list inside if formats like block if it splits +var list = [if (c) ...[1, 2,]]; +<<< +var list = [ + if (c) ...[ + 1, + 2, + ] +]; +>>> both spreads split if then must +var list = [if (c) ...[1, 2,] else ...[1, 2]]; +<<< +var list = [ + if (c) ...[ + 1, + 2, + ] else ...[ + 1, + 2 + ] +]; +>>> both spreads split if else must +var list = [if (c) ...[1, 2] else ...[1, 2,]]; +<<< +var list = [ + if (c) ...[ + 1, + 2 + ] else ...[ + 1, + 2, + ] +]; +>>> a split collection that isn't spread wraps and indents +var list = [if (c) [1,2,]]; +<<< +var list = [ + if (c) + [ + 1, + 2, + ] +]; +>>> a split collection that isn't spread wraps and indents +var list = [if (c) [1,2,] else thing]; +<<< +var list = [ + if (c) + [ + 1, + 2, + ] + else + thing +]; +>>> a split collection that isn't spread wraps and indents +var list = [if (c) thing else [1,2,]]; +<<< +var list = [ + if (c) + thing + else + [ + 1, + 2, + ] +]; +>>> lambda inside then +var list = [if (c) () { body; }]; +<<< +var list = [ + if (c) + () { + body; + } +]; +>>> lambda inside else +var list = [if (c) thing else () { body; }]; +<<< +var list = [ + if (c) + thing + else + () { + body; + } +]; +>>> nested if doesn't split if it fits +var list = [if (c) if (d) thing]; +<<< +var list = [if (c) if (d) thing]; +>>> split collection before nested if +var list = [if (c) if (d) fairlyLongThingHere]; +<<< +var list = [ + if (c) if (d) fairlyLongThingHere +]; +>>> just split outer if +var list = [if (condition) if (another) longThingHereThatIsLong]; +<<< +var list = [ + if (condition) + if (another) longThingHereThatIsLong +]; +>>> split inside condition +var list = [if (veryLongCondition + thatNeedsToSplit) thing]; +<<< +var list = [ + if (veryLongCondition + + thatNeedsToSplit) + thing +]; \ No newline at end of file diff --git a/test/splitting/lists.stmt b/test/splitting/lists.stmt index 86698f64..bb43056f 100644 --- a/test/splitting/lists.stmt +++ b/test/splitting/lists.stmt @@ -167,4 +167,58 @@ element, element +]; +>>> a spread list literal splits an outer list even if it fits +var list = [1, ...[2, 3], 4]; +<<< +var list = [ + 1, + ...[2, 3], + 4 +]; +>>> spread empty list does not force outer split +var list = [1, ...[], 4]; +<<< +var list = [1, ...[], 4]; +>>> split inside spread expression +var list = [1, ...some + very + long + spread + expression, 3]; +<<< +var list = [ + 1, + ...some + + very + + long + + spread + + expression, + 3 +]; +>>> spread cascade +var list = [1, ...thing..cascade()..another(), 4]; +<<< +var list = [ + 1, + ...thing + ..cascade() + ..another(), + 4 +]; +>>> spread lambda +var list = [1, ...() { body; }, 4]; +<<< +var list = [ + 1, + ...() { + body; + }, + 4 +]; +>>> spread immediately invoked lambda +var list = [1, ...() sync* { yield thing; }(), 4]; +<<< +var list = [ + 1, + ...() sync* { + yield thing; + }(), + 4 ]; \ No newline at end of file diff --git a/test/splitting/map_collection_if.stmt b/test/splitting/map_collection_if.stmt new file mode 100644 index 00000000..ef4758af --- /dev/null +++ b/test/splitting/map_collection_if.stmt @@ -0,0 +1,203 @@ +40 columns | +>>> split in condition +var map = {1: 1, if (veryLongConditionExpression || anotherPart) 2: 2}; +<<< +var map = { + 1: 1, + if (veryLongConditionExpression || + anotherPart) + 2: 2 +}; +>>> without else on one line +var map = {1: 1, if (c) 2: 2, 3: 3}; +<<< +var map = {1: 1, if (c) 2: 2, 3: 3}; +>>> with else on one line +var map = {1: 1, if (c) 2: 2 else 2: 2}; +<<< +var map = {1: 1, if (c) 2: 2 else 2: 2}; +>>> split collection before if +var map = {if (c) somewhatLongThingHere: 1}; +<<< +var map = { + if (c) somewhatLongThingHere: 1 +}; +>>> one line in multi-line +var map = {veryLongThingThatForcesASplit, if (c) 2: 2, 3: 3}; +<<< +var map = { + veryLongThingThatForcesASplit, + if (c) 2: 2, + 3: 3 +}; +>>> one line in multi-line with else +var map = {veryLongThingThatForcesASplit: 1, if (c) 2: 2 else 2: 2, 3: 3}; +<<< +var map = { + veryLongThingThatForcesASplit: 1, + if (c) 2: 2 else 2: 2, + 3: 3 +}; +>>> long then branch forces split +var map = {1: 1, if (condition) veryLongThingThatForcesASplit: 2, 3: 3}; +<<< +var map = { + 1: 1, + if (condition) + veryLongThingThatForcesASplit: 2, + 3: 3 +}; +>>> long then branch forces both to split +var map = {1: 1, if (condition) veryLongThingThatForcesASplit: 2 else 2: 2, 3: 3}; +<<< +var map = { + 1: 1, + if (condition) + veryLongThingThatForcesASplit: 2 + else + 2: 2, + 3: 3 +}; +>>> long else branch forces both to split +var map = {1: 1, if (condition) 2: 2 else veryLongThingThatForcesASplit: 2, 3: 3}; +<<< +var map = { + 1: 1, + if (condition) + 2: 2 + else + veryLongThingThatForcesASplit: 2, + 3: 3 +}; +>>> trailing comma +var map = {if (c) 2: 2,}; +<<< +var map = { + if (c) 2: 2, +}; +>>> spread list inside if stays on one line if it fits +var map = {if (c) ...{1: 1, 2: 2}}; +<<< +var map = { + if (c) ...{1: 1, 2: 2} +}; +>>> spread list inside if formats like block if it splits +var map = {if (c) ...{1: 1, 2: 2,}}; +<<< +var map = { + if (c) ...{ + 1: 1, + 2: 2, + } +}; +>>> both spreads split if then must +var map = {if (c) ...{1: 1, 2: 2,} else ...{1: 1, 2: 2}}; +<<< +var map = { + if (c) ...{ + 1: 1, + 2: 2, + } else ...{ + 1: 1, + 2: 2 + } +}; +>>> both spreads split if else must +var map = {if (c) ...{1: 1, 2: 2} else ...{1: 1, 2: 2,}}; +<<< +var map = { + if (c) ...{ + 1: 1, + 2: 2 + } else ...{ + 1: 1, + 2: 2, + } +}; +>>> a split collection that isn't spread wraps and indents +var map = {if (c) {1: 1,2: 2,}}; +<<< +var map = { + if (c) + { + 1: 1, + 2: 2, + } +}; +>>> a split collection that isn't spread wraps and indents +var map = {if (c) {1: 1,2: 2,} else thing: 3}; +<<< +var map = { + if (c) + { + 1: 1, + 2: 2, + } + else + thing: 3 +}; +>>> a split collection that isn't spread wraps and indents +var map = {if (c) thing: 0 else {1: 1,2: 2,}}; +<<< +var map = { + if (c) + thing: 0 + else + { + 1: 1, + 2: 2, + } +}; +>>> lambda inside then +var map = {if (c) k: () { body; }}; +<<< +var map = { + if (c) + k: () { + body; + } +}; +>>> lambda inside else +var map = {if (c) thing: 1 else k: () { body; }}; +<<< +var map = { + if (c) + thing: 1 + else + k: () { + body; + } +}; +>>> nested if doesn't split if it fits +var map = {if (c) if (d) thing: 1}; +<<< +var map = {if (c) if (d) thing: 1}; +>>> split collection before nested if +var map = {if (c) if (d) fairlyLongThingHere: 1}; +<<< +var map = { + if (c) if (d) fairlyLongThingHere: 1 +}; +>>> just split outer if +var map = {if (condition) if (another) longThingThatIsLong: 1}; +<<< +var map = { + if (condition) + if (another) longThingThatIsLong: 1 +}; +>>> split inside condition +var map = {if (veryLongCondition + thatNeedsToSplit) thing: 1}; +<<< +var map = { + if (veryLongCondition + + thatNeedsToSplit) + thing: 1 +}; +>>> split entry inside if +var map = { if (condition) veryLongKeyExpression: andAVeryLongValueExpression}; +<<< +var map = { + if (condition) + veryLongKeyExpression: + andAVeryLongValueExpression +}; \ No newline at end of file diff --git a/test/splitting/maps.stmt b/test/splitting/maps.stmt index 31da5ab7..2a12eb2a 100644 --- a/test/splitting/maps.stmt +++ b/test/splitting/maps.stmt @@ -159,4 +159,34 @@ value var map = { // comment a: value +}; +>>> spread cascade +var map = {1: 1, ...thing..cascade()..another(), 4: 4}; +<<< +var map = { + 1: 1, + ...thing + ..cascade() + ..another(), + 4: 4 +}; +>>> spread lambda +var map = {1: 1, ...() { body; }, 4: 4}; +<<< +var map = { + 1: 1, + ...() { + body; + }, + 4: 4 +}; +>>> spread immediately invoked lambda +var map = {1: 1, ...() sync* { yield thing; }(), 4: 4}; +<<< +var map = { + 1: 1, + ...() sync* { + yield thing; + }(), + 4: 4 }; \ No newline at end of file diff --git a/test/splitting/set_collection_if.stmt b/test/splitting/set_collection_if.stmt new file mode 100644 index 00000000..86375adf --- /dev/null +++ b/test/splitting/set_collection_if.stmt @@ -0,0 +1,195 @@ +40 columns | +>>> split in condition +var set = {1, if (veryLongConditionExpression || anotherPart) 2}; +<<< +var set = { + 1, + if (veryLongConditionExpression || + anotherPart) + 2 +}; +>>> without else on one line +var set = {1, if (c) 2, 3}; +<<< +var set = {1, if (c) 2, 3}; +>>> with else on one line +var set = {1, if (c) 2 else 2, 3}; +<<< +var set = {1, if (c) 2 else 2, 3}; +>>> split collection before if +var set = {if (c) somewhatLongThingHere}; +<<< +var set = { + if (c) somewhatLongThingHere +}; +>>> one line in multi-line +var set = {veryLongThingThatForcesASplit, if (c) 2, 3}; +<<< +var set = { + veryLongThingThatForcesASplit, + if (c) 2, + 3 +}; +>>> one line in multi-line with else +var set = {veryLongThingThatForcesASplit, if (c) 2 else 2, 3}; +<<< +var set = { + veryLongThingThatForcesASplit, + if (c) 2 else 2, + 3 +}; +>>> long then branch forces split +var set = {1, if (condition) veryLongThingThatForcesASplit, 3}; +<<< +var set = { + 1, + if (condition) + veryLongThingThatForcesASplit, + 3 +}; +>>> long then branch forces both to split +var set = {1, if (condition) veryLongThingThatForcesASplit else 2, 3}; +<<< +var set = { + 1, + if (condition) + veryLongThingThatForcesASplit + else + 2, + 3 +}; +>>> long else branch forces both to split +var set = {1, if (condition) 2 else veryLongThingThatForcesASplit, 3}; +<<< +var set = { + 1, + if (condition) + 2 + else + veryLongThingThatForcesASplit, + 3 +}; +>>> trailing comma +var set = {if (c) 2,}; +<<< +var set = { + if (c) 2, +}; +>>> spread list inside if stays on one line if it fits +var set = {if (c) ...{1, 2}}; +<<< +var set = { + if (c) ...{1, 2} +}; +>>> spread list inside if formats like block if it splits +var set = {if (c) ...{1, 2,}}; +<<< +var set = { + if (c) ...{ + 1, + 2, + } +}; +>>> both spreads split if then must +var set = {if (c) ...{1, 2,} else ...{1, 2}}; +<<< +var set = { + if (c) ...{ + 1, + 2, + } else ...{ + 1, + 2 + } +}; +>>> both spreads split if else must +var set = {if (c) ...{1, 2} else ...{1, 2,}}; +<<< +var set = { + if (c) ...{ + 1, + 2 + } else ...{ + 1, + 2, + } +}; +>>> a split collection that isn't spread wraps and indents +var set = {if (c) {1,2,}}; +<<< +var set = { + if (c) + { + 1, + 2, + } +}; +>>> a split collection that isn't spread wraps and indents +var set = {if (c) {1,2,} else thing}; +<<< +var set = { + if (c) + { + 1, + 2, + } + else + thing +}; +>>> a split collection that isn't spread wraps and indents +var set = {if (c) thing else {1,2,}}; +<<< +var set = { + if (c) + thing + else + { + 1, + 2, + } +}; +>>> lambda inside then +var set = {if (c) () { body; }}; +<<< +var set = { + if (c) + () { + body; + } +}; +>>> lambda inside else +var set = {if (c) thing else () { body; }}; +<<< +var set = { + if (c) + thing + else + () { + body; + } +}; +>>> nested if doesn't split if it fits +var set = {if (c) if (d) thing}; +<<< +var set = {if (c) if (d) thing}; +>>> split collection before nested if +var set = {if (c) if (d) fairlyLongThingHere}; +<<< +var set = { + if (c) if (d) fairlyLongThingHere +}; +>>> just split outer if +var set = {if (condition) if (another) longThingHereThatIsLong}; +<<< +var set = { + if (condition) + if (another) longThingHereThatIsLong +}; +>>> split inside condition +var set = {if (veryLongCondition + thatNeedsToSplit) thing}; +<<< +var set = { + if (veryLongCondition + + thatNeedsToSplit) + thing +}; \ No newline at end of file diff --git a/test/splitting/sets.stmt b/test/splitting/sets.stmt index 43e7c3fb..0ddcb412 100644 --- a/test/splitting/sets.stmt +++ b/test/splitting/sets.stmt @@ -174,4 +174,34 @@ var set = { element, element +}; +>>> spread cascade +var set = {1, ...thing..cascade()..another(), 4}; +<<< +var set = { + 1, + ...thing + ..cascade() + ..another(), + 4 +}; +>>> spread lambda +var set = {1, ...() { body; }, 4}; +<<< +var set = { + 1, + ...() { + body; + }, + 4 +}; +>>> spread immediately invoked lambda +var set = {1, ...() sync* { yield thing; }(), 4}; +<<< +var set = { + 1, + ...() sync* { + yield thing; + }(), + 4 }; \ No newline at end of file diff --git a/test/whitespace/collections.stmt b/test/whitespace/collections.stmt new file mode 100644 index 00000000..bcf71199 --- /dev/null +++ b/test/whitespace/collections.stmt @@ -0,0 +1,59 @@ +40 columns | +>>> empty map literal (dartbug.com/16382) +var m = { }; +<<< +var m = {}; +>>> +var m = {}; +<<< +var m = {}; +>>> generic map literal +< int,int >{ }; +<<< +{}; +>>> generic set literal +< int >{ }; +<<< +{}; +>>> list spread +var list = [ ... a,...b, ... +c]; +<<< +var list = [...a, ...b, ...c]; +>>> map spread +var map = { ... a,...b,1:2, ... +c}; +<<< +var map = {...a, ...b, 1: 2, ...c}; +>>> set spread +var set = { ... a,...b, 1, ... +c}; +<<< +var set = {...a, ...b, 1, ...c}; +>>> list null aware spread +var list = [ ...? a,...?b, ...? +c]; +<<< +var list = [...?a, ...?b, ...?c]; +>>> map null aware spread +var map = { ...? a,...?b,1:2, ...? +c}; +<<< +var map = {...?a, ...?b, 1: 2, ...?c}; +>>> set null aware spread +var set = { ...? a,...?b, 1, ...? +c}; +<<< +var set = {...?a, ...?b, 1, ...?c}; +>>> if +var list = [ if ( c ) 1 ,]; +<<< +var list = [ + if (c) 1, +]; +>>> if else +var list = [ if ( c ) 1 else 2 ,]; +<<< +var list = [ + if (c) 1 else 2, +]; \ No newline at end of file diff --git a/test/whitespace/expressions.stmt b/test/whitespace/expressions.stmt index c1ed6b29..10980d5e 100644 --- a/test/whitespace/expressions.stmt +++ b/test/whitespace/expressions.stmt @@ -32,22 +32,6 @@ x && y; <<< x && y; ->>> empty map literal (dartbug.com/16382) -var m = { }; -<<< -var m = {}; ->>> -var m = {}; -<<< -var m = {}; ->>> generic map literal -< int,int >{ }; -<<< -{}; ->>> generic set literal -< int >{ }; -<<< -{}; >>> unqualified symbol var x = #foo; <<<