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

Side by Side Diff: packages/dart_style/lib/src/call_chain_visitor.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 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
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.call_chain_visitor; 5 library dart_style.src.call_chain_visitor;
6 6
7 import 'package:analyzer/analyzer.dart'; 7 import 'package:analyzer/analyzer.dart';
8 8
9 import 'argument_list_visitor.dart'; 9 import 'argument_list_visitor.dart';
10 import 'rule/argument.dart'; 10 import 'rule/argument.dart';
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 87
88 /// Creates a new call chain visitor for [visitor] starting with [node]. 88 /// Creates a new call chain visitor for [visitor] starting with [node].
89 /// 89 ///
90 /// The [node] is the outermost expression containing the chained "." 90 /// The [node] is the outermost expression containing the chained "."
91 /// operators and must be a [MethodInvocation], [PropertyAccess] or 91 /// operators and must be a [MethodInvocation], [PropertyAccess] or
92 /// [PrefixedIdentifier]. 92 /// [PrefixedIdentifier].
93 factory CallChainVisitor(SourceVisitor visitor, Expression node) { 93 factory CallChainVisitor(SourceVisitor visitor, Expression node) {
94 var target; 94 var target;
95 95
96 // Recursively walk the chain of calls and turn the tree into a list. 96 // Recursively walk the chain of calls and turn the tree into a list.
97 var calls = []; 97 var calls = <Expression>[];
98 flatten(expression) { 98 flatten(expression) {
99 target = expression; 99 target = expression;
100 100
101 // Treat index expressions where the target is a valid call in a method 101 // Treat index expressions where the target is a valid call in a method
102 // chain as being part of the call. Handles cases like: 102 // chain as being part of the call. Handles cases like:
103 // 103 //
104 // receiver 104 // receiver
105 // .property 105 // .property
106 // .property[0] 106 // .property[0]
107 // .property 107 // .property
(...skipping 15 matching lines...) Expand all
123 123
124 flatten(node); 124 flatten(node);
125 125
126 // An expression that starts with a series of dotted names gets treated a 126 // An expression that starts with a series of dotted names gets treated a
127 // little specially. We don't force leading properties to split with the 127 // little specially. We don't force leading properties to split with the
128 // rest of the chain. Allows code like: 128 // rest of the chain. Allows code like:
129 // 129 //
130 // address.street.number 130 // address.street.number
131 // .toString() 131 // .toString()
132 // .length; 132 // .length;
133 var properties = []; 133 var properties = <Expression>[];
134 if (target is SimpleIdentifier) { 134 if (target is SimpleIdentifier) {
135 properties = calls.takeWhile((call) { 135 properties = calls.takeWhile((call) {
136 // Step into index expressions to see what the index is on. 136 // Step into index expressions to see what the index is on.
137 while (call is IndexExpression) call = call.target; 137 while (call is IndexExpression) {
138 call = (call as IndexExpression).target;
139 }
138 return call is! MethodInvocation; 140 return call is! MethodInvocation;
139 }).toList(); 141 }).toList();
140 } 142 }
141 143
142 calls.removeRange(0, properties.length); 144 calls.removeRange(0, properties.length);
143 145
144 // Separate out the block calls, if there are any. 146 // Separate out the block calls, if there are any.
145 var blockCalls; 147 List<Expression> blockCalls;
146 var hangingCall; 148 var hangingCall;
147 149
148 var inBlockCalls = false; 150 var inBlockCalls = false;
149 for (var call in calls) { 151 for (var call in calls) {
150 // See if this call is a method call whose arguments are block formatted. 152 // See if this call is a method call whose arguments are block formatted.
151 var isBlockCall = false; 153 var isBlockCall = false;
152 if (call is MethodInvocation) { 154 if (call is MethodInvocation) {
153 var args = new ArgumentListVisitor(visitor, call.argumentList); 155 var args = new ArgumentListVisitor(visitor, call.argumentList);
154 isBlockCall = args.hasBlockArguments; 156 isBlockCall = args.hasBlockArguments;
155 } 157 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 202
201 // Try to keep the entire method invocation one line. 203 // Try to keep the entire method invocation one line.
202 _visitor.builder.startSpan(); 204 _visitor.builder.startSpan();
203 205
204 // If a split in the target expression forces the first `.` to split, then 206 // If a split in the target expression forces the first `.` to split, then
205 // start the rule now so that it surrounds the target. 207 // start the rule now so that it surrounds the target.
206 var splitOnTarget = _forcesSplit(_target); 208 var splitOnTarget = _forcesSplit(_target);
207 209
208 if (splitOnTarget) { 210 if (splitOnTarget) {
209 if (_properties.length > 1) { 211 if (_properties.length > 1) {
210 _propertyRule = new MultiplePositionalRule(null, 0, 0); 212 _propertyRule = new PositionalRule(null, 0, 0);
211 _visitor.builder.startLazyRule(_propertyRule); 213 _visitor.builder.startLazyRule(_propertyRule);
212 } else if (_calls.isNotEmpty) { 214 } else if (_calls.isNotEmpty) {
213 _enableRule(lazy: true); 215 _enableRule(lazy: true);
214 } 216 }
215 } 217 }
216 218
217 _visitor.visit(_target); 219 _visitor.visit(_target);
218 220
219 // Leading properties split like positional arguments: either not at all, 221 // Leading properties split like positional arguments: either not at all,
220 // before one ".", or before all of them. 222 // before one ".", or before all of them.
221 if (_properties.length == 1) { 223 if (_properties.length == 1) {
222 _visitor.soloZeroSplit(); 224 _visitor.soloZeroSplit();
223 _writeCall(_properties.single); 225 _writeCall(_properties.single);
224 } else if (_properties.length > 1) { 226 } else if (_properties.length > 1) {
225 if (!splitOnTarget) { 227 if (!splitOnTarget) {
226 _propertyRule = new MultiplePositionalRule(null, 0, 0); 228 _propertyRule = new PositionalRule(null, 0, 0);
227 _visitor.builder.startRule(_propertyRule); 229 _visitor.builder.startRule(_propertyRule);
228 } 230 }
229 231
230 for (var property in _properties) { 232 for (var property in _properties) {
231 _propertyRule.beforeArgument(_visitor.zeroSplit()); 233 _propertyRule.beforeArgument(_visitor.zeroSplit());
232 _writeCall(property); 234 _writeCall(property);
233 } 235 }
234 236
235 _visitor.builder.endRule(); 237 _visitor.builder.endRule();
236 } 238 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 310
309 // Don't split right after a non-empty curly-bodied function. 311 // Don't split right after a non-empty curly-bodied function.
310 if (expression is FunctionExpression) { 312 if (expression is FunctionExpression) {
311 if (expression.body is! BlockFunctionBody) return false; 313 if (expression.body is! BlockFunctionBody) return false;
312 314
313 return (expression.body as BlockFunctionBody).block.statements.isEmpty; 315 return (expression.body as BlockFunctionBody).block.statements.isEmpty;
314 } 316 }
315 317
316 // If the expression ends in an argument list, base the splitting on the 318 // If the expression ends in an argument list, base the splitting on the
317 // last argument. 319 // last argument.
318 var argumentList; 320 ArgumentList argumentList;
319 if (expression is MethodInvocation) { 321 if (expression is MethodInvocation) {
320 argumentList = expression.argumentList; 322 argumentList = expression.argumentList;
321 } else if (expression is InstanceCreationExpression) { 323 } else if (expression is InstanceCreationExpression) {
322 argumentList = expression.argumentList; 324 argumentList = expression.argumentList;
323 } else if (expression is FunctionExpressionInvocation) { 325 } else if (expression is FunctionExpressionInvocation) {
324 argumentList = expression.argumentList; 326 argumentList = expression.argumentList;
325 } 327 }
326 328
327 // Any other kind of expression always splits. 329 // Any other kind of expression always splits.
328 if (argumentList == null) return true; 330 if (argumentList == null) return true;
329 if (argumentList.arguments.isEmpty) return true; 331 if (argumentList.arguments.isEmpty) return true;
330 332
331 var argument = argumentList.arguments.last; 333 var argument = argumentList.arguments.last;
332 if (argument is NamedExpression) argument = argument.expression; 334 if (argument is NamedExpression) {
335 argument = (argument as NamedExpression).expression;
336 }
333 337
334 // TODO(rnystrom): This logic is similar (but not identical) to 338 // TODO(rnystrom): This logic is similar (but not identical) to
335 // ArgumentListVisitor.hasBlockArguments. They overlap conceptually and 339 // ArgumentListVisitor.hasBlockArguments. They overlap conceptually and
336 // both have their own peculiar heuristics. It would be good to unify and 340 // both have their own peculiar heuristics. It would be good to unify and
337 // rationalize them. 341 // rationalize them.
338 342
339 return _forcesSplit(argument); 343 return _forcesSplit(argument);
340 } 344 }
341 345
342 /// Writes [call], which must be one of the supported expression types. 346 /// Writes [call], which must be one of the supported expression types.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 // "." when calling a single method on a single name. This is especially 394 // "." when calling a single method on a single name. This is especially
391 // important because the identifier is often a library prefix, and splitting 395 // important because the identifier is often a library prefix, and splitting
392 // there looks really odd. 396 // there looks really odd.
393 if (_properties.isEmpty && 397 if (_properties.isEmpty &&
394 _calls.length == 1 && 398 _calls.length == 1 &&
395 _blockCalls == null && 399 _blockCalls == null &&
396 _target is SimpleIdentifier) { 400 _target is SimpleIdentifier) {
397 _endSpan(); 401 _endSpan();
398 } 402 }
399 403
400 _visitor.visit(invocation.argumentList); 404 _visitor.builder.nestExpression();
405 _visitor.visit(invocation.typeArguments);
406 _visitor.visitArgumentList(invocation.argumentList, nestExpression: false);
407 _visitor.builder.unnest();
401 } 408 }
402 409
403 void _writeBlockCall(MethodInvocation invocation) { 410 void _writeBlockCall(MethodInvocation invocation) {
404 _visitor.token(invocation.operator); 411 _visitor.token(invocation.operator);
405 _visitor.token(invocation.methodName.token); 412 _visitor.token(invocation.methodName.token);
413 _visitor.visit(invocation.typeArguments);
406 _visitor.visit(invocation.argumentList); 414 _visitor.visit(invocation.argumentList);
407 } 415 }
408 416
409 /// If a [Rule] for the method chain is currently active, ends it. 417 /// If a [Rule] for the method chain is currently active, ends it.
410 void _disableRule() { 418 void _disableRule() {
411 if (_ruleEnabled == false) return; 419 if (_ruleEnabled == false) return;
412 420
413 _visitor.builder.endRule(); 421 _visitor.builder.endRule();
414 _ruleEnabled = false; 422 _ruleEnabled = false;
415 } 423 }
(...skipping 16 matching lines...) Expand all
432 } 440 }
433 441
434 /// Ends the span wrapping the call chain if it hasn't ended already. 442 /// Ends the span wrapping the call chain if it hasn't ended already.
435 void _endSpan() { 443 void _endSpan() {
436 if (_spanEnded) return; 444 if (_spanEnded) return;
437 445
438 _visitor.builder.endSpan(); 446 _visitor.builder.endSpan();
439 _spanEnded = true; 447 _spanEnded = true;
440 } 448 }
441 } 449 }
OLDNEW
« no previous file with comments | « packages/dart_style/lib/src/argument_list_visitor.dart ('k') | packages/dart_style/lib/src/chunk.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698