Index: lib/src/source_visitor.dart |
diff --git a/lib/src/source_visitor.dart b/lib/src/source_visitor.dart |
index 4fc1918b27bb31fc7b8307fbee7396ac660362a1..ec9ca709ae3162177299ef4c3a7aeb916c59db45 100644 |
--- a/lib/src/source_visitor.dart |
+++ b/lib/src/source_visitor.dart |
@@ -105,13 +105,51 @@ class SourceVisitor implements AstVisitor { |
// Nest around the parentheses in case there are comments before or after |
// them. |
_writer.nestExpression(); |
+ |
token(node.leftParenthesis); |
+ // Corner case: If the first argument to a method is a block-bodied |
+ // function, it looks bad if its parameter list gets wrapped to the next |
+ // line. Bump the cost to try to avoid that. This prefers: |
+ // |
+ // receiver |
+ // .method() |
+ // .chain((parameter, list) { |
+ // ... |
+ // }); |
+ // |
+ // over: |
+ // |
+ // receiver.method().chain( |
+ // (parameter, list) { |
+ // ... |
+ // }); |
+ // TODO(rnystrom): This causes a function expression's long parameter list |
+ // to get split instead, like: |
+ // |
+ // receiver.method((longParameter, |
+ // anotherParameter) { |
+ // ... |
+ // }); |
+ // |
+ // Instead of bumping the cost, this should wrap a span around the "(" |
+ // before the argument list and the function's parameter list. That requires |
+ // spans to not strictly be a stack, though, so would be a larger change |
+ // than I want to do right now. |
+ var cost = Cost.normal; |
+ if (node.arguments.isNotEmpty) { |
+ var firstArg = node.arguments.first; |
+ if (firstArg is FunctionExpression && |
+ firstArg.body is BlockFunctionBody) { |
+ cost = Cost.firstBlockArgument; |
+ } |
+ } |
+ |
// Allow splitting after "(". |
- var lastParam = zeroSplit(); |
+ var lastParam = zeroSplit(cost); |
// Try to keep the positional arguments together. |
- _writer.startSpan(); |
+ _writer.startSpan(Cost.positionalArguments); |
var i = 0; |
for (; i < node.arguments.length; i++) { |
@@ -979,8 +1017,11 @@ class SourceVisitor implements AstVisitor { |
} |
visitListLiteral(ListLiteral node) { |
+ // Corner case: Splitting inside a list looks bad if there's only one |
+ // element, so make those more costly. |
+ var cost = node.elements.length <= 1 ? Cost.singleElementList : Cost.normal; |
_visitCollectionLiteral( |
- node, node.leftBracket, node.elements, node.rightBracket); |
+ node, node.leftBracket, node.elements, node.rightBracket, cost); |
} |
visitMapLiteral(MapLiteral node) { |
@@ -1542,11 +1583,11 @@ class SourceVisitor implements AstVisitor { |
/// Visits the collection literal [node] whose body starts with [leftBracket], |
/// ends with [rightBracket] and contains [elements]. |
void _visitCollectionLiteral(TypedLiteral node, Token leftBracket, |
- Iterable<AstNode> elements, Token rightBracket) { |
+ Iterable<AstNode> elements, Token rightBracket, [int cost]) { |
modifier(node.constKeyword); |
visit(node.typeArguments); |
- _startBody(leftBracket); |
+ _startBody(leftBracket, cost: cost); |
// Each list element takes at least 3 characters (one character for the |
// element, one for the comma, one for the space), so force it to split if |
@@ -1649,11 +1690,11 @@ class SourceVisitor implements AstVisitor { |
/// |
/// If [space] is `true`, then the initial multisplit will use a space if not |
/// split. |
- void _startBody(Token leftBracket, {bool space: false}) { |
+ void _startBody(Token leftBracket, {int cost, bool space: false}) { |
token(leftBracket); |
// Indent the body. |
- _writer.startMultisplit(); |
+ _writer.startMultisplit(cost: cost); |
_writer.indent(); |
// Split after the bracket. |
@@ -1746,7 +1787,7 @@ class SourceVisitor implements AstVisitor { |
/// Writes a split that is the empty string when unsplit. |
/// |
/// Returns the newly created [SplitParam]. |
- SplitParam zeroSplit() => _writer.writeSplit(); |
+ SplitParam zeroSplit([int cost]) => _writer.writeSplit(cost: cost); |
/// Emit [token], along with any comments and formatted whitespace that comes |
/// before it. |