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

Side by Side Diff: lib/src/argument_list_visitor.dart

Issue 1258203006: Handle function arguments inside function calls. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Reformat self. Created 5 years, 4 months 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 unified diff | Download patch
« no previous file with comments | « CHANGELOG.md ('k') | lib/src/line_splitting/solve_state.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart_style.src.argument_list_visitor; 5 library dart_style.src.argument_list_visitor;
6 6
7 import 'package:analyzer/analyzer.dart'; 7 import 'package:analyzer/analyzer.dart';
8 8
9 import 'chunk.dart'; 9 import 'chunk.dart';
10 import 'rule/argument.dart'; 10 import 'rule/argument.dart';
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 var argumentsAfter = node.arguments.skip(functionsEnd).toList(); 90 var argumentsAfter = node.arguments.skip(functionsEnd).toList();
91 91
92 return new ArgumentListVisitor._( 92 return new ArgumentListVisitor._(
93 visitor, 93 visitor,
94 node, 94 node,
95 new ArgumentSublist(node.arguments, argumentsBefore), 95 new ArgumentSublist(node.arguments, argumentsBefore),
96 functions, 96 functions,
97 new ArgumentSublist(node.arguments, argumentsAfter)); 97 new ArgumentSublist(node.arguments, argumentsAfter));
98 } 98 }
99 99
100 ArgumentListVisitor._( 100 ArgumentListVisitor._(this._visitor, this._node, this._arguments,
101 this._visitor, 101 this._functions, this._argumentsAfterFunctions);
102 this._node,
103 this._arguments,
104 this._functions,
105 this._argumentsAfterFunctions);
106 102
107 /// Builds chunks for the call chain. 103 /// Builds chunks for the call chain.
108 void visit() { 104 void visit() {
109 // If there is just one positional argument, it tends to look weird to 105 // If there is just one positional argument, it tends to look weird to
110 // split before it, so try not to. 106 // split before it, so try not to.
111 if (_isSingle) _visitor.builder.startSpan(); 107 if (_isSingle) _visitor.builder.startSpan();
112 108
113 // Nest around the parentheses in case there are comments before or after 109 // Nest around the parentheses in case there are comments before or after
114 // them. 110 // them.
115 _visitor.builder.nestExpression(); 111 _visitor.builder.nestExpression();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 if (_isSingle) _visitor.builder.endSpan(); 151 if (_isSingle) _visitor.builder.endSpan();
156 } 152 }
157 153
158 /// Returns `true` if [expression] is a [FunctionExpression] with a block 154 /// Returns `true` if [expression] is a [FunctionExpression] with a block
159 /// body. 155 /// body.
160 static bool _isBlockFunction(Expression expression) { 156 static bool _isBlockFunction(Expression expression) {
161 if (expression is NamedExpression) { 157 if (expression is NamedExpression) {
162 expression = (expression as NamedExpression).expression; 158 expression = (expression as NamedExpression).expression;
163 } 159 }
164 160
161 // Allow functions wrapped in dotted method calls like "a.b.c(() { ... })".
162 if (expression is MethodInvocation) {
163 if (!_isValidWrappingTarget(expression.target)) return false;
164 if (expression.argumentList.arguments.length != 1) return false;
165
166 return _isBlockFunction(expression.argumentList.arguments.single);
167 }
168
165 // Curly body functions are. 169 // Curly body functions are.
166 if (expression is! FunctionExpression) return false; 170 if (expression is! FunctionExpression) return false;
167 var function = expression as FunctionExpression; 171 var function = expression as FunctionExpression;
168 return function.body is BlockFunctionBody; 172 return function.body is BlockFunctionBody;
169 } 173 }
174
175 /// Returns `true` if [expression] is a valid method invocation target for
176 /// an invocation that wraps a function literal argument.
177 static bool _isValidWrappingTarget(Expression expression) {
178 // Allow bare function calls.
179 if (expression == null) return true;
180
181 // Allow property accesses.
182 while (expression is PropertyAccess) {
183 expression = (expression as PropertyAccess).target;
184 }
185
186 if (expression is PrefixedIdentifier) return true;
187 if (expression is SimpleIdentifier) return true;
188
189 return false;
190 }
170 } 191 }
171 192
172 /// A range of arguments from a complete argument list. 193 /// A range of arguments from a complete argument list.
173 /// 194 ///
174 /// One of these typically covers all of the arguments in an invocation. But, 195 /// One of these typically covers all of the arguments in an invocation. But,
175 /// when an argument list has block functions in the middle, the arguments 196 /// when an argument list has block functions in the middle, the arguments
176 /// before and after the functions are treated as separate independent lists. 197 /// before and after the functions are treated as separate independent lists.
177 /// In that case, there will be two of these. 198 /// In that case, there will be two of these.
178 class ArgumentSublist { 199 class ArgumentSublist {
179 /// The full argument list from the AST. 200 /// The full argument list from the AST.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 var positionalRule = rule; 347 var positionalRule = rule;
327 var namedRule = new NamedRule(_collectionRule); 348 var namedRule = new NamedRule(_collectionRule);
328 visitor.builder.startRule(namedRule); 349 visitor.builder.startRule(namedRule);
329 350
330 // Let the positional args force the named ones to split. 351 // Let the positional args force the named ones to split.
331 if (positionalRule != null) { 352 if (positionalRule != null) {
332 positionalRule.setNamedArgsRule(namedRule); 353 positionalRule.setNamedArgsRule(namedRule);
333 } 354 }
334 355
335 // Split before the first named argument. 356 // Split before the first named argument.
336 namedRule.beforeArguments(visitor.builder.split( 357 namedRule.beforeArguments(
337 space: !_isFirstArgument(_named.first))); 358 visitor.builder.split(space: !_isFirstArgument(_named.first)));
338 359
339 for (var argument in _named) { 360 for (var argument in _named) {
340 _visitArgument(visitor, namedRule, argument); 361 _visitArgument(visitor, namedRule, argument);
341 362
342 // Write the split. 363 // Write the split.
343 if (argument != _named.last) visitor.split(); 364 if (argument != _named.last) visitor.split();
344 } 365 }
345 366
346 visitor.builder.endRule(); 367 visitor.builder.endRule();
347 } 368 }
348 369
349 void _visitArgument(SourceVisitor visitor, ArgumentRule rule, Expression argum ent) { 370 void _visitArgument(
371 SourceVisitor visitor, ArgumentRule rule, Expression argument) {
350 // If we're about to write a collection argument, handle it specially. 372 // If we're about to write a collection argument, handle it specially.
351 if (_collections.contains(argument)) { 373 if (_collections.contains(argument)) {
352 if (rule != null) rule.beforeCollection(); 374 if (rule != null) rule.beforeCollection();
353 375
354 // Tell it to use the rule we've already created. 376 // Tell it to use the rule we've already created.
355 visitor.setNextLiteralBodyRule(_collectionRule); 377 visitor.setNextLiteralBodyRule(_collectionRule);
356 } else if (_hasMultipleArguments) { 378 } else if (_hasMultipleArguments) {
357 // Corner case: If there is just a single argument, don't bump the 379 // Corner case: If there is just a single argument, don't bump the
358 // nesting. This lets us avoid spurious indentation in cases like: 380 // nesting. This lets us avoid spurious indentation in cases like:
359 // 381 //
(...skipping 27 matching lines...) Expand all
387 /// indentation to make them look more statement-like. 409 /// indentation to make them look more statement-like.
388 static bool _isCollectionArgument(Expression expression) { 410 static bool _isCollectionArgument(Expression expression) {
389 if (expression is NamedExpression) { 411 if (expression is NamedExpression) {
390 expression = (expression as NamedExpression).expression; 412 expression = (expression as NamedExpression).expression;
391 } 413 }
392 414
393 // TODO(rnystrom): Should we step into parenthesized expressions? 415 // TODO(rnystrom): Should we step into parenthesized expressions?
394 416
395 return expression is ListLiteral || expression is MapLiteral; 417 return expression is ListLiteral || expression is MapLiteral;
396 } 418 }
397 } 419 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | lib/src/line_splitting/solve_state.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698