| Index: pkg/analyzer/lib/src/services/formatter_impl.dart
|
| diff --git a/pkg/analyzer/lib/src/services/formatter_impl.dart b/pkg/analyzer/lib/src/services/formatter_impl.dart
|
| index 588464d5e591817ff7e223f8b6db6f522467a3b9..2bf8ef98edbe3bca36ded0332a0fb65460f5cc35 100644
|
| --- a/pkg/analyzer/lib/src/services/formatter_impl.dart
|
| +++ b/pkg/analyzer/lib/src/services/formatter_impl.dart
|
| @@ -385,6 +385,9 @@ class SourceVisitor implements AstVisitor {
|
| /// A weight for potential breakpoints.
|
| int currentBreakWeight = DEFAULT_SPACE_WEIGHT;
|
|
|
| + /// A weight of a potential breakpoint of the current level.
|
| + int levelBreakWeight = 0;
|
| +
|
| /// Original pre-format selection information (may be null).
|
| final Selection preSelection;
|
|
|
| @@ -423,8 +426,14 @@ class SourceVisitor implements AstVisitor {
|
|
|
| visitArgumentList(ArgumentList node) {
|
| token(node.leftParenthesis);
|
| - breakableNonSpace();
|
| - visitCommaSeparatedNodes(node.arguments);
|
| + if (node.arguments.isNotEmpty) {
|
| + withBreakLevel(() {
|
| + levelSpace(0);
|
| + visitCommaSeparatedNodes(
|
| + node.arguments,
|
| + followedBy: () => levelSpace());
|
| + });
|
| + }
|
| token(node.rightParenthesis);
|
| }
|
|
|
| @@ -455,11 +464,30 @@ class SourceVisitor implements AstVisitor {
|
| }
|
|
|
| visitBinaryExpression(BinaryExpression node) {
|
| - visit(node.leftOperand);
|
| - space();
|
| - token(node.operator);
|
| - space();
|
| - visit(node.rightOperand);
|
| + withBreakLevel(() {
|
| + Token operator = node.operator;
|
| + TokenType operatorType = operator.type;
|
| + int addOperands(List<Expression> operands, Expression e, int i) {
|
| + if (e is BinaryExpression && e.operator.type == operatorType) {
|
| + i = addOperands(operands, e.leftOperand, i);
|
| + i = addOperands(operands, e.rightOperand, i);
|
| + } else {
|
| + operands.insert(i++, e);
|
| + }
|
| + return i;
|
| + }
|
| + List<Expression> operands = [];
|
| + addOperands(operands, node.leftOperand, 0);
|
| + addOperands(operands, node.rightOperand, operands.length);
|
| + for (int i = 0; i < operands.length; i++) {
|
| + if (i != 0) {
|
| + space();
|
| + token(operator);
|
| + levelSpace();
|
| + }
|
| + visit(operands[i]);
|
| + }
|
| + });
|
| }
|
|
|
| visitBlock(Block node) {
|
| @@ -595,16 +623,18 @@ class SourceVisitor implements AstVisitor {
|
| }
|
|
|
| visitConditionalExpression(ConditionalExpression node) {
|
| - visit(node.condition);
|
| - space();
|
| - token(node.question);
|
| - allowContinuedLines((){
|
| - space();
|
| - visit(node.thenExpression);
|
| - space();
|
| - token(node.colon);
|
| + withBreakLevel(() {
|
| + visit(node.condition);
|
| space();
|
| - visit(node.elseExpression);
|
| + token(node.question);
|
| + allowContinuedLines((){
|
| + levelSpace();
|
| + visit(node.thenExpression);
|
| + space();
|
| + token(node.colon);
|
| + levelSpace();
|
| + visit(node.elseExpression);
|
| + });
|
| });
|
| }
|
|
|
| @@ -748,10 +778,12 @@ class SourceVisitor implements AstVisitor {
|
| }
|
|
|
| visitExpressionFunctionBody(ExpressionFunctionBody node) {
|
| - token(node.functionDefinition);
|
| - space();
|
| - visit(node.expression);
|
| - token(node.semicolon);
|
| + withBreakLevel(() {
|
| + token(node.functionDefinition);
|
| + levelSpace();
|
| + visit(node.expression);
|
| + token(node.semicolon);
|
| + });
|
| }
|
|
|
| visitExpressionStatement(ExpressionStatement node) {
|
| @@ -1023,7 +1055,10 @@ class SourceVisitor implements AstVisitor {
|
| visit(node.typeArguments);
|
| token(node.leftBracket);
|
| indent();
|
| - visitCommaSeparatedNodes(node.elements /*, followedBy: breakableSpace*/);
|
| + withBreakLevel(() {
|
| + levelSpace(0);
|
| + visitCommaSeparatedNodes(node.elements, followedBy: levelSpace);
|
| + });
|
| optionalTrailingComma(node.rightBracket);
|
| token(node.rightBracket, precededBy: unindent);
|
| }
|
| @@ -1573,6 +1608,18 @@ class SourceVisitor implements AstVisitor {
|
| emitEmptySpaces = true;
|
| }
|
|
|
| + /// Emit level spaces, even if empty (works as a break point).
|
| + levelSpace([int n = 1]) {
|
| + space(n: n, breakWeight: levelBreakWeight);
|
| + emitEmptySpaces = true;
|
| + }
|
| +
|
| + void withBreakLevel(process()) {
|
| + levelBreakWeight++;
|
| + process();
|
| + levelBreakWeight--;
|
| + }
|
| +
|
| /// Emit a non-breakable space.
|
| nonBreakingSpace() {
|
| space(breakWeight: UNBREAKABLE_SPACE_WEIGHT);
|
| @@ -1583,7 +1630,7 @@ class SourceVisitor implements AstVisitor {
|
| /// indent-level), otherwise line-leading spaces will be ignored.
|
| space({n: 1, allowLineLeading: false, breakWeight: DEFAULT_SPACE_WEIGHT}) {
|
| //TODO(pquitslund): replace with a proper space token
|
| - leadingSpaces+=n;
|
| + leadingSpaces += n;
|
| allowLineLeadingSpaces = allowLineLeading;
|
| currentBreakWeight = breakWeight;
|
| }
|
|
|