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

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

Issue 816773002: Add AccessSemantics support for calling typenames. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
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';
11 import 'package:analyzer/src/generated/element.dart'; 11 import 'package:analyzer/src/generated/element.dart';
12 12
13 // TODO(johnniwinther,paulberry): This should be a constant.
14 final AccessSemanticsVisitor ACCESS_SEMANTICS_VISITOR =
15 new AccessSemanticsVisitor();
16
13 /** 17 /**
14 * Enum representing the different kinds of destinations which a property 18 * Enum representing the different kinds of destinations which a property
15 * access or method or function invocation might refer to. 19 * access or method or function invocation might refer to.
16 */ 20 */
17 class AccessKind { 21 class AccessKind {
18 /** 22 /**
19 * The destination of the access is an instance method, property, or field 23 * The destination of the access is an instance method, property, or field
20 * of a class, and thus must be determined dynamically. 24 * of a class, and thus must be determined dynamically.
21 */ 25 */
22 static const AccessKind DYNAMIC = const AccessKind._('DYNAMIC'); 26 static const AccessKind DYNAMIC = const AccessKind._('DYNAMIC');
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 * The destination of the access is a property getter/setter that is defined 59 * The destination of the access is a property getter/setter that is defined
56 * statically within a class, or at top level within a library. 60 * statically within a class, or at top level within a library.
57 */ 61 */
58 static const AccessKind STATIC_PROPERTY = 62 static const AccessKind STATIC_PROPERTY =
59 const AccessKind._('STATIC_PROPERTY'); 63 const AccessKind._('STATIC_PROPERTY');
60 64
61 /** 65 /**
62 * The destination of the access is a toplevel class, function typedef, mixin 66 * The destination of the access is a toplevel class, function typedef, mixin
63 * application, or the built-in type "dynamic". 67 * application, or the built-in type "dynamic".
64 */ 68 */
65 static const AccessKind TOPLEVEL_TYPE = 69 static const AccessKind TOPLEVEL_TYPE = const AccessKind._('TOPLEVEL_TYPE');
66 const AccessKind._('TOPLEVEL_TYPE');
67 70
68 /** 71 /**
69 * The destination of the access is a type parameter of the enclosing class. 72 * The destination of the access is a type parameter of the enclosing class.
70 */ 73 */
71 static const AccessKind TYPE_PARAMETER = 74 static const AccessKind TYPE_PARAMETER = const AccessKind._('TYPE_PARAMETER');
72 const AccessKind._('TYPE_PARAMETER');
73 75
74 final String name; 76 final String name;
75 77
78 const AccessKind._(this.name);
79
76 String toString() => name; 80 String toString() => name;
77
78 const AccessKind._(this.name);
79 } 81 }
80 82
81 /** 83 /**
82 * Data structure used to classify the semantics of a property access or method 84 * Data structure used to classify the semantics of a property access or method
83 * or function invocation. 85 * or function invocation.
84 */ 86 */
85 // TODO(paulberry,johnniwinther): Support index operations in AccessSemantics. 87 // TODO(paulberry,johnniwinther): Support index operations in AccessSemantics.
86 class AccessSemantics { 88 class AccessSemantics {
87 /** 89 /**
88 * The kind of access. 90 * The kind of access.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 AccessSemantics.staticMethod(this.identifier, this.element, this.classElement, 163 AccessSemantics.staticMethod(this.identifier, this.element, this.classElement,
162 {this.isInvoke: false}) 164 {this.isInvoke: false})
163 : kind = AccessKind.STATIC_METHOD, 165 : kind = AccessKind.STATIC_METHOD,
164 target = null; 166 target = null;
165 167
166 AccessSemantics.staticProperty(this.identifier, this.element, 168 AccessSemantics.staticProperty(this.identifier, this.element,
167 this.classElement, {this.isInvoke: false}) 169 this.classElement, {this.isInvoke: false})
168 : kind = AccessKind.STATIC_PROPERTY, 170 : kind = AccessKind.STATIC_PROPERTY,
169 target = null; 171 target = null;
170 172
171 AccessSemantics.toplevelType(this.identifier, this.element) 173 AccessSemantics.toplevelType(this.identifier, this.element, {this.isInvoke:
174 false})
172 : kind = AccessKind.TOPLEVEL_TYPE, 175 : kind = AccessKind.TOPLEVEL_TYPE,
173 classElement = null, 176 classElement = null,
174 isInvoke = false,
175 target = null; 177 target = null;
176 178
177 AccessSemantics.typeParameter(this.identifier, this.element) 179 AccessSemantics.typeParameter(this.identifier, this.element, {this.isInvoke:
180 false})
178 : kind = AccessKind.TYPE_PARAMETER, 181 : kind = AccessKind.TYPE_PARAMETER,
179 classElement = null, 182 classElement = null,
180 isInvoke = false,
181 target = null; 183 target = null;
182 184
183 /** 185 /**
184 * True if this is a read access to a property, or a method tear-off. Note 186 * True if this is a read access to a property, or a method tear-off. Note
185 * that both [isRead] and [isWrite] will be true in the case of a 187 * that both [isRead] and [isWrite] will be true in the case of a
186 * read-modify-write operation (e.g. "+="). 188 * read-modify-write operation (e.g. "+=").
187 */ 189 */
188 bool get isRead => !isInvoke && identifier.inGetterContext(); 190 bool get isRead => !isInvoke && identifier.inGetterContext();
189 191
190 /** 192 /**
(...skipping 28 matching lines...) Expand all
219 sb.write('target=this.$identifier'); 221 sb.write('target=this.$identifier');
220 } else { 222 } else {
221 sb.write('target=$target.$identifier'); 223 sb.write('target=$target.$identifier');
222 } 224 }
223 } 225 }
224 sb.write(']'); 226 sb.write(']');
225 return sb.toString(); 227 return sb.toString();
226 } 228 }
227 } 229 }
228 230
229 // TODO(johnniwinther,paulberry): This should be a constant.
230 final AccessSemanticsVisitor ACCESS_SEMANTICS_VISITOR =
231 new AccessSemanticsVisitor();
232
233 // TODO(johnniwinther,paulberry): This should extend a non-recursive visitor. 231 // TODO(johnniwinther,paulberry): This should extend a non-recursive visitor.
234 class AccessSemanticsVisitor extends RecursiveAstVisitor<AccessSemantics> { 232 class AccessSemanticsVisitor extends RecursiveAstVisitor<AccessSemantics> {
235 /** 233 /**
236 * Return the semantics for [node]. 234 * Return the semantics for [node].
237 */ 235 */
238 @override 236 @override
239 AccessSemantics visitMethodInvocation(MethodInvocation node) { 237 AccessSemantics visitMethodInvocation(MethodInvocation node) {
240 Expression target = node.realTarget; 238 Expression target = node.realTarget;
241 Element staticElement = node.methodName.staticElement; 239 Element staticElement = node.methodName.staticElement;
242 if (target == null) { 240 if (target == null) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 } else if (staticElement is LocalVariableElement) { 290 } else if (staticElement is LocalVariableElement) {
293 return new AccessSemantics.localVariable( 291 return new AccessSemantics.localVariable(
294 node.methodName, 292 node.methodName,
295 staticElement, 293 staticElement,
296 isInvoke: true); 294 isInvoke: true);
297 } else if (staticElement is ParameterElement) { 295 } else if (staticElement is ParameterElement) {
298 return new AccessSemantics.parameter( 296 return new AccessSemantics.parameter(
299 node.methodName, 297 node.methodName,
300 staticElement, 298 staticElement,
301 isInvoke: true); 299 isInvoke: true);
300 } else if (staticElement is TypeParameterElement) {
301 return new AccessSemantics.typeParameter(
302 node.methodName,
303 staticElement,
304 isInvoke: true);
305 } else if (staticElement is ClassElement ||
306 staticElement is FunctionTypeAliasElement ||
307 staticElement is DynamicElementImpl) {
308 return new AccessSemantics.toplevelType(
309 node.methodName,
310 staticElement,
311 isInvoke: true);
302 } 312 }
303 } else if (target is Identifier) { 313 } else if (target is Identifier) {
304 Element targetStaticElement = target.staticElement; 314 Element targetStaticElement = target.staticElement;
305 if (targetStaticElement is PrefixElement) { 315 if (targetStaticElement is PrefixElement) {
306 if (staticElement == null) { 316 if (staticElement == null) {
307 return new AccessSemantics.dynamic( 317 return new AccessSemantics.dynamic(
308 node.methodName, 318 node.methodName,
309 null, 319 null,
310 isInvoke: true); 320 isInvoke: true);
311 } else if (staticElement is PropertyAccessorElement) { 321 } else if (staticElement is PropertyAccessorElement) {
312 if (staticElement.isSynthetic) { 322 if (staticElement.isSynthetic) {
313 return new AccessSemantics.staticField( 323 return new AccessSemantics.staticField(
314 node.methodName, 324 node.methodName,
315 staticElement.variable, 325 staticElement.variable,
316 null, 326 null,
317 isInvoke: true); 327 isInvoke: true);
318 } else { 328 } else {
319 return new AccessSemantics.staticProperty( 329 return new AccessSemantics.staticProperty(
320 node.methodName, 330 node.methodName,
321 staticElement, 331 staticElement,
322 null, 332 null,
323 isInvoke: true); 333 isInvoke: true);
324 } 334 }
335 } else if (staticElement is TypeParameterElement) {
336 return new AccessSemantics.typeParameter(
337 node.methodName,
338 staticElement,
339 isInvoke: true);
340 } else if (staticElement is ClassElement ||
341 staticElement is FunctionTypeAliasElement) {
342 return new AccessSemantics.toplevelType(
343 node.methodName,
344 staticElement,
345 isInvoke: true);
325 } else { 346 } else {
326 return new AccessSemantics.staticMethod( 347 return new AccessSemantics.staticMethod(
327 node.methodName, 348 node.methodName,
328 staticElement, 349 staticElement,
329 null, 350 null,
330 isInvoke: true); 351 isInvoke: true);
331 } 352 }
332 } else if (targetStaticElement is ClassElement) { 353 } else if (targetStaticElement is ClassElement) {
333 if (staticElement is PropertyAccessorElement) { 354 if (staticElement is PropertyAccessorElement) {
334 if (staticElement.isSynthetic) { 355 if (staticElement.isSynthetic) {
(...skipping 23 matching lines...) Expand all
358 379
359 /** 380 /**
360 * Return the access semantics for [node]. 381 * Return the access semantics for [node].
361 */ 382 */
362 @override 383 @override
363 AccessSemantics visitPrefixedIdentifier(PrefixedIdentifier node) { 384 AccessSemantics visitPrefixedIdentifier(PrefixedIdentifier node) {
364 return _classifyPrefixed(node.prefix, node.identifier); 385 return _classifyPrefixed(node.prefix, node.identifier);
365 } 386 }
366 387
367 /** 388 /**
368 * Helper function for classifying an expression of type
369 * Identifier.SimpleIdentifier.
370 */
371 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
372 Element lhsElement = lhs.staticElement;
373 Element rhsElement = rhs.staticElement;
374 if (lhsElement is PrefixElement) {
375 if (rhsElement is PropertyAccessorElement) {
376 if (rhsElement.isSynthetic) {
377 return new AccessSemantics.staticField(rhs, rhsElement.variable, null) ;
378 } else {
379 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
380 }
381 } else if (rhsElement is FunctionElement) {
382 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
383 } else if (rhsElement is ClassElement ||
384 rhsElement is FunctionTypeAliasElement) {
385 return new AccessSemantics.toplevelType(rhs, rhsElement);
386 } else {
387 return new AccessSemantics.dynamic(rhs, null);
388 }
389 } else if (lhsElement is ClassElement) {
390 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
391 return new AccessSemantics.staticField(
392 rhs,
393 rhsElement.variable,
394 lhsElement);
395 } else if (rhsElement is MethodElement) {
396 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
397 } else {
398 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
399 }
400 } else {
401 return new AccessSemantics.dynamic(rhs, lhs);
402 }
403 }
404
405 /**
406 * Return the access semantics for [node]. 389 * Return the access semantics for [node].
407 */ 390 */
408 @override 391 @override
409 AccessSemantics visitPropertyAccess(PropertyAccess node) { 392 AccessSemantics visitPropertyAccess(PropertyAccess node) {
410 if (node.target is Identifier) { 393 if (node.target is Identifier) {
411 return _classifyPrefixed(node.target, node.propertyName); 394 return _classifyPrefixed(node.target, node.propertyName);
412 } else { 395 } else {
413 return new AccessSemantics.dynamic(node.propertyName, node.realTarget); 396 return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
414 } 397 }
415 } 398 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 staticElement.enclosingElement); 465 staticElement.enclosingElement);
483 } else if (staticElement is TypeParameterElement) { 466 } else if (staticElement is TypeParameterElement) {
484 return new AccessSemantics.typeParameter(node, staticElement); 467 return new AccessSemantics.typeParameter(node, staticElement);
485 } else if (staticElement is ClassElement || 468 } else if (staticElement is ClassElement ||
486 staticElement is FunctionTypeAliasElement || 469 staticElement is FunctionTypeAliasElement ||
487 staticElement is DynamicElementImpl) { 470 staticElement is DynamicElementImpl) {
488 return new AccessSemantics.toplevelType(node, staticElement); 471 return new AccessSemantics.toplevelType(node, staticElement);
489 } 472 }
490 return new AccessSemantics.dynamic(node, null); 473 return new AccessSemantics.dynamic(node, null);
491 } 474 }
492 } 475
476 /**
477 * Helper function for classifying an expression of type
478 * Identifier.SimpleIdentifier.
479 */
480 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
481 Element lhsElement = lhs.staticElement;
482 Element rhsElement = rhs.staticElement;
483 if (lhsElement is PrefixElement) {
484 if (rhsElement is PropertyAccessorElement) {
485 if (rhsElement.isSynthetic) {
486 return new AccessSemantics.staticField(
487 rhs,
488 rhsElement.variable,
489 null);
490 } else {
491 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
492 }
493 } else if (rhsElement is FunctionElement) {
494 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
495 } else if (rhsElement is ClassElement ||
496 rhsElement is FunctionTypeAliasElement) {
497 return new AccessSemantics.toplevelType(rhs, rhsElement);
498 } else {
499 return new AccessSemantics.dynamic(rhs, null);
500 }
501 } else if (lhsElement is ClassElement) {
502 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
503 return new AccessSemantics.staticField(
504 rhs,
505 rhsElement.variable,
506 lhsElement);
507 } else if (rhsElement is MethodElement) {
508 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
509 } else {
510 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
511 }
512 } else {
513 return new AccessSemantics.dynamic(rhs, lhs);
514 }
515 }
516 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698