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

Side by Side Diff: pkg/analyzer2dart/lib/src/identifier_semantics.dart

Issue 652403005: Support assignment of locals in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | pkg/analyzer2dart/lib/src/modely.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 /** 5 /**
6 * Code for classifying the semantics of identifiers appearing in a Dart file. 6 * Code for classifying the semantics of identifiers appearing in a Dart file.
7 */ 7 */
8 library analyzer2dart.identifierSemantics; 8 library analyzer2dart.identifierSemantics;
9 9
10 import 'package:analyzer/analyzer.dart'; 10 import 'package:analyzer/analyzer.dart';
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 62
63 String toString() => name; 63 String toString() => name;
64 64
65 const AccessKind._(this.name); 65 const AccessKind._(this.name);
66 } 66 }
67 67
68 /** 68 /**
69 * Data structure used to classify the semantics of a property access or method 69 * Data structure used to classify the semantics of a property access or method
70 * or function invocation. 70 * or function invocation.
71 */ 71 */
72 // TODO(paulberry,johnniwinther): Support index operations in AccessSemantics.
72 class AccessSemantics { 73 class AccessSemantics {
73 /** 74 /**
74 * The kind of access. 75 * The kind of access.
75 */ 76 */
76 final AccessKind kind; 77 final AccessKind kind;
77 78
78 /** 79 /**
79 * The identifier being used to access the property, method, or function. 80 * The identifier being used to access the property, method, or function.
80 */ 81 */
81 final SimpleIdentifier identifier; 82 final SimpleIdentifier identifier;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 sb.write('target=this.$identifier'); 193 sb.write('target=this.$identifier');
193 } else { 194 } else {
194 sb.write('target=$target.$identifier'); 195 sb.write('target=$target.$identifier');
195 } 196 }
196 } 197 }
197 sb.write(']'); 198 sb.write(']');
198 return sb.toString(); 199 return sb.toString();
199 } 200 }
200 } 201 }
201 202
202 /** 203 // TODO(johnniwinther,paulberry): This should be a constant.
203 * Return the semantics for [node]. 204 final AccessSemanticsVisitor ACCESS_SEMANTICS_VISITOR =
204 */ 205 new AccessSemanticsVisitor();
205 AccessSemantics classifyMethodInvocation(MethodInvocation node) { 206
206 Expression target = node.realTarget; 207 // TODO(johnniwinther,paulberry): This should extend a non-recursive visitor.
207 Element staticElement = node.methodName.staticElement; 208 class AccessSemanticsVisitor extends RecursiveAstVisitor<AccessSemantics> {
208 if (target == null) { 209 /**
209 if (staticElement is FunctionElement) { 210 * Return the semantics for [node].
210 if (staticElement.enclosingElement is CompilationUnitElement) { 211 */
212 @override
213 AccessSemantics visitMethodInvocation(MethodInvocation node) {
214 Expression target = node.realTarget;
215 Element staticElement = node.methodName.staticElement;
216 if (target == null) {
217 if (staticElement is FunctionElement) {
218 if (staticElement.enclosingElement is CompilationUnitElement) {
219 return new AccessSemantics.staticMethod(
220 node.methodName,
221 staticElement,
222 null,
223 isInvoke: true);
224 } else {
225 return new AccessSemantics.localFunction(
226 node.methodName,
227 staticElement,
228 isInvoke: true);
229 }
230 } else if (staticElement is MethodElement && staticElement.isStatic) {
211 return new AccessSemantics.staticMethod( 231 return new AccessSemantics.staticMethod(
212 node.methodName, 232 node.methodName,
213 staticElement, 233 staticElement,
214 null, 234 staticElement.enclosingElement,
215 isInvoke: true); 235 isInvoke: true);
216 } else { 236 } else if (staticElement is PropertyAccessorElement) {
217 return new AccessSemantics.localFunction( 237 if (staticElement.isSynthetic) {
238 if (staticElement.enclosingElement is CompilationUnitElement) {
239 return new AccessSemantics.staticField(
240 node.methodName,
241 staticElement.variable,
242 null,
243 isInvoke: true);
244 } else if (staticElement.isStatic) {
245 return new AccessSemantics.staticField(
246 node.methodName,
247 staticElement.variable,
248 staticElement.enclosingElement,
249 isInvoke: true);
250 }
251 } else {
252 if (staticElement.enclosingElement is CompilationUnitElement) {
253 return new AccessSemantics.staticProperty(
254 node.methodName,
255 staticElement,
256 null,
257 isInvoke: true);
258 } else if (staticElement.isStatic) {
259 return new AccessSemantics.staticProperty(
260 node.methodName,
261 staticElement,
262 staticElement.enclosingElement,
263 isInvoke: true);
264 }
265 }
266 } else if (staticElement is LocalVariableElement) {
267 return new AccessSemantics.localVariable(
218 node.methodName, 268 node.methodName,
219 staticElement, 269 staticElement,
220 isInvoke: true); 270 isInvoke: true);
221 } 271 } else if (staticElement is ParameterElement) {
222 } else if (staticElement is MethodElement && staticElement.isStatic) { 272 return new AccessSemantics.parameter(
223 return new AccessSemantics.staticMethod( 273 node.methodName,
224 node.methodName, 274 staticElement,
225 staticElement, 275 isInvoke: true);
226 staticElement.enclosingElement, 276 }
227 isInvoke: true); 277 } else if (target is Identifier) {
228 } else if (staticElement is PropertyAccessorElement) { 278 Element targetStaticElement = target.staticElement;
279 if (targetStaticElement is PrefixElement) {
280 if (staticElement == null) {
281 return new AccessSemantics.dynamic(
282 node.methodName,
283 null,
284 isInvoke: true);
285 } else if (staticElement is PropertyAccessorElement) {
286 if (staticElement.isSynthetic) {
287 return new AccessSemantics.staticField(
288 node.methodName,
289 staticElement.variable,
290 null,
291 isInvoke: true);
292 } else {
293 return new AccessSemantics.staticProperty(
294 node.methodName,
295 staticElement,
296 null,
297 isInvoke: true);
298 }
299 } else {
300 return new AccessSemantics.staticMethod(
301 node.methodName,
302 staticElement,
303 null,
304 isInvoke: true);
305 }
306 } else if (targetStaticElement is ClassElement) {
307 if (staticElement is PropertyAccessorElement) {
308 if (staticElement.isSynthetic) {
309 return new AccessSemantics.staticField(
310 node.methodName,
311 staticElement.variable,
312 targetStaticElement,
313 isInvoke: true);
314 } else {
315 return new AccessSemantics.staticProperty(
316 node.methodName,
317 staticElement,
318 targetStaticElement,
319 isInvoke: true);
320 }
321 } else {
322 return new AccessSemantics.staticMethod(
323 node.methodName,
324 staticElement,
325 targetStaticElement,
326 isInvoke: true);
327 }
328 }
329 }
330 return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
331 }
332
333 /**
334 * Return the access semantics for [node].
335 */
336 @override
337 AccessSemantics visitPrefixedIdentifier(PrefixedIdentifier node) {
338 return _classifyPrefixed(node.prefix, node.identifier);
339 }
340
341 /**
342 * Helper function for classifying an expression of type
343 * Identifier.SimpleIdentifier.
344 */
345 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
346 Element lhsElement = lhs.staticElement;
347 Element rhsElement = rhs.staticElement;
348 if (lhsElement is PrefixElement) {
349 if (rhsElement is PropertyAccessorElement) {
350 if (rhsElement.isSynthetic) {
351 return new AccessSemantics.staticField(rhs, rhsElement.variable, null) ;
352 } else {
353 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
354 }
355 } else if (rhsElement is FunctionElement) {
356 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
357 } else {
358 return new AccessSemantics.dynamic(rhs, null);
359 }
360 } else if (lhsElement is ClassElement) {
361 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
362 return new AccessSemantics.staticField(
363 rhs,
364 rhsElement.variable,
365 lhsElement);
366 } else if (rhsElement is MethodElement) {
367 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
368 } else {
369 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
370 }
371 } else {
372 return new AccessSemantics.dynamic(rhs, lhs);
373 }
374 }
375
376 /**
377 * Return the access semantics for [node].
378 */
379 @override
380 AccessSemantics visitPropertyAccess(PropertyAccess node) {
381 if (node.target is Identifier) {
382 return _classifyPrefixed(node.target, node.propertyName);
383 } else {
384 return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
385 }
386 }
387
388 /**
389 * Return the access semantics for [node].
390 *
391 * Note: if [node] is the right hand side of a [PropertyAccess] or
392 * [PrefixedIdentifier], or the method name of a [MethodInvocation], the retur n
393 * value is null, since the semantics are determined by the parent. In
394 * practice these cases should never arise because the parent will visit the
395 * parent node before visiting this one.
396 */
397 @override
398 AccessSemantics visitSimpleIdentifier(SimpleIdentifier node) {
399 AstNode parent = node.parent;
400 if (node.inDeclarationContext()) {
401 // This identifier is a declaration, not a use.
402 return null;
403 }
404 if (parent is TypeName) {
405 // TODO(paulberry): handle this case. Or, perhaps it would be better to
406 // require clients not to visit the children of a TypeName when visiting
407 // the AST structure.
408 //
409 // TODO(paulberry): be sure to consider type literals, e.g.:
410 // class A {}
411 // var a = A;
412 return null;
413 }
414 if ((parent is PropertyAccess && parent.propertyName == node) ||
415 (parent is PrefixedIdentifier && parent.identifier == node) ||
416 (parent is MethodInvocation && parent.methodName == node)) {
417 // The access semantics are determined by the parent.
418 return null;
419 }
420 // TODO(paulberry): handle PrefixElement.
421 Element staticElement = node.staticElement;
422 if (staticElement is PropertyAccessorElement) {
229 if (staticElement.isSynthetic) { 423 if (staticElement.isSynthetic) {
230 if (staticElement.enclosingElement is CompilationUnitElement) { 424 if (staticElement.enclosingElement is CompilationUnitElement) {
231 return new AccessSemantics.staticField( 425 return new AccessSemantics.staticField(
232 node.methodName, 426 node,
233 staticElement.variable, 427 staticElement.variable,
234 null, 428 null);
235 isInvoke: true);
236 } else if (staticElement.isStatic) { 429 } else if (staticElement.isStatic) {
237 return new AccessSemantics.staticField( 430 return new AccessSemantics.staticField(
238 node.methodName, 431 node,
239 staticElement.variable, 432 staticElement.variable,
240 staticElement.enclosingElement, 433 staticElement.enclosingElement);
241 isInvoke: true);
242 } 434 }
243 } else { 435 } else {
244 if (staticElement.enclosingElement is CompilationUnitElement) { 436 if (staticElement.enclosingElement is CompilationUnitElement) {
245 return new AccessSemantics.staticProperty( 437 return new AccessSemantics.staticProperty(node, staticElement, null);
246 node.methodName,
247 staticElement,
248 null,
249 isInvoke: true);
250 } else if (staticElement.isStatic) { 438 } else if (staticElement.isStatic) {
251 return new AccessSemantics.staticProperty( 439 return new AccessSemantics.staticProperty(
252 node.methodName, 440 node,
253 staticElement, 441 staticElement,
254 staticElement.enclosingElement, 442 staticElement.enclosingElement);
255 isInvoke: true);
256 } 443 }
257 } 444 }
258 } else if (staticElement is LocalVariableElement) { 445 } else if (staticElement is LocalVariableElement) {
259 return new AccessSemantics.localVariable( 446 return new AccessSemantics.localVariable(node, staticElement);
260 node.methodName, 447 } else if (staticElement is ParameterElement) {
448 return new AccessSemantics.parameter(node, staticElement);
449 } else if (staticElement is FunctionElement) {
450 if (staticElement.enclosingElement is CompilationUnitElement) {
451 return new AccessSemantics.staticMethod(node, staticElement, null);
452 } else {
453 return new AccessSemantics.localFunction(node, staticElement);
454 }
455 } else if (staticElement is MethodElement && staticElement.isStatic) {
456 return new AccessSemantics.staticMethod(
457 node,
261 staticElement, 458 staticElement,
262 isInvoke: true); 459 staticElement.enclosingElement);
263 } else if (staticElement is ParameterElement) { 460 }
264 return new AccessSemantics.parameter( 461 return new AccessSemantics.dynamic(node, null);
265 node.methodName, 462 }
266 staticElement, 463 }
267 isInvoke: true);
268 }
269 } else if (target is Identifier) {
270 Element targetStaticElement = target.staticElement;
271 if (targetStaticElement is PrefixElement) {
272 if (staticElement == null) {
273 return new AccessSemantics.dynamic(
274 node.methodName,
275 null,
276 isInvoke: true);
277 } else if (staticElement is PropertyAccessorElement) {
278 if (staticElement.isSynthetic) {
279 return new AccessSemantics.staticField(
280 node.methodName,
281 staticElement.variable,
282 null,
283 isInvoke: true);
284 } else {
285 return new AccessSemantics.staticProperty(
286 node.methodName,
287 staticElement,
288 null,
289 isInvoke: true);
290 }
291 } else {
292 return new AccessSemantics.staticMethod(
293 node.methodName,
294 staticElement,
295 null,
296 isInvoke: true);
297 }
298 } else if (targetStaticElement is ClassElement) {
299 if (staticElement is PropertyAccessorElement) {
300 if (staticElement.isSynthetic) {
301 return new AccessSemantics.staticField(
302 node.methodName,
303 staticElement.variable,
304 targetStaticElement,
305 isInvoke: true);
306 } else {
307 return new AccessSemantics.staticProperty(
308 node.methodName,
309 staticElement,
310 targetStaticElement,
311 isInvoke: true);
312 }
313 } else {
314 return new AccessSemantics.staticMethod(
315 node.methodName,
316 staticElement,
317 targetStaticElement,
318 isInvoke: true);
319 }
320 }
321 }
322 return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
323 }
324
325 /**
326 * Return the access semantics for [node].
327 */
328 AccessSemantics classifyPrefixedIdentifier(PrefixedIdentifier node) {
329 return _classifyPrefixed(node.prefix, node.identifier);
330 }
331
332 /**
333 * Helper function for classifying an expression of type
334 * Identifier.SimpleIdentifier.
335 */
336 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
337 Element lhsElement = lhs.staticElement;
338 Element rhsElement = rhs.staticElement;
339 if (lhsElement is PrefixElement) {
340 if (rhsElement is PropertyAccessorElement) {
341 if (rhsElement.isSynthetic) {
342 return new AccessSemantics.staticField(rhs, rhsElement.variable, null);
343 } else {
344 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
345 }
346 } else if (rhsElement is FunctionElement) {
347 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
348 } else {
349 return new AccessSemantics.dynamic(rhs, null);
350 }
351 } else if (lhsElement is ClassElement) {
352 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
353 return new AccessSemantics.staticField(
354 rhs,
355 rhsElement.variable,
356 lhsElement);
357 } else if (rhsElement is MethodElement) {
358 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
359 } else {
360 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
361 }
362 } else {
363 return new AccessSemantics.dynamic(rhs, lhs);
364 }
365 }
366
367 /**
368 * Return the access semantics for [node].
369 */
370 AccessSemantics classifyPropertyAccess(PropertyAccess node) {
371 if (node.target is Identifier) {
372 return _classifyPrefixed(node.target, node.propertyName);
373 } else {
374 return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
375 }
376 }
377
378 /**
379 * Return the access semantics for [node].
380 *
381 * Note: if [node] is the right hand side of a [PropertyAccess] or
382 * [PrefixedIdentifier], or the method name of a [MethodInvocation], the return
383 * value is null, since the semantics are determined by the parent. In
384 * practice these cases should never arise because the parent will visit the
385 * parent node before visiting this one.
386 */
387 AccessSemantics classifySimpleIdentifier(SimpleIdentifier node) {
388 AstNode parent = node.parent;
389 if (node.inDeclarationContext()) {
390 // This identifier is a declaration, not a use.
391 return null;
392 }
393 if (parent is TypeName) {
394 // TODO(paulberry): handle this case. Or, perhaps it would be better to
395 // require clients not to visit the children of a TypeName when visiting
396 // the AST structure.
397 //
398 // TODO(paulberry): be sure to consider type literals, e.g.:
399 // class A {}
400 // var a = A;
401 return null;
402 }
403 if ((parent is PropertyAccess && parent.propertyName == node) ||
404 (parent is PrefixedIdentifier && parent.identifier == node) ||
405 (parent is MethodInvocation && parent.methodName == node)) {
406 // The access semantics are determined by the parent.
407 return null;
408 }
409 // TODO(paulberry): handle PrefixElement.
410 Element staticElement = node.staticElement;
411 if (staticElement is PropertyAccessorElement) {
412 if (staticElement.isSynthetic) {
413 if (staticElement.enclosingElement is CompilationUnitElement) {
414 return new AccessSemantics.staticField(
415 node,
416 staticElement.variable,
417 null);
418 } else if (staticElement.isStatic) {
419 return new AccessSemantics.staticField(
420 node,
421 staticElement.variable,
422 staticElement.enclosingElement);
423 }
424 } else {
425 if (staticElement.enclosingElement is CompilationUnitElement) {
426 return new AccessSemantics.staticProperty(node, staticElement, null);
427 } else if (staticElement.isStatic) {
428 return new AccessSemantics.staticProperty(
429 node,
430 staticElement,
431 staticElement.enclosingElement);
432 }
433 }
434 } else if (staticElement is LocalVariableElement) {
435 return new AccessSemantics.localVariable(node, staticElement);
436 } else if (staticElement is ParameterElement) {
437 return new AccessSemantics.parameter(node, staticElement);
438 } else if (staticElement is FunctionElement) {
439 if (staticElement.enclosingElement is CompilationUnitElement) {
440 return new AccessSemantics.staticMethod(node, staticElement, null);
441 } else {
442 return new AccessSemantics.localFunction(node, staticElement);
443 }
444 } else if (staticElement is MethodElement && staticElement.isStatic) {
445 return new AccessSemantics.staticMethod(
446 node,
447 staticElement,
448 staticElement.enclosingElement);
449 }
450 return new AccessSemantics.dynamic(node, null);
451 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | pkg/analyzer2dart/lib/src/modely.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698