Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 */ | 51 */ |
| 52 static const AccessKind STATIC_METHOD = const AccessKind._('STATIC_METHOD'); | 52 static const AccessKind STATIC_METHOD = const AccessKind._('STATIC_METHOD'); |
| 53 | 53 |
| 54 /** | 54 /** |
| 55 * The destination of the access is a property getter/setter that is defined | 55 * 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. | 56 * statically within a class, or at top level within a library. |
| 57 */ | 57 */ |
| 58 static const AccessKind STATIC_PROPERTY = | 58 static const AccessKind STATIC_PROPERTY = |
| 59 const AccessKind._('STATIC_PROPERTY'); | 59 const AccessKind._('STATIC_PROPERTY'); |
| 60 | 60 |
| 61 /** | |
| 62 * The destination of the access is a toplevel class. | |
| 63 */ | |
| 64 static const AccessKind TOPLEVEL_CLASS = | |
| 65 const AccessKind._('TOPLEVEL_CLASS'); | |
| 66 | |
| 67 /** | |
| 68 * The destination of the access is a type parameter of the enclosing class. | |
| 69 */ | |
| 70 static const AccessKind TYPE_PARAMETER = | |
| 71 const AccessKind._('TYPE_PARAMETER'); | |
| 72 | |
| 61 final String name; | 73 final String name; |
| 62 | 74 |
| 63 String toString() => name; | 75 String toString() => name; |
| 64 | 76 |
| 65 const AccessKind._(this.name); | 77 const AccessKind._(this.name); |
| 66 } | 78 } |
| 67 | 79 |
| 68 /** | 80 /** |
| 69 * Data structure used to classify the semantics of a property access or method | 81 * Data structure used to classify the semantics of a property access or method |
| 70 * or function invocation. | 82 * or function invocation. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 84 /** | 96 /** |
| 85 * The element being accessed, if statically known. This will be null if | 97 * The element being accessed, if statically known. This will be null if |
| 86 * [kind] is DYNAMIC or if the element is undefined (e.g. an attempt to | 98 * [kind] is DYNAMIC or if the element is undefined (e.g. an attempt to |
| 87 * access a non-existent static method in a class). | 99 * access a non-existent static method in a class). |
| 88 */ | 100 */ |
| 89 final Element element; | 101 final Element element; |
| 90 | 102 |
| 91 /** | 103 /** |
| 92 * The class containing the element being accessed, if this is a static | 104 * The class containing the element being accessed, if this is a static |
| 93 * reference to an element in a class. This will be null if [kind] is | 105 * reference to an element in a class. This will be null if [kind] is |
| 94 * DYNAMIC, LOCAL_FUNCTION, LOCAL_VARIABLE, or PARAMETER, or if the element | 106 * DYNAMIC, LOCAL_FUNCTION, LOCAL_VARIABLE, PARAMETER, TOPLEVEL_CLASS, or |
| 95 * being accessed is defined at toplevel within a library. | 107 * TYPE_PARAMETER, or if the element being accessed is defined at toplevel |
| 108 * within a library. | |
| 96 * | 109 * |
| 97 * Note: it is possible for [classElement] to be non-null and for [element] | 110 * Note: it is possible for [classElement] to be non-null and for [element] |
| 98 * to be null; for example this occurs if the element being accessed is a | 111 * to be null; for example this occurs if the element being accessed is a |
| 99 * non-existent static method or field inside an existing class. | 112 * non-existent static method or field inside an existing class. |
| 100 */ | 113 */ |
| 101 final ClassElement classElement; | 114 final ClassElement classElement; |
| 102 | 115 |
| 103 // TODO(paulberry): would it also be useful to store the libraryElement? | 116 // TODO(paulberry): would it also be useful to store the libraryElement? |
| 104 | 117 |
| 105 /** | 118 /** |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 AccessSemantics.staticMethod(this.identifier, this.element, this.classElement, | 160 AccessSemantics.staticMethod(this.identifier, this.element, this.classElement, |
| 148 {this.isInvoke: false}) | 161 {this.isInvoke: false}) |
| 149 : kind = AccessKind.STATIC_METHOD, | 162 : kind = AccessKind.STATIC_METHOD, |
| 150 target = null; | 163 target = null; |
| 151 | 164 |
| 152 AccessSemantics.staticProperty(this.identifier, this.element, | 165 AccessSemantics.staticProperty(this.identifier, this.element, |
| 153 this.classElement, {this.isInvoke: false}) | 166 this.classElement, {this.isInvoke: false}) |
| 154 : kind = AccessKind.STATIC_PROPERTY, | 167 : kind = AccessKind.STATIC_PROPERTY, |
| 155 target = null; | 168 target = null; |
| 156 | 169 |
| 170 AccessSemantics.toplevelClass(this.identifier, this.element) | |
| 171 : kind = AccessKind.TOPLEVEL_CLASS, | |
| 172 classElement = null, | |
| 173 isInvoke = false, | |
| 174 target = null; | |
| 175 | |
| 176 AccessSemantics.typeParameter(this.identifier, this.element) | |
| 177 : kind = AccessKind.TYPE_PARAMETER, | |
| 178 classElement = null, | |
| 179 isInvoke = false, | |
| 180 target = null; | |
| 181 | |
| 157 /** | 182 /** |
| 158 * True if this is a read access to a property, or a method tear-off. Note | 183 * True if this is a read access to a property, or a method tear-off. Note |
| 159 * that both [isRead] and [isWrite] will be true in the case of a | 184 * that both [isRead] and [isWrite] will be true in the case of a |
| 160 * read-modify-write operation (e.g. "+="). | 185 * read-modify-write operation (e.g. "+="). |
| 161 */ | 186 */ |
| 162 bool get isRead => !isInvoke && identifier.inGetterContext(); | 187 bool get isRead => !isInvoke && identifier.inGetterContext(); |
| 163 | 188 |
| 164 /** | 189 /** |
| 165 * True if this is a write access to a property, or an (erroneous) attempt to | 190 * True if this is a write access to a property, or an (erroneous) attempt to |
| 166 * write to a method. Note that both [isRead] and [isWrite] will be true in | 191 * write to a method. Note that both [isRead] and [isWrite] will be true in |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 Element rhsElement = rhs.staticElement; | 372 Element rhsElement = rhs.staticElement; |
| 348 if (lhsElement is PrefixElement) { | 373 if (lhsElement is PrefixElement) { |
| 349 if (rhsElement is PropertyAccessorElement) { | 374 if (rhsElement is PropertyAccessorElement) { |
| 350 if (rhsElement.isSynthetic) { | 375 if (rhsElement.isSynthetic) { |
| 351 return new AccessSemantics.staticField(rhs, rhsElement.variable, null) ; | 376 return new AccessSemantics.staticField(rhs, rhsElement.variable, null) ; |
| 352 } else { | 377 } else { |
| 353 return new AccessSemantics.staticProperty(rhs, rhsElement, null); | 378 return new AccessSemantics.staticProperty(rhs, rhsElement, null); |
| 354 } | 379 } |
| 355 } else if (rhsElement is FunctionElement) { | 380 } else if (rhsElement is FunctionElement) { |
| 356 return new AccessSemantics.staticMethod(rhs, rhsElement, null); | 381 return new AccessSemantics.staticMethod(rhs, rhsElement, null); |
| 382 } else if (rhsElement is ClassElement) { | |
| 383 return new AccessSemantics.toplevelClass(rhs, rhsElement); | |
| 357 } else { | 384 } else { |
| 358 return new AccessSemantics.dynamic(rhs, null); | 385 return new AccessSemantics.dynamic(rhs, null); |
| 359 } | 386 } |
| 360 } else if (lhsElement is ClassElement) { | 387 } else if (lhsElement is ClassElement) { |
| 361 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) { | 388 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) { |
| 362 return new AccessSemantics.staticField( | 389 return new AccessSemantics.staticField( |
| 363 rhs, | 390 rhs, |
| 364 rhsElement.variable, | 391 rhsElement.variable, |
| 365 lhsElement); | 392 lhsElement); |
| 366 } else if (rhsElement is MethodElement) { | 393 } else if (rhsElement is MethodElement) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 395 * parent node before visiting this one. | 422 * parent node before visiting this one. |
| 396 */ | 423 */ |
| 397 @override | 424 @override |
| 398 AccessSemantics visitSimpleIdentifier(SimpleIdentifier node) { | 425 AccessSemantics visitSimpleIdentifier(SimpleIdentifier node) { |
| 399 AstNode parent = node.parent; | 426 AstNode parent = node.parent; |
| 400 if (node.inDeclarationContext()) { | 427 if (node.inDeclarationContext()) { |
| 401 // This identifier is a declaration, not a use. | 428 // This identifier is a declaration, not a use. |
| 402 return null; | 429 return null; |
| 403 } | 430 } |
| 404 if (parent is TypeName) { | 431 if (parent is TypeName) { |
| 405 // TODO(paulberry): handle this case. Or, perhaps it would be better to | 432 // TODO(paulberry): do we need to handle this case? |
| 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; | 433 return null; |
| 413 } | 434 } |
| 414 if ((parent is PropertyAccess && parent.propertyName == node) || | 435 if ((parent is PropertyAccess && parent.propertyName == node) || |
| 415 (parent is PrefixedIdentifier && parent.identifier == node) || | 436 (parent is PrefixedIdentifier && parent.identifier == node) || |
| 416 (parent is MethodInvocation && parent.methodName == node)) { | 437 (parent is MethodInvocation && parent.methodName == node)) { |
| 417 // The access semantics are determined by the parent. | 438 // The access semantics are determined by the parent. |
| 418 return null; | 439 return null; |
| 419 } | 440 } |
| 420 // TODO(paulberry): handle PrefixElement. | 441 // TODO(paulberry): handle PrefixElement. |
| 421 Element staticElement = node.staticElement; | 442 Element staticElement = node.staticElement; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 450 if (staticElement.enclosingElement is CompilationUnitElement) { | 471 if (staticElement.enclosingElement is CompilationUnitElement) { |
| 451 return new AccessSemantics.staticMethod(node, staticElement, null); | 472 return new AccessSemantics.staticMethod(node, staticElement, null); |
| 452 } else { | 473 } else { |
| 453 return new AccessSemantics.localFunction(node, staticElement); | 474 return new AccessSemantics.localFunction(node, staticElement); |
| 454 } | 475 } |
| 455 } else if (staticElement is MethodElement && staticElement.isStatic) { | 476 } else if (staticElement is MethodElement && staticElement.isStatic) { |
| 456 return new AccessSemantics.staticMethod( | 477 return new AccessSemantics.staticMethod( |
| 457 node, | 478 node, |
| 458 staticElement, | 479 staticElement, |
| 459 staticElement.enclosingElement); | 480 staticElement.enclosingElement); |
| 481 } else if (staticElement is TypeParameterElement) { | |
| 482 return new AccessSemantics.typeParameter(node, staticElement); | |
| 483 } else if (staticElement is ClassElement) { | |
| 484 return new AccessSemantics.toplevelClass(node, staticElement); | |
|
Johnni Winther
2014/11/11 12:49:45
How do you handle 'dynamic' as a type literal?
Paul Berry
2014/11/11 13:22:34
Whoops, I forgot to handle this case. I also forg
| |
| 460 } | 485 } |
| 461 return new AccessSemantics.dynamic(node, null); | 486 return new AccessSemantics.dynamic(node, null); |
| 462 } | 487 } |
| 463 } | 488 } |
| OLD | NEW |