OLD | NEW |
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 'dart:math' as math; |
| 8 |
7 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
8 import 'package:analyzer/src/generated/scanner.dart'; | 10 import 'package:analyzer/src/generated/scanner.dart'; |
9 | 11 |
10 import 'chunk.dart'; | 12 import 'chunk.dart'; |
11 import 'rule/argument.dart'; | 13 import 'rule/argument.dart'; |
12 import 'rule/rule.dart'; | 14 import 'rule/rule.dart'; |
13 import 'source_visitor.dart'; | 15 import 'source_visitor.dart'; |
14 | 16 |
15 /// Helper class for [SourceVisitor] that handles visiting and writing an | 17 /// Helper class for [SourceVisitor] that handles visiting and writing an |
16 /// [ArgumentList], including all of the special code needed to handle function | 18 /// [ArgumentList], including all of the special code needed to handle function |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 256 |
255 // Count the trailing arguments that are collection literals. | 257 // Count the trailing arguments that are collection literals. |
256 var trailingCollections = 0; | 258 var trailingCollections = 0; |
257 if (leadingCollections != arguments.length) { | 259 if (leadingCollections != arguments.length) { |
258 for (var argument in arguments.reversed) { | 260 for (var argument in arguments.reversed) { |
259 if (!collections.containsKey(argument)) break; | 261 if (!collections.containsKey(argument)) break; |
260 trailingCollections++; | 262 trailingCollections++; |
261 } | 263 } |
262 } | 264 } |
263 | 265 |
264 // If only some of the named arguments are collections, treat none of them | |
265 // specially. Avoids cases like: | |
266 // | |
267 // function( | |
268 // a: arg, | |
269 // b: [ | |
270 // ... | |
271 // ]); | |
272 if (trailingCollections < named.length) trailingCollections = 0; | |
273 | |
274 // Collections must all be a prefix or suffix of the argument list (and not | 266 // Collections must all be a prefix or suffix of the argument list (and not |
275 // both). | 267 // both). |
276 if (leadingCollections != collections.length) leadingCollections = 0; | 268 if (leadingCollections != collections.length) leadingCollections = 0; |
277 if (trailingCollections != collections.length) trailingCollections = 0; | 269 if (trailingCollections != collections.length) trailingCollections = 0; |
278 | 270 |
279 // Ignore any collections in the middle of the argument list. | 271 // Ignore any collections in the middle of the argument list. |
280 if (leadingCollections == 0 && trailingCollections == 0) { | 272 if (leadingCollections == 0 && trailingCollections == 0) { |
281 collections.clear(); | 273 collections.clear(); |
282 } | 274 } |
283 | 275 |
(...skipping 17 matching lines...) Expand all Loading... |
301 PositionalRule _visitPositional(SourceVisitor visitor) { | 293 PositionalRule _visitPositional(SourceVisitor visitor) { |
302 if (_positional.isEmpty) return null; | 294 if (_positional.isEmpty) return null; |
303 | 295 |
304 // Allow splitting after "(". | 296 // Allow splitting after "(". |
305 var rule; | 297 var rule; |
306 if (_positional.length == 1) { | 298 if (_positional.length == 1) { |
307 rule = new SinglePositionalRule(_collectionRule, | 299 rule = new SinglePositionalRule(_collectionRule, |
308 splitsOnInnerRules: _allArguments.length > 1 && | 300 splitsOnInnerRules: _allArguments.length > 1 && |
309 !_collections.containsKey(_positional.first)); | 301 !_collections.containsKey(_positional.first)); |
310 } else { | 302 } else { |
311 // Only count the positional bodies in the positional rule. | 303 // Only count the collections in the positional rule. |
312 var leadingPositional = _leadingCollections; | 304 var leadingCollections = |
313 if (_leadingCollections == _positional.length + _named.length) { | 305 math.min(_leadingCollections, _positional.length); |
314 leadingPositional -= _named.length; | 306 var trailingCollections = |
315 } | 307 math.max(_trailingCollections - _named.length, 0); |
316 | |
317 var trailingPositional = _trailingCollections - _named.length; | |
318 rule = new MultiplePositionalRule( | 308 rule = new MultiplePositionalRule( |
319 _collectionRule, leadingPositional, trailingPositional); | 309 _collectionRule, leadingCollections, trailingCollections); |
320 } | 310 } |
321 | 311 |
322 visitor.builder.startRule(rule); | 312 _visitArguments(visitor, _positional, rule); |
323 | |
324 _previousSplit = | |
325 visitor.builder.split(space: !_isFirstArgument(_positional.first)); | |
326 rule.beforeArgument(_previousSplit); | |
327 | |
328 // Try to not split the arguments. | |
329 visitor.builder.startSpan(Cost.positionalArguments); | |
330 | |
331 for (var argument in _positional) { | |
332 _visitArgument(visitor, rule, argument); | |
333 | |
334 // Positional arguments split independently. | |
335 if (argument != _positional.last) { | |
336 _previousSplit = visitor.split(); | |
337 rule.beforeArgument(_previousSplit); | |
338 } | |
339 } | |
340 | |
341 visitor.builder.endSpan(); | |
342 visitor.builder.endRule(); | |
343 | |
344 return rule; | 313 return rule; |
345 } | 314 } |
346 | 315 |
347 /// Writes the named arguments, if any. | 316 /// Writes the named arguments, if any. |
348 void _visitNamed(SourceVisitor visitor, PositionalRule rule) { | 317 void _visitNamed(SourceVisitor visitor, PositionalRule positionalRule) { |
349 if (_named.isEmpty) return; | 318 if (_named.isEmpty) return; |
350 | 319 |
351 var positionalRule = rule; | 320 // Only count the collections in the named rule. |
352 var namedRule = new NamedRule( | 321 var leadingCollections = |
353 containsCollections: _leadingCollections > _positional.length || | 322 math.max(_leadingCollections - _positional.length, 0); |
354 _trailingCollections > 0); | 323 var trailingCollections = math.min(_trailingCollections, _named.length); |
355 visitor.builder.startRule(namedRule); | 324 var namedRule = |
| 325 new NamedRule(_collectionRule, leadingCollections, trailingCollections); |
356 | 326 |
357 // Let the positional args force the named ones to split. | 327 // Let the positional args force the named ones to split. |
358 if (positionalRule != null) { | 328 if (positionalRule != null) { |
359 positionalRule.setNamedArgsRule(namedRule); | 329 positionalRule.setNamedArgsRule(namedRule); |
360 } | 330 } |
361 | 331 |
362 // Split before the first named argument. | 332 _visitArguments(visitor, _named, namedRule); |
| 333 } |
| 334 |
| 335 void _visitArguments( |
| 336 SourceVisitor visitor, List<Expression> arguments, ArgumentRule rule) { |
| 337 visitor.builder.startRule(rule); |
| 338 |
| 339 // Split before the first argument. |
363 _previousSplit = | 340 _previousSplit = |
364 visitor.builder.split(space: !_isFirstArgument(_named.first)); | 341 visitor.builder.split(space: !_isFirstArgument(arguments.first)); |
365 namedRule.beforeArguments(_previousSplit); | 342 rule.beforeArgument(_previousSplit); |
366 | 343 |
367 for (var argument in _named) { | 344 // Try to not split the positional arguments. |
368 _visitArgument(visitor, namedRule, argument); | 345 if (arguments == _positional) { |
| 346 visitor.builder.startSpan(Cost.positionalArguments); |
| 347 } |
| 348 |
| 349 for (var argument in arguments) { |
| 350 _visitArgument(visitor, rule, argument); |
369 | 351 |
370 // Write the split. | 352 // Write the split. |
371 if (argument != _named.last) _previousSplit = visitor.split(); | 353 if (argument != arguments.last) { |
| 354 _previousSplit = visitor.split(); |
| 355 rule.beforeArgument(_previousSplit); |
| 356 } |
372 } | 357 } |
373 | 358 |
| 359 if (arguments == _positional) visitor.builder.endSpan(); |
| 360 |
374 visitor.builder.endRule(); | 361 visitor.builder.endRule(); |
375 } | 362 } |
376 | 363 |
377 void _visitArgument( | 364 void _visitArgument( |
378 SourceVisitor visitor, ArgumentRule rule, Expression argument) { | 365 SourceVisitor visitor, ArgumentRule rule, Expression argument) { |
379 // If we're about to write a collection argument, handle it specially. | 366 // If we're about to write a collection argument, handle it specially. |
380 if (_collections.containsKey(argument)) { | 367 if (_collections.containsKey(argument)) { |
381 if (rule != null) rule.beforeCollection(); | 368 if (rule != null) rule.beforeCollection(); |
382 | 369 |
383 // Tell it to use the rule we've already created. | 370 // Tell it to use the rule we've already created. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 409 |
423 // TODO(rnystrom): Should we step into parenthesized expressions? | 410 // TODO(rnystrom): Should we step into parenthesized expressions? |
424 | 411 |
425 if (expression is ListLiteral) return expression.leftBracket; | 412 if (expression is ListLiteral) return expression.leftBracket; |
426 if (expression is MapLiteral) return expression.leftBracket; | 413 if (expression is MapLiteral) return expression.leftBracket; |
427 | 414 |
428 // Not a collection literal. | 415 // Not a collection literal. |
429 return null; | 416 return null; |
430 } | 417 } |
431 } | 418 } |
OLD | NEW |