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

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

Issue 1355203002: Handle index expressions in the middle of call chains. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Handle chained indexes. Created 5 years, 3 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 | « example/format.dart ('k') | lib/src/source_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.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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 /// operators and must be a [MethodInvocation], [PropertyAccess] or 44 /// operators and must be a [MethodInvocation], [PropertyAccess] or
45 /// [PrefixedIdentifier]. 45 /// [PrefixedIdentifier].
46 factory CallChainVisitor(SourceVisitor visitor, Expression node) { 46 factory CallChainVisitor(SourceVisitor visitor, Expression node) {
47 var target; 47 var target;
48 48
49 // Recursively walk the chain of calls and turn the tree into a list. 49 // Recursively walk the chain of calls and turn the tree into a list.
50 var calls = []; 50 var calls = [];
51 flatten(expression) { 51 flatten(expression) {
52 target = expression; 52 target = expression;
53 53
54 if (expression is MethodInvocation && expression.target != null) { 54 // Treat index expressions where the target is a valid call in a method
55 flatten(expression.target); 55 // chain as being part of the call. Handles cases like:
56 //
57 // receiver
58 // .property
59 // .property[0]
60 // .property
61 // .property;
62 var call = expression;
63 while (call is IndexExpression) call = call.target;
64
65 if (call is MethodInvocation && call.target != null) {
66 flatten(call.target);
56 calls.add(expression); 67 calls.add(expression);
57 } else if (expression is PropertyAccess && expression.target != null) { 68 } else if (call is PropertyAccess && call.target != null) {
58 flatten(expression.target); 69 flatten(call.target);
59 calls.add(expression); 70 calls.add(expression);
60 } else if (expression is PrefixedIdentifier) { 71 } else if (call is PrefixedIdentifier) {
61 flatten(expression.prefix); 72 flatten(call.prefix);
62 calls.add(expression); 73 calls.add(expression);
63 } 74 }
64 } 75 }
65 76
66 flatten(node); 77 flatten(node);
67 78
68 // An expression that starts with a series of dotted names gets treated a 79 // An expression that starts with a series of dotted names gets treated a
69 // little specially. We don't force leading properties to split with the 80 // little specially. We don't force leading properties to split with the
70 // rest of the chain. Allows code like: 81 // rest of the chain. Allows code like:
71 // 82 //
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 139 }
129 140
130 _disableRule(); 141 _disableRule();
131 _endSpan(); 142 _endSpan();
132 143
133 if (unnest) _visitor.builder.unnest(); 144 if (unnest) _visitor.builder.unnest();
134 } 145 }
135 146
136 /// Writes [call], which must be one of the supported expression types. 147 /// Writes [call], which must be one of the supported expression types.
137 void _writeCall(Expression call) { 148 void _writeCall(Expression call) {
138 if (call is MethodInvocation) { 149 if (call is IndexExpression) {
150 _visitor.builder.nestExpression();
151 _writeCall(call.target);
152 _visitor.finishIndexExpression(call);
153 _visitor.builder.unnest();
154 } else if (call is MethodInvocation) {
139 _writeInvocation(call); 155 _writeInvocation(call);
140 } else if (call is PropertyAccess) { 156 } else if (call is PropertyAccess) {
141 _writePropertyAccess(call); 157 _visitor.token(call.operator);
158 _visitor.visit(call.propertyName);
142 } else if (call is PrefixedIdentifier) { 159 } else if (call is PrefixedIdentifier) {
143 _writePrefixedIdentifier(call); 160 _visitor.token(call.period);
161 _visitor.visit(call.identifier);
144 } else { 162 } else {
145 // Unexpected type. 163 // Unexpected type.
146 assert(false); 164 assert(false);
147 } 165 }
148 } 166 }
149 167
150 void _writeInvocation(MethodInvocation invocation) { 168 void _writeInvocation(MethodInvocation invocation) {
151 _visitor.token(invocation.operator); 169 _visitor.token(invocation.operator);
152 _visitor.token(invocation.methodName.token); 170 _visitor.token(invocation.methodName.token);
153 171
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 _calls.length == 1 && 222 _calls.length == 1 &&
205 _target is SimpleIdentifier) { 223 _target is SimpleIdentifier) {
206 _endSpan(); 224 _endSpan();
207 } 225 }
208 226
209 _visitor.visit(invocation.argumentList); 227 _visitor.visit(invocation.argumentList);
210 228
211 if (args.nestMethodArguments) _visitor.builder.endBlockArgumentNesting(); 229 if (args.nestMethodArguments) _visitor.builder.endBlockArgumentNesting();
212 } 230 }
213 231
214 void _writePropertyAccess(PropertyAccess property) {
215 _visitor.token(property.operator);
216 _visitor.visit(property.propertyName);
217 }
218
219 void _writePrefixedIdentifier(PrefixedIdentifier prefix) {
220 _visitor.token(prefix.period);
221 _visitor.visit(prefix.identifier);
222 }
223
224 /// If a [Rule] for the method chain is currently active, ends it. 232 /// If a [Rule] for the method chain is currently active, ends it.
225 void _disableRule() { 233 void _disableRule() {
226 if (_ruleEnabled == false) return; 234 if (_ruleEnabled == false) return;
227 235
228 _visitor.builder.endRule(); 236 _visitor.builder.endRule();
229 _ruleEnabled = false; 237 _ruleEnabled = false;
230 } 238 }
231 239
232 /// Creates a new method chain [Rule] if one is not already active. 240 /// Creates a new method chain [Rule] if one is not already active.
233 void _enableRule() { 241 void _enableRule() {
234 if (_ruleEnabled) return; 242 if (_ruleEnabled) return;
235 243
236 _visitor.builder.startRule(); 244 _visitor.builder.startRule();
237 _ruleEnabled = true; 245 _ruleEnabled = true;
238 } 246 }
239 247
240 /// Ends the span wrapping the call chain if it hasn't ended already. 248 /// Ends the span wrapping the call chain if it hasn't ended already.
241 void _endSpan() { 249 void _endSpan() {
242 if (_spanEnded) return; 250 if (_spanEnded) return;
243 251
244 _visitor.builder.endSpan(); 252 _visitor.builder.endSpan();
245 _spanEnded = true; 253 _spanEnded = true;
246 } 254 }
247 } 255 }
OLDNEW
« no previous file with comments | « example/format.dart ('k') | lib/src/source_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698