Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Unified Diff: packages/dart_style/lib/src/source_visitor.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/dart_style/lib/src/rule/type_argument.dart ('k') | packages/dart_style/lib/src/whitespace.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/dart_style/lib/src/source_visitor.dart
diff --git a/packages/dart_style/lib/src/source_visitor.dart b/packages/dart_style/lib/src/source_visitor.dart
index 524db2ecf8fe427478953bda1181ddf9019ffd19..a34b36789e70b91f0226e75fd12f41c67e349361 100644
--- a/packages/dart_style/lib/src/source_visitor.dart
+++ b/packages/dart_style/lib/src/source_visitor.dart
@@ -15,6 +15,7 @@ import 'chunk_builder.dart';
import 'dart_formatter.dart';
import 'rule/argument.dart';
import 'rule/combinator.dart';
+import 'rule/metadata.dart';
import 'rule/rule.dart';
import 'rule/type_argument.dart';
import 'source_code.dart';
@@ -47,15 +48,6 @@ class SourceVisitor implements AstVisitor {
/// This is calculated and cached by [_findSelectionEnd].
int _selectionEnd;
- /// The rule that should be used for the contents of a literal body that are
- /// about to be written.
- ///
- /// This is set by [visitArgumentList] to ensure that all block arguments
- /// share a rule.
- ///
- /// If `null`, a literal body creates its own rule.
- Rule _nextLiteralBodyRule;
-
/// A stack that tracks forcing nested collections to split.
///
/// Each entry corresponds to a collection currently being visited and the
@@ -68,6 +60,29 @@ class SourceVisitor implements AstVisitor {
/// split.
final List<bool> _collectionSplits = [];
+ /// The stack of current rules for handling parameter metadata.
+ ///
+ /// Each time a parameter (or type parameter) list is begun, a single rule
+ /// for all of the metadata annotations on parameters in that list is pushed
+ /// onto this stack. We reuse this rule for all annotations so that they split
+ /// in unison.
+ final List<MetadataRule> _metadataRules = [];
+
+ /// The mapping for collection literals that are managed by the argument
+ /// list that contains them.
+ ///
+ /// When a collection literal appears inside an [ArgumentSublist], the
+ /// argument list provides a rule for the body to split to ensure that all
+ /// collections split in unison. It also tracks the chunk before the
+ /// argument that determines whether or not the collection body is indented
+ /// like an expression or a statement.
+ ///
+ /// Before a collection literal argument is visited, [ArgumentSublist] binds
+ /// itself to the left bracket token of each collection literal it controls.
+ /// When we later visit that literal, we use the token to find that
+ /// association.
+ final Map<Token, ArgumentSublist> _collectionArgumentLists = {};
+
/// Initialize a newly created visitor to write source code representing
/// the visited nodes to the given [writer].
SourceVisitor(this._formatter, this._lineInfo, this._source) {
@@ -170,7 +185,17 @@ class SourceVisitor implements AstVisitor {
visitBinaryExpression(BinaryExpression node) {
builder.startSpan();
- builder.nestExpression();
+
+ // If a binary operator sequence appears immediately after a `=>`, don't
+ // add an extra level of nesting. Instead, let the subsequent operands line
+ // up with the first, as in:
+ //
+ // method() =>
+ // argument &&
+ // argument &&
+ // argument;
+ var isArrowBody = node.parent is ExpressionFunctionBody;
+ if (!isArrowBody) builder.nestExpression();
// Start lazily so we don't force the operator to split if a line comment
// appears before the first operand.
@@ -202,12 +227,20 @@ class SourceVisitor implements AstVisitor {
builder.endBlockArgumentNesting();
- builder.unnest();
+ if (!isArrowBody) builder.unnest();
builder.endSpan();
builder.endRule();
}
visitBlock(Block node) {
+ // Don't allow splitting in an empty block.
+ if (node.statements.isEmpty &&
+ node.rightBracket.precedingComments == null) {
+ token(node.leftBracket);
+ token(node.rightBracket);
+ return;
+ }
+
// For a block that is not a function body, just bump the indentation and
// keep it in the current block.
if (node.parent is! BlockFunctionBody) {
@@ -284,7 +317,7 @@ class SourceVisitor implements AstVisitor {
visitNodes(node.cascadeSections, between: zeroSplit);
builder.endRule();
} else {
- builder.startRule(new HardSplitRule());
+ builder.startRule(new Rule.hard());
zeroSplit();
visitNodes(node.cascadeSections, between: zeroSplit);
builder.endRule();
@@ -515,10 +548,15 @@ class SourceVisitor implements AstVisitor {
// ":" if the parameters and initialization list don't all fit on one line.
builder.startRule();
+ // If the redirecting constructor happens to wrap, we want to make sure
+ // the parameter list gets more deeply indented.
+ if (node.redirectedConstructor != null) builder.nestExpression();
+
_visitBody(node.parameters, node.body, () {
// Check for redirects or initializer lists.
if (node.redirectedConstructor != null) {
_visitConstructorRedirects(node);
+ builder.unnest();
} else if (node.initializers.isNotEmpty) {
_visitConstructorInitializers(node);
}
@@ -526,7 +564,8 @@ class SourceVisitor implements AstVisitor {
}
void _visitConstructorRedirects(ConstructorDeclaration node) {
- token(node.separator /* = */, before: space, after: space);
+ token(node.separator /* = */, before: space);
+ soloSplit();
visitCommaSeparatedNodes(node.initializers);
visit(node.redirectedConstructor);
}
@@ -600,7 +639,7 @@ class SourceVisitor implements AstVisitor {
if (node.separator.type == TokenType.EQ) space();
token(node.separator);
- soloSplit(Cost.assignment);
+ soloSplit(_assignmentCost(node.defaultValue));
visit(node.defaultValue);
builder.unnest();
@@ -609,18 +648,22 @@ class SourceVisitor implements AstVisitor {
}
visitDoStatement(DoStatement node) {
- _simpleStatement(node, () {
- token(node.doKeyword);
- space();
- visit(node.body);
- space();
- token(node.whileKeyword);
- space();
- token(node.leftParenthesis);
- soloZeroSplit();
- visit(node.condition);
- token(node.rightParenthesis);
- });
+ builder.nestExpression();
+ token(node.doKeyword);
+ space();
+ builder.unnest(now: false);
+ visit(node.body);
+
+ builder.nestExpression();
+ space();
+ token(node.whileKeyword);
+ space();
+ token(node.leftParenthesis);
+ soloZeroSplit();
+ visit(node.condition);
+ token(node.rightParenthesis);
+ token(node.semicolon);
+ builder.unnest();
}
visitDoubleLiteral(DoubleLiteral node) {
@@ -682,7 +725,10 @@ class SourceVisitor implements AstVisitor {
// Split after the "=>", using the rule created before the parameters
// by _visitBody().
split();
- builder.endRule();
+
+ // If the body is a binary operator expression, then we want to force the
+ // split at `=>` if the operators split. See visitBinaryExpression().
+ if (node.expression is! BinaryExpression) builder.endRule();
if (_isInLambda(node)) builder.endSpan();
@@ -692,6 +738,8 @@ class SourceVisitor implements AstVisitor {
builder.endSpan();
builder.endBlockArgumentNesting();
+ if (node.expression is BinaryExpression) builder.endRule();
+
token(node.semicolon);
}
@@ -744,9 +792,9 @@ class SourceVisitor implements AstVisitor {
space();
visit(node.iterable);
token(node.rightParenthesis);
- space();
- visit(node.body);
- builder.unnest();
+ builder.unnest(now: false);
+
+ _visitLoopBody(node.body);
}
visitFormalParameterList(FormalParameterList node) {
@@ -771,6 +819,8 @@ class SourceVisitor implements AstVisitor {
builder.nestExpression();
token(node.leftParenthesis);
+ _metadataRules.add(new MetadataRule());
+
var rule;
if (requiredParams.isNotEmpty) {
if (requiredParams.length > 1) {
@@ -779,6 +829,8 @@ class SourceVisitor implements AstVisitor {
rule = new SinglePositionalRule(null);
}
+ _metadataRules.last.bindPositionalRule(rule);
+
builder.startRule(rule);
if (_isInLambda(node)) {
// Don't allow splitting before the first argument (i.e. right after
@@ -806,13 +858,17 @@ class SourceVisitor implements AstVisitor {
}
if (optionalParams.isNotEmpty) {
- var namedRule = new NamedRule(null);
+ var namedRule = new NamedRule(null, 0, 0);
if (rule != null) rule.setNamedArgsRule(namedRule);
+ _metadataRules.last.bindNamedRule(namedRule);
+
builder.startRule(namedRule);
- namedRule
- .beforeArguments(builder.split(space: requiredParams.isNotEmpty));
+ // Make sure multi-line default values are indented.
+ builder.startBlockArgumentNesting();
+
+ namedRule.beforeArgument(builder.split(space: requiredParams.isNotEmpty));
// "[" or "{" for optional parameters.
token(node.leftDelimiter);
@@ -822,15 +878,18 @@ class SourceVisitor implements AstVisitor {
// Write the trailing comma.
if (param != node.parameters.last) token(param.endToken.next);
- if (param != optionalParams.last) split();
+ if (param != optionalParams.last) namedRule.beforeArgument(split());
}
+ builder.endBlockArgumentNesting();
builder.endRule();
// "]" or "}" for optional parameters.
token(node.rightDelimiter);
}
+ _metadataRules.removeLast();
+
token(node.rightParenthesis);
builder.unnest();
}
@@ -847,9 +906,9 @@ class SourceVisitor implements AstVisitor {
if (node.initialization != null) {
visit(node.initialization);
} else if (node.variables != null) {
- // Indent split variables more so they aren't at the same level
+ // Nest split variables more so they aren't at the same level
// as the rest of the loop clauses.
- builder.indent(Indent.loopVariable);
+ builder.nestExpression();
// Allow the variables to stay unsplit even if the clauses split.
builder.startRule();
@@ -864,7 +923,7 @@ class SourceVisitor implements AstVisitor {
});
builder.endRule();
- builder.unindent();
+ builder.unnest();
}
token(node.leftSeparator);
@@ -890,21 +949,11 @@ class SourceVisitor implements AstVisitor {
builder.endRule();
builder.unnest();
- // The body.
- if (node.body is! EmptyStatement) space();
- visit(node.body);
+ _visitLoopBody(node.body);
}
visitFunctionDeclaration(FunctionDeclaration node) {
- visitMemberMetadata(node.metadata);
-
- builder.nestExpression();
- modifier(node.externalKeyword);
- visit(node.returnType, after: space);
- modifier(node.propertyKeyword);
- visit(node.name);
- visit(node.functionExpression);
- builder.unnest();
+ _visitMemberDeclaration(node, node.functionExpression);
}
visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
@@ -956,10 +1005,35 @@ class SourceVisitor implements AstVisitor {
token(node.leftParenthesis);
visit(node.condition);
token(node.rightParenthesis);
+ builder.unnest(now: false);
- space();
- visit(node.thenStatement);
- builder.unnest();
+ visitClause(Statement clause) {
+ if (clause is Block || clause is IfStatement) {
+ space();
+ visit(clause);
+ } else {
+ // Allow splitting in an expression-bodied if even though it's against
+ // the style guide. Since we can't fix the code itself to follow the
+ // style guide, we should at least format it as well as we can.
+ builder.nestExpression(indent: 2, now: true);
+ builder.startRule();
+
+ // If there is an else clause, always split before both the then and
+ // else statements.
+ if (node.elseStatement != null) {
+ builder.writeWhitespace(Whitespace.nestedNewline);
+ } else {
+ split();
+ }
+
+ visit(clause);
+
+ builder.endRule();
+ builder.unnest();
+ }
+ }
+
+ visitClause(node.thenStatement);
if (node.elseStatement != null) {
if (node.thenStatement is Block) {
@@ -972,8 +1046,7 @@ class SourceVisitor implements AstVisitor {
}
token(node.elseKeyword);
- space();
- visit(node.elseStatement);
+ visitClause(node.elseStatement);
}
}
@@ -1012,8 +1085,18 @@ class SourceVisitor implements AstVisitor {
visit(node.target);
}
+ finishIndexExpression(node);
+
+ builder.unnest();
+ }
+
+ /// Visit the index part of [node], excluding the target.
+ ///
+ /// Called by [CallChainVisitor] to handle index expressions in the middle of
+ /// call chains.
+ void finishIndexExpression(IndexExpression node) {
if (node.target is IndexExpression) {
- // Corner case: On a chain of [] accesses, allow splitting between them.
+ // Edge case: On a chain of [] accesses, allow splitting between them.
// Produces nicer output in cases like:
//
// someJson['property']['property']['property']['property']...
@@ -1026,14 +1109,15 @@ class SourceVisitor implements AstVisitor {
visit(node.index);
token(node.rightBracket);
builder.endSpan();
- builder.unnest();
}
visitInstanceCreationExpression(InstanceCreationExpression node) {
builder.startSpan();
token(node.keyword);
space();
+ builder.startSpan(Cost.constructorName);
visit(node.constructorName);
+ builder.endSpan();
visit(node.argumentList);
builder.endSpan();
}
@@ -1112,16 +1196,7 @@ class SourceVisitor implements AstVisitor {
}
visitMethodDeclaration(MethodDeclaration node) {
- visitMemberMetadata(node.metadata);
-
- modifier(node.externalKeyword);
- modifier(node.modifierKeyword);
- visit(node.returnType, after: space);
- modifier(node.propertyKeyword);
- modifier(node.operatorKeyword);
- visit(node.name);
-
- _visitBody(node.parameters, node.body);
+ _visitMemberDeclaration(node, node);
}
visitMethodInvocation(MethodInvocation node) {
@@ -1149,7 +1224,16 @@ class SourceVisitor implements AstVisitor {
builder.nestExpression();
builder.startSpan();
visit(node.name);
- visit(node.expression, before: soloSplit);
+
+ // Don't allow a split between a name and a collection. Instead, we want
+ // the collection itself to split, or to split before the argument.
+ if (node.expression is ListLiteral || node.expression is MapLiteral) {
+ space();
+ } else {
+ soloSplit();
+ }
+
+ visit(node.expression);
builder.endSpan();
builder.unnest();
}
@@ -1184,6 +1268,8 @@ class SourceVisitor implements AstVisitor {
}
visitPartDirective(PartDirective node) {
+ visitDeclarationMetadata(node.metadata);
+
_simpleStatement(node, () {
token(node.keyword);
space();
@@ -1192,6 +1278,8 @@ class SourceVisitor implements AstVisitor {
}
visitPartOfDirective(PartOfDirective node) {
+ visitDeclarationMetadata(node.metadata);
+
_simpleStatement(node, () {
token(node.keyword);
space();
@@ -1207,9 +1295,7 @@ class SourceVisitor implements AstVisitor {
}
visitPrefixedIdentifier(PrefixedIdentifier node) {
- visit(node.prefix);
- token(node.period);
- visit(node.identifier);
+ new CallChainVisitor(this, node).visit();
}
visitPrefixExpression(PrefixExpression node) {
@@ -1357,6 +1443,7 @@ class SourceVisitor implements AstVisitor {
token(node.rightParenthesis);
space();
token(node.leftBracket);
+ builder.unnest();
builder.indent();
newline();
@@ -1365,7 +1452,6 @@ class SourceVisitor implements AstVisitor {
builder.unindent();
newline();
});
- builder.unnest();
}
visitSymbolLiteral(SymbolLiteral node) {
@@ -1425,7 +1511,11 @@ class SourceVisitor implements AstVisitor {
}
visitTypeParameterList(TypeParameterList node) {
+ _metadataRules.add(new MetadataRule());
+
_visitGenericList(node.leftBracket, node.rightBracket, node.typeParameters);
+
+ _metadataRules.removeLast();
}
visitVariableDeclaration(VariableDeclaration node) {
@@ -1437,8 +1527,14 @@ class SourceVisitor implements AstVisitor {
visitVariableDeclarationList(VariableDeclarationList node) {
visitDeclarationMetadata(node.metadata);
+
+ // Allow but try to avoid splitting between the type and name.
+ builder.startSpan();
+
modifier(node.keyword);
- visit(node.type, after: space);
+ visit(node.type, after: soloSplit);
+
+ builder.endSpan();
// Use a single rule for all of the variables. If there are multiple
// declarations, we will try to keep them all on one line. If that isn't
@@ -1463,9 +1559,9 @@ class SourceVisitor implements AstVisitor {
soloZeroSplit();
visit(node.condition);
token(node.rightParenthesis);
- if (node.body is! EmptyStatement) space();
- visit(node.body);
- builder.unnest();
+ builder.unnest(now: false);
+
+ _visitLoopBody(node.body);
}
visitWithClause(WithClause node) {
@@ -1524,11 +1620,29 @@ class SourceVisitor implements AstVisitor {
/// These are always on the same line as the parameter.
void visitParameterMetadata(
NodeList<Annotation> metadata, void visitParameter()) {
+ if (metadata == null || metadata.isEmpty) {
+ visitParameter();
+ return;
+ }
+
// Split before all of the annotations or none.
- builder.startRule();
- visitNodes(metadata, between: split, after: split);
+ builder.startLazyRule(_metadataRules.last);
+
+ visitNodes(metadata, between: split, after: () {
+ // Don't nest until right before the last metadata. Ensures we only
+ // indent the parameter and not any of the metadata:
+ //
+ // function(
+ // @LongAnnotation
+ // @LongAnnotation
+ // indentedParameter) {}
+ builder.nestExpression(now: true);
+ split();
+ });
visitParameter();
+ builder.unnest();
+
// Wrap the rule around the parameter too. If it splits, we want to force
// the annotations to split as well.
builder.endRule();
@@ -1543,7 +1657,7 @@ class SourceVisitor implements AstVisitor {
void _visitAssignment(Token equalsOperator, Expression rightHandSide) {
space();
token(equalsOperator);
- soloSplit(Cost.assignment);
+ soloSplit(_assignmentCost(rightHandSide));
builder.startSpan();
visit(rightHandSide);
builder.endSpan();
@@ -1577,6 +1691,37 @@ class SourceVisitor implements AstVisitor {
builder.endRule();
}
+ /// Visits a top-level function or method declaration.
+ ///
+ /// The two AST node types are very similar but, alas, share no common
+ /// interface type in analyzer, hence the dynamic typing.
+ void _visitMemberDeclaration(
+ /* FunctionDeclaration|MethodDeclaration */ node,
+ /* FunctionExpression|MethodDeclaration */ function) {
+ visitMemberMetadata(node.metadata);
+
+ // Nest the signature in case we have to split between the return type and
+ // name.
+ builder.nestExpression();
+ builder.startSpan();
+ modifier(node.externalKeyword);
+ if (node is MethodDeclaration) modifier(node.modifierKeyword);
+ visit(node.returnType, after: soloSplit);
+ modifier(node.propertyKeyword);
+ if (node is MethodDeclaration) modifier(node.operatorKeyword);
+ visit(node.name);
+ builder.endSpan();
+
+ // If the body is a block, we need to exit any nesting first. If it's an
+ // expression, we want to wrap the nesting around that so that the body
+ // gets nested farther.
+ if (function.body is! ExpressionFunctionBody) builder.unnest();
+
+ _visitBody(function.parameters, function.body);
+
+ if (function.body is ExpressionFunctionBody) builder.unnest();
+ }
+
/// Visit the given function [parameters] followed by its [body], printing a
/// space before it if it's not empty.
///
@@ -1611,16 +1756,15 @@ class SourceVisitor implements AstVisitor {
builder.nestExpression();
// This rule is ended by visitExpressionFunctionBody().
- builder.startLazyRule(new SimpleRule(cost: Cost.arrow));
+ builder.startLazyRule(new Rule(Cost.arrow));
}
if (parameters != null) {
builder.nestExpression();
-
visit(parameters);
- if (afterParameters != null) afterParameters();
-
builder.unnest();
+
+ if (afterParameters != null) afterParameters();
}
visit(body);
@@ -1628,6 +1772,29 @@ class SourceVisitor implements AstVisitor {
if (body is ExpressionFunctionBody) builder.unnest();
}
+ /// Visits the body statement of a `for` or `for in` loop.
+ void _visitLoopBody(Statement body) {
+ if (body is EmptyStatement) {
+ // No space before the ";".
+ visit(body);
+ } else if (body is Block) {
+ space();
+ visit(body);
+ } else {
+ // Allow splitting in an expression-bodied for even though it's against
+ // the style guide. Since we can't fix the code itself to follow the
+ // style guide, we should at least format it as well as we can.
+ builder.nestExpression(indent: 2, now: true);
+ builder.startRule();
+
+ split();
+ visit(body);
+
+ builder.endRule();
+ builder.unnest();
+ }
+ }
+
/// Visit a list of [nodes] if not null, optionally separated and/or preceded
/// and followed by the given functions.
void visitNodes(Iterable<AstNode> nodes, {before(), between(), after()}) {
@@ -1674,10 +1841,6 @@ class SourceVisitor implements AstVisitor {
if (elements.isEmpty && rightBracket.precedingComments == null) {
token(leftBracket);
token(rightBracket);
-
- // Clear this out in case this empty collection is in an argument list.
- // We don't want this rule to bleed over to some other collection.
- _nextLiteralBodyRule = null;
return;
}
@@ -1694,7 +1857,7 @@ class SourceVisitor implements AstVisitor {
// Always use a hard rule to split the elements. The parent chunk of
// the collection will handle the unsplit case, so this only comes
// into play when the collection is split.
- var rule = new HardSplitRule();
+ var rule = new Rule.hard();
builder.startRule(rule);
// If a collection contains a line comment, we assume it's a big complex
@@ -1712,7 +1875,7 @@ class SourceVisitor implements AstVisitor {
soloSplit();
}
} else {
- builder.blockSplit(space: true);
+ builder.split(nest: false, space: true);
}
}
@@ -1733,6 +1896,37 @@ class SourceVisitor implements AstVisitor {
_endLiteralBody(rightBracket, ignoredRule: rule, forceSplit: force);
}
+ /// Gets the cost to split at an assignment (or `:` in the case of a named
+ /// default value) with the given [rightHandSide].
+ ///
+ /// "Block-like" expressions (collections and cascades) bind a bit tighter
+ /// because it looks better to have code like:
+ ///
+ /// var list = [
+ /// element,
+ /// element,
+ /// element
+ /// ];
+ ///
+ /// var builder = new SomeBuilderClass()
+ /// ..method()
+ /// ..method();
+ ///
+ /// over:
+ ///
+ /// var list =
+ /// [element, element, element];
+ ///
+ /// var builder =
+ /// new SomeBuilderClass()..method()..method();
+ int _assignmentCost(Expression rightHandSide) {
+ if (rightHandSide is ListLiteral) return Cost.assignBlock;
+ if (rightHandSide is MapLiteral) return Cost.assignBlock;
+ if (rightHandSide is CascadeExpression) return Cost.assignBlock;
+
+ return Cost.assign;
+ }
+
/// Returns `true` if the collection withs [elements] delimited by
/// [rightBracket] contains any line comments.
///
@@ -1765,16 +1959,21 @@ class SourceVisitor implements AstVisitor {
void _startLiteralBody(Token leftBracket) {
token(leftBracket);
- // Split the literal. Use the explicitly given rule if we have one.
- // Otherwise, create a new rule.
- var rule = _nextLiteralBodyRule;
- _nextLiteralBodyRule = null;
+ // 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 (_collectionArgumentLists.containsKey(leftBracket)) {
+ var argumentList = _collectionArgumentLists[leftBracket];
+ rule = argumentList.collectionRule;
+ argumentChunk = argumentList.previousSplit;
+ }
// Create a rule for whether or not to split the block contents.
builder.startRule(rule);
// Process the collection contents as a separate set of chunks.
- builder = builder.startBlock();
+ builder = builder.startBlock(argumentChunk);
}
/// Ends the literal body started by a call to [_startLiteralBody()].
@@ -1834,10 +2033,13 @@ class SourceVisitor implements AstVisitor {
builder.unnest();
}
- /// Makes [rule] the rule that will be used for the contents of a collection
- /// or function literal body that are about to be visited.
- void setNextLiteralBodyRule(Rule rule) {
- _nextLiteralBodyRule = rule;
+ /// Marks the collection literal that starts with [leftBracket] as being
+ /// controlled by [argumentList].
+ ///
+ /// When the collection is visited, [argumentList] will determine the
+ /// indentation and splitting rule for the collection.
+ void beforeCollection(Token leftBracket, ArgumentSublist argumentList) {
+ _collectionArgumentLists[leftBracket] = argumentList;
}
/// Writes an bracket-delimited body and handles indenting and starting the
@@ -1854,14 +2056,14 @@ class SourceVisitor implements AstVisitor {
// Split after the bracket.
builder.startRule();
- builder.blockSplit(space: space, isDouble: false);
+ builder.split(isDouble: false, nest: false, space: space);
body();
token(rightBracket, before: () {
// Split before the closing bracket character.
builder.unindent();
- builder.blockSplit(space: space);
+ builder.split(nest: false, space: space);
});
builder.endRule();
@@ -1869,7 +2071,8 @@ class SourceVisitor implements AstVisitor {
/// Returns `true` if [node] is immediately contained within an anonymous
/// [FunctionExpression].
- bool _isInLambda(AstNode node) => node.parent is FunctionExpression &&
+ bool _isInLambda(AstNode node) =>
+ node.parent is FunctionExpression &&
node.parent.parent is! FunctionDeclaration;
/// Writes the string literal [string] to the output.
@@ -1945,7 +2148,7 @@ class SourceVisitor implements AstVisitor {
/// Writes a single space split with its own rule.
void soloSplit([int cost]) {
- builder.startRule(new SimpleRule(cost: cost));
+ builder.startRule(new Rule(cost));
split();
builder.endRule();
}
« no previous file with comments | « packages/dart_style/lib/src/rule/type_argument.dart ('k') | packages/dart_style/lib/src/whitespace.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698