| 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 |