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

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

Issue 1493553002: Smarter splitting around named collection arguments. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Created 5 years 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/call_chain_visitor.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 '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
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
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
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 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | lib/src/call_chain_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698