| 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 /** |
| 6 * This library is deprecated. Please convert all references to this library to |
| 7 * reference one of the following public libraries: |
| 8 * * package:analyzer/dart/element/element.dart |
| 9 * * package:analyzer/dart/element/type.dart |
| 10 * * package:analyzer/dart/element/visitor.dart |
| 11 * |
| 12 * If your code is using API's not available in these public libraries, please |
| 13 * contact the analyzer team to either find an alternate API or have the API you |
| 14 * depend on added to the public API. |
| 15 */ |
| 5 library analyzer.src.generated.element; | 16 library analyzer.src.generated.element; |
| 6 | 17 |
| 7 import 'dart:collection'; | |
| 8 import 'dart:math' show min; | |
| 9 | |
| 10 import 'package:analyzer/dart/element/element.dart'; | |
| 11 import 'package:analyzer/dart/element/type.dart'; | |
| 12 import 'package:analyzer/dart/element/visitor.dart'; | |
| 13 import 'package:analyzer/src/generated/ast.dart'; | |
| 14 import 'package:analyzer/src/generated/constant.dart' | |
| 15 show DartObject, EvaluationResultImpl; | |
| 16 import 'package:analyzer/src/generated/engine.dart' | |
| 17 show AnalysisContext, AnalysisEngine, AnalysisException; | |
| 18 import 'package:analyzer/src/generated/java_core.dart'; | |
| 19 import 'package:analyzer/src/generated/java_engine.dart'; | |
| 20 import 'package:analyzer/src/generated/resolver.dart'; | |
| 21 import 'package:analyzer/src/generated/scanner.dart' show Keyword; | |
| 22 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; | |
| 23 import 'package:analyzer/src/generated/source.dart'; | |
| 24 import 'package:analyzer/src/generated/utilities_collection.dart'; | |
| 25 import 'package:analyzer/src/generated/utilities_dart.dart'; | |
| 26 import 'package:analyzer/src/generated/utilities_general.dart'; | |
| 27 | |
| 28 export 'package:analyzer/dart/element/element.dart'; | 18 export 'package:analyzer/dart/element/element.dart'; |
| 29 export 'package:analyzer/dart/element/type.dart'; | 19 export 'package:analyzer/dart/element/type.dart'; |
| 30 export 'package:analyzer/dart/element/visitor.dart'; | 20 export 'package:analyzer/dart/element/visitor.dart'; |
| 31 | 21 export 'package:analyzer/src/dart/element/element.dart'; |
| 32 /** | 22 export 'package:analyzer/src/dart/element/member.dart'; |
| 33 * For AST nodes that could be in both the getter and setter contexts | 23 export 'package:analyzer/src/dart/element/type.dart'; |
| 34 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved | |
| 35 * elements are stored in the AST node, in an [AuxiliaryElements]. Because | |
| 36 * resolved elements are either statically resolved or resolved using propagated | |
| 37 * type information, this class is a wrapper for a pair of [ExecutableElement]s, | |
| 38 * not just a single [ExecutableElement]. | |
| 39 */ | |
| 40 class AuxiliaryElements { | |
| 41 /** | |
| 42 * The element based on propagated type information, or `null` if the AST | |
| 43 * structure has not been resolved or if the node could not be resolved. | |
| 44 */ | |
| 45 final ExecutableElement propagatedElement; | |
| 46 | |
| 47 /** | |
| 48 * The element based on static type information, or `null` if the AST | |
| 49 * structure has not been resolved or if the node could not be resolved. | |
| 50 */ | |
| 51 final ExecutableElement staticElement; | |
| 52 | |
| 53 /** | |
| 54 * Initialize a newly created pair to have both the [staticElement] and the | |
| 55 * [propagatedElement]. | |
| 56 */ | |
| 57 AuxiliaryElements(this.staticElement, this.propagatedElement); | |
| 58 } | |
| 59 | |
| 60 /** | |
| 61 * A [Type] that represents the type 'bottom'. | |
| 62 */ | |
| 63 class BottomTypeImpl extends TypeImpl { | |
| 64 /** | |
| 65 * The unique instance of this class. | |
| 66 */ | |
| 67 static BottomTypeImpl _INSTANCE = new BottomTypeImpl._(); | |
| 68 | |
| 69 /** | |
| 70 * Return the unique instance of this class. | |
| 71 */ | |
| 72 static BottomTypeImpl get instance => _INSTANCE; | |
| 73 | |
| 74 /** | |
| 75 * Prevent the creation of instances of this class. | |
| 76 */ | |
| 77 BottomTypeImpl._() : super(null, "<bottom>"); | |
| 78 | |
| 79 @override | |
| 80 int get hashCode => 0; | |
| 81 | |
| 82 @override | |
| 83 bool get isBottom => true; | |
| 84 | |
| 85 @override | |
| 86 bool operator ==(Object object) => identical(object, this); | |
| 87 | |
| 88 @override | |
| 89 bool isMoreSpecificThan(DartType type, | |
| 90 [bool withDynamic = false, Set<Element> visitedElements]) => | |
| 91 true; | |
| 92 | |
| 93 @override | |
| 94 bool isSubtypeOf(DartType type) => true; | |
| 95 | |
| 96 @override | |
| 97 bool isSupertypeOf(DartType type) => false; | |
| 98 | |
| 99 @override | |
| 100 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 101 | |
| 102 @override | |
| 103 BottomTypeImpl substitute2( | |
| 104 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 105 [List<FunctionTypeAliasElement> prune]) => | |
| 106 this; | |
| 107 } | |
| 108 | |
| 109 /** | |
| 110 * Type created internally if a circular reference is ever detected. Behaves | |
| 111 * like `dynamic`, except that when converted to a string it is displayed as | |
| 112 * `...`. | |
| 113 */ | |
| 114 class CircularTypeImpl extends DynamicTypeImpl { | |
| 115 CircularTypeImpl() : super._circular(); | |
| 116 | |
| 117 @override | |
| 118 int get hashCode => 1; | |
| 119 | |
| 120 @override | |
| 121 bool operator ==(Object object) => object is CircularTypeImpl; | |
| 122 | |
| 123 @override | |
| 124 void appendTo(StringBuffer buffer) { | |
| 125 buffer.write('...'); | |
| 126 } | |
| 127 | |
| 128 @override | |
| 129 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 130 } | |
| 131 | |
| 132 /** | |
| 133 * A concrete implementation of a [ClassElement]. | |
| 134 */ | |
| 135 class ClassElementImpl extends ElementImpl implements ClassElement { | |
| 136 /** | |
| 137 * A list containing all of the accessors (getters and setters) contained in | |
| 138 * this class. | |
| 139 */ | |
| 140 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; | |
| 141 | |
| 142 /** | |
| 143 * For classes which are not mixin applications, a list containing all of the | |
| 144 * constructors contained in this class, or `null` if the list of | |
| 145 * constructors has not yet been built. | |
| 146 * | |
| 147 * For classes which are mixin applications, the list of constructors is | |
| 148 * computed on the fly by the [constructors] getter, and this field is | |
| 149 * `null`. | |
| 150 */ | |
| 151 List<ConstructorElement> _constructors; | |
| 152 | |
| 153 /** | |
| 154 * A list containing all of the fields contained in this class. | |
| 155 */ | |
| 156 List<FieldElement> _fields = FieldElement.EMPTY_LIST; | |
| 157 | |
| 158 /** | |
| 159 * A list containing all of the mixins that are applied to the class being | |
| 160 * extended in order to derive the superclass of this class. | |
| 161 */ | |
| 162 List<InterfaceType> mixins = InterfaceType.EMPTY_LIST; | |
| 163 | |
| 164 /** | |
| 165 * A list containing all of the interfaces that are implemented by this class. | |
| 166 */ | |
| 167 List<InterfaceType> interfaces = InterfaceType.EMPTY_LIST; | |
| 168 | |
| 169 /** | |
| 170 * A list containing all of the methods contained in this class. | |
| 171 */ | |
| 172 List<MethodElement> _methods = MethodElement.EMPTY_LIST; | |
| 173 | |
| 174 /** | |
| 175 * The superclass of the class, or `null` if the class does not have an | |
| 176 * explicit superclass. | |
| 177 */ | |
| 178 InterfaceType supertype; | |
| 179 | |
| 180 /** | |
| 181 * The type defined by the class. | |
| 182 */ | |
| 183 InterfaceType type; | |
| 184 | |
| 185 /** | |
| 186 * A list containing all of the type parameters defined for this class. | |
| 187 */ | |
| 188 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 189 | |
| 190 /** | |
| 191 * The [SourceRange] of the `with` clause, `null` if there is no one. | |
| 192 */ | |
| 193 SourceRange withClauseRange; | |
| 194 | |
| 195 /** | |
| 196 * A flag indicating whether the types associated with the instance members of | |
| 197 * this class have been inferred. | |
| 198 */ | |
| 199 bool hasBeenInferred = false; | |
| 200 | |
| 201 /** | |
| 202 * Initialize a newly created class element to have the given [name] at the | |
| 203 * given [offset] in the file that contains the declaration of this element. | |
| 204 */ | |
| 205 ClassElementImpl(String name, int offset) : super(name, offset); | |
| 206 | |
| 207 /** | |
| 208 * Initialize a newly created class element to have the given [name]. | |
| 209 */ | |
| 210 ClassElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 211 | |
| 212 /** | |
| 213 * Set whether this class is abstract. | |
| 214 */ | |
| 215 void set abstract(bool isAbstract) { | |
| 216 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 217 } | |
| 218 | |
| 219 @override | |
| 220 List<PropertyAccessorElement> get accessors => _accessors; | |
| 221 | |
| 222 /** | |
| 223 * Set the accessors contained in this class to the given [accessors]. | |
| 224 */ | |
| 225 void set accessors(List<PropertyAccessorElement> accessors) { | |
| 226 for (PropertyAccessorElement accessor in accessors) { | |
| 227 (accessor as PropertyAccessorElementImpl).enclosingElement = this; | |
| 228 } | |
| 229 this._accessors = accessors; | |
| 230 } | |
| 231 | |
| 232 @override | |
| 233 List<InterfaceType> get allSupertypes { | |
| 234 List<InterfaceType> list = new List<InterfaceType>(); | |
| 235 _collectAllSupertypes(list); | |
| 236 return list; | |
| 237 } | |
| 238 | |
| 239 @override | |
| 240 List<ConstructorElement> get constructors { | |
| 241 if (!isMixinApplication) { | |
| 242 assert(_constructors != null); | |
| 243 return _constructors == null | |
| 244 ? ConstructorElement.EMPTY_LIST | |
| 245 : _constructors; | |
| 246 } | |
| 247 | |
| 248 return _computeMixinAppConstructors(); | |
| 249 } | |
| 250 | |
| 251 /** | |
| 252 * Set the constructors contained in this class to the given [constructors]. | |
| 253 * | |
| 254 * Should only be used for class elements that are not mixin applications. | |
| 255 */ | |
| 256 void set constructors(List<ConstructorElement> constructors) { | |
| 257 assert(!isMixinApplication); | |
| 258 for (ConstructorElement constructor in constructors) { | |
| 259 (constructor as ConstructorElementImpl).enclosingElement = this; | |
| 260 } | |
| 261 this._constructors = constructors; | |
| 262 } | |
| 263 | |
| 264 /** | |
| 265 * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should | |
| 266 * be reported for this class. | |
| 267 */ | |
| 268 bool get doesMixinLackConstructors { | |
| 269 if (!isMixinApplication && mixins.isEmpty) { | |
| 270 // This class is not a mixin application and it doesn't have a "with" | |
| 271 // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is | |
| 272 // inapplicable. | |
| 273 return false; | |
| 274 } | |
| 275 if (supertype == null) { | |
| 276 // Should never happen, since Object is the only class that has no | |
| 277 // supertype, and it should have been caught by the test above. | |
| 278 assert(false); | |
| 279 return false; | |
| 280 } | |
| 281 // Find the nearest class in the supertype chain that is not a mixin | |
| 282 // application. | |
| 283 ClassElement nearestNonMixinClass = supertype.element; | |
| 284 if (nearestNonMixinClass.isMixinApplication) { | |
| 285 // Use a list to keep track of the classes we've seen, so that we won't | |
| 286 // go into an infinite loop in the event of a non-trivial loop in the | |
| 287 // class hierarchy. | |
| 288 List<ClassElementImpl> classesSeen = <ClassElementImpl>[this]; | |
| 289 while (nearestNonMixinClass.isMixinApplication) { | |
| 290 if (classesSeen.contains(nearestNonMixinClass)) { | |
| 291 // Loop in the class hierarchy (which is reported elsewhere). Don't | |
| 292 // confuse the user with further errors. | |
| 293 return false; | |
| 294 } | |
| 295 classesSeen.add(nearestNonMixinClass); | |
| 296 if (nearestNonMixinClass.supertype == null) { | |
| 297 // Should never happen, since Object is the only class that has no | |
| 298 // supertype, and it is not a mixin application. | |
| 299 assert(false); | |
| 300 return false; | |
| 301 } | |
| 302 nearestNonMixinClass = nearestNonMixinClass.supertype.element; | |
| 303 } | |
| 304 } | |
| 305 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); | |
| 306 } | |
| 307 | |
| 308 /** | |
| 309 * Set whether this class is defined by an enum declaration. | |
| 310 */ | |
| 311 void set enum2(bool isEnum) { | |
| 312 setModifier(Modifier.ENUM, isEnum); | |
| 313 } | |
| 314 | |
| 315 @override | |
| 316 List<FieldElement> get fields => _fields; | |
| 317 | |
| 318 /** | |
| 319 * Set the fields contained in this class to the given [fields]. | |
| 320 */ | |
| 321 void set fields(List<FieldElement> fields) { | |
| 322 for (FieldElement field in fields) { | |
| 323 (field as FieldElementImpl).enclosingElement = this; | |
| 324 } | |
| 325 this._fields = fields; | |
| 326 } | |
| 327 | |
| 328 @override | |
| 329 bool get hasNonFinalField { | |
| 330 List<ClassElement> classesToVisit = new List<ClassElement>(); | |
| 331 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 332 classesToVisit.add(this); | |
| 333 while (!classesToVisit.isEmpty) { | |
| 334 ClassElement currentElement = classesToVisit.removeAt(0); | |
| 335 if (visitedClasses.add(currentElement)) { | |
| 336 // check fields | |
| 337 for (FieldElement field in currentElement.fields) { | |
| 338 if (!field.isFinal && | |
| 339 !field.isConst && | |
| 340 !field.isStatic && | |
| 341 !field.isSynthetic) { | |
| 342 return true; | |
| 343 } | |
| 344 } | |
| 345 // check mixins | |
| 346 for (InterfaceType mixinType in currentElement.mixins) { | |
| 347 ClassElement mixinElement = mixinType.element; | |
| 348 classesToVisit.add(mixinElement); | |
| 349 } | |
| 350 // check super | |
| 351 InterfaceType supertype = currentElement.supertype; | |
| 352 if (supertype != null) { | |
| 353 ClassElement superElement = supertype.element; | |
| 354 if (superElement != null) { | |
| 355 classesToVisit.add(superElement); | |
| 356 } | |
| 357 } | |
| 358 } | |
| 359 } | |
| 360 // not found | |
| 361 return false; | |
| 362 } | |
| 363 | |
| 364 @override | |
| 365 bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); | |
| 366 | |
| 367 /** | |
| 368 * Set whether this class references 'super'. | |
| 369 */ | |
| 370 void set hasReferenceToSuper(bool isReferencedSuper) { | |
| 371 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); | |
| 372 } | |
| 373 | |
| 374 @override | |
| 375 bool get hasStaticMember { | |
| 376 for (MethodElement method in _methods) { | |
| 377 if (method.isStatic) { | |
| 378 return true; | |
| 379 } | |
| 380 } | |
| 381 for (PropertyAccessorElement accessor in _accessors) { | |
| 382 if (accessor.isStatic) { | |
| 383 return true; | |
| 384 } | |
| 385 } | |
| 386 return false; | |
| 387 } | |
| 388 | |
| 389 @override | |
| 390 bool get isAbstract => hasModifier(Modifier.ABSTRACT); | |
| 391 | |
| 392 @override | |
| 393 bool get isEnum => hasModifier(Modifier.ENUM); | |
| 394 | |
| 395 @override | |
| 396 bool get isMixinApplication => hasModifier(Modifier.MIXIN_APPLICATION); | |
| 397 | |
| 398 @override | |
| 399 bool get isOrInheritsProxy => | |
| 400 _safeIsOrInheritsProxy(this, new HashSet<ClassElement>()); | |
| 401 | |
| 402 @override | |
| 403 bool get isProxy { | |
| 404 for (ElementAnnotation annotation in metadata) { | |
| 405 if (annotation.isProxy) { | |
| 406 return true; | |
| 407 } | |
| 408 } | |
| 409 return false; | |
| 410 } | |
| 411 | |
| 412 @override | |
| 413 bool get isValidMixin => hasModifier(Modifier.MIXIN); | |
| 414 | |
| 415 @override | |
| 416 ElementKind get kind => ElementKind.CLASS; | |
| 417 | |
| 418 @override | |
| 419 List<MethodElement> get methods => _methods; | |
| 420 | |
| 421 /** | |
| 422 * Set the methods contained in this class to the given [methods]. | |
| 423 */ | |
| 424 void set methods(List<MethodElement> methods) { | |
| 425 for (MethodElement method in methods) { | |
| 426 (method as MethodElementImpl).enclosingElement = this; | |
| 427 } | |
| 428 this._methods = methods; | |
| 429 } | |
| 430 | |
| 431 /** | |
| 432 * Set whether this class is a mixin application. | |
| 433 */ | |
| 434 void set mixinApplication(bool isMixinApplication) { | |
| 435 setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); | |
| 436 } | |
| 437 | |
| 438 @override | |
| 439 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 440 | |
| 441 /** | |
| 442 * Set the type parameters defined for this class to the given | |
| 443 * [typeParameters]. | |
| 444 */ | |
| 445 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 446 for (TypeParameterElement typeParameter in typeParameters) { | |
| 447 (typeParameter as TypeParameterElementImpl).enclosingElement = this; | |
| 448 } | |
| 449 this._typeParameters = typeParameters; | |
| 450 } | |
| 451 | |
| 452 @override | |
| 453 ConstructorElement get unnamedConstructor { | |
| 454 for (ConstructorElement element in constructors) { | |
| 455 String name = element.displayName; | |
| 456 if (name == null || name.isEmpty) { | |
| 457 return element; | |
| 458 } | |
| 459 } | |
| 460 return null; | |
| 461 } | |
| 462 | |
| 463 /** | |
| 464 * Set whether this class is a valid mixin. | |
| 465 */ | |
| 466 void set validMixin(bool isValidMixin) { | |
| 467 setModifier(Modifier.MIXIN, isValidMixin); | |
| 468 } | |
| 469 | |
| 470 @override | |
| 471 accept(ElementVisitor visitor) => visitor.visitClassElement(this); | |
| 472 | |
| 473 @override | |
| 474 void appendTo(StringBuffer buffer) { | |
| 475 if (isAbstract) { | |
| 476 buffer.write('abstract '); | |
| 477 } | |
| 478 buffer.write('class '); | |
| 479 String name = displayName; | |
| 480 if (name == null) { | |
| 481 buffer.write("{unnamed class}"); | |
| 482 } else { | |
| 483 buffer.write(name); | |
| 484 } | |
| 485 int variableCount = _typeParameters.length; | |
| 486 if (variableCount > 0) { | |
| 487 buffer.write("<"); | |
| 488 for (int i = 0; i < variableCount; i++) { | |
| 489 if (i > 0) { | |
| 490 buffer.write(", "); | |
| 491 } | |
| 492 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 493 } | |
| 494 buffer.write(">"); | |
| 495 } | |
| 496 if (supertype != null && !supertype.isObject) { | |
| 497 buffer.write(' extends '); | |
| 498 buffer.write(supertype.displayName); | |
| 499 } | |
| 500 if (mixins.isNotEmpty) { | |
| 501 buffer.write(' with '); | |
| 502 buffer.write(mixins.map((t) => t.displayName).join(', ')); | |
| 503 } | |
| 504 if (interfaces.isNotEmpty) { | |
| 505 buffer.write(' implements '); | |
| 506 buffer.write(interfaces.map((t) => t.displayName).join(', ')); | |
| 507 } | |
| 508 } | |
| 509 | |
| 510 @override | |
| 511 NamedCompilationUnitMember computeNode() { | |
| 512 if (isEnum) { | |
| 513 return getNodeMatching((node) => node is EnumDeclaration); | |
| 514 } else { | |
| 515 return getNodeMatching( | |
| 516 (node) => node is ClassDeclaration || node is ClassTypeAlias); | |
| 517 } | |
| 518 } | |
| 519 | |
| 520 @override | |
| 521 ElementImpl getChild(String identifier) { | |
| 522 // | |
| 523 // The casts in this method are safe because the set methods would have | |
| 524 // thrown a CCE if any of the elements in the arrays were not of the | |
| 525 // expected types. | |
| 526 // | |
| 527 for (PropertyAccessorElement accessor in _accessors) { | |
| 528 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { | |
| 529 return accessor as PropertyAccessorElementImpl; | |
| 530 } | |
| 531 } | |
| 532 for (ConstructorElement constructor in _constructors) { | |
| 533 if ((constructor as ConstructorElementImpl).identifier == identifier) { | |
| 534 return constructor as ConstructorElementImpl; | |
| 535 } | |
| 536 } | |
| 537 for (FieldElement field in _fields) { | |
| 538 if ((field as FieldElementImpl).identifier == identifier) { | |
| 539 return field as FieldElementImpl; | |
| 540 } | |
| 541 } | |
| 542 for (MethodElement method in _methods) { | |
| 543 if ((method as MethodElementImpl).identifier == identifier) { | |
| 544 return method as MethodElementImpl; | |
| 545 } | |
| 546 } | |
| 547 for (TypeParameterElement typeParameter in _typeParameters) { | |
| 548 if ((typeParameter as TypeParameterElementImpl).identifier == | |
| 549 identifier) { | |
| 550 return typeParameter as TypeParameterElementImpl; | |
| 551 } | |
| 552 } | |
| 553 return null; | |
| 554 } | |
| 555 | |
| 556 @override | |
| 557 FieldElement getField(String name) { | |
| 558 for (FieldElement fieldElement in _fields) { | |
| 559 if (name == fieldElement.name) { | |
| 560 return fieldElement; | |
| 561 } | |
| 562 } | |
| 563 return null; | |
| 564 } | |
| 565 | |
| 566 @override | |
| 567 PropertyAccessorElement getGetter(String getterName) { | |
| 568 for (PropertyAccessorElement accessor in _accessors) { | |
| 569 if (accessor.isGetter && accessor.name == getterName) { | |
| 570 return accessor; | |
| 571 } | |
| 572 } | |
| 573 return null; | |
| 574 } | |
| 575 | |
| 576 @override | |
| 577 MethodElement getMethod(String methodName) { | |
| 578 for (MethodElement method in _methods) { | |
| 579 if (method.name == methodName) { | |
| 580 return method; | |
| 581 } | |
| 582 } | |
| 583 return null; | |
| 584 } | |
| 585 | |
| 586 @override | |
| 587 ConstructorElement getNamedConstructor(String name) { | |
| 588 for (ConstructorElement element in constructors) { | |
| 589 String elementName = element.name; | |
| 590 if (elementName != null && elementName == name) { | |
| 591 return element; | |
| 592 } | |
| 593 } | |
| 594 return null; | |
| 595 } | |
| 596 | |
| 597 @override | |
| 598 PropertyAccessorElement getSetter(String setterName) { | |
| 599 // TODO (jwren) revisit- should we append '=' here or require clients to | |
| 600 // include it? | |
| 601 // Do we need the check for isSetter below? | |
| 602 if (!StringUtilities.endsWithChar(setterName, 0x3D)) { | |
| 603 setterName += '='; | |
| 604 } | |
| 605 for (PropertyAccessorElement accessor in _accessors) { | |
| 606 if (accessor.isSetter && accessor.name == setterName) { | |
| 607 return accessor; | |
| 608 } | |
| 609 } | |
| 610 return null; | |
| 611 } | |
| 612 | |
| 613 @override | |
| 614 bool isSuperConstructorAccessible(ConstructorElement constructor) { | |
| 615 // If this class has no mixins, then all superclass constructors are | |
| 616 // accessible. | |
| 617 if (mixins.isEmpty) { | |
| 618 return true; | |
| 619 } | |
| 620 // Otherwise only constructors that lack optional parameters are | |
| 621 // accessible (see dartbug.com/19576). | |
| 622 for (ParameterElement parameter in constructor.parameters) { | |
| 623 if (parameter.parameterKind != ParameterKind.REQUIRED) { | |
| 624 return false; | |
| 625 } | |
| 626 } | |
| 627 return true; | |
| 628 } | |
| 629 | |
| 630 @override | |
| 631 MethodElement lookUpConcreteMethod( | |
| 632 String methodName, LibraryElement library) => | |
| 633 _internalLookUpConcreteMethod(methodName, library, true); | |
| 634 | |
| 635 @override | |
| 636 PropertyAccessorElement lookUpGetter( | |
| 637 String getterName, LibraryElement library) => | |
| 638 _internalLookUpGetter(getterName, library, true); | |
| 639 | |
| 640 @override | |
| 641 PropertyAccessorElement lookUpInheritedConcreteGetter( | |
| 642 String getterName, LibraryElement library) => | |
| 643 _internalLookUpConcreteGetter(getterName, library, false); | |
| 644 | |
| 645 @override | |
| 646 MethodElement lookUpInheritedConcreteMethod( | |
| 647 String methodName, LibraryElement library) => | |
| 648 _internalLookUpConcreteMethod(methodName, library, false); | |
| 649 | |
| 650 @override | |
| 651 PropertyAccessorElement lookUpInheritedConcreteSetter( | |
| 652 String setterName, LibraryElement library) => | |
| 653 _internalLookUpConcreteSetter(setterName, library, false); | |
| 654 | |
| 655 @override | |
| 656 MethodElement lookUpInheritedMethod( | |
| 657 String methodName, LibraryElement library) => | |
| 658 _internalLookUpMethod(methodName, library, false); | |
| 659 | |
| 660 @override | |
| 661 MethodElement lookUpMethod(String methodName, LibraryElement library) => | |
| 662 _internalLookUpMethod(methodName, library, true); | |
| 663 | |
| 664 @override | |
| 665 PropertyAccessorElement lookUpSetter( | |
| 666 String setterName, LibraryElement library) => | |
| 667 _internalLookUpSetter(setterName, library, true); | |
| 668 | |
| 669 @override | |
| 670 void visitChildren(ElementVisitor visitor) { | |
| 671 super.visitChildren(visitor); | |
| 672 safelyVisitChildren(_accessors, visitor); | |
| 673 safelyVisitChildren(_constructors, visitor); | |
| 674 safelyVisitChildren(_fields, visitor); | |
| 675 safelyVisitChildren(_methods, visitor); | |
| 676 safelyVisitChildren(_typeParameters, visitor); | |
| 677 } | |
| 678 | |
| 679 void _collectAllSupertypes(List<InterfaceType> supertypes) { | |
| 680 List<InterfaceType> typesToVisit = new List<InterfaceType>(); | |
| 681 List<ClassElement> visitedClasses = new List<ClassElement>(); | |
| 682 typesToVisit.add(this.type); | |
| 683 while (!typesToVisit.isEmpty) { | |
| 684 InterfaceType currentType = typesToVisit.removeAt(0); | |
| 685 ClassElement currentElement = currentType.element; | |
| 686 if (!visitedClasses.contains(currentElement)) { | |
| 687 visitedClasses.add(currentElement); | |
| 688 if (!identical(currentType, this.type)) { | |
| 689 supertypes.add(currentType); | |
| 690 } | |
| 691 InterfaceType supertype = currentType.superclass; | |
| 692 if (supertype != null) { | |
| 693 typesToVisit.add(supertype); | |
| 694 } | |
| 695 for (InterfaceType type in currentElement.interfaces) { | |
| 696 typesToVisit.add(type); | |
| 697 } | |
| 698 for (InterfaceType type in currentElement.mixins) { | |
| 699 ClassElement element = type.element; | |
| 700 if (!visitedClasses.contains(element)) { | |
| 701 supertypes.add(type); | |
| 702 } | |
| 703 } | |
| 704 } | |
| 705 } | |
| 706 } | |
| 707 | |
| 708 /** | |
| 709 * Compute a list of constructors for this class, which is a mixin | |
| 710 * application. If specified, [visitedClasses] is a list of the other mixin | |
| 711 * application classes which have been visited on the way to reaching this | |
| 712 * one (this is used to detect circularities). | |
| 713 */ | |
| 714 List<ConstructorElement> _computeMixinAppConstructors( | |
| 715 [List<ClassElementImpl> visitedClasses = null]) { | |
| 716 // First get the list of constructors of the superclass which need to be | |
| 717 // forwarded to this class. | |
| 718 Iterable<ConstructorElement> constructorsToForward; | |
| 719 if (supertype == null) { | |
| 720 // Shouldn't ever happen, since the only class with no supertype is | |
| 721 // Object, and it isn't a mixin application. But for safety's sake just | |
| 722 // assume an empty list. | |
| 723 assert(false); | |
| 724 constructorsToForward = <ConstructorElement>[]; | |
| 725 } else if (!supertype.element.isMixinApplication) { | |
| 726 List<ConstructorElement> superclassConstructors = | |
| 727 supertype.element.constructors; | |
| 728 // Filter out any constructors with optional parameters (see | |
| 729 // dartbug.com/15101). | |
| 730 constructorsToForward = | |
| 731 superclassConstructors.where(isSuperConstructorAccessible); | |
| 732 } else { | |
| 733 if (visitedClasses == null) { | |
| 734 visitedClasses = <ClassElementImpl>[this]; | |
| 735 } else { | |
| 736 if (visitedClasses.contains(this)) { | |
| 737 // Loop in the class hierarchy. Don't try to forward any | |
| 738 // constructors. | |
| 739 return <ConstructorElement>[]; | |
| 740 } | |
| 741 visitedClasses.add(this); | |
| 742 } | |
| 743 try { | |
| 744 ClassElementImpl superclass = supertype.element; | |
| 745 constructorsToForward = | |
| 746 superclass._computeMixinAppConstructors(visitedClasses); | |
| 747 } finally { | |
| 748 visitedClasses.removeLast(); | |
| 749 } | |
| 750 } | |
| 751 | |
| 752 // Figure out the type parameter substitution we need to perform in order | |
| 753 // to produce constructors for this class. We want to be robust in the | |
| 754 // face of errors, so drop any extra type arguments and fill in any missing | |
| 755 // ones with `dynamic`. | |
| 756 List<DartType> parameterTypes = | |
| 757 TypeParameterTypeImpl.getTypes(supertype.typeParameters); | |
| 758 List<DartType> argumentTypes = new List<DartType>.filled( | |
| 759 parameterTypes.length, DynamicTypeImpl.instance); | |
| 760 for (int i = 0; i < supertype.typeArguments.length; i++) { | |
| 761 if (i >= argumentTypes.length) { | |
| 762 break; | |
| 763 } | |
| 764 argumentTypes[i] = supertype.typeArguments[i]; | |
| 765 } | |
| 766 | |
| 767 // Now create an implicit constructor for every constructor found above, | |
| 768 // substituting type parameters as appropriate. | |
| 769 return constructorsToForward | |
| 770 .map((ConstructorElement superclassConstructor) { | |
| 771 ConstructorElementImpl implicitConstructor = | |
| 772 new ConstructorElementImpl(superclassConstructor.name, -1); | |
| 773 implicitConstructor.synthetic = true; | |
| 774 implicitConstructor.redirectedConstructor = superclassConstructor; | |
| 775 implicitConstructor.const2 = superclassConstructor.isConst; | |
| 776 implicitConstructor.returnType = type; | |
| 777 List<ParameterElement> superParameters = superclassConstructor.parameters; | |
| 778 int count = superParameters.length; | |
| 779 if (count > 0) { | |
| 780 List<ParameterElement> implicitParameters = | |
| 781 new List<ParameterElement>(count); | |
| 782 for (int i = 0; i < count; i++) { | |
| 783 ParameterElement superParameter = superParameters[i]; | |
| 784 ParameterElementImpl implicitParameter = | |
| 785 new ParameterElementImpl(superParameter.name, -1); | |
| 786 implicitParameter.const3 = superParameter.isConst; | |
| 787 implicitParameter.final2 = superParameter.isFinal; | |
| 788 implicitParameter.parameterKind = superParameter.parameterKind; | |
| 789 implicitParameter.synthetic = true; | |
| 790 implicitParameter.type = | |
| 791 superParameter.type.substitute2(argumentTypes, parameterTypes); | |
| 792 implicitParameters[i] = implicitParameter; | |
| 793 } | |
| 794 implicitConstructor.parameters = implicitParameters; | |
| 795 } | |
| 796 implicitConstructor.enclosingElement = this; | |
| 797 implicitConstructor.type = new FunctionTypeImpl(implicitConstructor); | |
| 798 return implicitConstructor; | |
| 799 }).toList(); | |
| 800 } | |
| 801 | |
| 802 PropertyAccessorElement _internalLookUpConcreteGetter( | |
| 803 String getterName, LibraryElement library, bool includeThisClass) { | |
| 804 PropertyAccessorElement getter = | |
| 805 _internalLookUpGetter(getterName, library, includeThisClass); | |
| 806 while (getter != null && getter.isAbstract) { | |
| 807 Element definingClass = getter.enclosingElement; | |
| 808 if (definingClass is! ClassElementImpl) { | |
| 809 return null; | |
| 810 } | |
| 811 getter = (definingClass as ClassElementImpl) | |
| 812 ._internalLookUpGetter(getterName, library, false); | |
| 813 } | |
| 814 return getter; | |
| 815 } | |
| 816 | |
| 817 MethodElement _internalLookUpConcreteMethod( | |
| 818 String methodName, LibraryElement library, bool includeThisClass) { | |
| 819 MethodElement method = | |
| 820 _internalLookUpMethod(methodName, library, includeThisClass); | |
| 821 while (method != null && method.isAbstract) { | |
| 822 ClassElement definingClass = method.enclosingElement; | |
| 823 if (definingClass == null) { | |
| 824 return null; | |
| 825 } | |
| 826 method = definingClass.lookUpInheritedMethod(methodName, library); | |
| 827 } | |
| 828 return method; | |
| 829 } | |
| 830 | |
| 831 PropertyAccessorElement _internalLookUpConcreteSetter( | |
| 832 String setterName, LibraryElement library, bool includeThisClass) { | |
| 833 PropertyAccessorElement setter = | |
| 834 _internalLookUpSetter(setterName, library, includeThisClass); | |
| 835 while (setter != null && setter.isAbstract) { | |
| 836 Element definingClass = setter.enclosingElement; | |
| 837 if (definingClass is! ClassElementImpl) { | |
| 838 return null; | |
| 839 } | |
| 840 setter = (definingClass as ClassElementImpl) | |
| 841 ._internalLookUpSetter(setterName, library, false); | |
| 842 } | |
| 843 return setter; | |
| 844 } | |
| 845 | |
| 846 PropertyAccessorElement _internalLookUpGetter( | |
| 847 String getterName, LibraryElement library, bool includeThisClass) { | |
| 848 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 849 ClassElement currentElement = this; | |
| 850 if (includeThisClass) { | |
| 851 PropertyAccessorElement element = currentElement.getGetter(getterName); | |
| 852 if (element != null && element.isAccessibleIn(library)) { | |
| 853 return element; | |
| 854 } | |
| 855 } | |
| 856 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 857 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 858 ClassElement mixinElement = mixin.element; | |
| 859 if (mixinElement != null) { | |
| 860 PropertyAccessorElement element = mixinElement.getGetter(getterName); | |
| 861 if (element != null && element.isAccessibleIn(library)) { | |
| 862 return element; | |
| 863 } | |
| 864 } | |
| 865 } | |
| 866 InterfaceType supertype = currentElement.supertype; | |
| 867 if (supertype == null) { | |
| 868 return null; | |
| 869 } | |
| 870 currentElement = supertype.element; | |
| 871 PropertyAccessorElement element = currentElement.getGetter(getterName); | |
| 872 if (element != null && element.isAccessibleIn(library)) { | |
| 873 return element; | |
| 874 } | |
| 875 } | |
| 876 return null; | |
| 877 } | |
| 878 | |
| 879 MethodElement _internalLookUpMethod( | |
| 880 String methodName, LibraryElement library, bool includeThisClass) { | |
| 881 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 882 ClassElement currentElement = this; | |
| 883 if (includeThisClass) { | |
| 884 MethodElement element = currentElement.getMethod(methodName); | |
| 885 if (element != null && element.isAccessibleIn(library)) { | |
| 886 return element; | |
| 887 } | |
| 888 } | |
| 889 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 890 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 891 ClassElement mixinElement = mixin.element; | |
| 892 if (mixinElement != null) { | |
| 893 MethodElement element = mixinElement.getMethod(methodName); | |
| 894 if (element != null && element.isAccessibleIn(library)) { | |
| 895 return element; | |
| 896 } | |
| 897 } | |
| 898 } | |
| 899 InterfaceType supertype = currentElement.supertype; | |
| 900 if (supertype == null) { | |
| 901 return null; | |
| 902 } | |
| 903 currentElement = supertype.element; | |
| 904 MethodElement element = currentElement.getMethod(methodName); | |
| 905 if (element != null && element.isAccessibleIn(library)) { | |
| 906 return element; | |
| 907 } | |
| 908 } | |
| 909 return null; | |
| 910 } | |
| 911 | |
| 912 PropertyAccessorElement _internalLookUpSetter( | |
| 913 String setterName, LibraryElement library, bool includeThisClass) { | |
| 914 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 915 ClassElement currentElement = this; | |
| 916 if (includeThisClass) { | |
| 917 PropertyAccessorElement element = currentElement.getSetter(setterName); | |
| 918 if (element != null && element.isAccessibleIn(library)) { | |
| 919 return element; | |
| 920 } | |
| 921 } | |
| 922 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 923 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 924 ClassElement mixinElement = mixin.element; | |
| 925 if (mixinElement != null) { | |
| 926 PropertyAccessorElement element = mixinElement.getSetter(setterName); | |
| 927 if (element != null && element.isAccessibleIn(library)) { | |
| 928 return element; | |
| 929 } | |
| 930 } | |
| 931 } | |
| 932 InterfaceType supertype = currentElement.supertype; | |
| 933 if (supertype == null) { | |
| 934 return null; | |
| 935 } | |
| 936 currentElement = supertype.element; | |
| 937 PropertyAccessorElement element = currentElement.getSetter(setterName); | |
| 938 if (element != null && element.isAccessibleIn(library)) { | |
| 939 return element; | |
| 940 } | |
| 941 } | |
| 942 return null; | |
| 943 } | |
| 944 | |
| 945 bool _safeIsOrInheritsProxy( | |
| 946 ClassElement classElt, HashSet<ClassElement> visitedClassElts) { | |
| 947 if (visitedClassElts.contains(classElt)) { | |
| 948 return false; | |
| 949 } | |
| 950 visitedClassElts.add(classElt); | |
| 951 if (classElt.isProxy) { | |
| 952 return true; | |
| 953 } else if (classElt.supertype != null && | |
| 954 _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { | |
| 955 return true; | |
| 956 } | |
| 957 List<InterfaceType> supertypes = classElt.interfaces; | |
| 958 for (int i = 0; i < supertypes.length; i++) { | |
| 959 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { | |
| 960 return true; | |
| 961 } | |
| 962 } | |
| 963 supertypes = classElt.mixins; | |
| 964 for (int i = 0; i < supertypes.length; i++) { | |
| 965 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { | |
| 966 return true; | |
| 967 } | |
| 968 } | |
| 969 return false; | |
| 970 } | |
| 971 } | |
| 972 | |
| 973 /** | |
| 974 * A concrete implementation of a [CompilationUnitElement]. | |
| 975 */ | |
| 976 class CompilationUnitElementImpl extends UriReferencedElementImpl | |
| 977 implements CompilationUnitElement { | |
| 978 /** | |
| 979 * The source that corresponds to this compilation unit. | |
| 980 */ | |
| 981 Source source; | |
| 982 | |
| 983 /** | |
| 984 * The source of the library containing this compilation unit. | |
| 985 * | |
| 986 * This is the same as the source of the containing [LibraryElement], | |
| 987 * except that it does not require the containing [LibraryElement] to be | |
| 988 * computed. | |
| 989 */ | |
| 990 Source librarySource; | |
| 991 | |
| 992 /** | |
| 993 * A list containing all of the top-level accessors (getters and setters) | |
| 994 * contained in this compilation unit. | |
| 995 */ | |
| 996 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; | |
| 997 | |
| 998 /** | |
| 999 * A list containing all of the enums contained in this compilation unit. | |
| 1000 */ | |
| 1001 List<ClassElement> _enums = ClassElement.EMPTY_LIST; | |
| 1002 | |
| 1003 /** | |
| 1004 * A list containing all of the top-level functions contained in this | |
| 1005 * compilation unit. | |
| 1006 */ | |
| 1007 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; | |
| 1008 | |
| 1009 /** | |
| 1010 * A list containing all of the function type aliases contained in this | |
| 1011 * compilation unit. | |
| 1012 */ | |
| 1013 List<FunctionTypeAliasElement> _typeAliases = | |
| 1014 FunctionTypeAliasElement.EMPTY_LIST; | |
| 1015 | |
| 1016 /** | |
| 1017 * A list containing all of the types contained in this compilation unit. | |
| 1018 */ | |
| 1019 List<ClassElement> _types = ClassElement.EMPTY_LIST; | |
| 1020 | |
| 1021 /** | |
| 1022 * A list containing all of the variables contained in this compilation unit. | |
| 1023 */ | |
| 1024 List<TopLevelVariableElement> _variables = TopLevelVariableElement.EMPTY_LIST; | |
| 1025 | |
| 1026 /** | |
| 1027 * A map from offsets to elements of this unit at these offsets. | |
| 1028 */ | |
| 1029 final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>(); | |
| 1030 | |
| 1031 /** | |
| 1032 * Initialize a newly created compilation unit element to have the given | |
| 1033 * [name]. | |
| 1034 */ | |
| 1035 CompilationUnitElementImpl(String name) : super(name, -1); | |
| 1036 | |
| 1037 @override | |
| 1038 List<PropertyAccessorElement> get accessors => _accessors; | |
| 1039 | |
| 1040 /** | |
| 1041 * Set the top-level accessors (getters and setters) contained in this | |
| 1042 * compilation unit to the given [accessors]. | |
| 1043 */ | |
| 1044 void set accessors(List<PropertyAccessorElement> accessors) { | |
| 1045 for (PropertyAccessorElement accessor in accessors) { | |
| 1046 (accessor as PropertyAccessorElementImpl).enclosingElement = this; | |
| 1047 } | |
| 1048 this._accessors = accessors; | |
| 1049 } | |
| 1050 | |
| 1051 @override | |
| 1052 LibraryElement get enclosingElement => | |
| 1053 super.enclosingElement as LibraryElement; | |
| 1054 | |
| 1055 @override | |
| 1056 List<ClassElement> get enums => _enums; | |
| 1057 | |
| 1058 /** | |
| 1059 * Set the enums contained in this compilation unit to the given [enums]. | |
| 1060 */ | |
| 1061 void set enums(List<ClassElement> enums) { | |
| 1062 for (ClassElement enumDeclaration in enums) { | |
| 1063 (enumDeclaration as ClassElementImpl).enclosingElement = this; | |
| 1064 } | |
| 1065 this._enums = enums; | |
| 1066 } | |
| 1067 | |
| 1068 @override | |
| 1069 List<FunctionElement> get functions => _functions; | |
| 1070 | |
| 1071 /** | |
| 1072 * Set the top-level functions contained in this compilation unit to the given | |
| 1073 * [functions]. | |
| 1074 */ | |
| 1075 void set functions(List<FunctionElement> functions) { | |
| 1076 for (FunctionElement function in functions) { | |
| 1077 (function as FunctionElementImpl).enclosingElement = this; | |
| 1078 } | |
| 1079 this._functions = functions; | |
| 1080 } | |
| 1081 | |
| 1082 @override | |
| 1083 List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases; | |
| 1084 | |
| 1085 @override | |
| 1086 int get hashCode => source.hashCode; | |
| 1087 | |
| 1088 @override | |
| 1089 bool get hasLoadLibraryFunction { | |
| 1090 for (int i = 0; i < _functions.length; i++) { | |
| 1091 if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) { | |
| 1092 return true; | |
| 1093 } | |
| 1094 } | |
| 1095 return false; | |
| 1096 } | |
| 1097 | |
| 1098 @override | |
| 1099 String get identifier => source.encoding; | |
| 1100 | |
| 1101 @override | |
| 1102 ElementKind get kind => ElementKind.COMPILATION_UNIT; | |
| 1103 | |
| 1104 @override | |
| 1105 List<TopLevelVariableElement> get topLevelVariables => _variables; | |
| 1106 | |
| 1107 /** | |
| 1108 * Set the top-level variables contained in this compilation unit to the given | |
| 1109 * [variables]. | |
| 1110 */ | |
| 1111 void set topLevelVariables(List<TopLevelVariableElement> variables) { | |
| 1112 for (TopLevelVariableElement field in variables) { | |
| 1113 (field as TopLevelVariableElementImpl).enclosingElement = this; | |
| 1114 } | |
| 1115 this._variables = variables; | |
| 1116 } | |
| 1117 | |
| 1118 /** | |
| 1119 * Set the function type aliases contained in this compilation unit to the | |
| 1120 * given [typeAliases]. | |
| 1121 */ | |
| 1122 void set typeAliases(List<FunctionTypeAliasElement> typeAliases) { | |
| 1123 for (FunctionTypeAliasElement typeAlias in typeAliases) { | |
| 1124 (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this; | |
| 1125 } | |
| 1126 this._typeAliases = typeAliases; | |
| 1127 } | |
| 1128 | |
| 1129 @override | |
| 1130 List<ClassElement> get types => _types; | |
| 1131 | |
| 1132 /** | |
| 1133 * Set the types contained in this compilation unit to the given [types]. | |
| 1134 */ | |
| 1135 void set types(List<ClassElement> types) { | |
| 1136 for (ClassElement type in types) { | |
| 1137 (type as ClassElementImpl).enclosingElement = this; | |
| 1138 } | |
| 1139 this._types = types; | |
| 1140 } | |
| 1141 | |
| 1142 @override | |
| 1143 bool operator ==(Object object) => | |
| 1144 object is CompilationUnitElementImpl && source == object.source; | |
| 1145 | |
| 1146 @override | |
| 1147 accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this); | |
| 1148 | |
| 1149 /** | |
| 1150 * This method is invoked after this unit was incrementally resolved. | |
| 1151 */ | |
| 1152 void afterIncrementalResolution() { | |
| 1153 _offsetToElementMap.clear(); | |
| 1154 } | |
| 1155 | |
| 1156 @override | |
| 1157 void appendTo(StringBuffer buffer) { | |
| 1158 if (source == null) { | |
| 1159 buffer.write("{compilation unit}"); | |
| 1160 } else { | |
| 1161 buffer.write(source.fullName); | |
| 1162 } | |
| 1163 } | |
| 1164 | |
| 1165 @override | |
| 1166 CompilationUnit computeNode() => unit; | |
| 1167 | |
| 1168 @override | |
| 1169 ElementImpl getChild(String identifier) { | |
| 1170 // | |
| 1171 // The casts in this method are safe because the set methods would have | |
| 1172 // thrown a CCE if any of the elements in the arrays were not of the | |
| 1173 // expected types. | |
| 1174 // | |
| 1175 for (PropertyAccessorElement accessor in _accessors) { | |
| 1176 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { | |
| 1177 return accessor as PropertyAccessorElementImpl; | |
| 1178 } | |
| 1179 } | |
| 1180 for (VariableElement variable in _variables) { | |
| 1181 if ((variable as VariableElementImpl).identifier == identifier) { | |
| 1182 return variable as VariableElementImpl; | |
| 1183 } | |
| 1184 } | |
| 1185 for (ExecutableElement function in _functions) { | |
| 1186 if ((function as ExecutableElementImpl).identifier == identifier) { | |
| 1187 return function as ExecutableElementImpl; | |
| 1188 } | |
| 1189 } | |
| 1190 for (FunctionTypeAliasElement typeAlias in _typeAliases) { | |
| 1191 if ((typeAlias as FunctionTypeAliasElementImpl).identifier == | |
| 1192 identifier) { | |
| 1193 return typeAlias as FunctionTypeAliasElementImpl; | |
| 1194 } | |
| 1195 } | |
| 1196 for (ClassElement type in _types) { | |
| 1197 if ((type as ClassElementImpl).identifier == identifier) { | |
| 1198 return type as ClassElementImpl; | |
| 1199 } | |
| 1200 } | |
| 1201 for (ClassElement type in _enums) { | |
| 1202 if ((type as ClassElementImpl).identifier == identifier) { | |
| 1203 return type as ClassElementImpl; | |
| 1204 } | |
| 1205 } | |
| 1206 return null; | |
| 1207 } | |
| 1208 | |
| 1209 @override | |
| 1210 Element getElementAt(int offset) { | |
| 1211 if (_offsetToElementMap.isEmpty) { | |
| 1212 accept(new _BuildOffsetToElementMap(_offsetToElementMap)); | |
| 1213 } | |
| 1214 return _offsetToElementMap[offset]; | |
| 1215 } | |
| 1216 | |
| 1217 @override | |
| 1218 ClassElement getEnum(String enumName) { | |
| 1219 for (ClassElement enumDeclaration in _enums) { | |
| 1220 if (enumDeclaration.name == enumName) { | |
| 1221 return enumDeclaration; | |
| 1222 } | |
| 1223 } | |
| 1224 return null; | |
| 1225 } | |
| 1226 | |
| 1227 @override | |
| 1228 ClassElement getType(String className) { | |
| 1229 for (ClassElement type in _types) { | |
| 1230 if (type.name == className) { | |
| 1231 return type; | |
| 1232 } | |
| 1233 } | |
| 1234 return null; | |
| 1235 } | |
| 1236 | |
| 1237 /** | |
| 1238 * Replace the given [from] top-level variable with [to] in this compilation u
nit. | |
| 1239 */ | |
| 1240 void replaceTopLevelVariable( | |
| 1241 TopLevelVariableElement from, TopLevelVariableElement to) { | |
| 1242 int index = _variables.indexOf(from); | |
| 1243 _variables[index] = to; | |
| 1244 } | |
| 1245 | |
| 1246 @override | |
| 1247 void visitChildren(ElementVisitor visitor) { | |
| 1248 super.visitChildren(visitor); | |
| 1249 safelyVisitChildren(_accessors, visitor); | |
| 1250 safelyVisitChildren(_enums, visitor); | |
| 1251 safelyVisitChildren(_functions, visitor); | |
| 1252 safelyVisitChildren(_typeAliases, visitor); | |
| 1253 safelyVisitChildren(_types, visitor); | |
| 1254 safelyVisitChildren(_variables, visitor); | |
| 1255 } | |
| 1256 } | |
| 1257 | |
| 1258 /** | |
| 1259 * A [FieldElement] for a 'const' or 'final' field that has an initializer. | |
| 1260 * | |
| 1261 * TODO(paulberry): we should rename this class to reflect the fact that it's | |
| 1262 * used for both const and final fields. However, we shouldn't do so until | |
| 1263 * we've created an API for reading the values of constants; until that API is | |
| 1264 * available, clients are likely to read constant values by casting to | |
| 1265 * ConstFieldElementImpl, so it would be a breaking change to rename this | |
| 1266 * class. | |
| 1267 */ | |
| 1268 class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement { | |
| 1269 /** | |
| 1270 * The result of evaluating this variable's initializer. | |
| 1271 */ | |
| 1272 EvaluationResultImpl _result; | |
| 1273 | |
| 1274 /** | |
| 1275 * Initialize a newly created synthetic field element to have the given | |
| 1276 * [name] and [offset]. | |
| 1277 */ | |
| 1278 ConstFieldElementImpl(String name, int offset) : super(name, offset); | |
| 1279 | |
| 1280 /** | |
| 1281 * Initialize a newly created field element to have the given [name]. | |
| 1282 */ | |
| 1283 ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1284 | |
| 1285 @override | |
| 1286 DartObject get constantValue => _result.value; | |
| 1287 | |
| 1288 @override | |
| 1289 EvaluationResultImpl get evaluationResult => _result; | |
| 1290 | |
| 1291 @override | |
| 1292 void set evaluationResult(EvaluationResultImpl result) { | |
| 1293 this._result = result; | |
| 1294 } | |
| 1295 } | |
| 1296 | |
| 1297 /** | |
| 1298 * A [LocalVariableElement] for a local 'const' variable that has an | |
| 1299 * initializer. | |
| 1300 */ | |
| 1301 class ConstLocalVariableElementImpl extends LocalVariableElementImpl | |
| 1302 with ConstVariableElement { | |
| 1303 /** | |
| 1304 * The result of evaluating this variable's initializer. | |
| 1305 */ | |
| 1306 EvaluationResultImpl _result; | |
| 1307 | |
| 1308 /** | |
| 1309 * Initialize a newly created local variable element to have the given [name] | |
| 1310 * and [offset]. | |
| 1311 */ | |
| 1312 ConstLocalVariableElementImpl(String name, int offset) : super(name, offset); | |
| 1313 | |
| 1314 /** | |
| 1315 * Initialize a newly created local variable element to have the given [name]. | |
| 1316 */ | |
| 1317 ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1318 | |
| 1319 @override | |
| 1320 DartObject get constantValue => _result.value; | |
| 1321 | |
| 1322 @override | |
| 1323 EvaluationResultImpl get evaluationResult => _result; | |
| 1324 | |
| 1325 @override | |
| 1326 void set evaluationResult(EvaluationResultImpl result) { | |
| 1327 this._result = result; | |
| 1328 } | |
| 1329 } | |
| 1330 | |
| 1331 /** | |
| 1332 * A concrete implementation of a [ConstructorElement]. | |
| 1333 */ | |
| 1334 class ConstructorElementImpl extends ExecutableElementImpl | |
| 1335 implements ConstructorElement { | |
| 1336 /** | |
| 1337 * The constructor to which this constructor is redirecting. | |
| 1338 */ | |
| 1339 ConstructorElement redirectedConstructor; | |
| 1340 | |
| 1341 /** | |
| 1342 * The initializers for this constructor (used for evaluating constant | |
| 1343 * instance creation expressions). | |
| 1344 */ | |
| 1345 List<ConstructorInitializer> constantInitializers; | |
| 1346 | |
| 1347 /** | |
| 1348 * The offset of the `.` before this constructor name or `null` if not named. | |
| 1349 */ | |
| 1350 int periodOffset; | |
| 1351 | |
| 1352 /** | |
| 1353 * Return the offset of the character immediately following the last character | |
| 1354 * of this constructor's name, or `null` if not named. | |
| 1355 */ | |
| 1356 int nameEnd; | |
| 1357 | |
| 1358 /** | |
| 1359 * True if this constructor has been found by constant evaluation to be free | |
| 1360 * of redirect cycles, and is thus safe to evaluate. | |
| 1361 */ | |
| 1362 bool isCycleFree = false; | |
| 1363 | |
| 1364 /** | |
| 1365 * Initialize a newly created constructor element to have the given [name] and | |
| 1366 * [offset]. | |
| 1367 */ | |
| 1368 ConstructorElementImpl(String name, int offset) : super(name, offset); | |
| 1369 | |
| 1370 /** | |
| 1371 * Initialize a newly created constructor element to have the given [name]. | |
| 1372 */ | |
| 1373 ConstructorElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1374 | |
| 1375 /** | |
| 1376 * Set whether this constructor represents a 'const' constructor. | |
| 1377 */ | |
| 1378 void set const2(bool isConst) { | |
| 1379 setModifier(Modifier.CONST, isConst); | |
| 1380 } | |
| 1381 | |
| 1382 @override | |
| 1383 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 1384 | |
| 1385 /** | |
| 1386 * Set whether this constructor represents a factory method. | |
| 1387 */ | |
| 1388 void set factory(bool isFactory) { | |
| 1389 setModifier(Modifier.FACTORY, isFactory); | |
| 1390 } | |
| 1391 | |
| 1392 @override | |
| 1393 bool get isConst => hasModifier(Modifier.CONST); | |
| 1394 | |
| 1395 @override | |
| 1396 bool get isDefaultConstructor { | |
| 1397 // unnamed | |
| 1398 String name = this.name; | |
| 1399 if (name != null && name.length != 0) { | |
| 1400 return false; | |
| 1401 } | |
| 1402 // no required parameters | |
| 1403 for (ParameterElement parameter in parameters) { | |
| 1404 if (parameter.parameterKind == ParameterKind.REQUIRED) { | |
| 1405 return false; | |
| 1406 } | |
| 1407 } | |
| 1408 // OK, can be used as default constructor | |
| 1409 return true; | |
| 1410 } | |
| 1411 | |
| 1412 @override | |
| 1413 bool get isFactory => hasModifier(Modifier.FACTORY); | |
| 1414 | |
| 1415 @override | |
| 1416 bool get isStatic => false; | |
| 1417 | |
| 1418 @override | |
| 1419 ElementKind get kind => ElementKind.CONSTRUCTOR; | |
| 1420 | |
| 1421 @override | |
| 1422 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); | |
| 1423 | |
| 1424 @override | |
| 1425 void appendTo(StringBuffer buffer) { | |
| 1426 if (enclosingElement == null) { | |
| 1427 String message; | |
| 1428 String name = displayName; | |
| 1429 if (name != null && !name.isEmpty) { | |
| 1430 message = | |
| 1431 'Found constructor element named $name with no enclosing element'; | |
| 1432 } else { | |
| 1433 message = 'Found unnamed constructor element with no enclosing element'; | |
| 1434 } | |
| 1435 AnalysisEngine.instance.logger.logError(message); | |
| 1436 buffer.write('<unknown class>'); | |
| 1437 } else { | |
| 1438 buffer.write(enclosingElement.displayName); | |
| 1439 } | |
| 1440 String name = displayName; | |
| 1441 if (name != null && !name.isEmpty) { | |
| 1442 buffer.write("."); | |
| 1443 buffer.write(name); | |
| 1444 } | |
| 1445 super.appendTo(buffer); | |
| 1446 } | |
| 1447 | |
| 1448 @override | |
| 1449 ConstructorDeclaration computeNode() => | |
| 1450 getNodeMatching((node) => node is ConstructorDeclaration); | |
| 1451 } | |
| 1452 | |
| 1453 /** | |
| 1454 * A constructor element defined in a parameterized type where the values of the | |
| 1455 * type parameters are known. | |
| 1456 */ | |
| 1457 class ConstructorMember extends ExecutableMember implements ConstructorElement { | |
| 1458 /** | |
| 1459 * Initialize a newly created element to represent a constructor, based on the | |
| 1460 * [baseElement], defined by the [definingType]. If [type] is passed, it | |
| 1461 * represents the full type of the member, and will take precedence over | |
| 1462 * the [definingType]. | |
| 1463 */ | |
| 1464 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType, | |
| 1465 [FunctionType type]) | |
| 1466 : super(baseElement, definingType, type); | |
| 1467 | |
| 1468 @override | |
| 1469 ConstructorElement get baseElement => super.baseElement as ConstructorElement; | |
| 1470 | |
| 1471 @override | |
| 1472 InterfaceType get definingType => super.definingType as InterfaceType; | |
| 1473 | |
| 1474 @override | |
| 1475 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 1476 | |
| 1477 @override | |
| 1478 bool get isConst => baseElement.isConst; | |
| 1479 | |
| 1480 @override | |
| 1481 bool get isDefaultConstructor => baseElement.isDefaultConstructor; | |
| 1482 | |
| 1483 @override | |
| 1484 bool get isFactory => baseElement.isFactory; | |
| 1485 | |
| 1486 @override | |
| 1487 int get nameEnd => baseElement.nameEnd; | |
| 1488 | |
| 1489 @override | |
| 1490 int get periodOffset => baseElement.periodOffset; | |
| 1491 | |
| 1492 @override | |
| 1493 ConstructorElement get redirectedConstructor => | |
| 1494 from(baseElement.redirectedConstructor, definingType); | |
| 1495 | |
| 1496 @override | |
| 1497 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); | |
| 1498 | |
| 1499 @override | |
| 1500 ConstructorDeclaration computeNode() => baseElement.computeNode(); | |
| 1501 | |
| 1502 @override | |
| 1503 String toString() { | |
| 1504 ConstructorElement baseElement = this.baseElement; | |
| 1505 List<ParameterElement> parameters = this.parameters; | |
| 1506 FunctionType type = this.type; | |
| 1507 StringBuffer buffer = new StringBuffer(); | |
| 1508 buffer.write(baseElement.enclosingElement.displayName); | |
| 1509 String name = displayName; | |
| 1510 if (name != null && !name.isEmpty) { | |
| 1511 buffer.write("."); | |
| 1512 buffer.write(name); | |
| 1513 } | |
| 1514 buffer.write("("); | |
| 1515 int parameterCount = parameters.length; | |
| 1516 for (int i = 0; i < parameterCount; i++) { | |
| 1517 if (i > 0) { | |
| 1518 buffer.write(", "); | |
| 1519 } | |
| 1520 buffer.write(parameters[i]); | |
| 1521 } | |
| 1522 buffer.write(")"); | |
| 1523 if (type != null) { | |
| 1524 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 1525 buffer.write(type.returnType); | |
| 1526 } | |
| 1527 return buffer.toString(); | |
| 1528 } | |
| 1529 | |
| 1530 /** | |
| 1531 * If the given [constructor]'s type is different when any type parameters | |
| 1532 * from the defining type's declaration are replaced with the actual type | |
| 1533 * arguments from the [definingType], create a constructor member representing | |
| 1534 * the given constructor. Return the member that was created, or the original | |
| 1535 * constructor if no member was created. | |
| 1536 */ | |
| 1537 static ConstructorElement from( | |
| 1538 ConstructorElement constructor, InterfaceType definingType) { | |
| 1539 if (constructor == null || definingType.typeArguments.length == 0) { | |
| 1540 return constructor; | |
| 1541 } | |
| 1542 FunctionType baseType = constructor.type; | |
| 1543 if (baseType == null) { | |
| 1544 // TODO(brianwilkerson) We need to understand when this can happen. | |
| 1545 return constructor; | |
| 1546 } | |
| 1547 List<DartType> argumentTypes = definingType.typeArguments; | |
| 1548 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 1549 FunctionType substitutedType = | |
| 1550 baseType.substitute2(argumentTypes, parameterTypes); | |
| 1551 if (baseType == substitutedType) { | |
| 1552 return constructor; | |
| 1553 } | |
| 1554 return new ConstructorMember(constructor, definingType, substitutedType); | |
| 1555 } | |
| 1556 } | |
| 1557 | |
| 1558 /** | |
| 1559 * A [TopLevelVariableElement] for a top-level 'const' variable that has an | |
| 1560 * initializer. | |
| 1561 */ | |
| 1562 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl | |
| 1563 with ConstVariableElement { | |
| 1564 /** | |
| 1565 * The result of evaluating this variable's initializer. | |
| 1566 */ | |
| 1567 EvaluationResultImpl _result; | |
| 1568 | |
| 1569 /** | |
| 1570 * Initialize a newly created top-level variable element to have the given | |
| 1571 * [name]. | |
| 1572 */ | |
| 1573 ConstTopLevelVariableElementImpl(Identifier name) : super.forNode(name); | |
| 1574 | |
| 1575 @override | |
| 1576 DartObject get constantValue => _result.value; | |
| 1577 | |
| 1578 @override | |
| 1579 EvaluationResultImpl get evaluationResult => _result; | |
| 1580 | |
| 1581 @override | |
| 1582 void set evaluationResult(EvaluationResultImpl result) { | |
| 1583 this._result = result; | |
| 1584 } | |
| 1585 } | |
| 1586 | |
| 1587 /** | |
| 1588 * Mixin used by elements that represent constant variables and have | |
| 1589 * initializers. | |
| 1590 * | |
| 1591 * Note that in correct Dart code, all constant variables must have | |
| 1592 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 1593 * in which case there might be some constant variables that lack initializers. | |
| 1594 * This interface is only used for constant variables that have initializers. | |
| 1595 * | |
| 1596 * This class is not intended to be part of the public API for analyzer. | |
| 1597 */ | |
| 1598 abstract class ConstVariableElement { | |
| 1599 /** | |
| 1600 * If this element represents a constant variable, and it has an initializer, | |
| 1601 * a copy of the initializer for the constant. Otherwise `null`. | |
| 1602 * | |
| 1603 * Note that in correct Dart code, all constant variables must have | |
| 1604 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 1605 * in which case there might be some constant variables that lack | |
| 1606 * initializers. | |
| 1607 */ | |
| 1608 Expression constantInitializer; | |
| 1609 } | |
| 1610 | |
| 1611 /** | |
| 1612 * A [FieldFormalParameterElementImpl] for parameters that have an initializer. | |
| 1613 */ | |
| 1614 class DefaultFieldFormalParameterElementImpl | |
| 1615 extends FieldFormalParameterElementImpl with ConstVariableElement { | |
| 1616 /** | |
| 1617 * The result of evaluating this variable's initializer. | |
| 1618 */ | |
| 1619 EvaluationResultImpl _result; | |
| 1620 | |
| 1621 /** | |
| 1622 * Initialize a newly created parameter element to have the given [name]. | |
| 1623 */ | |
| 1624 DefaultFieldFormalParameterElementImpl(Identifier name) : super(name); | |
| 1625 | |
| 1626 @override | |
| 1627 DartObject get constantValue => _result.value; | |
| 1628 | |
| 1629 @override | |
| 1630 EvaluationResultImpl get evaluationResult => _result; | |
| 1631 | |
| 1632 @override | |
| 1633 void set evaluationResult(EvaluationResultImpl result) { | |
| 1634 this._result = result; | |
| 1635 } | |
| 1636 } | |
| 1637 | |
| 1638 /** | |
| 1639 * A [ParameterElement] for parameters that have an initializer. | |
| 1640 */ | |
| 1641 class DefaultParameterElementImpl extends ParameterElementImpl | |
| 1642 with ConstVariableElement { | |
| 1643 /** | |
| 1644 * The result of evaluating this variable's initializer. | |
| 1645 */ | |
| 1646 EvaluationResultImpl _result; | |
| 1647 | |
| 1648 /** | |
| 1649 * Initialize a newly created parameter element to have the given [name]. | |
| 1650 */ | |
| 1651 DefaultParameterElementImpl(Identifier name) : super.forNode(name); | |
| 1652 | |
| 1653 @override | |
| 1654 DartObject get constantValue => _result.value; | |
| 1655 | |
| 1656 @override | |
| 1657 EvaluationResultImpl get evaluationResult => _result; | |
| 1658 | |
| 1659 @override | |
| 1660 void set evaluationResult(EvaluationResultImpl result) { | |
| 1661 this._result = result; | |
| 1662 } | |
| 1663 | |
| 1664 @override | |
| 1665 DefaultFormalParameter computeNode() => | |
| 1666 getNodeMatching((node) => node is DefaultFormalParameter); | |
| 1667 } | |
| 1668 | |
| 1669 /** | |
| 1670 * The synthetic element representing the declaration of the type `dynamic`. | |
| 1671 */ | |
| 1672 class DynamicElementImpl extends ElementImpl implements TypeDefiningElement { | |
| 1673 /** | |
| 1674 * Return the unique instance of this class. | |
| 1675 */ | |
| 1676 static DynamicElementImpl get instance => | |
| 1677 DynamicTypeImpl.instance.element as DynamicElementImpl; | |
| 1678 | |
| 1679 @override | |
| 1680 DynamicTypeImpl type; | |
| 1681 | |
| 1682 /** | |
| 1683 * Initialize a newly created instance of this class. Instances of this class | |
| 1684 * should <b>not</b> be created except as part of creating the type associated | |
| 1685 * with this element. The single instance of this class should be accessed | |
| 1686 * through the method [getInstance]. | |
| 1687 */ | |
| 1688 DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) { | |
| 1689 setModifier(Modifier.SYNTHETIC, true); | |
| 1690 } | |
| 1691 | |
| 1692 @override | |
| 1693 ElementKind get kind => ElementKind.DYNAMIC; | |
| 1694 | |
| 1695 @override | |
| 1696 accept(ElementVisitor visitor) => null; | |
| 1697 } | |
| 1698 | |
| 1699 /** | |
| 1700 * The [Type] representing the type `dynamic`. | |
| 1701 */ | |
| 1702 class DynamicTypeImpl extends TypeImpl { | |
| 1703 /** | |
| 1704 * The unique instance of this class. | |
| 1705 */ | |
| 1706 static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl._(); | |
| 1707 | |
| 1708 /** | |
| 1709 * Return the unique instance of this class. | |
| 1710 */ | |
| 1711 static DynamicTypeImpl get instance => _INSTANCE; | |
| 1712 | |
| 1713 /** | |
| 1714 * Prevent the creation of instances of this class. | |
| 1715 */ | |
| 1716 DynamicTypeImpl._() | |
| 1717 : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) { | |
| 1718 (element as DynamicElementImpl).type = this; | |
| 1719 } | |
| 1720 | |
| 1721 /** | |
| 1722 * Constructor used by [CircularTypeImpl]. | |
| 1723 */ | |
| 1724 DynamicTypeImpl._circular() | |
| 1725 : super(_INSTANCE.element, Keyword.DYNAMIC.syntax); | |
| 1726 | |
| 1727 @override | |
| 1728 int get hashCode => 1; | |
| 1729 | |
| 1730 @override | |
| 1731 bool get isDynamic => true; | |
| 1732 | |
| 1733 @override | |
| 1734 bool operator ==(Object object) => identical(object, this); | |
| 1735 | |
| 1736 @override | |
| 1737 bool isMoreSpecificThan(DartType type, | |
| 1738 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 1739 // T is S | |
| 1740 if (identical(this, type)) { | |
| 1741 return true; | |
| 1742 } | |
| 1743 // else | |
| 1744 return withDynamic; | |
| 1745 } | |
| 1746 | |
| 1747 @override | |
| 1748 bool isSubtypeOf(DartType type) => true; | |
| 1749 | |
| 1750 @override | |
| 1751 bool isSupertypeOf(DartType type) => true; | |
| 1752 | |
| 1753 @override | |
| 1754 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 1755 | |
| 1756 @override | |
| 1757 DartType substitute2( | |
| 1758 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 1759 [List<FunctionTypeAliasElement> prune]) { | |
| 1760 int length = parameterTypes.length; | |
| 1761 for (int i = 0; i < length; i++) { | |
| 1762 if (parameterTypes[i] == this) { | |
| 1763 return argumentTypes[i]; | |
| 1764 } | |
| 1765 } | |
| 1766 return this; | |
| 1767 } | |
| 1768 } | |
| 1769 | |
| 1770 /** | |
| 1771 * A concrete implementation of an [ElementAnnotation]. | |
| 1772 */ | |
| 1773 class ElementAnnotationImpl implements ElementAnnotation { | |
| 1774 /** | |
| 1775 * The name of the class used to mark an element as being deprecated. | |
| 1776 */ | |
| 1777 static String _DEPRECATED_CLASS_NAME = "Deprecated"; | |
| 1778 | |
| 1779 /** | |
| 1780 * The name of the top-level variable used to mark an element as being | |
| 1781 * deprecated. | |
| 1782 */ | |
| 1783 static String _DEPRECATED_VARIABLE_NAME = "deprecated"; | |
| 1784 | |
| 1785 /** | |
| 1786 * The name of the top-level variable used to mark a method as being expected | |
| 1787 * to override an inherited method. | |
| 1788 */ | |
| 1789 static String _OVERRIDE_VARIABLE_NAME = "override"; | |
| 1790 | |
| 1791 /** | |
| 1792 * The name of the top-level variable used to mark a class as implementing a | |
| 1793 * proxy object. | |
| 1794 */ | |
| 1795 static String PROXY_VARIABLE_NAME = "proxy"; | |
| 1796 | |
| 1797 /** | |
| 1798 * The element representing the field, variable, or constructor being used as | |
| 1799 * an annotation. | |
| 1800 */ | |
| 1801 final Element element; | |
| 1802 | |
| 1803 /** | |
| 1804 * The result of evaluating this annotation as a compile-time constant | |
| 1805 * expression, or `null` if the compilation unit containing the variable has | |
| 1806 * not been resolved. | |
| 1807 */ | |
| 1808 EvaluationResultImpl evaluationResult; | |
| 1809 | |
| 1810 /** | |
| 1811 * Initialize a newly created annotation. The given [element] is the element | |
| 1812 * representing the field, variable, or constructor being used as an | |
| 1813 * annotation. | |
| 1814 */ | |
| 1815 ElementAnnotationImpl(this.element); | |
| 1816 | |
| 1817 @override | |
| 1818 DartObject get constantValue => evaluationResult.value; | |
| 1819 | |
| 1820 @override | |
| 1821 bool get isDeprecated { | |
| 1822 if (element != null) { | |
| 1823 LibraryElement library = element.library; | |
| 1824 if (library != null && library.isDartCore) { | |
| 1825 if (element is ConstructorElement) { | |
| 1826 ConstructorElement constructorElement = element as ConstructorElement; | |
| 1827 if (constructorElement.enclosingElement.name == | |
| 1828 _DEPRECATED_CLASS_NAME) { | |
| 1829 return true; | |
| 1830 } | |
| 1831 } else if (element is PropertyAccessorElement && | |
| 1832 element.name == _DEPRECATED_VARIABLE_NAME) { | |
| 1833 return true; | |
| 1834 } | |
| 1835 } | |
| 1836 } | |
| 1837 return false; | |
| 1838 } | |
| 1839 | |
| 1840 @override | |
| 1841 bool get isOverride { | |
| 1842 if (element != null) { | |
| 1843 LibraryElement library = element.library; | |
| 1844 if (library != null && library.isDartCore) { | |
| 1845 if (element is PropertyAccessorElement && | |
| 1846 element.name == _OVERRIDE_VARIABLE_NAME) { | |
| 1847 return true; | |
| 1848 } | |
| 1849 } | |
| 1850 } | |
| 1851 return false; | |
| 1852 } | |
| 1853 | |
| 1854 @override | |
| 1855 bool get isProxy { | |
| 1856 if (element != null) { | |
| 1857 LibraryElement library = element.library; | |
| 1858 if (library != null && library.isDartCore) { | |
| 1859 if (element is PropertyAccessorElement && | |
| 1860 element.name == PROXY_VARIABLE_NAME) { | |
| 1861 return true; | |
| 1862 } | |
| 1863 } | |
| 1864 } | |
| 1865 return false; | |
| 1866 } | |
| 1867 | |
| 1868 @override | |
| 1869 String toString() => '@$element'; | |
| 1870 } | |
| 1871 | |
| 1872 /** | |
| 1873 * A base class for concrete implementations of an [Element]. | |
| 1874 */ | |
| 1875 abstract class ElementImpl implements Element { | |
| 1876 /** | |
| 1877 * An Unicode right arrow. | |
| 1878 */ | |
| 1879 static final String RIGHT_ARROW = " \u2192 "; | |
| 1880 | |
| 1881 static int _NEXT_ID = 0; | |
| 1882 | |
| 1883 final int id = _NEXT_ID++; | |
| 1884 | |
| 1885 /** | |
| 1886 * The enclosing element of this element, or `null` if this element is at the | |
| 1887 * root of the element structure. | |
| 1888 */ | |
| 1889 ElementImpl _enclosingElement; | |
| 1890 | |
| 1891 /** | |
| 1892 * The name of this element. | |
| 1893 */ | |
| 1894 String _name; | |
| 1895 | |
| 1896 /** | |
| 1897 * The offset of the name of this element in the file that contains the | |
| 1898 * declaration of this element. | |
| 1899 */ | |
| 1900 int _nameOffset = 0; | |
| 1901 | |
| 1902 /** | |
| 1903 * A bit-encoded form of the modifiers associated with this element. | |
| 1904 */ | |
| 1905 int _modifiers = 0; | |
| 1906 | |
| 1907 /** | |
| 1908 * A list containing all of the metadata associated with this element. | |
| 1909 */ | |
| 1910 List<ElementAnnotation> metadata = ElementAnnotation.EMPTY_LIST; | |
| 1911 | |
| 1912 /** | |
| 1913 * A cached copy of the calculated hashCode for this element. | |
| 1914 */ | |
| 1915 int _cachedHashCode; | |
| 1916 | |
| 1917 /** | |
| 1918 * A cached copy of the calculated location for this element. | |
| 1919 */ | |
| 1920 ElementLocation _cachedLocation; | |
| 1921 | |
| 1922 /** | |
| 1923 * The offset to the beginning of the documentation comment, | |
| 1924 * or `null` if this element does not have a documentation comment. | |
| 1925 */ | |
| 1926 int _docRangeOffset; | |
| 1927 | |
| 1928 /** | |
| 1929 * The length of the documentation comment range for this element. | |
| 1930 */ | |
| 1931 int _docRangeLength; | |
| 1932 | |
| 1933 /** | |
| 1934 * Initialize a newly created element to have the given [name] at the given | |
| 1935 * [_nameOffset]. | |
| 1936 */ | |
| 1937 ElementImpl(String name, this._nameOffset) { | |
| 1938 this._name = StringUtilities.intern(name); | |
| 1939 } | |
| 1940 | |
| 1941 /** | |
| 1942 * Initialize a newly created element to have the given [name]. | |
| 1943 */ | |
| 1944 ElementImpl.forNode(Identifier name) | |
| 1945 : this(name == null ? "" : name.name, name == null ? -1 : name.offset); | |
| 1946 | |
| 1947 @override | |
| 1948 AnalysisContext get context { | |
| 1949 if (_enclosingElement == null) { | |
| 1950 return null; | |
| 1951 } | |
| 1952 return _enclosingElement.context; | |
| 1953 } | |
| 1954 | |
| 1955 @override | |
| 1956 String get displayName => _name; | |
| 1957 | |
| 1958 @override | |
| 1959 SourceRange get docRange { | |
| 1960 if (_docRangeOffset != null && _docRangeLength != null) { | |
| 1961 return new SourceRange(_docRangeOffset, _docRangeLength); | |
| 1962 } | |
| 1963 return null; | |
| 1964 } | |
| 1965 | |
| 1966 @override | |
| 1967 Element get enclosingElement => _enclosingElement; | |
| 1968 | |
| 1969 /** | |
| 1970 * Set the enclosing element of this element to the given [element]. | |
| 1971 */ | |
| 1972 void set enclosingElement(Element element) { | |
| 1973 _enclosingElement = element as ElementImpl; | |
| 1974 _cachedLocation = null; | |
| 1975 _cachedHashCode = null; | |
| 1976 } | |
| 1977 | |
| 1978 @override | |
| 1979 int get hashCode { | |
| 1980 // TODO: We might want to re-visit this optimization in the future. | |
| 1981 // We cache the hash code value as this is a very frequently called method. | |
| 1982 if (_cachedHashCode == null) { | |
| 1983 int hashIdentifier = identifier.hashCode; | |
| 1984 Element enclosing = enclosingElement; | |
| 1985 if (enclosing != null) { | |
| 1986 _cachedHashCode = hashIdentifier + enclosing.hashCode; | |
| 1987 } else { | |
| 1988 _cachedHashCode = hashIdentifier; | |
| 1989 } | |
| 1990 } | |
| 1991 return _cachedHashCode; | |
| 1992 } | |
| 1993 | |
| 1994 /** | |
| 1995 * Return an identifier that uniquely identifies this element among the | |
| 1996 * children of this element's parent. | |
| 1997 */ | |
| 1998 String get identifier => name; | |
| 1999 | |
| 2000 @override | |
| 2001 bool get isDeprecated { | |
| 2002 for (ElementAnnotation annotation in metadata) { | |
| 2003 if (annotation.isDeprecated) { | |
| 2004 return true; | |
| 2005 } | |
| 2006 } | |
| 2007 return false; | |
| 2008 } | |
| 2009 | |
| 2010 @override | |
| 2011 bool get isOverride { | |
| 2012 for (ElementAnnotation annotation in metadata) { | |
| 2013 if (annotation.isOverride) { | |
| 2014 return true; | |
| 2015 } | |
| 2016 } | |
| 2017 return false; | |
| 2018 } | |
| 2019 | |
| 2020 @override | |
| 2021 bool get isPrivate { | |
| 2022 String name = displayName; | |
| 2023 if (name == null) { | |
| 2024 return true; | |
| 2025 } | |
| 2026 return Identifier.isPrivateName(name); | |
| 2027 } | |
| 2028 | |
| 2029 @override | |
| 2030 bool get isPublic => !isPrivate; | |
| 2031 | |
| 2032 @override | |
| 2033 bool get isSynthetic => hasModifier(Modifier.SYNTHETIC); | |
| 2034 | |
| 2035 @override | |
| 2036 LibraryElement get library => | |
| 2037 getAncestor((element) => element is LibraryElement); | |
| 2038 | |
| 2039 @override | |
| 2040 ElementLocation get location { | |
| 2041 if (_cachedLocation == null) { | |
| 2042 _cachedLocation = new ElementLocationImpl.con1(this); | |
| 2043 } | |
| 2044 return _cachedLocation; | |
| 2045 } | |
| 2046 | |
| 2047 @override | |
| 2048 String get name => _name; | |
| 2049 | |
| 2050 void set name(String name) { | |
| 2051 this._name = name; | |
| 2052 _cachedLocation = null; | |
| 2053 _cachedHashCode = null; | |
| 2054 } | |
| 2055 | |
| 2056 @override | |
| 2057 int get nameLength => displayName != null ? displayName.length : 0; | |
| 2058 | |
| 2059 @override | |
| 2060 int get nameOffset => _nameOffset; | |
| 2061 | |
| 2062 /** | |
| 2063 * Sets the offset of the name of this element in the file that contains the | |
| 2064 * declaration of this element. | |
| 2065 */ | |
| 2066 void set nameOffset(int offset) { | |
| 2067 _nameOffset = offset; | |
| 2068 _cachedHashCode = null; | |
| 2069 _cachedLocation = null; | |
| 2070 } | |
| 2071 | |
| 2072 @override | |
| 2073 Source get source { | |
| 2074 if (_enclosingElement == null) { | |
| 2075 return null; | |
| 2076 } | |
| 2077 return _enclosingElement.source; | |
| 2078 } | |
| 2079 | |
| 2080 /** | |
| 2081 * Set whether this element is synthetic. | |
| 2082 */ | |
| 2083 void set synthetic(bool isSynthetic) { | |
| 2084 setModifier(Modifier.SYNTHETIC, isSynthetic); | |
| 2085 } | |
| 2086 | |
| 2087 @override | |
| 2088 CompilationUnit get unit => context.resolveCompilationUnit(source, library); | |
| 2089 | |
| 2090 @override | |
| 2091 bool operator ==(Object object) { | |
| 2092 if (identical(this, object)) { | |
| 2093 return true; | |
| 2094 } | |
| 2095 if (object == null || hashCode != object.hashCode) { | |
| 2096 return false; | |
| 2097 } | |
| 2098 return object.runtimeType == runtimeType && | |
| 2099 (object as Element).location == location; | |
| 2100 } | |
| 2101 | |
| 2102 /** | |
| 2103 * Append a textual representation of this element to the given [buffer]. | |
| 2104 */ | |
| 2105 void appendTo(StringBuffer buffer) { | |
| 2106 if (_name == null) { | |
| 2107 buffer.write("<unnamed "); | |
| 2108 buffer.write(runtimeType.toString()); | |
| 2109 buffer.write(">"); | |
| 2110 } else { | |
| 2111 buffer.write(_name); | |
| 2112 } | |
| 2113 } | |
| 2114 | |
| 2115 @override | |
| 2116 String computeDocumentationComment() { | |
| 2117 AnalysisContext context = this.context; | |
| 2118 if (context == null) { | |
| 2119 return null; | |
| 2120 } | |
| 2121 return context.computeDocumentationComment(this); | |
| 2122 } | |
| 2123 | |
| 2124 @override | |
| 2125 AstNode computeNode() => getNodeMatching((node) => node is AstNode); | |
| 2126 | |
| 2127 /** | |
| 2128 * Set this element as the enclosing element for given [element]. | |
| 2129 */ | |
| 2130 void encloseElement(ElementImpl element) { | |
| 2131 element.enclosingElement = this; | |
| 2132 } | |
| 2133 | |
| 2134 @override | |
| 2135 Element getAncestor(Predicate<Element> predicate) { | |
| 2136 Element ancestor = _enclosingElement; | |
| 2137 while (ancestor != null && !predicate(ancestor)) { | |
| 2138 ancestor = ancestor.enclosingElement; | |
| 2139 } | |
| 2140 return ancestor; | |
| 2141 } | |
| 2142 | |
| 2143 /** | |
| 2144 * Return the child of this element that is uniquely identified by the given | |
| 2145 * [identifier], or `null` if there is no such child. | |
| 2146 */ | |
| 2147 ElementImpl getChild(String identifier) => null; | |
| 2148 | |
| 2149 @override | |
| 2150 String getExtendedDisplayName(String shortName) { | |
| 2151 if (shortName == null) { | |
| 2152 shortName = displayName; | |
| 2153 } | |
| 2154 Source source = this.source; | |
| 2155 if (source != null) { | |
| 2156 return "$shortName (${source.fullName})"; | |
| 2157 } | |
| 2158 return shortName; | |
| 2159 } | |
| 2160 | |
| 2161 /** | |
| 2162 * Return the resolved [AstNode] of the given type enclosing [getNameOffset]. | |
| 2163 */ | |
| 2164 AstNode getNodeMatching(Predicate<AstNode> predicate) { | |
| 2165 CompilationUnit unit = this.unit; | |
| 2166 if (unit == null) { | |
| 2167 return null; | |
| 2168 } | |
| 2169 int offset = nameOffset; | |
| 2170 AstNode node = new NodeLocator(offset).searchWithin(unit); | |
| 2171 if (node == null) { | |
| 2172 return null; | |
| 2173 } | |
| 2174 return node.getAncestor(predicate); | |
| 2175 } | |
| 2176 | |
| 2177 /** | |
| 2178 * Return `true` if this element has the given [modifier] associated with it. | |
| 2179 */ | |
| 2180 bool hasModifier(Modifier modifier) => | |
| 2181 BooleanArray.getEnum(_modifiers, modifier); | |
| 2182 | |
| 2183 @override | |
| 2184 bool isAccessibleIn(LibraryElement library) { | |
| 2185 if (Identifier.isPrivateName(_name)) { | |
| 2186 return library == this.library; | |
| 2187 } | |
| 2188 return true; | |
| 2189 } | |
| 2190 | |
| 2191 /** | |
| 2192 * If the given [child] is not `null`, use the given [visitor] to visit it. | |
| 2193 */ | |
| 2194 void safelyVisitChild(Element child, ElementVisitor visitor) { | |
| 2195 if (child != null) { | |
| 2196 child.accept(visitor); | |
| 2197 } | |
| 2198 } | |
| 2199 | |
| 2200 /** | |
| 2201 * Use the given [visitor] to visit all of the [children] in the given array. | |
| 2202 */ | |
| 2203 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { | |
| 2204 if (children != null) { | |
| 2205 for (Element child in children) { | |
| 2206 child.accept(visitor); | |
| 2207 } | |
| 2208 } | |
| 2209 } | |
| 2210 | |
| 2211 /** | |
| 2212 * Set the documentation comment source range for this element. | |
| 2213 */ | |
| 2214 void setDocRange(int offset, int length) { | |
| 2215 _docRangeOffset = offset; | |
| 2216 _docRangeLength = length; | |
| 2217 } | |
| 2218 | |
| 2219 /** | |
| 2220 * Set whether the given [modifier] is associated with this element to | |
| 2221 * correspond to the given [value]. | |
| 2222 */ | |
| 2223 void setModifier(Modifier modifier, bool value) { | |
| 2224 _modifiers = BooleanArray.setEnum(_modifiers, modifier, value); | |
| 2225 } | |
| 2226 | |
| 2227 @override | |
| 2228 String toString() { | |
| 2229 StringBuffer buffer = new StringBuffer(); | |
| 2230 appendTo(buffer); | |
| 2231 return buffer.toString(); | |
| 2232 } | |
| 2233 | |
| 2234 @override | |
| 2235 void visitChildren(ElementVisitor visitor) { | |
| 2236 // There are no children to visit | |
| 2237 } | |
| 2238 } | |
| 2239 | |
| 2240 /** | |
| 2241 * A concrete implementation of an [ElementLocation]. | |
| 2242 */ | |
| 2243 class ElementLocationImpl implements ElementLocation { | |
| 2244 /** | |
| 2245 * The character used to separate components in the encoded form. | |
| 2246 */ | |
| 2247 static int _SEPARATOR_CHAR = 0x3B; | |
| 2248 | |
| 2249 /** | |
| 2250 * The path to the element whose location is represented by this object. | |
| 2251 */ | |
| 2252 List<String> _components; | |
| 2253 | |
| 2254 /** | |
| 2255 * The object managing [indexKeyId] and [indexLocationId]. | |
| 2256 */ | |
| 2257 Object indexOwner; | |
| 2258 | |
| 2259 /** | |
| 2260 * A cached id of this location in index. | |
| 2261 */ | |
| 2262 int indexKeyId; | |
| 2263 | |
| 2264 /** | |
| 2265 * A cached id of this location in index. | |
| 2266 */ | |
| 2267 int indexLocationId; | |
| 2268 | |
| 2269 /** | |
| 2270 * Initialize a newly created location to represent the given [element]. | |
| 2271 */ | |
| 2272 ElementLocationImpl.con1(Element element) { | |
| 2273 List<String> components = new List<String>(); | |
| 2274 Element ancestor = element; | |
| 2275 while (ancestor != null) { | |
| 2276 components.insert(0, (ancestor as ElementImpl).identifier); | |
| 2277 ancestor = ancestor.enclosingElement; | |
| 2278 } | |
| 2279 this._components = components; | |
| 2280 } | |
| 2281 | |
| 2282 /** | |
| 2283 * Initialize a newly created location from the given [encoding]. | |
| 2284 */ | |
| 2285 ElementLocationImpl.con2(String encoding) { | |
| 2286 this._components = _decode(encoding); | |
| 2287 } | |
| 2288 | |
| 2289 /** | |
| 2290 * Initialize a newly created location from the given [components]. | |
| 2291 */ | |
| 2292 ElementLocationImpl.con3(List<String> components) { | |
| 2293 this._components = components; | |
| 2294 } | |
| 2295 | |
| 2296 @override | |
| 2297 List<String> get components => _components; | |
| 2298 | |
| 2299 @override | |
| 2300 String get encoding { | |
| 2301 StringBuffer buffer = new StringBuffer(); | |
| 2302 int length = _components.length; | |
| 2303 for (int i = 0; i < length; i++) { | |
| 2304 if (i > 0) { | |
| 2305 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 2306 } | |
| 2307 _encode(buffer, _components[i]); | |
| 2308 } | |
| 2309 return buffer.toString(); | |
| 2310 } | |
| 2311 | |
| 2312 @override | |
| 2313 int get hashCode { | |
| 2314 int result = 1; | |
| 2315 for (int i = 0; i < _components.length; i++) { | |
| 2316 String component = _components[i]; | |
| 2317 result = 31 * result + component.hashCode; | |
| 2318 } | |
| 2319 return result; | |
| 2320 } | |
| 2321 | |
| 2322 @override | |
| 2323 bool operator ==(Object object) { | |
| 2324 if (identical(this, object)) { | |
| 2325 return true; | |
| 2326 } | |
| 2327 if (object is! ElementLocationImpl) { | |
| 2328 return false; | |
| 2329 } | |
| 2330 ElementLocationImpl location = object as ElementLocationImpl; | |
| 2331 List<String> otherComponents = location._components; | |
| 2332 int length = _components.length; | |
| 2333 if (otherComponents.length != length) { | |
| 2334 return false; | |
| 2335 } | |
| 2336 for (int i = 0; i < length; i++) { | |
| 2337 if (_components[i] != otherComponents[i]) { | |
| 2338 return false; | |
| 2339 } | |
| 2340 } | |
| 2341 return true; | |
| 2342 } | |
| 2343 | |
| 2344 @override | |
| 2345 String toString() => encoding; | |
| 2346 | |
| 2347 /** | |
| 2348 * Decode the [encoding] of a location into a list of components and return | |
| 2349 * the components. | |
| 2350 */ | |
| 2351 List<String> _decode(String encoding) { | |
| 2352 List<String> components = new List<String>(); | |
| 2353 StringBuffer buffer = new StringBuffer(); | |
| 2354 int index = 0; | |
| 2355 int length = encoding.length; | |
| 2356 while (index < length) { | |
| 2357 int currentChar = encoding.codeUnitAt(index); | |
| 2358 if (currentChar == _SEPARATOR_CHAR) { | |
| 2359 if (index + 1 < length && | |
| 2360 encoding.codeUnitAt(index + 1) == _SEPARATOR_CHAR) { | |
| 2361 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 2362 index += 2; | |
| 2363 } else { | |
| 2364 components.add(buffer.toString()); | |
| 2365 buffer = new StringBuffer(); | |
| 2366 index++; | |
| 2367 } | |
| 2368 } else { | |
| 2369 buffer.writeCharCode(currentChar); | |
| 2370 index++; | |
| 2371 } | |
| 2372 } | |
| 2373 components.add(buffer.toString()); | |
| 2374 return components; | |
| 2375 } | |
| 2376 | |
| 2377 /** | |
| 2378 * Append an encoded form of the given [component] to the given [buffer]. | |
| 2379 */ | |
| 2380 void _encode(StringBuffer buffer, String component) { | |
| 2381 int length = component.length; | |
| 2382 for (int i = 0; i < length; i++) { | |
| 2383 int currentChar = component.codeUnitAt(i); | |
| 2384 if (currentChar == _SEPARATOR_CHAR) { | |
| 2385 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 2386 } | |
| 2387 buffer.writeCharCode(currentChar); | |
| 2388 } | |
| 2389 } | |
| 2390 } | |
| 2391 | |
| 2392 /** | |
| 2393 * A base class for concrete implementations of an [ExecutableElement]. | |
| 2394 */ | |
| 2395 abstract class ExecutableElementImpl extends ElementImpl | |
| 2396 implements ExecutableElement { | |
| 2397 /** | |
| 2398 * A list containing all of the functions defined within this executable | |
| 2399 * element. | |
| 2400 */ | |
| 2401 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; | |
| 2402 | |
| 2403 /** | |
| 2404 * A list containing all of the labels defined within this executable element. | |
| 2405 */ | |
| 2406 List<LabelElement> _labels = LabelElement.EMPTY_LIST; | |
| 2407 | |
| 2408 /** | |
| 2409 * A list containing all of the local variables defined within this executable | |
| 2410 * element. | |
| 2411 */ | |
| 2412 List<LocalVariableElement> _localVariables = LocalVariableElement.EMPTY_LIST; | |
| 2413 | |
| 2414 /** | |
| 2415 * A list containing all of the parameters defined by this executable element. | |
| 2416 */ | |
| 2417 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 2418 | |
| 2419 /** | |
| 2420 * A list containing all of the type parameters defined for this executable | |
| 2421 * element. | |
| 2422 */ | |
| 2423 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 2424 | |
| 2425 /** | |
| 2426 * The return type defined by this executable element. | |
| 2427 */ | |
| 2428 DartType returnType; | |
| 2429 | |
| 2430 /** | |
| 2431 * The type of function defined by this executable element. | |
| 2432 */ | |
| 2433 FunctionType type; | |
| 2434 | |
| 2435 /** | |
| 2436 * Initialize a newly created executable element to have the given [name] and | |
| 2437 * [offset]. | |
| 2438 */ | |
| 2439 ExecutableElementImpl(String name, int offset) : super(name, offset); | |
| 2440 | |
| 2441 /** | |
| 2442 * Initialize a newly created executable element to have the given [name]. | |
| 2443 */ | |
| 2444 ExecutableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 2445 | |
| 2446 /** | |
| 2447 * Set whether this executable element's body is asynchronous. | |
| 2448 */ | |
| 2449 void set asynchronous(bool isAsynchronous) { | |
| 2450 setModifier(Modifier.ASYNCHRONOUS, isAsynchronous); | |
| 2451 } | |
| 2452 | |
| 2453 /** | |
| 2454 * Set whether this executable element is external. | |
| 2455 */ | |
| 2456 void set external(bool isExternal) { | |
| 2457 setModifier(Modifier.EXTERNAL, isExternal); | |
| 2458 } | |
| 2459 | |
| 2460 @override | |
| 2461 List<FunctionElement> get functions => _functions; | |
| 2462 | |
| 2463 /** | |
| 2464 * Set the functions defined within this executable element to the given | |
| 2465 * [functions]. | |
| 2466 */ | |
| 2467 void set functions(List<FunctionElement> functions) { | |
| 2468 for (FunctionElement function in functions) { | |
| 2469 (function as FunctionElementImpl).enclosingElement = this; | |
| 2470 } | |
| 2471 this._functions = functions; | |
| 2472 } | |
| 2473 | |
| 2474 /** | |
| 2475 * Set whether this method's body is a generator. | |
| 2476 */ | |
| 2477 void set generator(bool isGenerator) { | |
| 2478 setModifier(Modifier.GENERATOR, isGenerator); | |
| 2479 } | |
| 2480 | |
| 2481 @override | |
| 2482 bool get hasImplicitReturnType => hasModifier(Modifier.IMPLICIT_TYPE); | |
| 2483 | |
| 2484 /** | |
| 2485 * Set whether this executable element has an implicit return type. | |
| 2486 */ | |
| 2487 void set hasImplicitReturnType(bool hasImplicitReturnType) { | |
| 2488 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType); | |
| 2489 } | |
| 2490 | |
| 2491 @override | |
| 2492 bool get isAbstract => hasModifier(Modifier.ABSTRACT); | |
| 2493 | |
| 2494 @override | |
| 2495 bool get isAsynchronous => hasModifier(Modifier.ASYNCHRONOUS); | |
| 2496 | |
| 2497 @override | |
| 2498 bool get isExternal => hasModifier(Modifier.EXTERNAL); | |
| 2499 | |
| 2500 @override | |
| 2501 bool get isGenerator => hasModifier(Modifier.GENERATOR); | |
| 2502 | |
| 2503 @override | |
| 2504 bool get isOperator => false; | |
| 2505 | |
| 2506 @override | |
| 2507 bool get isSynchronous => !hasModifier(Modifier.ASYNCHRONOUS); | |
| 2508 | |
| 2509 @override | |
| 2510 List<LabelElement> get labels => _labels; | |
| 2511 | |
| 2512 /** | |
| 2513 * Set the labels defined within this executable element to the given | |
| 2514 * [labels]. | |
| 2515 */ | |
| 2516 void set labels(List<LabelElement> labels) { | |
| 2517 for (LabelElement label in labels) { | |
| 2518 (label as LabelElementImpl).enclosingElement = this; | |
| 2519 } | |
| 2520 this._labels = labels; | |
| 2521 } | |
| 2522 | |
| 2523 @override | |
| 2524 List<LocalVariableElement> get localVariables => _localVariables; | |
| 2525 | |
| 2526 /** | |
| 2527 * Set the local variables defined within this executable element to the given | |
| 2528 * [variables]. | |
| 2529 */ | |
| 2530 void set localVariables(List<LocalVariableElement> variables) { | |
| 2531 for (LocalVariableElement variable in variables) { | |
| 2532 (variable as LocalVariableElementImpl).enclosingElement = this; | |
| 2533 } | |
| 2534 this._localVariables = variables; | |
| 2535 } | |
| 2536 | |
| 2537 @override | |
| 2538 List<ParameterElement> get parameters => _parameters; | |
| 2539 | |
| 2540 /** | |
| 2541 * Set the parameters defined by this executable element to the given | |
| 2542 * [parameters]. | |
| 2543 */ | |
| 2544 void set parameters(List<ParameterElement> parameters) { | |
| 2545 for (ParameterElement parameter in parameters) { | |
| 2546 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 2547 } | |
| 2548 this._parameters = parameters; | |
| 2549 } | |
| 2550 | |
| 2551 @override | |
| 2552 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 2553 | |
| 2554 /** | |
| 2555 * Set the type parameters defined by this executable element to the given | |
| 2556 * [typeParameters]. | |
| 2557 */ | |
| 2558 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 2559 for (TypeParameterElement parameter in typeParameters) { | |
| 2560 (parameter as TypeParameterElementImpl).enclosingElement = this; | |
| 2561 } | |
| 2562 this._typeParameters = typeParameters; | |
| 2563 } | |
| 2564 | |
| 2565 @override | |
| 2566 void appendTo(StringBuffer buffer) { | |
| 2567 if (this.kind != ElementKind.GETTER) { | |
| 2568 int typeParameterCount = _typeParameters.length; | |
| 2569 if (typeParameterCount > 0) { | |
| 2570 buffer.write('<'); | |
| 2571 for (int i = 0; i < typeParameterCount; i++) { | |
| 2572 if (i > 0) { | |
| 2573 buffer.write(", "); | |
| 2574 } | |
| 2575 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 2576 } | |
| 2577 buffer.write('>'); | |
| 2578 } | |
| 2579 buffer.write("("); | |
| 2580 String closing = null; | |
| 2581 ParameterKind kind = ParameterKind.REQUIRED; | |
| 2582 int parameterCount = _parameters.length; | |
| 2583 for (int i = 0; i < parameterCount; i++) { | |
| 2584 if (i > 0) { | |
| 2585 buffer.write(", "); | |
| 2586 } | |
| 2587 ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl; | |
| 2588 ParameterKind parameterKind = parameter.parameterKind; | |
| 2589 if (parameterKind != kind) { | |
| 2590 if (closing != null) { | |
| 2591 buffer.write(closing); | |
| 2592 } | |
| 2593 if (parameterKind == ParameterKind.POSITIONAL) { | |
| 2594 buffer.write("["); | |
| 2595 closing = "]"; | |
| 2596 } else if (parameterKind == ParameterKind.NAMED) { | |
| 2597 buffer.write("{"); | |
| 2598 closing = "}"; | |
| 2599 } else { | |
| 2600 closing = null; | |
| 2601 } | |
| 2602 } | |
| 2603 kind = parameterKind; | |
| 2604 parameter.appendToWithoutDelimiters(buffer); | |
| 2605 } | |
| 2606 if (closing != null) { | |
| 2607 buffer.write(closing); | |
| 2608 } | |
| 2609 buffer.write(")"); | |
| 2610 } | |
| 2611 if (type != null) { | |
| 2612 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 2613 buffer.write(type.returnType); | |
| 2614 } | |
| 2615 } | |
| 2616 | |
| 2617 @override | |
| 2618 ElementImpl getChild(String identifier) { | |
| 2619 for (ExecutableElement function in _functions) { | |
| 2620 if ((function as ExecutableElementImpl).identifier == identifier) { | |
| 2621 return function as ExecutableElementImpl; | |
| 2622 } | |
| 2623 } | |
| 2624 for (LabelElement label in _labels) { | |
| 2625 if ((label as LabelElementImpl).identifier == identifier) { | |
| 2626 return label as LabelElementImpl; | |
| 2627 } | |
| 2628 } | |
| 2629 for (VariableElement variable in _localVariables) { | |
| 2630 if ((variable as VariableElementImpl).identifier == identifier) { | |
| 2631 return variable as VariableElementImpl; | |
| 2632 } | |
| 2633 } | |
| 2634 for (ParameterElement parameter in _parameters) { | |
| 2635 if ((parameter as ParameterElementImpl).identifier == identifier) { | |
| 2636 return parameter as ParameterElementImpl; | |
| 2637 } | |
| 2638 } | |
| 2639 return null; | |
| 2640 } | |
| 2641 | |
| 2642 @override | |
| 2643 void visitChildren(ElementVisitor visitor) { | |
| 2644 super.visitChildren(visitor); | |
| 2645 safelyVisitChildren(_functions, visitor); | |
| 2646 safelyVisitChildren(_labels, visitor); | |
| 2647 safelyVisitChildren(_localVariables, visitor); | |
| 2648 safelyVisitChildren(_parameters, visitor); | |
| 2649 } | |
| 2650 } | |
| 2651 | |
| 2652 /** | |
| 2653 * An executable element defined in a parameterized type where the values of the | |
| 2654 * type parameters are known. | |
| 2655 */ | |
| 2656 abstract class ExecutableMember extends Member implements ExecutableElement { | |
| 2657 @override | |
| 2658 final FunctionType type; | |
| 2659 | |
| 2660 /** | |
| 2661 * Initialize a newly created element to represent a callable element (like a | |
| 2662 * method or function or property), based on the [baseElement], defined by the | |
| 2663 * [definingType]. If [type] is passed, it represents the full type of the | |
| 2664 * member, and will take precedence over the [definingType]. | |
| 2665 */ | |
| 2666 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType, | |
| 2667 [FunctionType type]) | |
| 2668 : type = type ?? | |
| 2669 baseElement.type.substitute2(definingType.typeArguments, | |
| 2670 TypeParameterTypeImpl.getTypes(definingType.typeParameters)), | |
| 2671 super(baseElement, definingType); | |
| 2672 | |
| 2673 @override | |
| 2674 ExecutableElement get baseElement => super.baseElement as ExecutableElement; | |
| 2675 | |
| 2676 @override | |
| 2677 List<FunctionElement> get functions { | |
| 2678 // | |
| 2679 // Elements within this element should have type parameters substituted, | |
| 2680 // just like this element. | |
| 2681 // | |
| 2682 throw new UnsupportedOperationException(); | |
| 2683 // return getBaseElement().getFunctions(); | |
| 2684 } | |
| 2685 | |
| 2686 @override | |
| 2687 bool get hasImplicitReturnType => baseElement.hasImplicitReturnType; | |
| 2688 | |
| 2689 @override | |
| 2690 bool get isAbstract => baseElement.isAbstract; | |
| 2691 | |
| 2692 @override | |
| 2693 bool get isAsynchronous => baseElement.isAsynchronous; | |
| 2694 | |
| 2695 @override | |
| 2696 bool get isExternal => baseElement.isExternal; | |
| 2697 | |
| 2698 @override | |
| 2699 bool get isGenerator => baseElement.isGenerator; | |
| 2700 | |
| 2701 @override | |
| 2702 bool get isOperator => baseElement.isOperator; | |
| 2703 | |
| 2704 @override | |
| 2705 bool get isStatic => baseElement.isStatic; | |
| 2706 | |
| 2707 @override | |
| 2708 bool get isSynchronous => baseElement.isSynchronous; | |
| 2709 | |
| 2710 @override | |
| 2711 List<LabelElement> get labels => baseElement.labels; | |
| 2712 | |
| 2713 @override | |
| 2714 List<LocalVariableElement> get localVariables { | |
| 2715 // | |
| 2716 // Elements within this element should have type parameters substituted, | |
| 2717 // just like this element. | |
| 2718 // | |
| 2719 throw new UnsupportedOperationException(); | |
| 2720 // return getBaseElement().getLocalVariables(); | |
| 2721 } | |
| 2722 | |
| 2723 @override | |
| 2724 List<ParameterElement> get parameters => type.parameters; | |
| 2725 | |
| 2726 @override | |
| 2727 DartType get returnType => type.returnType; | |
| 2728 | |
| 2729 @override | |
| 2730 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; | |
| 2731 | |
| 2732 @override | |
| 2733 void visitChildren(ElementVisitor visitor) { | |
| 2734 // TODO(brianwilkerson) We need to finish implementing the accessors used | |
| 2735 // below so that we can safely invoke them. | |
| 2736 super.visitChildren(visitor); | |
| 2737 safelyVisitChildren(baseElement.functions, visitor); | |
| 2738 safelyVisitChildren(labels, visitor); | |
| 2739 safelyVisitChildren(baseElement.localVariables, visitor); | |
| 2740 safelyVisitChildren(parameters, visitor); | |
| 2741 } | |
| 2742 } | |
| 2743 | |
| 2744 /** | |
| 2745 * A concrete implementation of an [ExportElement]. | |
| 2746 */ | |
| 2747 class ExportElementImpl extends UriReferencedElementImpl | |
| 2748 implements ExportElement { | |
| 2749 /** | |
| 2750 * The library that is exported from this library by this export directive. | |
| 2751 */ | |
| 2752 LibraryElement exportedLibrary; | |
| 2753 | |
| 2754 /** | |
| 2755 * The combinators that were specified as part of the export directive in the | |
| 2756 * order in which they were specified. | |
| 2757 */ | |
| 2758 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; | |
| 2759 | |
| 2760 /** | |
| 2761 * Initialize a newly created export element at the given [offset]. | |
| 2762 */ | |
| 2763 ExportElementImpl(int offset) : super(null, offset); | |
| 2764 | |
| 2765 @override | |
| 2766 String get identifier => exportedLibrary.name; | |
| 2767 | |
| 2768 @override | |
| 2769 ElementKind get kind => ElementKind.EXPORT; | |
| 2770 | |
| 2771 @override | |
| 2772 accept(ElementVisitor visitor) => visitor.visitExportElement(this); | |
| 2773 | |
| 2774 @override | |
| 2775 void appendTo(StringBuffer buffer) { | |
| 2776 buffer.write("export "); | |
| 2777 (exportedLibrary as LibraryElementImpl).appendTo(buffer); | |
| 2778 } | |
| 2779 } | |
| 2780 | |
| 2781 /** | |
| 2782 * A concrete implementation of a [FieldElement]. | |
| 2783 */ | |
| 2784 class FieldElementImpl extends PropertyInducingElementImpl | |
| 2785 implements FieldElement { | |
| 2786 /** | |
| 2787 * Initialize a newly created synthetic field element to have the given [name] | |
| 2788 * at the given [offset]. | |
| 2789 */ | |
| 2790 FieldElementImpl(String name, int offset) : super(name, offset); | |
| 2791 | |
| 2792 /** | |
| 2793 * Initialize a newly created field element to have the given [name]. | |
| 2794 */ | |
| 2795 FieldElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 2796 | |
| 2797 @override | |
| 2798 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 2799 | |
| 2800 @override | |
| 2801 bool get isEnumConstant => | |
| 2802 enclosingElement != null ? enclosingElement.isEnum : false; | |
| 2803 | |
| 2804 @override | |
| 2805 ElementKind get kind => ElementKind.FIELD; | |
| 2806 | |
| 2807 /** | |
| 2808 * Set whether this field is static. | |
| 2809 */ | |
| 2810 void set static(bool isStatic) { | |
| 2811 setModifier(Modifier.STATIC, isStatic); | |
| 2812 } | |
| 2813 | |
| 2814 @override | |
| 2815 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); | |
| 2816 | |
| 2817 @override | |
| 2818 AstNode computeNode() { | |
| 2819 if (isEnumConstant) { | |
| 2820 return getNodeMatching((node) => node is EnumConstantDeclaration); | |
| 2821 } else { | |
| 2822 return getNodeMatching((node) => node is VariableDeclaration); | |
| 2823 } | |
| 2824 } | |
| 2825 } | |
| 2826 | |
| 2827 /** | |
| 2828 * A [ParameterElementImpl] that has the additional information of the | |
| 2829 * [FieldElement] associated with the parameter. | |
| 2830 */ | |
| 2831 class FieldFormalParameterElementImpl extends ParameterElementImpl | |
| 2832 implements FieldFormalParameterElement { | |
| 2833 /** | |
| 2834 * The field associated with this field formal parameter. | |
| 2835 */ | |
| 2836 FieldElement field; | |
| 2837 | |
| 2838 /** | |
| 2839 * Initialize a newly created parameter element to have the given [name]. | |
| 2840 */ | |
| 2841 FieldFormalParameterElementImpl(Identifier name) : super.forNode(name); | |
| 2842 | |
| 2843 @override | |
| 2844 bool get isInitializingFormal => true; | |
| 2845 | |
| 2846 @override | |
| 2847 accept(ElementVisitor visitor) => | |
| 2848 visitor.visitFieldFormalParameterElement(this); | |
| 2849 } | |
| 2850 | |
| 2851 /** | |
| 2852 * A parameter element defined in a parameterized type where the values of the | |
| 2853 * type parameters are known. | |
| 2854 */ | |
| 2855 class FieldFormalParameterMember extends ParameterMember | |
| 2856 implements FieldFormalParameterElement { | |
| 2857 /** | |
| 2858 * Initialize a newly created element to represent a field formal parameter, | |
| 2859 * based on the [baseElement], defined by the [definingType]. If [type] | |
| 2860 * is passed it will be used as the substituted type for this member. | |
| 2861 */ | |
| 2862 FieldFormalParameterMember( | |
| 2863 FieldFormalParameterElement baseElement, ParameterizedType definingType, | |
| 2864 [DartType type]) | |
| 2865 : super(baseElement, definingType, type); | |
| 2866 | |
| 2867 @override | |
| 2868 FieldElement get field { | |
| 2869 FieldElement field = (baseElement as FieldFormalParameterElement).field; | |
| 2870 if (field is FieldElement) { | |
| 2871 return FieldMember.from( | |
| 2872 field, substituteFor(field.enclosingElement.type)); | |
| 2873 } | |
| 2874 return field; | |
| 2875 } | |
| 2876 | |
| 2877 @override | |
| 2878 accept(ElementVisitor visitor) => | |
| 2879 visitor.visitFieldFormalParameterElement(this); | |
| 2880 } | |
| 2881 | |
| 2882 /** | |
| 2883 * A field element defined in a parameterized type where the values of the type | |
| 2884 * parameters are known. | |
| 2885 */ | |
| 2886 class FieldMember extends VariableMember implements FieldElement { | |
| 2887 /** | |
| 2888 * Initialize a newly created element to represent a field, based on the | |
| 2889 * [baseElement], defined by the [definingType]. | |
| 2890 */ | |
| 2891 FieldMember(FieldElement baseElement, InterfaceType definingType) | |
| 2892 : super(baseElement, definingType); | |
| 2893 | |
| 2894 @override | |
| 2895 FieldElement get baseElement => super.baseElement as FieldElement; | |
| 2896 | |
| 2897 @override | |
| 2898 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 2899 | |
| 2900 @override | |
| 2901 PropertyAccessorElement get getter => | |
| 2902 PropertyAccessorMember.from(baseElement.getter, definingType); | |
| 2903 | |
| 2904 @override | |
| 2905 bool get isEnumConstant => baseElement.isEnumConstant; | |
| 2906 | |
| 2907 @override | |
| 2908 DartType get propagatedType => substituteFor(baseElement.propagatedType); | |
| 2909 | |
| 2910 @override | |
| 2911 PropertyAccessorElement get setter => | |
| 2912 PropertyAccessorMember.from(baseElement.setter, definingType); | |
| 2913 | |
| 2914 @override | |
| 2915 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); | |
| 2916 | |
| 2917 @override | |
| 2918 VariableDeclaration computeNode() => baseElement.computeNode(); | |
| 2919 | |
| 2920 @override | |
| 2921 String toString() => '$type $displayName'; | |
| 2922 | |
| 2923 /** | |
| 2924 * If the given [field]'s type is different when any type parameters from the | |
| 2925 * defining type's declaration are replaced with the actual type arguments | |
| 2926 * from the [definingType], create a field member representing the given | |
| 2927 * field. Return the member that was created, or the base field if no member | |
| 2928 * was created. | |
| 2929 */ | |
| 2930 static FieldElement from(FieldElement field, ParameterizedType definingType) { | |
| 2931 if (!_isChangedByTypeSubstitution(field, definingType)) { | |
| 2932 return field; | |
| 2933 } | |
| 2934 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 2935 // instance. It would use more memory but speed up some operations. | |
| 2936 // We need to see how often the type is being re-computed. | |
| 2937 return new FieldMember(field, definingType); | |
| 2938 } | |
| 2939 | |
| 2940 /** | |
| 2941 * Determine whether the given [field]'s type is changed when type parameters | |
| 2942 * from the [definingType]'s declaration are replaced with the actual type | |
| 2943 * arguments from the defining type. | |
| 2944 */ | |
| 2945 static bool _isChangedByTypeSubstitution( | |
| 2946 FieldElement field, ParameterizedType definingType) { | |
| 2947 List<DartType> argumentTypes = definingType.typeArguments; | |
| 2948 if (field != null && argumentTypes.length != 0) { | |
| 2949 DartType baseType = field.type; | |
| 2950 List<DartType> parameterTypes = | |
| 2951 TypeParameterTypeImpl.getTypes(definingType.typeParameters); | |
| 2952 if (baseType != null) { | |
| 2953 DartType substitutedType = | |
| 2954 baseType.substitute2(argumentTypes, parameterTypes); | |
| 2955 if (baseType != substitutedType) { | |
| 2956 return true; | |
| 2957 } | |
| 2958 } | |
| 2959 // If the field has a propagated type, then we need to check whether the | |
| 2960 // propagated type needs substitution. | |
| 2961 DartType basePropagatedType = field.propagatedType; | |
| 2962 if (basePropagatedType != null) { | |
| 2963 DartType substitutedPropagatedType = | |
| 2964 basePropagatedType.substitute2(argumentTypes, parameterTypes); | |
| 2965 if (basePropagatedType != substitutedPropagatedType) { | |
| 2966 return true; | |
| 2967 } | |
| 2968 } | |
| 2969 } | |
| 2970 return false; | |
| 2971 } | |
| 2972 } | |
| 2973 | |
| 2974 /** | |
| 2975 * A concrete implementation of a [FunctionElement]. | |
| 2976 */ | |
| 2977 class FunctionElementImpl extends ExecutableElementImpl | |
| 2978 implements FunctionElement { | |
| 2979 /** | |
| 2980 * The offset to the beginning of the visible range for this element. | |
| 2981 */ | |
| 2982 int _visibleRangeOffset = 0; | |
| 2983 | |
| 2984 /** | |
| 2985 * The length of the visible range for this element, or `-1` if this element | |
| 2986 * does not have a visible range. | |
| 2987 */ | |
| 2988 int _visibleRangeLength = -1; | |
| 2989 | |
| 2990 /** | |
| 2991 * Initialize a newly created function element to have the given [name] and | |
| 2992 * [offset]. | |
| 2993 */ | |
| 2994 FunctionElementImpl(String name, int offset) : super(name, offset); | |
| 2995 | |
| 2996 /** | |
| 2997 * Initialize a newly created function element to have the given [name]. | |
| 2998 */ | |
| 2999 FunctionElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 3000 | |
| 3001 /** | |
| 3002 * Initialize a newly created function element to have no name and the given | |
| 3003 * [offset]. This is used for function expressions, that have no name. | |
| 3004 */ | |
| 3005 FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset); | |
| 3006 | |
| 3007 @override | |
| 3008 String get identifier { | |
| 3009 String identifier = super.identifier; | |
| 3010 if (!isStatic) { | |
| 3011 identifier += "@$nameOffset"; | |
| 3012 } | |
| 3013 return identifier; | |
| 3014 } | |
| 3015 | |
| 3016 @override | |
| 3017 bool get isEntryPoint { | |
| 3018 return isStatic && displayName == FunctionElement.MAIN_FUNCTION_NAME; | |
| 3019 } | |
| 3020 | |
| 3021 @override | |
| 3022 bool get isStatic => enclosingElement is CompilationUnitElement; | |
| 3023 | |
| 3024 @override | |
| 3025 ElementKind get kind => ElementKind.FUNCTION; | |
| 3026 | |
| 3027 @override | |
| 3028 SourceRange get visibleRange { | |
| 3029 if (_visibleRangeLength < 0) { | |
| 3030 return null; | |
| 3031 } | |
| 3032 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 3033 } | |
| 3034 | |
| 3035 @override | |
| 3036 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this); | |
| 3037 | |
| 3038 @override | |
| 3039 void appendTo(StringBuffer buffer) { | |
| 3040 String name = displayName; | |
| 3041 if (name != null) { | |
| 3042 buffer.write(name); | |
| 3043 } | |
| 3044 super.appendTo(buffer); | |
| 3045 } | |
| 3046 | |
| 3047 @override | |
| 3048 FunctionDeclaration computeNode() => | |
| 3049 getNodeMatching((node) => node is FunctionDeclaration); | |
| 3050 | |
| 3051 /** | |
| 3052 * Set the visible range for this element to the range starting at the given | |
| 3053 * [offset] with the given [length]. | |
| 3054 */ | |
| 3055 void setVisibleRange(int offset, int length) { | |
| 3056 _visibleRangeOffset = offset; | |
| 3057 _visibleRangeLength = length; | |
| 3058 } | |
| 3059 | |
| 3060 /** | |
| 3061 * Set the parameters defined by this type alias to the given [parameters] | |
| 3062 * without becoming the parent of the parameters. This should only be used by | |
| 3063 * the [TypeResolverVisitor] when creating a synthetic type alias. | |
| 3064 */ | |
| 3065 void shareParameters(List<ParameterElement> parameters) { | |
| 3066 this._parameters = parameters; | |
| 3067 } | |
| 3068 } | |
| 3069 | |
| 3070 /** | |
| 3071 * An element of a generic function, where the type parameters are known. | |
| 3072 */ | |
| 3073 // TODO(jmesserly): the term "function member" is a bit weird, but it allows | |
| 3074 // a certain consistency. | |
| 3075 class FunctionMember extends ExecutableMember implements FunctionElement { | |
| 3076 /** | |
| 3077 * Initialize a newly created element to represent a function, based on the | |
| 3078 * [baseElement], with the corresponding function [type]. | |
| 3079 */ | |
| 3080 FunctionMember(FunctionElement baseElement, [DartType type]) | |
| 3081 : super(baseElement, null, type); | |
| 3082 | |
| 3083 @override | |
| 3084 FunctionElement get baseElement => super.baseElement as FunctionElement; | |
| 3085 | |
| 3086 @override | |
| 3087 Element get enclosingElement => baseElement.enclosingElement; | |
| 3088 | |
| 3089 @override | |
| 3090 bool get isEntryPoint => baseElement.isEntryPoint; | |
| 3091 | |
| 3092 @override | |
| 3093 SourceRange get visibleRange => baseElement.visibleRange; | |
| 3094 | |
| 3095 @override | |
| 3096 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this); | |
| 3097 | |
| 3098 @override | |
| 3099 FunctionDeclaration computeNode() => baseElement.computeNode(); | |
| 3100 | |
| 3101 @override | |
| 3102 String toString() { | |
| 3103 StringBuffer buffer = new StringBuffer(); | |
| 3104 buffer.write(baseElement.displayName); | |
| 3105 (type as FunctionTypeImpl).appendTo(buffer); | |
| 3106 return buffer.toString(); | |
| 3107 } | |
| 3108 | |
| 3109 /** | |
| 3110 * If the given [method]'s type is different when any type parameters from the | |
| 3111 * defining type's declaration are replaced with the actual type arguments | |
| 3112 * from the [definingType], create a method member representing the given | |
| 3113 * method. Return the member that was created, or the base method if no member | |
| 3114 * was created. | |
| 3115 */ | |
| 3116 static MethodElement from( | |
| 3117 MethodElement method, ParameterizedType definingType) { | |
| 3118 if (method == null || definingType.typeArguments.length == 0) { | |
| 3119 return method; | |
| 3120 } | |
| 3121 FunctionType baseType = method.type; | |
| 3122 List<DartType> argumentTypes = definingType.typeArguments; | |
| 3123 List<DartType> parameterTypes = | |
| 3124 TypeParameterTypeImpl.getTypes(definingType.typeParameters); | |
| 3125 FunctionType substitutedType = | |
| 3126 baseType.substitute2(argumentTypes, parameterTypes); | |
| 3127 if (baseType == substitutedType) { | |
| 3128 return method; | |
| 3129 } | |
| 3130 return new MethodMember(method, definingType, substitutedType); | |
| 3131 } | |
| 3132 } | |
| 3133 | |
| 3134 /** | |
| 3135 * A concrete implementation of a [FunctionTypeAliasElement]. | |
| 3136 */ | |
| 3137 class FunctionTypeAliasElementImpl extends ElementImpl | |
| 3138 implements FunctionTypeAliasElement { | |
| 3139 /** | |
| 3140 * A list containing all of the parameters defined by this type alias. | |
| 3141 */ | |
| 3142 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 3143 | |
| 3144 /** | |
| 3145 * The return type defined by this type alias. | |
| 3146 */ | |
| 3147 DartType returnType; | |
| 3148 | |
| 3149 /** | |
| 3150 * The type of function defined by this type alias. | |
| 3151 */ | |
| 3152 FunctionType type; | |
| 3153 | |
| 3154 /** | |
| 3155 * A list containing all of the type parameters defined for this type. | |
| 3156 */ | |
| 3157 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 3158 | |
| 3159 /** | |
| 3160 * Initialize a newly created type alias element to have the given name. | |
| 3161 * | |
| 3162 * [name] the name of this element | |
| 3163 * [nameOffset] the offset of the name of this element in the file that | |
| 3164 * contains the declaration of this element | |
| 3165 */ | |
| 3166 FunctionTypeAliasElementImpl(String name, int nameOffset) | |
| 3167 : super(name, nameOffset); | |
| 3168 | |
| 3169 /** | |
| 3170 * Initialize a newly created type alias element to have the given [name]. | |
| 3171 */ | |
| 3172 FunctionTypeAliasElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 3173 | |
| 3174 @override | |
| 3175 CompilationUnitElement get enclosingElement => | |
| 3176 super.enclosingElement as CompilationUnitElement; | |
| 3177 | |
| 3178 @override | |
| 3179 ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS; | |
| 3180 | |
| 3181 @override | |
| 3182 List<ParameterElement> get parameters => _parameters; | |
| 3183 | |
| 3184 /** | |
| 3185 * Set the parameters defined by this type alias to the given [parameters]. | |
| 3186 */ | |
| 3187 void set parameters(List<ParameterElement> parameters) { | |
| 3188 if (parameters != null) { | |
| 3189 for (ParameterElement parameter in parameters) { | |
| 3190 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 3191 } | |
| 3192 } | |
| 3193 this._parameters = parameters; | |
| 3194 } | |
| 3195 | |
| 3196 @override | |
| 3197 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 3198 | |
| 3199 /** | |
| 3200 * Set the type parameters defined for this type to the given | |
| 3201 * [typeParameters]. | |
| 3202 */ | |
| 3203 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 3204 for (TypeParameterElement typeParameter in typeParameters) { | |
| 3205 (typeParameter as TypeParameterElementImpl).enclosingElement = this; | |
| 3206 } | |
| 3207 this._typeParameters = typeParameters; | |
| 3208 } | |
| 3209 | |
| 3210 @override | |
| 3211 accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this); | |
| 3212 | |
| 3213 @override | |
| 3214 void appendTo(StringBuffer buffer) { | |
| 3215 buffer.write("typedef "); | |
| 3216 buffer.write(displayName); | |
| 3217 int typeParameterCount = _typeParameters.length; | |
| 3218 if (typeParameterCount > 0) { | |
| 3219 buffer.write("<"); | |
| 3220 for (int i = 0; i < typeParameterCount; i++) { | |
| 3221 if (i > 0) { | |
| 3222 buffer.write(", "); | |
| 3223 } | |
| 3224 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 3225 } | |
| 3226 buffer.write(">"); | |
| 3227 } | |
| 3228 buffer.write("("); | |
| 3229 int parameterCount = _parameters.length; | |
| 3230 for (int i = 0; i < parameterCount; i++) { | |
| 3231 if (i > 0) { | |
| 3232 buffer.write(", "); | |
| 3233 } | |
| 3234 (_parameters[i] as ParameterElementImpl).appendTo(buffer); | |
| 3235 } | |
| 3236 buffer.write(")"); | |
| 3237 if (type != null) { | |
| 3238 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 3239 buffer.write(type.returnType); | |
| 3240 } else if (returnType != null) { | |
| 3241 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 3242 buffer.write(returnType); | |
| 3243 } | |
| 3244 } | |
| 3245 | |
| 3246 @override | |
| 3247 FunctionTypeAlias computeNode() => | |
| 3248 getNodeMatching((node) => node is FunctionTypeAlias); | |
| 3249 | |
| 3250 @override | |
| 3251 ElementImpl getChild(String identifier) { | |
| 3252 for (VariableElement parameter in _parameters) { | |
| 3253 if ((parameter as VariableElementImpl).identifier == identifier) { | |
| 3254 return parameter as VariableElementImpl; | |
| 3255 } | |
| 3256 } | |
| 3257 for (TypeParameterElement typeParameter in _typeParameters) { | |
| 3258 if ((typeParameter as TypeParameterElementImpl).identifier == | |
| 3259 identifier) { | |
| 3260 return typeParameter as TypeParameterElementImpl; | |
| 3261 } | |
| 3262 } | |
| 3263 return null; | |
| 3264 } | |
| 3265 | |
| 3266 @override | |
| 3267 void visitChildren(ElementVisitor visitor) { | |
| 3268 super.visitChildren(visitor); | |
| 3269 safelyVisitChildren(_parameters, visitor); | |
| 3270 safelyVisitChildren(_typeParameters, visitor); | |
| 3271 } | |
| 3272 } | |
| 3273 | |
| 3274 /** | |
| 3275 * The type of a function, method, constructor, getter, or setter. | |
| 3276 */ | |
| 3277 class FunctionTypeImpl extends TypeImpl implements FunctionType { | |
| 3278 /** | |
| 3279 * The list of [typeArguments]. | |
| 3280 */ | |
| 3281 List<DartType> _typeArguments; | |
| 3282 | |
| 3283 /** | |
| 3284 * The list of [typeParameters]. | |
| 3285 */ | |
| 3286 List<TypeParameterElement> _typeParameters; | |
| 3287 | |
| 3288 /** | |
| 3289 * The list of [boundTypeParameters]. | |
| 3290 */ | |
| 3291 List<TypeParameterElement> _boundTypeParameters; | |
| 3292 | |
| 3293 /** | |
| 3294 * The set of typedefs which should not be expanded when exploring this type, | |
| 3295 * to avoid creating infinite types in response to self-referential typedefs. | |
| 3296 */ | |
| 3297 final List<FunctionTypeAliasElement> prunedTypedefs; | |
| 3298 | |
| 3299 /** | |
| 3300 * Initialize a newly created function type to be declared by the given | |
| 3301 * [element], and also initialize [typeArguments] to match the | |
| 3302 * [typeParameters], which permits later substitution. | |
| 3303 */ | |
| 3304 FunctionTypeImpl(ExecutableElement element, | |
| 3305 [List<FunctionTypeAliasElement> prunedTypedefs]) | |
| 3306 : this._(element, null, prunedTypedefs, null, null, null); | |
| 3307 | |
| 3308 /** | |
| 3309 * Initialize a newly created function type to be declared by the given | |
| 3310 * [element]. | |
| 3311 */ | |
| 3312 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element, | |
| 3313 [List<FunctionTypeAliasElement> prunedTypedefs]) | |
| 3314 : this._(element, element?.name, prunedTypedefs, null, null, null); | |
| 3315 | |
| 3316 /** | |
| 3317 * Private constructor. | |
| 3318 */ | |
| 3319 FunctionTypeImpl._( | |
| 3320 TypeParameterizedElement element, | |
| 3321 String name, | |
| 3322 this.prunedTypedefs, | |
| 3323 List<DartType> typeArguments, | |
| 3324 List<TypeParameterElement> typeParameters, | |
| 3325 List<TypeParameterElement> boundTypeParameters) | |
| 3326 : super(element, name) { | |
| 3327 _boundTypeParameters = boundTypeParameters ?? | |
| 3328 element?.typeParameters ?? | |
| 3329 TypeParameterElement.EMPTY_LIST; | |
| 3330 | |
| 3331 if (typeParameters == null) { | |
| 3332 // Combine the generic type variables from all enclosing contexts, except | |
| 3333 // for this generic function's type variables. Those variables are | |
| 3334 // tracked in [boundTypeParameters]. | |
| 3335 typeParameters = <TypeParameterElement>[]; | |
| 3336 Element e = element?.enclosingElement; | |
| 3337 while (e != null) { | |
| 3338 if (e is TypeParameterizedElement) { | |
| 3339 typeParameters.addAll((e as TypeParameterizedElement).typeParameters); | |
| 3340 } | |
| 3341 e = e.enclosingElement; | |
| 3342 } | |
| 3343 } | |
| 3344 _typeParameters = typeParameters; | |
| 3345 | |
| 3346 if (typeArguments == null) { | |
| 3347 // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can | |
| 3348 // make it generic, which will allow it to return List<DartType> instead | |
| 3349 // of List<TypeParameterType>. | |
| 3350 if (typeParameters.isEmpty) { | |
| 3351 typeArguments = DartType.EMPTY_LIST; | |
| 3352 } else { | |
| 3353 typeArguments = new List<DartType>.from( | |
| 3354 typeParameters.map((t) => t.type), | |
| 3355 growable: false); | |
| 3356 } | |
| 3357 } | |
| 3358 _typeArguments = typeArguments; | |
| 3359 } | |
| 3360 | |
| 3361 /** | |
| 3362 * Return the base parameter elements of this function element. | |
| 3363 */ | |
| 3364 List<ParameterElement> get baseParameters => element.parameters; | |
| 3365 | |
| 3366 /** | |
| 3367 * Return the return type defined by this function's element. | |
| 3368 */ | |
| 3369 DartType get baseReturnType => element.returnType; | |
| 3370 | |
| 3371 @override | |
| 3372 List<TypeParameterElement> get boundTypeParameters => _boundTypeParameters; | |
| 3373 | |
| 3374 @override | |
| 3375 String get displayName { | |
| 3376 String name = this.name; | |
| 3377 if (name == null || name.length == 0) { | |
| 3378 // Function types have an empty name when they are defined implicitly by | |
| 3379 // either a closure or as part of a parameter declaration. | |
| 3380 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 3381 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 3382 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; | |
| 3383 DartType returnType = this.returnType; | |
| 3384 StringBuffer buffer = new StringBuffer(); | |
| 3385 buffer.write("("); | |
| 3386 bool needsComma = false; | |
| 3387 if (normalParameterTypes.length > 0) { | |
| 3388 for (DartType type in normalParameterTypes) { | |
| 3389 if (needsComma) { | |
| 3390 buffer.write(", "); | |
| 3391 } else { | |
| 3392 needsComma = true; | |
| 3393 } | |
| 3394 buffer.write(type.displayName); | |
| 3395 } | |
| 3396 } | |
| 3397 if (optionalParameterTypes.length > 0) { | |
| 3398 if (needsComma) { | |
| 3399 buffer.write(", "); | |
| 3400 needsComma = false; | |
| 3401 } | |
| 3402 buffer.write("["); | |
| 3403 for (DartType type in optionalParameterTypes) { | |
| 3404 if (needsComma) { | |
| 3405 buffer.write(", "); | |
| 3406 } else { | |
| 3407 needsComma = true; | |
| 3408 } | |
| 3409 buffer.write(type.displayName); | |
| 3410 } | |
| 3411 buffer.write("]"); | |
| 3412 needsComma = true; | |
| 3413 } | |
| 3414 if (namedParameterTypes.length > 0) { | |
| 3415 if (needsComma) { | |
| 3416 buffer.write(", "); | |
| 3417 needsComma = false; | |
| 3418 } | |
| 3419 buffer.write("{"); | |
| 3420 namedParameterTypes.forEach((String name, DartType type) { | |
| 3421 if (needsComma) { | |
| 3422 buffer.write(", "); | |
| 3423 } else { | |
| 3424 needsComma = true; | |
| 3425 } | |
| 3426 buffer.write(name); | |
| 3427 buffer.write(": "); | |
| 3428 buffer.write(type.displayName); | |
| 3429 }); | |
| 3430 buffer.write("}"); | |
| 3431 needsComma = true; | |
| 3432 } | |
| 3433 buffer.write(")"); | |
| 3434 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 3435 if (returnType == null) { | |
| 3436 buffer.write("null"); | |
| 3437 } else { | |
| 3438 buffer.write(returnType.displayName); | |
| 3439 } | |
| 3440 name = buffer.toString(); | |
| 3441 } | |
| 3442 return name; | |
| 3443 } | |
| 3444 | |
| 3445 @override | |
| 3446 FunctionTypedElement get element => super.element; | |
| 3447 | |
| 3448 @override | |
| 3449 int get hashCode { | |
| 3450 if (element == null) { | |
| 3451 return 0; | |
| 3452 } | |
| 3453 // Reference the arrays of parameters | |
| 3454 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 3455 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 3456 Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values; | |
| 3457 // Generate the hashCode | |
| 3458 int code = (returnType as TypeImpl).hashCode; | |
| 3459 for (int i = 0; i < normalParameterTypes.length; i++) { | |
| 3460 code = (code << 1) + (normalParameterTypes[i] as TypeImpl).hashCode; | |
| 3461 } | |
| 3462 for (int i = 0; i < optionalParameterTypes.length; i++) { | |
| 3463 code = (code << 1) + (optionalParameterTypes[i] as TypeImpl).hashCode; | |
| 3464 } | |
| 3465 for (DartType type in namedParameterTypes) { | |
| 3466 code = (code << 1) + (type as TypeImpl).hashCode; | |
| 3467 } | |
| 3468 return code; | |
| 3469 } | |
| 3470 | |
| 3471 /** | |
| 3472 * The type arguments that were used to instantiate this function type, if | |
| 3473 * any, otherwise this will return an empty list. | |
| 3474 * | |
| 3475 * Given a function type `f`: | |
| 3476 * | |
| 3477 * f == f.originalFunction.instantiate(f.instantiatedTypeArguments) | |
| 3478 * | |
| 3479 * Will always hold. | |
| 3480 */ | |
| 3481 List<DartType> get instantiatedTypeArguments { | |
| 3482 int typeParameterCount = element.type.boundTypeParameters.length; | |
| 3483 if (typeParameterCount == 0) { | |
| 3484 return DartType.EMPTY_LIST; | |
| 3485 } | |
| 3486 // The substituted types at the end should be our bound type parameters. | |
| 3487 int skipCount = typeArguments.length - typeParameterCount; | |
| 3488 return new List<DartType>.from(typeArguments.skip(skipCount)); | |
| 3489 } | |
| 3490 | |
| 3491 @override | |
| 3492 Map<String, DartType> get namedParameterTypes { | |
| 3493 LinkedHashMap<String, DartType> namedParameterTypes = | |
| 3494 new LinkedHashMap<String, DartType>(); | |
| 3495 List<ParameterElement> parameters = baseParameters; | |
| 3496 if (parameters.length == 0) { | |
| 3497 return namedParameterTypes; | |
| 3498 } | |
| 3499 List<DartType> typeParameters = | |
| 3500 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 3501 for (ParameterElement parameter in parameters) { | |
| 3502 if (parameter.parameterKind == ParameterKind.NAMED) { | |
| 3503 DartType type = parameter.type; | |
| 3504 if (typeArguments.length != 0 && | |
| 3505 typeArguments.length == typeParameters.length) { | |
| 3506 type = (type as TypeImpl) | |
| 3507 .substitute2(typeArguments, typeParameters, newPrune); | |
| 3508 } else { | |
| 3509 type = (type as TypeImpl).pruned(newPrune); | |
| 3510 } | |
| 3511 namedParameterTypes[parameter.name] = type; | |
| 3512 } | |
| 3513 } | |
| 3514 return namedParameterTypes; | |
| 3515 } | |
| 3516 | |
| 3517 /** | |
| 3518 * Determine the new set of typedefs which should be pruned when expanding | |
| 3519 * this function type. | |
| 3520 */ | |
| 3521 List<FunctionTypeAliasElement> get newPrune { | |
| 3522 Element element = this.element; | |
| 3523 if (element is FunctionTypeAliasElement && !element.isSynthetic) { | |
| 3524 // This typedef should be pruned, along with anything that was previously | |
| 3525 // pruned. | |
| 3526 if (prunedTypedefs == null) { | |
| 3527 return <FunctionTypeAliasElement>[element]; | |
| 3528 } else { | |
| 3529 return new List<FunctionTypeAliasElement>.from(prunedTypedefs) | |
| 3530 ..add(element); | |
| 3531 } | |
| 3532 } else { | |
| 3533 // This is not a typedef, so nothing additional needs to be pruned. | |
| 3534 return prunedTypedefs; | |
| 3535 } | |
| 3536 } | |
| 3537 | |
| 3538 @override | |
| 3539 List<DartType> get normalParameterTypes { | |
| 3540 List<ParameterElement> parameters = baseParameters; | |
| 3541 if (parameters.length == 0) { | |
| 3542 return DartType.EMPTY_LIST; | |
| 3543 } | |
| 3544 List<DartType> typeParameters = | |
| 3545 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 3546 List<DartType> types = new List<DartType>(); | |
| 3547 for (ParameterElement parameter in parameters) { | |
| 3548 if (parameter.parameterKind == ParameterKind.REQUIRED) { | |
| 3549 DartType type = parameter.type; | |
| 3550 if (typeArguments.length != 0 && | |
| 3551 typeArguments.length == typeParameters.length) { | |
| 3552 type = (type as TypeImpl) | |
| 3553 .substitute2(typeArguments, typeParameters, newPrune); | |
| 3554 } else { | |
| 3555 type = (type as TypeImpl).pruned(newPrune); | |
| 3556 } | |
| 3557 types.add(type); | |
| 3558 } | |
| 3559 } | |
| 3560 return types; | |
| 3561 } | |
| 3562 | |
| 3563 @override | |
| 3564 List<DartType> get optionalParameterTypes { | |
| 3565 List<ParameterElement> parameters = baseParameters; | |
| 3566 if (parameters.length == 0) { | |
| 3567 return DartType.EMPTY_LIST; | |
| 3568 } | |
| 3569 List<DartType> typeParameters = | |
| 3570 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 3571 List<DartType> types = new List<DartType>(); | |
| 3572 for (ParameterElement parameter in parameters) { | |
| 3573 if (parameter.parameterKind == ParameterKind.POSITIONAL) { | |
| 3574 DartType type = parameter.type; | |
| 3575 if (typeArguments.length != 0 && | |
| 3576 typeArguments.length == typeParameters.length) { | |
| 3577 type = (type as TypeImpl) | |
| 3578 .substitute2(typeArguments, typeParameters, newPrune); | |
| 3579 } else { | |
| 3580 type = (type as TypeImpl).pruned(newPrune); | |
| 3581 } | |
| 3582 types.add(type); | |
| 3583 } | |
| 3584 } | |
| 3585 return types; | |
| 3586 } | |
| 3587 | |
| 3588 /** | |
| 3589 * If this is an instantiation of a generic function type, this will get | |
| 3590 * the original function from which it was instantiated. | |
| 3591 * | |
| 3592 * Otherwise, this will return `this`. | |
| 3593 */ | |
| 3594 FunctionTypeImpl get originalFunction { | |
| 3595 if (element.type.boundTypeParameters.isEmpty) { | |
| 3596 return this; | |
| 3597 } | |
| 3598 return (element.type as FunctionTypeImpl).substitute2(typeArguments, | |
| 3599 TypeParameterTypeImpl.getTypes(typeParameters), prunedTypedefs); | |
| 3600 } | |
| 3601 | |
| 3602 @override | |
| 3603 List<ParameterElement> get parameters { | |
| 3604 List<ParameterElement> baseParameters = this.baseParameters; | |
| 3605 // no parameters, quick return | |
| 3606 int parameterCount = baseParameters.length; | |
| 3607 if (parameterCount == 0) { | |
| 3608 return baseParameters; | |
| 3609 } | |
| 3610 // create specialized parameters | |
| 3611 List<ParameterElement> specializedParameters = | |
| 3612 new List<ParameterElement>(parameterCount); | |
| 3613 for (int i = 0; i < parameterCount; i++) { | |
| 3614 specializedParameters[i] = ParameterMember.from(baseParameters[i], this); | |
| 3615 } | |
| 3616 return specializedParameters; | |
| 3617 } | |
| 3618 | |
| 3619 @override | |
| 3620 DartType get returnType { | |
| 3621 DartType baseReturnType = this.baseReturnType; | |
| 3622 if (baseReturnType == null) { | |
| 3623 // TODO(brianwilkerson) This is a patch. The return type should never be | |
| 3624 // null and we need to understand why it is and fix it. | |
| 3625 return DynamicTypeImpl.instance; | |
| 3626 } | |
| 3627 // If there are no arguments to substitute, or if the arguments size doesn't | |
| 3628 // match the parameter size, return the base return type. | |
| 3629 if (typeArguments.length == 0 || | |
| 3630 typeArguments.length != typeParameters.length) { | |
| 3631 return (baseReturnType as TypeImpl).pruned(newPrune); | |
| 3632 } | |
| 3633 return (baseReturnType as TypeImpl).substitute2(typeArguments, | |
| 3634 TypeParameterTypeImpl.getTypes(typeParameters), newPrune); | |
| 3635 } | |
| 3636 | |
| 3637 /** | |
| 3638 * A list containing the actual types of the type arguments. | |
| 3639 */ | |
| 3640 List<DartType> get typeArguments => _typeArguments; | |
| 3641 | |
| 3642 @override | |
| 3643 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 3644 | |
| 3645 @override | |
| 3646 bool operator ==(Object object) { | |
| 3647 if (object is! FunctionTypeImpl) { | |
| 3648 return false; | |
| 3649 } | |
| 3650 FunctionTypeImpl otherType = object as FunctionTypeImpl; | |
| 3651 if (boundTypeParameters.length != otherType.boundTypeParameters.length) { | |
| 3652 return false; | |
| 3653 } | |
| 3654 // `<T>T -> T` should be equal to `<U>U -> U` | |
| 3655 // To test this, we instantiate both types with the same (unique) type | |
| 3656 // variables, and see if the result is equal. | |
| 3657 if (boundTypeParameters.isNotEmpty) { | |
| 3658 List<DartType> instantiateTypeArgs = new List<DartType>(); | |
| 3659 List<DartType> variablesThis = new List<DartType>(); | |
| 3660 List<DartType> variablesOther = new List<DartType>(); | |
| 3661 for (int i = 0; i < boundTypeParameters.length; i++) { | |
| 3662 TypeParameterElement pThis = boundTypeParameters[i]; | |
| 3663 TypeParameterElement pOther = otherType.boundTypeParameters[i]; | |
| 3664 TypeParameterTypeImpl pFresh = new TypeParameterTypeImpl( | |
| 3665 new TypeParameterElementImpl(pThis.name, -1)); | |
| 3666 instantiateTypeArgs.add(pFresh); | |
| 3667 variablesThis.add(pThis.type); | |
| 3668 variablesOther.add(pOther.type); | |
| 3669 // Check that the bounds are equal after equating the previous | |
| 3670 // bound variables. | |
| 3671 if (pThis.bound?.substitute2(instantiateTypeArgs, variablesThis) != | |
| 3672 pOther.bound?.substitute2(instantiateTypeArgs, variablesOther)) { | |
| 3673 return false; | |
| 3674 } | |
| 3675 } | |
| 3676 // After instantiation, they will no longer have boundTypeParameters, | |
| 3677 // so we will continue below. | |
| 3678 return this.instantiate(instantiateTypeArgs) == | |
| 3679 otherType.instantiate(instantiateTypeArgs); | |
| 3680 } | |
| 3681 | |
| 3682 return returnType == otherType.returnType && | |
| 3683 TypeImpl.equalArrays( | |
| 3684 normalParameterTypes, otherType.normalParameterTypes) && | |
| 3685 TypeImpl.equalArrays( | |
| 3686 optionalParameterTypes, otherType.optionalParameterTypes) && | |
| 3687 _equals(namedParameterTypes, otherType.namedParameterTypes); | |
| 3688 } | |
| 3689 | |
| 3690 @override | |
| 3691 void appendTo(StringBuffer buffer) { | |
| 3692 if (boundTypeParameters.isNotEmpty) { | |
| 3693 // To print a type with type variables, first make sure we have unique | |
| 3694 // variable names to print. | |
| 3695 Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>(); | |
| 3696 _freeVariablesInFunctionType(this, freeVariables); | |
| 3697 | |
| 3698 Set<String> namesToAvoid = new HashSet<String>(); | |
| 3699 for (DartType arg in freeVariables) { | |
| 3700 if (arg is TypeParameterType) { | |
| 3701 namesToAvoid.add(arg.displayName); | |
| 3702 } | |
| 3703 } | |
| 3704 | |
| 3705 List<DartType> instantiateTypeArgs = new List<DartType>(); | |
| 3706 List<DartType> variables = new List<DartType>(); | |
| 3707 buffer.write("<"); | |
| 3708 for (TypeParameterElement e in boundTypeParameters) { | |
| 3709 if (e != boundTypeParameters[0]) { | |
| 3710 buffer.write(","); | |
| 3711 } | |
| 3712 String name = e.name; | |
| 3713 int counter = 0; | |
| 3714 while (!namesToAvoid.add(name)) { | |
| 3715 // Unicode subscript-zero is U+2080, zero is U+0030. Other digits | |
| 3716 // are sequential from there. Thus +0x2050 will get us the subscript. | |
| 3717 String subscript = new String.fromCharCodes( | |
| 3718 counter.toString().codeUnits.map((n) => n + 0x2050)); | |
| 3719 | |
| 3720 name = e.name + subscript; | |
| 3721 counter++; | |
| 3722 } | |
| 3723 TypeParameterTypeImpl t = | |
| 3724 new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1)); | |
| 3725 t.appendTo(buffer); | |
| 3726 instantiateTypeArgs.add(t); | |
| 3727 variables.add(e.type); | |
| 3728 if (e.bound != null) { | |
| 3729 buffer.write(" extends "); | |
| 3730 TypeImpl renamed = | |
| 3731 e.bound.substitute2(instantiateTypeArgs, variables); | |
| 3732 renamed.appendTo(buffer); | |
| 3733 } | |
| 3734 } | |
| 3735 buffer.write(">"); | |
| 3736 | |
| 3737 // Instantiate it and print the resulting type. After instantiation, it | |
| 3738 // will no longer have boundTypeParameters, so we will continue below. | |
| 3739 this.instantiate(instantiateTypeArgs).appendTo(buffer); | |
| 3740 return; | |
| 3741 } | |
| 3742 | |
| 3743 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 3744 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 3745 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; | |
| 3746 DartType returnType = this.returnType; | |
| 3747 buffer.write("("); | |
| 3748 bool needsComma = false; | |
| 3749 if (normalParameterTypes.isNotEmpty) { | |
| 3750 for (DartType type in normalParameterTypes) { | |
| 3751 if (needsComma) { | |
| 3752 buffer.write(", "); | |
| 3753 } else { | |
| 3754 needsComma = true; | |
| 3755 } | |
| 3756 (type as TypeImpl).appendTo(buffer); | |
| 3757 } | |
| 3758 } | |
| 3759 if (optionalParameterTypes.isNotEmpty) { | |
| 3760 if (needsComma) { | |
| 3761 buffer.write(", "); | |
| 3762 needsComma = false; | |
| 3763 } | |
| 3764 buffer.write("["); | |
| 3765 for (DartType type in optionalParameterTypes) { | |
| 3766 if (needsComma) { | |
| 3767 buffer.write(", "); | |
| 3768 } else { | |
| 3769 needsComma = true; | |
| 3770 } | |
| 3771 (type as TypeImpl).appendTo(buffer); | |
| 3772 } | |
| 3773 buffer.write("]"); | |
| 3774 needsComma = true; | |
| 3775 } | |
| 3776 if (namedParameterTypes.isNotEmpty) { | |
| 3777 if (needsComma) { | |
| 3778 buffer.write(", "); | |
| 3779 needsComma = false; | |
| 3780 } | |
| 3781 buffer.write("{"); | |
| 3782 namedParameterTypes.forEach((String name, DartType type) { | |
| 3783 if (needsComma) { | |
| 3784 buffer.write(", "); | |
| 3785 } else { | |
| 3786 needsComma = true; | |
| 3787 } | |
| 3788 buffer.write(name); | |
| 3789 buffer.write(": "); | |
| 3790 (type as TypeImpl).appendTo(buffer); | |
| 3791 }); | |
| 3792 buffer.write("}"); | |
| 3793 needsComma = true; | |
| 3794 } | |
| 3795 buffer.write(")"); | |
| 3796 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 3797 if (returnType == null) { | |
| 3798 buffer.write("null"); | |
| 3799 } else { | |
| 3800 (returnType as TypeImpl).appendTo(buffer); | |
| 3801 } | |
| 3802 } | |
| 3803 | |
| 3804 @override | |
| 3805 FunctionTypeImpl instantiate(List<DartType> argumentTypes) { | |
| 3806 if (argumentTypes.length != boundTypeParameters.length) { | |
| 3807 throw new IllegalArgumentException( | |
| 3808 "argumentTypes.length (${argumentTypes.length}) != " | |
| 3809 "boundTypeParameters.length (${boundTypeParameters.length})"); | |
| 3810 } | |
| 3811 if (argumentTypes.isEmpty) { | |
| 3812 return this; | |
| 3813 } | |
| 3814 | |
| 3815 // Given: | |
| 3816 // {U/T} <S> T -> S | |
| 3817 // Where {U/T} represents the typeArguments (U) and typeParameters (T) list, | |
| 3818 // and <S> represents the boundTypeParameters. | |
| 3819 // | |
| 3820 // Now instantiate([V]), and the result should be: | |
| 3821 // {U/T, V/S} T -> S. | |
| 3822 List<TypeParameterElement> newTypeParams = typeParameters.toList(); | |
| 3823 List<DartType> newTypeArgs = typeArguments.toList(); | |
| 3824 newTypeParams.addAll(boundTypeParameters); | |
| 3825 newTypeArgs.addAll(argumentTypes); | |
| 3826 | |
| 3827 return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs, | |
| 3828 newTypeParams, TypeParameterElement.EMPTY_LIST); | |
| 3829 } | |
| 3830 | |
| 3831 @override | |
| 3832 bool isAssignableTo(DartType type) { | |
| 3833 // A function type T may be assigned to a function type S, written T <=> S, | |
| 3834 // iff T <: S. | |
| 3835 return isSubtypeOf(type); | |
| 3836 } | |
| 3837 | |
| 3838 @override | |
| 3839 bool isMoreSpecificThan(DartType type, | |
| 3840 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 3841 // Note: visitedElements is only used for breaking recursion in the type | |
| 3842 // hierarchy; we don't use it when recursing into the function type. | |
| 3843 | |
| 3844 // trivial base cases | |
| 3845 if (type == null) { | |
| 3846 return false; | |
| 3847 } else if (identical(this, type) || | |
| 3848 type.isDynamic || | |
| 3849 type.isDartCoreFunction || | |
| 3850 type.isObject) { | |
| 3851 return true; | |
| 3852 } else if (type is! FunctionType) { | |
| 3853 return false; | |
| 3854 } else if (this == type) { | |
| 3855 return true; | |
| 3856 } | |
| 3857 FunctionType t = this; | |
| 3858 FunctionType s = type as FunctionType; | |
| 3859 List<DartType> tTypes = t.normalParameterTypes; | |
| 3860 List<DartType> tOpTypes = t.optionalParameterTypes; | |
| 3861 List<DartType> sTypes = s.normalParameterTypes; | |
| 3862 List<DartType> sOpTypes = s.optionalParameterTypes; | |
| 3863 // If one function has positional and the other has named parameters, | |
| 3864 // return false. | |
| 3865 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || | |
| 3866 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { | |
| 3867 return false; | |
| 3868 } | |
| 3869 // named parameters case | |
| 3870 if (t.namedParameterTypes.length > 0) { | |
| 3871 // check that the number of required parameters are equal, and check that | |
| 3872 // every t_i is more specific than every s_i | |
| 3873 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { | |
| 3874 return false; | |
| 3875 } else if (t.normalParameterTypes.length > 0) { | |
| 3876 for (int i = 0; i < tTypes.length; i++) { | |
| 3877 if (!(tTypes[i] as TypeImpl) | |
| 3878 .isMoreSpecificThan(sTypes[i], withDynamic)) { | |
| 3879 return false; | |
| 3880 } | |
| 3881 } | |
| 3882 } | |
| 3883 Map<String, DartType> namedTypesT = t.namedParameterTypes; | |
| 3884 Map<String, DartType> namedTypesS = s.namedParameterTypes; | |
| 3885 // if k >= m is false, return false: the passed function type has more | |
| 3886 // named parameter types than this | |
| 3887 if (namedTypesT.length < namedTypesS.length) { | |
| 3888 return false; | |
| 3889 } | |
| 3890 // Loop through each element in S verifying that T has a matching | |
| 3891 // parameter name and that the corresponding type is more specific then | |
| 3892 // the type in S. | |
| 3893 for (String keyS in namedTypesS.keys) { | |
| 3894 DartType typeT = namedTypesT[keyS]; | |
| 3895 if (typeT == null) { | |
| 3896 return false; | |
| 3897 } | |
| 3898 if (!(typeT as TypeImpl) | |
| 3899 .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) { | |
| 3900 return false; | |
| 3901 } | |
| 3902 } | |
| 3903 } else if (s.namedParameterTypes.length > 0) { | |
| 3904 return false; | |
| 3905 } else { | |
| 3906 // positional parameter case | |
| 3907 int tArgLength = tTypes.length + tOpTypes.length; | |
| 3908 int sArgLength = sTypes.length + sOpTypes.length; | |
| 3909 // Check that the total number of parameters in t is greater than or equal | |
| 3910 // to the number of parameters in s and that the number of required | |
| 3911 // parameters in s is greater than or equal to the number of required | |
| 3912 // parameters in t. | |
| 3913 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { | |
| 3914 return false; | |
| 3915 } | |
| 3916 if (tOpTypes.length == 0 && sOpTypes.length == 0) { | |
| 3917 // No positional arguments, don't copy contents to new array | |
| 3918 for (int i = 0; i < sTypes.length; i++) { | |
| 3919 if (!(tTypes[i] as TypeImpl) | |
| 3920 .isMoreSpecificThan(sTypes[i], withDynamic)) { | |
| 3921 return false; | |
| 3922 } | |
| 3923 } | |
| 3924 } else { | |
| 3925 // Else, we do have positional parameters, copy required and positional | |
| 3926 // parameter types into arrays to do the compare (for loop below). | |
| 3927 List<DartType> tAllTypes = new List<DartType>(sArgLength); | |
| 3928 for (int i = 0; i < tTypes.length; i++) { | |
| 3929 tAllTypes[i] = tTypes[i]; | |
| 3930 } | |
| 3931 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 3932 tAllTypes[i] = tOpTypes[j]; | |
| 3933 } | |
| 3934 List<DartType> sAllTypes = new List<DartType>(sArgLength); | |
| 3935 for (int i = 0; i < sTypes.length; i++) { | |
| 3936 sAllTypes[i] = sTypes[i]; | |
| 3937 } | |
| 3938 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 3939 sAllTypes[i] = sOpTypes[j]; | |
| 3940 } | |
| 3941 for (int i = 0; i < sAllTypes.length; i++) { | |
| 3942 if (!(tAllTypes[i] as TypeImpl) | |
| 3943 .isMoreSpecificThan(sAllTypes[i], withDynamic)) { | |
| 3944 return false; | |
| 3945 } | |
| 3946 } | |
| 3947 } | |
| 3948 } | |
| 3949 DartType tRetType = t.returnType; | |
| 3950 DartType sRetType = s.returnType; | |
| 3951 return sRetType.isVoid || | |
| 3952 (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic); | |
| 3953 } | |
| 3954 | |
| 3955 @override | |
| 3956 bool isSubtypeOf(DartType type) { | |
| 3957 // trivial base cases | |
| 3958 if (type == null) { | |
| 3959 return false; | |
| 3960 } else if (identical(this, type) || | |
| 3961 type.isDynamic || | |
| 3962 type.isDartCoreFunction || | |
| 3963 type.isObject) { | |
| 3964 return true; | |
| 3965 } else if (type is! FunctionType) { | |
| 3966 return false; | |
| 3967 } else if (this == type) { | |
| 3968 return true; | |
| 3969 } | |
| 3970 FunctionType t = this; | |
| 3971 FunctionType s = type as FunctionType; | |
| 3972 List<DartType> tTypes = t.normalParameterTypes; | |
| 3973 List<DartType> tOpTypes = t.optionalParameterTypes; | |
| 3974 List<DartType> sTypes = s.normalParameterTypes; | |
| 3975 List<DartType> sOpTypes = s.optionalParameterTypes; | |
| 3976 // If one function has positional and the other has named parameters, | |
| 3977 // return false. | |
| 3978 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || | |
| 3979 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { | |
| 3980 return false; | |
| 3981 } | |
| 3982 // named parameters case | |
| 3983 if (t.namedParameterTypes.length > 0) { | |
| 3984 // check that the number of required parameters are equal, | |
| 3985 // and check that every t_i is assignable to every s_i | |
| 3986 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { | |
| 3987 return false; | |
| 3988 } else if (t.normalParameterTypes.length > 0) { | |
| 3989 for (int i = 0; i < tTypes.length; i++) { | |
| 3990 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { | |
| 3991 return false; | |
| 3992 } | |
| 3993 } | |
| 3994 } | |
| 3995 Map<String, DartType> namedTypesT = t.namedParameterTypes; | |
| 3996 Map<String, DartType> namedTypesS = s.namedParameterTypes; | |
| 3997 // if k >= m is false, return false: the passed function type has more | |
| 3998 // named parameter types than this | |
| 3999 if (namedTypesT.length < namedTypesS.length) { | |
| 4000 return false; | |
| 4001 } | |
| 4002 // Loop through each element in S verifying that T has a matching | |
| 4003 // parameter name and that the corresponding type is assignable to the | |
| 4004 // type in S. | |
| 4005 for (String keyS in namedTypesS.keys) { | |
| 4006 DartType typeT = namedTypesT[keyS]; | |
| 4007 if (typeT == null) { | |
| 4008 return false; | |
| 4009 } | |
| 4010 if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) { | |
| 4011 return false; | |
| 4012 } | |
| 4013 } | |
| 4014 } else if (s.namedParameterTypes.length > 0) { | |
| 4015 return false; | |
| 4016 } else { | |
| 4017 // positional parameter case | |
| 4018 int tArgLength = tTypes.length + tOpTypes.length; | |
| 4019 int sArgLength = sTypes.length + sOpTypes.length; | |
| 4020 // Check that the total number of parameters in t is greater than or | |
| 4021 // equal to the number of parameters in s and that the number of | |
| 4022 // required parameters in s is greater than or equal to the number of | |
| 4023 // required parameters in t. | |
| 4024 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { | |
| 4025 return false; | |
| 4026 } | |
| 4027 if (tOpTypes.length == 0 && sOpTypes.length == 0) { | |
| 4028 // No positional arguments, don't copy contents to new array | |
| 4029 for (int i = 0; i < sTypes.length; i++) { | |
| 4030 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { | |
| 4031 return false; | |
| 4032 } | |
| 4033 } | |
| 4034 } else { | |
| 4035 // Else, we do have positional parameters, copy required and | |
| 4036 // positional parameter types into arrays to do the compare (for loop | |
| 4037 // below). | |
| 4038 List<DartType> tAllTypes = new List<DartType>(sArgLength); | |
| 4039 for (int i = 0; i < tTypes.length; i++) { | |
| 4040 tAllTypes[i] = tTypes[i]; | |
| 4041 } | |
| 4042 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 4043 tAllTypes[i] = tOpTypes[j]; | |
| 4044 } | |
| 4045 List<DartType> sAllTypes = new List<DartType>(sArgLength); | |
| 4046 for (int i = 0; i < sTypes.length; i++) { | |
| 4047 sAllTypes[i] = sTypes[i]; | |
| 4048 } | |
| 4049 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 4050 sAllTypes[i] = sOpTypes[j]; | |
| 4051 } | |
| 4052 for (int i = 0; i < sAllTypes.length; i++) { | |
| 4053 if (!(tAllTypes[i] as TypeImpl).isAssignableTo(sAllTypes[i])) { | |
| 4054 return false; | |
| 4055 } | |
| 4056 } | |
| 4057 } | |
| 4058 } | |
| 4059 DartType tRetType = t.returnType; | |
| 4060 DartType sRetType = s.returnType; | |
| 4061 return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType); | |
| 4062 } | |
| 4063 | |
| 4064 @override | |
| 4065 TypeImpl pruned(List<FunctionTypeAliasElement> prune) { | |
| 4066 if (prune == null) { | |
| 4067 return this; | |
| 4068 } else if (prune.contains(element)) { | |
| 4069 // Circularity found. Prune the type declaration. | |
| 4070 return new CircularTypeImpl(); | |
| 4071 } else { | |
| 4072 // There should never be a reason to prune a type that has already been | |
| 4073 // pruned, since pruning is only done when expanding a function type | |
| 4074 // alias, and function type aliases are always expanded by starting with | |
| 4075 // base types. | |
| 4076 assert(this.prunedTypedefs == null); | |
| 4077 List<DartType> typeArgs = typeArguments | |
| 4078 .map((TypeImpl t) => t.pruned(prune)) | |
| 4079 .toList(growable: false); | |
| 4080 return new FunctionTypeImpl._(element, name, prune, typeArgs, | |
| 4081 _typeParameters, _boundTypeParameters); | |
| 4082 } | |
| 4083 } | |
| 4084 | |
| 4085 @override | |
| 4086 DartType substitute2( | |
| 4087 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 4088 [List<FunctionTypeAliasElement> prune]) { | |
| 4089 // Pruned types should only ever result from performing type variable | |
| 4090 // substitution, and it doesn't make sense to substitute again after | |
| 4091 // substituting once. | |
| 4092 assert(this.prunedTypedefs == null); | |
| 4093 if (argumentTypes.length != parameterTypes.length) { | |
| 4094 throw new IllegalArgumentException( | |
| 4095 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); | |
| 4096 } | |
| 4097 Element element = this.element; | |
| 4098 if (prune != null && prune.contains(element)) { | |
| 4099 // Circularity found. Prune the type declaration. | |
| 4100 return new CircularTypeImpl(); | |
| 4101 } | |
| 4102 if (argumentTypes.length == 0) { | |
| 4103 return this.pruned(prune); | |
| 4104 } | |
| 4105 List<DartType> typeArgs = | |
| 4106 TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes); | |
| 4107 return new FunctionTypeImpl._( | |
| 4108 element, name, prune, typeArgs, _typeParameters, _boundTypeParameters); | |
| 4109 } | |
| 4110 | |
| 4111 @override | |
| 4112 FunctionTypeImpl substitute3(List<DartType> argumentTypes) => | |
| 4113 substitute2(argumentTypes, typeArguments); | |
| 4114 | |
| 4115 void _freeVariablesInFunctionType( | |
| 4116 FunctionType type, Set<TypeParameterType> free) { | |
| 4117 // Make some fresh variables to avoid capture. | |
| 4118 List<DartType> typeArgs = DartType.EMPTY_LIST; | |
| 4119 if (type.boundTypeParameters.isNotEmpty) { | |
| 4120 typeArgs = new List<DartType>.from(type.boundTypeParameters.map((e) => | |
| 4121 new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1)))); | |
| 4122 | |
| 4123 type = type.instantiate(typeArgs); | |
| 4124 } | |
| 4125 | |
| 4126 for (ParameterElement p in type.parameters) { | |
| 4127 _freeVariablesInType(p.type, free); | |
| 4128 } | |
| 4129 _freeVariablesInType(type.returnType, free); | |
| 4130 | |
| 4131 // Remove all of our bound variables. | |
| 4132 free.removeAll(typeArgs); | |
| 4133 } | |
| 4134 | |
| 4135 void _freeVariablesInInterfaceType( | |
| 4136 InterfaceType type, Set<TypeParameterType> free) { | |
| 4137 for (DartType typeArg in type.typeArguments) { | |
| 4138 _freeVariablesInType(typeArg, free); | |
| 4139 } | |
| 4140 } | |
| 4141 | |
| 4142 void _freeVariablesInType(DartType type, Set<TypeParameterType> free) { | |
| 4143 if (type is TypeParameterType) { | |
| 4144 free.add(type); | |
| 4145 } else if (type is FunctionType) { | |
| 4146 _freeVariablesInFunctionType(type, free); | |
| 4147 } else if (type is InterfaceType) { | |
| 4148 _freeVariablesInInterfaceType(type, free); | |
| 4149 } | |
| 4150 } | |
| 4151 | |
| 4152 /** | |
| 4153 * Compute the least upper bound of types [f] and [g], both of which are | |
| 4154 * known to be function types. | |
| 4155 * | |
| 4156 * In the event that f and g have different numbers of required parameters, | |
| 4157 * `null` is returned, in which case the least upper bound is the interface | |
| 4158 * type `Function`. | |
| 4159 */ | |
| 4160 static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) { | |
| 4161 // TODO(paulberry): implement this. | |
| 4162 return null; | |
| 4163 } | |
| 4164 | |
| 4165 /** | |
| 4166 * Return `true` if all of the name/type pairs in the first map ([firstTypes]) | |
| 4167 * are equal to the corresponding name/type pairs in the second map | |
| 4168 * ([secondTypes]). The maps are expected to iterate over their entries in the | |
| 4169 * same order in which those entries were added to the map. | |
| 4170 */ | |
| 4171 static bool _equals( | |
| 4172 Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) { | |
| 4173 if (secondTypes.length != firstTypes.length) { | |
| 4174 return false; | |
| 4175 } | |
| 4176 Iterator<String> firstKeys = firstTypes.keys.iterator; | |
| 4177 Iterator<String> secondKeys = secondTypes.keys.iterator; | |
| 4178 while (firstKeys.moveNext() && secondKeys.moveNext()) { | |
| 4179 String firstKey = firstKeys.current; | |
| 4180 String secondKey = secondKeys.current; | |
| 4181 TypeImpl firstType = firstTypes[firstKey]; | |
| 4182 TypeImpl secondType = secondTypes[secondKey]; | |
| 4183 if (firstKey != secondKey || firstType != secondType) { | |
| 4184 return false; | |
| 4185 } | |
| 4186 } | |
| 4187 return true; | |
| 4188 } | |
| 4189 } | |
| 4190 | |
| 4191 /** | |
| 4192 * A concrete implementation of a [HideElementCombinator]. | |
| 4193 */ | |
| 4194 class HideElementCombinatorImpl implements HideElementCombinator { | |
| 4195 /** | |
| 4196 * The names that are not to be made visible in the importing library even if | |
| 4197 * they are defined in the imported library. | |
| 4198 */ | |
| 4199 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY; | |
| 4200 | |
| 4201 @override | |
| 4202 String toString() { | |
| 4203 StringBuffer buffer = new StringBuffer(); | |
| 4204 buffer.write("show "); | |
| 4205 int count = hiddenNames.length; | |
| 4206 for (int i = 0; i < count; i++) { | |
| 4207 if (i > 0) { | |
| 4208 buffer.write(", "); | |
| 4209 } | |
| 4210 buffer.write(hiddenNames[i]); | |
| 4211 } | |
| 4212 return buffer.toString(); | |
| 4213 } | |
| 4214 } | |
| 4215 | |
| 4216 /** | |
| 4217 * A concrete implementation of an [ImportElement]. | |
| 4218 */ | |
| 4219 class ImportElementImpl extends UriReferencedElementImpl | |
| 4220 implements ImportElement { | |
| 4221 /** | |
| 4222 * The offset of the prefix of this import in the file that contains the this | |
| 4223 * import directive, or `-1` if this import is synthetic. | |
| 4224 */ | |
| 4225 int prefixOffset = 0; | |
| 4226 | |
| 4227 /** | |
| 4228 * The library that is imported into this library by this import directive. | |
| 4229 */ | |
| 4230 LibraryElement importedLibrary; | |
| 4231 | |
| 4232 /** | |
| 4233 * The combinators that were specified as part of the import directive in the | |
| 4234 * order in which they were specified. | |
| 4235 */ | |
| 4236 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; | |
| 4237 | |
| 4238 /** | |
| 4239 * The prefix that was specified as part of the import directive, or `null` if | |
| 4240 * there was no prefix specified. | |
| 4241 */ | |
| 4242 PrefixElement prefix; | |
| 4243 | |
| 4244 /** | |
| 4245 * Initialize a newly created import element at the given [offset]. | |
| 4246 * The offset may be `-1` if the import is synthetic. | |
| 4247 */ | |
| 4248 ImportElementImpl(int offset) : super(null, offset); | |
| 4249 | |
| 4250 /** | |
| 4251 * Set whether this import is for a deferred library. | |
| 4252 */ | |
| 4253 void set deferred(bool isDeferred) { | |
| 4254 setModifier(Modifier.DEFERRED, isDeferred); | |
| 4255 } | |
| 4256 | |
| 4257 @override | |
| 4258 String get identifier => | |
| 4259 "${(importedLibrary as LibraryElementImpl).identifier}@$nameOffset"; | |
| 4260 | |
| 4261 @override | |
| 4262 bool get isDeferred => hasModifier(Modifier.DEFERRED); | |
| 4263 | |
| 4264 @override | |
| 4265 ElementKind get kind => ElementKind.IMPORT; | |
| 4266 | |
| 4267 @override | |
| 4268 accept(ElementVisitor visitor) => visitor.visitImportElement(this); | |
| 4269 | |
| 4270 @override | |
| 4271 void appendTo(StringBuffer buffer) { | |
| 4272 buffer.write("import "); | |
| 4273 (importedLibrary as LibraryElementImpl).appendTo(buffer); | |
| 4274 } | |
| 4275 | |
| 4276 @override | |
| 4277 void visitChildren(ElementVisitor visitor) { | |
| 4278 super.visitChildren(visitor); | |
| 4279 safelyVisitChild(prefix, visitor); | |
| 4280 } | |
| 4281 } | |
| 4282 | |
| 4283 /** | |
| 4284 * A concrete implementation of an [InterfaceType]. | |
| 4285 */ | |
| 4286 class InterfaceTypeImpl extends TypeImpl implements InterfaceType { | |
| 4287 /** | |
| 4288 * A list containing the actual types of the type arguments. | |
| 4289 */ | |
| 4290 List<DartType> typeArguments = DartType.EMPTY_LIST; | |
| 4291 | |
| 4292 /** | |
| 4293 * The set of typedefs which should not be expanded when exploring this type, | |
| 4294 * to avoid creating infinite types in response to self-referential typedefs. | |
| 4295 */ | |
| 4296 final List<FunctionTypeAliasElement> prunedTypedefs; | |
| 4297 | |
| 4298 /** | |
| 4299 * Initialize a newly created type to be declared by the given [element]. | |
| 4300 */ | |
| 4301 InterfaceTypeImpl(ClassElement element, [this.prunedTypedefs]) | |
| 4302 : super(element, element.displayName); | |
| 4303 | |
| 4304 /** | |
| 4305 * Initialize a newly created type to have the given [name]. This constructor | |
| 4306 * should only be used in cases where there is no declaration of the type. | |
| 4307 */ | |
| 4308 InterfaceTypeImpl.named(String name) | |
| 4309 : prunedTypedefs = null, | |
| 4310 super(null, name); | |
| 4311 | |
| 4312 /** | |
| 4313 * Private constructor. | |
| 4314 */ | |
| 4315 InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs) | |
| 4316 : super(element, name); | |
| 4317 | |
| 4318 @override | |
| 4319 List<PropertyAccessorElement> get accessors { | |
| 4320 List<PropertyAccessorElement> accessors = element.accessors; | |
| 4321 List<PropertyAccessorElement> members = | |
| 4322 new List<PropertyAccessorElement>(accessors.length); | |
| 4323 for (int i = 0; i < accessors.length; i++) { | |
| 4324 members[i] = PropertyAccessorMember.from(accessors[i], this); | |
| 4325 } | |
| 4326 return members; | |
| 4327 } | |
| 4328 | |
| 4329 @override | |
| 4330 List<ConstructorElement> get constructors { | |
| 4331 List<ConstructorElement> constructors = element.constructors; | |
| 4332 List<ConstructorElement> members = | |
| 4333 new List<ConstructorElement>(constructors.length); | |
| 4334 for (int i = 0; i < constructors.length; i++) { | |
| 4335 members[i] = ConstructorMember.from(constructors[i], this); | |
| 4336 } | |
| 4337 return members; | |
| 4338 } | |
| 4339 | |
| 4340 @override | |
| 4341 String get displayName { | |
| 4342 String name = this.name; | |
| 4343 List<DartType> typeArguments = this.typeArguments; | |
| 4344 bool allDynamic = true; | |
| 4345 for (DartType type in typeArguments) { | |
| 4346 if (type != null && !type.isDynamic) { | |
| 4347 allDynamic = false; | |
| 4348 break; | |
| 4349 } | |
| 4350 } | |
| 4351 // If there is at least one non-dynamic type, then list them out | |
| 4352 if (!allDynamic) { | |
| 4353 StringBuffer buffer = new StringBuffer(); | |
| 4354 buffer.write(name); | |
| 4355 buffer.write("<"); | |
| 4356 for (int i = 0; i < typeArguments.length; i++) { | |
| 4357 if (i != 0) { | |
| 4358 buffer.write(", "); | |
| 4359 } | |
| 4360 DartType typeArg = typeArguments[i]; | |
| 4361 buffer.write(typeArg.displayName); | |
| 4362 } | |
| 4363 buffer.write(">"); | |
| 4364 name = buffer.toString(); | |
| 4365 } | |
| 4366 return name; | |
| 4367 } | |
| 4368 | |
| 4369 @override | |
| 4370 ClassElement get element => super.element as ClassElement; | |
| 4371 | |
| 4372 @override | |
| 4373 int get hashCode { | |
| 4374 ClassElement element = this.element; | |
| 4375 if (element == null) { | |
| 4376 return 0; | |
| 4377 } | |
| 4378 return element.hashCode; | |
| 4379 } | |
| 4380 | |
| 4381 @override | |
| 4382 List<InterfaceType> get interfaces { | |
| 4383 ClassElement classElement = element; | |
| 4384 List<InterfaceType> interfaces = classElement.interfaces; | |
| 4385 List<TypeParameterElement> typeParameters = classElement.typeParameters; | |
| 4386 List<DartType> parameterTypes = classElement.type.typeArguments; | |
| 4387 if (typeParameters.length == 0) { | |
| 4388 return interfaces; | |
| 4389 } | |
| 4390 int count = interfaces.length; | |
| 4391 List<InterfaceType> typedInterfaces = new List<InterfaceType>(count); | |
| 4392 for (int i = 0; i < count; i++) { | |
| 4393 typedInterfaces[i] = | |
| 4394 interfaces[i].substitute2(typeArguments, parameterTypes); | |
| 4395 } | |
| 4396 return typedInterfaces; | |
| 4397 } | |
| 4398 | |
| 4399 @override | |
| 4400 bool get isDartCoreFunction { | |
| 4401 ClassElement element = this.element; | |
| 4402 if (element == null) { | |
| 4403 return false; | |
| 4404 } | |
| 4405 return element.name == "Function" && element.library.isDartCore; | |
| 4406 } | |
| 4407 | |
| 4408 @override | |
| 4409 bool get isObject => element.supertype == null; | |
| 4410 | |
| 4411 @override | |
| 4412 List<MethodElement> get methods { | |
| 4413 List<MethodElement> methods = element.methods; | |
| 4414 List<MethodElement> members = new List<MethodElement>(methods.length); | |
| 4415 for (int i = 0; i < methods.length; i++) { | |
| 4416 members[i] = MethodMember.from(methods[i], this); | |
| 4417 } | |
| 4418 return members; | |
| 4419 } | |
| 4420 | |
| 4421 @override | |
| 4422 List<InterfaceType> get mixins { | |
| 4423 ClassElement classElement = element; | |
| 4424 List<InterfaceType> mixins = classElement.mixins; | |
| 4425 List<TypeParameterElement> typeParameters = classElement.typeParameters; | |
| 4426 List<DartType> parameterTypes = classElement.type.typeArguments; | |
| 4427 if (typeParameters.length == 0) { | |
| 4428 return mixins; | |
| 4429 } | |
| 4430 int count = mixins.length; | |
| 4431 List<InterfaceType> typedMixins = new List<InterfaceType>(count); | |
| 4432 for (int i = 0; i < count; i++) { | |
| 4433 typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes); | |
| 4434 } | |
| 4435 return typedMixins; | |
| 4436 } | |
| 4437 | |
| 4438 @override | |
| 4439 InterfaceType get superclass { | |
| 4440 ClassElement classElement = element; | |
| 4441 InterfaceType supertype = classElement.supertype; | |
| 4442 if (supertype == null) { | |
| 4443 return null; | |
| 4444 } | |
| 4445 List<DartType> typeParameters = classElement.type.typeArguments; | |
| 4446 if (typeArguments.length == 0 || | |
| 4447 typeArguments.length != typeParameters.length) { | |
| 4448 return supertype; | |
| 4449 } | |
| 4450 return supertype.substitute2(typeArguments, typeParameters); | |
| 4451 } | |
| 4452 | |
| 4453 @override | |
| 4454 List<TypeParameterElement> get typeParameters => element.typeParameters; | |
| 4455 | |
| 4456 @override | |
| 4457 bool operator ==(Object object) { | |
| 4458 if (identical(object, this)) { | |
| 4459 return true; | |
| 4460 } | |
| 4461 if (object is! InterfaceTypeImpl) { | |
| 4462 return false; | |
| 4463 } | |
| 4464 InterfaceTypeImpl otherType = object as InterfaceTypeImpl; | |
| 4465 return (element == otherType.element) && | |
| 4466 TypeImpl.equalArrays(typeArguments, otherType.typeArguments); | |
| 4467 } | |
| 4468 | |
| 4469 @override | |
| 4470 void appendTo(StringBuffer buffer) { | |
| 4471 buffer.write(name); | |
| 4472 int argumentCount = typeArguments.length; | |
| 4473 if (argumentCount > 0) { | |
| 4474 buffer.write("<"); | |
| 4475 for (int i = 0; i < argumentCount; i++) { | |
| 4476 if (i > 0) { | |
| 4477 buffer.write(", "); | |
| 4478 } | |
| 4479 (typeArguments[i] as TypeImpl).appendTo(buffer); | |
| 4480 } | |
| 4481 buffer.write(">"); | |
| 4482 } | |
| 4483 } | |
| 4484 | |
| 4485 @override | |
| 4486 PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember | |
| 4487 .from((element as ClassElementImpl).getGetter(getterName), this); | |
| 4488 | |
| 4489 @override | |
| 4490 MethodElement getMethod(String methodName) => MethodMember.from( | |
| 4491 (element as ClassElementImpl).getMethod(methodName), this); | |
| 4492 | |
| 4493 @override | |
| 4494 PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember | |
| 4495 .from((element as ClassElementImpl).getSetter(setterName), this); | |
| 4496 | |
| 4497 @override | |
| 4498 bool isDirectSupertypeOf(InterfaceType type) { | |
| 4499 InterfaceType i = this; | |
| 4500 InterfaceType j = type; | |
| 4501 ClassElement jElement = j.element; | |
| 4502 InterfaceType supertype = jElement.supertype; | |
| 4503 // | |
| 4504 // If J has no direct supertype then it is Object, and Object has no direct | |
| 4505 // supertypes. | |
| 4506 // | |
| 4507 if (supertype == null) { | |
| 4508 return false; | |
| 4509 } | |
| 4510 // | |
| 4511 // I is listed in the extends clause of J. | |
| 4512 // | |
| 4513 List<DartType> jArgs = j.typeArguments; | |
| 4514 List<DartType> jVars = jElement.type.typeArguments; | |
| 4515 supertype = supertype.substitute2(jArgs, jVars); | |
| 4516 if (supertype == i) { | |
| 4517 return true; | |
| 4518 } | |
| 4519 // | |
| 4520 // I is listed in the implements clause of J. | |
| 4521 // | |
| 4522 for (InterfaceType interfaceType in jElement.interfaces) { | |
| 4523 interfaceType = interfaceType.substitute2(jArgs, jVars); | |
| 4524 if (interfaceType == i) { | |
| 4525 return true; | |
| 4526 } | |
| 4527 } | |
| 4528 // | |
| 4529 // I is listed in the with clause of J. | |
| 4530 // | |
| 4531 for (InterfaceType mixinType in jElement.mixins) { | |
| 4532 mixinType = mixinType.substitute2(jArgs, jVars); | |
| 4533 if (mixinType == i) { | |
| 4534 return true; | |
| 4535 } | |
| 4536 } | |
| 4537 // | |
| 4538 // J is a mixin application of the mixin of I. | |
| 4539 // | |
| 4540 // TODO(brianwilkerson) Determine whether this needs to be implemented or | |
| 4541 // whether it is covered by the case above. | |
| 4542 return false; | |
| 4543 } | |
| 4544 | |
| 4545 @override | |
| 4546 bool isMoreSpecificThan(DartType type, | |
| 4547 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 4548 // | |
| 4549 // S is dynamic. | |
| 4550 // The test to determine whether S is dynamic is done here because dynamic | |
| 4551 // is not an instance of InterfaceType. | |
| 4552 // | |
| 4553 if (type.isDynamic) { | |
| 4554 return true; | |
| 4555 } | |
| 4556 // | |
| 4557 // A type T is more specific than a type S, written T << S, | |
| 4558 // if one of the following conditions is met: | |
| 4559 // | |
| 4560 // Reflexivity: T is S. | |
| 4561 // | |
| 4562 if (this == type) { | |
| 4563 return true; | |
| 4564 } | |
| 4565 if (type is InterfaceType) { | |
| 4566 // | |
| 4567 // T is bottom. (This case is handled by the class BottomTypeImpl.) | |
| 4568 // | |
| 4569 // Direct supertype: S is a direct supertype of T. | |
| 4570 // | |
| 4571 if (type.isDirectSupertypeOf(this)) { | |
| 4572 return true; | |
| 4573 } | |
| 4574 // | |
| 4575 // Covariance: T is of the form I<T1, ..., Tn> and S is of the form | |
| 4576 // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n. | |
| 4577 // | |
| 4578 ClassElement tElement = this.element; | |
| 4579 ClassElement sElement = type.element; | |
| 4580 if (tElement == sElement) { | |
| 4581 List<DartType> tArguments = typeArguments; | |
| 4582 List<DartType> sArguments = type.typeArguments; | |
| 4583 if (tArguments.length != sArguments.length) { | |
| 4584 return false; | |
| 4585 } | |
| 4586 for (int i = 0; i < tArguments.length; i++) { | |
| 4587 if (!(tArguments[i] as TypeImpl) | |
| 4588 .isMoreSpecificThan(sArguments[i], withDynamic)) { | |
| 4589 return false; | |
| 4590 } | |
| 4591 } | |
| 4592 return true; | |
| 4593 } | |
| 4594 } | |
| 4595 // | |
| 4596 // Transitivity: T << U and U << S. | |
| 4597 // | |
| 4598 // First check for infinite loops | |
| 4599 if (element == null) { | |
| 4600 return false; | |
| 4601 } | |
| 4602 if (visitedElements == null) { | |
| 4603 visitedElements = new HashSet<ClassElement>(); | |
| 4604 } else if (visitedElements.contains(element)) { | |
| 4605 return false; | |
| 4606 } | |
| 4607 visitedElements.add(element); | |
| 4608 try { | |
| 4609 // Iterate over all of the types U that are more specific than T because | |
| 4610 // they are direct supertypes of T and return true if any of them are more | |
| 4611 // specific than S. | |
| 4612 InterfaceTypeImpl supertype = superclass; | |
| 4613 if (supertype != null && | |
| 4614 supertype.isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 4615 return true; | |
| 4616 } | |
| 4617 for (InterfaceType interfaceType in interfaces) { | |
| 4618 if ((interfaceType as InterfaceTypeImpl) | |
| 4619 .isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 4620 return true; | |
| 4621 } | |
| 4622 } | |
| 4623 for (InterfaceType mixinType in mixins) { | |
| 4624 if ((mixinType as InterfaceTypeImpl) | |
| 4625 .isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 4626 return true; | |
| 4627 } | |
| 4628 } | |
| 4629 // If a type I includes an instance method named `call`, and the type of | |
| 4630 // `call` is the function type F, then I is considered to be more specific | |
| 4631 // than F. | |
| 4632 MethodElement callMethod = getMethod('call'); | |
| 4633 if (callMethod != null && !callMethod.isStatic) { | |
| 4634 FunctionTypeImpl callType = callMethod.type; | |
| 4635 if (callType.isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 4636 return true; | |
| 4637 } | |
| 4638 } | |
| 4639 return false; | |
| 4640 } finally { | |
| 4641 visitedElements.remove(element); | |
| 4642 } | |
| 4643 } | |
| 4644 | |
| 4645 @override | |
| 4646 ConstructorElement lookUpConstructor( | |
| 4647 String constructorName, LibraryElement library) { | |
| 4648 // prepare base ConstructorElement | |
| 4649 ConstructorElement constructorElement; | |
| 4650 if (constructorName == null) { | |
| 4651 constructorElement = element.unnamedConstructor; | |
| 4652 } else { | |
| 4653 constructorElement = element.getNamedConstructor(constructorName); | |
| 4654 } | |
| 4655 // not found or not accessible | |
| 4656 if (constructorElement == null || | |
| 4657 !constructorElement.isAccessibleIn(library)) { | |
| 4658 return null; | |
| 4659 } | |
| 4660 // return member | |
| 4661 return ConstructorMember.from(constructorElement, this); | |
| 4662 } | |
| 4663 | |
| 4664 @override | |
| 4665 PropertyAccessorElement lookUpGetter( | |
| 4666 String getterName, LibraryElement library) { | |
| 4667 PropertyAccessorElement element = getGetter(getterName); | |
| 4668 if (element != null && element.isAccessibleIn(library)) { | |
| 4669 return element; | |
| 4670 } | |
| 4671 return lookUpGetterInSuperclass(getterName, library); | |
| 4672 } | |
| 4673 | |
| 4674 @override | |
| 4675 PropertyAccessorElement lookUpGetterInSuperclass( | |
| 4676 String getterName, LibraryElement library) { | |
| 4677 for (InterfaceType mixin in mixins.reversed) { | |
| 4678 PropertyAccessorElement element = mixin.getGetter(getterName); | |
| 4679 if (element != null && element.isAccessibleIn(library)) { | |
| 4680 return element; | |
| 4681 } | |
| 4682 } | |
| 4683 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 4684 InterfaceType supertype = superclass; | |
| 4685 ClassElement supertypeElement = | |
| 4686 supertype == null ? null : supertype.element; | |
| 4687 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 4688 visitedClasses.add(supertypeElement); | |
| 4689 PropertyAccessorElement element = supertype.getGetter(getterName); | |
| 4690 if (element != null && element.isAccessibleIn(library)) { | |
| 4691 return element; | |
| 4692 } | |
| 4693 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 4694 element = mixin.getGetter(getterName); | |
| 4695 if (element != null && element.isAccessibleIn(library)) { | |
| 4696 return element; | |
| 4697 } | |
| 4698 } | |
| 4699 supertype = supertype.superclass; | |
| 4700 supertypeElement = supertype == null ? null : supertype.element; | |
| 4701 } | |
| 4702 return null; | |
| 4703 } | |
| 4704 | |
| 4705 @override | |
| 4706 PropertyAccessorElement lookUpInheritedGetter(String name, | |
| 4707 {LibraryElement library, bool thisType: true}) { | |
| 4708 PropertyAccessorElement result; | |
| 4709 if (thisType) { | |
| 4710 result = lookUpGetter(name, library); | |
| 4711 } else { | |
| 4712 result = lookUpGetterInSuperclass(name, library); | |
| 4713 } | |
| 4714 if (result != null) { | |
| 4715 return result; | |
| 4716 } | |
| 4717 return _lookUpMemberInInterfaces(this, false, library, | |
| 4718 new HashSet<ClassElement>(), (InterfaceType t) => t.getGetter(name)); | |
| 4719 } | |
| 4720 | |
| 4721 @override | |
| 4722 ExecutableElement lookUpInheritedGetterOrMethod(String name, | |
| 4723 {LibraryElement library}) { | |
| 4724 ExecutableElement result = | |
| 4725 lookUpGetter(name, library) ?? lookUpMethod(name, library); | |
| 4726 | |
| 4727 if (result != null) { | |
| 4728 return result; | |
| 4729 } | |
| 4730 return _lookUpMemberInInterfaces( | |
| 4731 this, | |
| 4732 false, | |
| 4733 library, | |
| 4734 new HashSet<ClassElement>(), | |
| 4735 (InterfaceType t) => t.getGetter(name) ?? t.getMethod(name)); | |
| 4736 } | |
| 4737 | |
| 4738 @override | |
| 4739 MethodElement lookUpInheritedMethod(String name, | |
| 4740 {LibraryElement library, bool thisType: true}) { | |
| 4741 MethodElement result; | |
| 4742 if (thisType) { | |
| 4743 result = lookUpMethod(name, library); | |
| 4744 } else { | |
| 4745 result = lookUpMethodInSuperclass(name, library); | |
| 4746 } | |
| 4747 if (result != null) { | |
| 4748 return result; | |
| 4749 } | |
| 4750 return _lookUpMemberInInterfaces(this, false, library, | |
| 4751 new HashSet<ClassElement>(), (InterfaceType t) => t.getMethod(name)); | |
| 4752 } | |
| 4753 | |
| 4754 @override | |
| 4755 PropertyAccessorElement lookUpInheritedSetter(String name, | |
| 4756 {LibraryElement library, bool thisType: true}) { | |
| 4757 PropertyAccessorElement result; | |
| 4758 if (thisType) { | |
| 4759 result = lookUpSetter(name, library); | |
| 4760 } else { | |
| 4761 result = lookUpSetterInSuperclass(name, library); | |
| 4762 } | |
| 4763 if (result != null) { | |
| 4764 return result; | |
| 4765 } | |
| 4766 return _lookUpMemberInInterfaces(this, false, library, | |
| 4767 new HashSet<ClassElement>(), (t) => t.getSetter(name)); | |
| 4768 } | |
| 4769 | |
| 4770 @override | |
| 4771 MethodElement lookUpMethod(String methodName, LibraryElement library) { | |
| 4772 MethodElement element = getMethod(methodName); | |
| 4773 if (element != null && element.isAccessibleIn(library)) { | |
| 4774 return element; | |
| 4775 } | |
| 4776 return lookUpMethodInSuperclass(methodName, library); | |
| 4777 } | |
| 4778 | |
| 4779 @override | |
| 4780 MethodElement lookUpMethodInSuperclass( | |
| 4781 String methodName, LibraryElement library) { | |
| 4782 for (InterfaceType mixin in mixins.reversed) { | |
| 4783 MethodElement element = mixin.getMethod(methodName); | |
| 4784 if (element != null && element.isAccessibleIn(library)) { | |
| 4785 return element; | |
| 4786 } | |
| 4787 } | |
| 4788 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 4789 InterfaceType supertype = superclass; | |
| 4790 ClassElement supertypeElement = | |
| 4791 supertype == null ? null : supertype.element; | |
| 4792 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 4793 visitedClasses.add(supertypeElement); | |
| 4794 MethodElement element = supertype.getMethod(methodName); | |
| 4795 if (element != null && element.isAccessibleIn(library)) { | |
| 4796 return element; | |
| 4797 } | |
| 4798 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 4799 element = mixin.getMethod(methodName); | |
| 4800 if (element != null && element.isAccessibleIn(library)) { | |
| 4801 return element; | |
| 4802 } | |
| 4803 } | |
| 4804 supertype = supertype.superclass; | |
| 4805 supertypeElement = supertype == null ? null : supertype.element; | |
| 4806 } | |
| 4807 return null; | |
| 4808 } | |
| 4809 | |
| 4810 @override | |
| 4811 PropertyAccessorElement lookUpSetter( | |
| 4812 String setterName, LibraryElement library) { | |
| 4813 PropertyAccessorElement element = getSetter(setterName); | |
| 4814 if (element != null && element.isAccessibleIn(library)) { | |
| 4815 return element; | |
| 4816 } | |
| 4817 return lookUpSetterInSuperclass(setterName, library); | |
| 4818 } | |
| 4819 | |
| 4820 @override | |
| 4821 PropertyAccessorElement lookUpSetterInSuperclass( | |
| 4822 String setterName, LibraryElement library) { | |
| 4823 for (InterfaceType mixin in mixins.reversed) { | |
| 4824 PropertyAccessorElement element = mixin.getSetter(setterName); | |
| 4825 if (element != null && element.isAccessibleIn(library)) { | |
| 4826 return element; | |
| 4827 } | |
| 4828 } | |
| 4829 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 4830 InterfaceType supertype = superclass; | |
| 4831 ClassElement supertypeElement = | |
| 4832 supertype == null ? null : supertype.element; | |
| 4833 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 4834 visitedClasses.add(supertypeElement); | |
| 4835 PropertyAccessorElement element = supertype.getSetter(setterName); | |
| 4836 if (element != null && element.isAccessibleIn(library)) { | |
| 4837 return element; | |
| 4838 } | |
| 4839 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 4840 element = mixin.getSetter(setterName); | |
| 4841 if (element != null && element.isAccessibleIn(library)) { | |
| 4842 return element; | |
| 4843 } | |
| 4844 } | |
| 4845 supertype = supertype.superclass; | |
| 4846 supertypeElement = supertype == null ? null : supertype.element; | |
| 4847 } | |
| 4848 return null; | |
| 4849 } | |
| 4850 | |
| 4851 @override | |
| 4852 InterfaceTypeImpl pruned(List<FunctionTypeAliasElement> prune) { | |
| 4853 if (prune == null) { | |
| 4854 return this; | |
| 4855 } else { | |
| 4856 // There should never be a reason to prune a type that has already been | |
| 4857 // pruned, since pruning is only done when expanding a function type | |
| 4858 // alias, and function type aliases are always expanded by starting with | |
| 4859 // base types. | |
| 4860 assert(this.prunedTypedefs == null); | |
| 4861 InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune); | |
| 4862 result.typeArguments = | |
| 4863 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList(); | |
| 4864 return result; | |
| 4865 } | |
| 4866 } | |
| 4867 | |
| 4868 @override | |
| 4869 InterfaceTypeImpl substitute2( | |
| 4870 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 4871 [List<FunctionTypeAliasElement> prune]) { | |
| 4872 if (argumentTypes.length != parameterTypes.length) { | |
| 4873 throw new IllegalArgumentException( | |
| 4874 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); | |
| 4875 } | |
| 4876 if (argumentTypes.length == 0 || typeArguments.length == 0) { | |
| 4877 return this.pruned(prune); | |
| 4878 } | |
| 4879 List<DartType> newTypeArguments = TypeImpl.substitute( | |
| 4880 typeArguments, argumentTypes, parameterTypes, prune); | |
| 4881 if (JavaArrays.equals(newTypeArguments, typeArguments)) { | |
| 4882 return this; | |
| 4883 } | |
| 4884 InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune); | |
| 4885 newType.typeArguments = newTypeArguments; | |
| 4886 return newType; | |
| 4887 } | |
| 4888 | |
| 4889 @override | |
| 4890 InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => | |
| 4891 substitute2(argumentTypes, typeArguments); | |
| 4892 | |
| 4893 /** | |
| 4894 * Compute the least upper bound of types [i] and [j], both of which are | |
| 4895 * known to be interface types. | |
| 4896 * | |
| 4897 * In the event that the algorithm fails (which might occur due to a bug in | |
| 4898 * the analyzer), `null` is returned. | |
| 4899 */ | |
| 4900 static InterfaceType computeLeastUpperBound( | |
| 4901 InterfaceType i, InterfaceType j) { | |
| 4902 // compute set of supertypes | |
| 4903 Set<InterfaceType> si = computeSuperinterfaceSet(i); | |
| 4904 Set<InterfaceType> sj = computeSuperinterfaceSet(j); | |
| 4905 // union si with i and sj with j | |
| 4906 si.add(i); | |
| 4907 sj.add(j); | |
| 4908 // compute intersection, reference as set 's' | |
| 4909 List<InterfaceType> s = _intersection(si, sj); | |
| 4910 // for each element in Set s, compute the largest inheritance path to Object | |
| 4911 List<int> depths = new List<int>.filled(s.length, 0); | |
| 4912 int maxDepth = 0; | |
| 4913 for (int n = 0; n < s.length; n++) { | |
| 4914 depths[n] = computeLongestInheritancePathToObject(s[n]); | |
| 4915 if (depths[n] > maxDepth) { | |
| 4916 maxDepth = depths[n]; | |
| 4917 } | |
| 4918 } | |
| 4919 // ensure that the currently computed maxDepth is unique, | |
| 4920 // otherwise, decrement and test for uniqueness again | |
| 4921 for (; maxDepth >= 0; maxDepth--) { | |
| 4922 int indexOfLeastUpperBound = -1; | |
| 4923 int numberOfTypesAtMaxDepth = 0; | |
| 4924 for (int m = 0; m < depths.length; m++) { | |
| 4925 if (depths[m] == maxDepth) { | |
| 4926 numberOfTypesAtMaxDepth++; | |
| 4927 indexOfLeastUpperBound = m; | |
| 4928 } | |
| 4929 } | |
| 4930 if (numberOfTypesAtMaxDepth == 1) { | |
| 4931 return s[indexOfLeastUpperBound]; | |
| 4932 } | |
| 4933 } | |
| 4934 // Should be impossible--there should always be exactly one type with the | |
| 4935 // maximum depth. | |
| 4936 assert(false); | |
| 4937 return null; | |
| 4938 } | |
| 4939 | |
| 4940 /** | |
| 4941 * Return the length of the longest inheritance path from the given [type] to | |
| 4942 * Object. | |
| 4943 * | |
| 4944 * See [computeLeastUpperBound]. | |
| 4945 */ | |
| 4946 static int computeLongestInheritancePathToObject(InterfaceType type) => | |
| 4947 _computeLongestInheritancePathToObject( | |
| 4948 type, 0, new HashSet<ClassElement>()); | |
| 4949 | |
| 4950 /** | |
| 4951 * Returns the set of all superinterfaces of the given [type]. | |
| 4952 * | |
| 4953 * See [computeLeastUpperBound]. | |
| 4954 */ | |
| 4955 static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => | |
| 4956 _computeSuperinterfaceSet(type, new HashSet<InterfaceType>()); | |
| 4957 | |
| 4958 /** | |
| 4959 * Returns a "smart" version of the "least upper bound" of the given types. | |
| 4960 * | |
| 4961 * If these types have the same element and differ only in terms of the type | |
| 4962 * arguments, attempts to find a compatible set of type arguments. | |
| 4963 * | |
| 4964 * Otherwise, calls [DartType.getLeastUpperBound]. | |
| 4965 */ | |
| 4966 static InterfaceType getSmartLeastUpperBound( | |
| 4967 InterfaceType first, InterfaceType second) { | |
| 4968 // TODO(paulberry): this needs to be deprecated and replaced with a method | |
| 4969 // in [TypeSystem], since it relies on the deprecated functionality of | |
| 4970 // [DartType.getLeastUpperBound]. | |
| 4971 if (first.element == second.element) { | |
| 4972 return _leastUpperBound(first, second); | |
| 4973 } | |
| 4974 AnalysisContext context = first.element.context; | |
| 4975 return context.typeSystem | |
| 4976 .getLeastUpperBound(context.typeProvider, first, second); | |
| 4977 } | |
| 4978 | |
| 4979 /** | |
| 4980 * Return the length of the longest inheritance path from a subtype of the | |
| 4981 * given [type] to Object, where the given [depth] is the length of the | |
| 4982 * longest path from the subtype to this type. The set of [visitedTypes] is | |
| 4983 * used to prevent infinite recursion in the case of a cyclic type structure. | |
| 4984 * | |
| 4985 * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound]. | |
| 4986 */ | |
| 4987 static int _computeLongestInheritancePathToObject( | |
| 4988 InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) { | |
| 4989 ClassElement classElement = type.element; | |
| 4990 // Object case | |
| 4991 if (classElement.supertype == null || visitedTypes.contains(classElement)) { | |
| 4992 return depth; | |
| 4993 } | |
| 4994 int longestPath = 1; | |
| 4995 try { | |
| 4996 visitedTypes.add(classElement); | |
| 4997 List<InterfaceType> superinterfaces = classElement.interfaces; | |
| 4998 int pathLength; | |
| 4999 if (superinterfaces.length > 0) { | |
| 5000 // loop through each of the superinterfaces recursively calling this | |
| 5001 // method and keeping track of the longest path to return | |
| 5002 for (InterfaceType superinterface in superinterfaces) { | |
| 5003 pathLength = _computeLongestInheritancePathToObject( | |
| 5004 superinterface, depth + 1, visitedTypes); | |
| 5005 if (pathLength > longestPath) { | |
| 5006 longestPath = pathLength; | |
| 5007 } | |
| 5008 } | |
| 5009 } | |
| 5010 // finally, perform this same check on the super type | |
| 5011 // TODO(brianwilkerson) Does this also need to add in the number of mixin | |
| 5012 // classes? | |
| 5013 InterfaceType supertype = classElement.supertype; | |
| 5014 pathLength = _computeLongestInheritancePathToObject( | |
| 5015 supertype, depth + 1, visitedTypes); | |
| 5016 if (pathLength > longestPath) { | |
| 5017 longestPath = pathLength; | |
| 5018 } | |
| 5019 } finally { | |
| 5020 visitedTypes.remove(classElement); | |
| 5021 } | |
| 5022 return longestPath; | |
| 5023 } | |
| 5024 | |
| 5025 /** | |
| 5026 * Add all of the superinterfaces of the given [type] to the given [set]. | |
| 5027 * Return the [set] as a convenience. | |
| 5028 * | |
| 5029 * See [computeSuperinterfaceSet], and [computeLeastUpperBound]. | |
| 5030 */ | |
| 5031 static Set<InterfaceType> _computeSuperinterfaceSet( | |
| 5032 InterfaceType type, HashSet<InterfaceType> set) { | |
| 5033 Element element = type.element; | |
| 5034 if (element != null) { | |
| 5035 List<InterfaceType> superinterfaces = type.interfaces; | |
| 5036 for (InterfaceType superinterface in superinterfaces) { | |
| 5037 if (set.add(superinterface)) { | |
| 5038 _computeSuperinterfaceSet(superinterface, set); | |
| 5039 } | |
| 5040 } | |
| 5041 InterfaceType supertype = type.superclass; | |
| 5042 if (supertype != null) { | |
| 5043 if (set.add(supertype)) { | |
| 5044 _computeSuperinterfaceSet(supertype, set); | |
| 5045 } | |
| 5046 } | |
| 5047 } | |
| 5048 return set; | |
| 5049 } | |
| 5050 | |
| 5051 /** | |
| 5052 * Return the intersection of the [first] and [second] sets of types, where | |
| 5053 * intersection is based on the equality of the types themselves. | |
| 5054 */ | |
| 5055 static List<InterfaceType> _intersection( | |
| 5056 Set<InterfaceType> first, Set<InterfaceType> second) { | |
| 5057 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); | |
| 5058 result.retainAll(second); | |
| 5059 return new List.from(result); | |
| 5060 } | |
| 5061 | |
| 5062 /** | |
| 5063 * Return the "least upper bound" of the given types under the assumption that | |
| 5064 * the types have the same element and differ only in terms of the type | |
| 5065 * arguments. | |
| 5066 * | |
| 5067 * The resulting type is composed by comparing the corresponding type | |
| 5068 * arguments, keeping those that are the same, and using 'dynamic' for those | |
| 5069 * that are different. | |
| 5070 */ | |
| 5071 static InterfaceType _leastUpperBound( | |
| 5072 InterfaceType firstType, InterfaceType secondType) { | |
| 5073 ClassElement firstElement = firstType.element; | |
| 5074 ClassElement secondElement = secondType.element; | |
| 5075 if (firstElement != secondElement) { | |
| 5076 throw new IllegalArgumentException('The same elements expected, but ' | |
| 5077 '$firstElement and $secondElement are given.'); | |
| 5078 } | |
| 5079 if (firstType == secondType) { | |
| 5080 return firstType; | |
| 5081 } | |
| 5082 List<DartType> firstArguments = firstType.typeArguments; | |
| 5083 List<DartType> secondArguments = secondType.typeArguments; | |
| 5084 int argumentCount = firstArguments.length; | |
| 5085 if (argumentCount == 0) { | |
| 5086 return firstType; | |
| 5087 } | |
| 5088 List<DartType> lubArguments = new List<DartType>(argumentCount); | |
| 5089 for (int i = 0; i < argumentCount; i++) { | |
| 5090 // | |
| 5091 // Ideally we would take the least upper bound of the two argument types, | |
| 5092 // but this can cause an infinite recursion (such as when finding the | |
| 5093 // least upper bound of String and num). | |
| 5094 // | |
| 5095 if (firstArguments[i] == secondArguments[i]) { | |
| 5096 lubArguments[i] = firstArguments[i]; | |
| 5097 } | |
| 5098 if (lubArguments[i] == null) { | |
| 5099 lubArguments[i] = DynamicTypeImpl.instance; | |
| 5100 } | |
| 5101 } | |
| 5102 InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement); | |
| 5103 lub.typeArguments = lubArguments; | |
| 5104 return lub; | |
| 5105 } | |
| 5106 | |
| 5107 /** | |
| 5108 * Look up the getter with the given [name] in the interfaces | |
| 5109 * implemented by the given [targetType], either directly or indirectly. | |
| 5110 * Return the element representing the getter that was found, or `null` if | |
| 5111 * there is no getter with the given name. The flag [includeTargetType] should | |
| 5112 * be `true` if the search should include the target type. The | |
| 5113 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 5114 * been examined, used to prevent infinite recursion and to optimize the | |
| 5115 * search. | |
| 5116 */ | |
| 5117 static ExecutableElement _lookUpMemberInInterfaces( | |
| 5118 InterfaceType targetType, | |
| 5119 bool includeTargetType, | |
| 5120 LibraryElement library, | |
| 5121 HashSet<ClassElement> visitedInterfaces, | |
| 5122 ExecutableElement getMember(InterfaceType type)) { | |
| 5123 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 5124 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 5125 // describes a much more complex scheme for finding the inherited member. | |
| 5126 // We need to follow that scheme. The code below should cover the 80% case. | |
| 5127 ClassElement targetClass = targetType.element; | |
| 5128 if (!visitedInterfaces.add(targetClass)) { | |
| 5129 return null; | |
| 5130 } | |
| 5131 if (includeTargetType) { | |
| 5132 ExecutableElement member = getMember(targetType); | |
| 5133 if (member != null && member.isAccessibleIn(library)) { | |
| 5134 return member; | |
| 5135 } | |
| 5136 } | |
| 5137 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 5138 ExecutableElement member = _lookUpMemberInInterfaces( | |
| 5139 interfaceType, true, library, visitedInterfaces, getMember); | |
| 5140 if (member != null) { | |
| 5141 return member; | |
| 5142 } | |
| 5143 } | |
| 5144 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 5145 ExecutableElement member = _lookUpMemberInInterfaces( | |
| 5146 mixinType, true, library, visitedInterfaces, getMember); | |
| 5147 if (member != null) { | |
| 5148 return member; | |
| 5149 } | |
| 5150 } | |
| 5151 InterfaceType superclass = targetType.superclass; | |
| 5152 if (superclass == null) { | |
| 5153 return null; | |
| 5154 } | |
| 5155 return _lookUpMemberInInterfaces( | |
| 5156 superclass, true, library, visitedInterfaces, getMember); | |
| 5157 } | |
| 5158 } | |
| 5159 | |
| 5160 /** | |
| 5161 * A concrete implementation of a [LabelElement]. | |
| 5162 */ | |
| 5163 class LabelElementImpl extends ElementImpl implements LabelElement { | |
| 5164 /** | |
| 5165 * A flag indicating whether this label is associated with a `switch` | |
| 5166 * statement. | |
| 5167 */ | |
| 5168 // TODO(brianwilkerson) Make this a modifier. | |
| 5169 final bool _onSwitchStatement; | |
| 5170 | |
| 5171 /** | |
| 5172 * A flag indicating whether this label is associated with a `switch` member | |
| 5173 * (`case` or `default`). | |
| 5174 */ | |
| 5175 // TODO(brianwilkerson) Make this a modifier. | |
| 5176 final bool _onSwitchMember; | |
| 5177 | |
| 5178 /** | |
| 5179 * Initialize a newly created label element to have the given [name]. | |
| 5180 * [onSwitchStatement] should be `true` if this label is associated with a | |
| 5181 * `switch` statement and [onSwitchMember] should be `true` if this label is | |
| 5182 * associated with a `switch` member. | |
| 5183 */ | |
| 5184 LabelElementImpl( | |
| 5185 Identifier name, this._onSwitchStatement, this._onSwitchMember) | |
| 5186 : super.forNode(name); | |
| 5187 | |
| 5188 @override | |
| 5189 ExecutableElement get enclosingElement => | |
| 5190 super.enclosingElement as ExecutableElement; | |
| 5191 | |
| 5192 /** | |
| 5193 * Return `true` if this label is associated with a `switch` member (`case` or | |
| 5194 * `default`). | |
| 5195 */ | |
| 5196 bool get isOnSwitchMember => _onSwitchMember; | |
| 5197 | |
| 5198 /** | |
| 5199 * Return `true` if this label is associated with a `switch` statement. | |
| 5200 */ | |
| 5201 bool get isOnSwitchStatement => _onSwitchStatement; | |
| 5202 | |
| 5203 @override | |
| 5204 ElementKind get kind => ElementKind.LABEL; | |
| 5205 | |
| 5206 @override | |
| 5207 accept(ElementVisitor visitor) => visitor.visitLabelElement(this); | |
| 5208 } | |
| 5209 | |
| 5210 /** | |
| 5211 * A concrete implementation of a [LibraryElement]. | |
| 5212 */ | |
| 5213 class LibraryElementImpl extends ElementImpl implements LibraryElement { | |
| 5214 /** | |
| 5215 * The analysis context in which this library is defined. | |
| 5216 */ | |
| 5217 final AnalysisContext context; | |
| 5218 | |
| 5219 /** | |
| 5220 * The compilation unit that defines this library. | |
| 5221 */ | |
| 5222 CompilationUnitElement _definingCompilationUnit; | |
| 5223 | |
| 5224 /** | |
| 5225 * The entry point for this library, or `null` if this library does not have | |
| 5226 * an entry point. | |
| 5227 */ | |
| 5228 FunctionElement entryPoint; | |
| 5229 | |
| 5230 /** | |
| 5231 * A list containing specifications of all of the imports defined in this | |
| 5232 * library. | |
| 5233 */ | |
| 5234 List<ImportElement> _imports = ImportElement.EMPTY_LIST; | |
| 5235 | |
| 5236 /** | |
| 5237 * A list containing specifications of all of the exports defined in this | |
| 5238 * library. | |
| 5239 */ | |
| 5240 List<ExportElement> _exports = ExportElement.EMPTY_LIST; | |
| 5241 | |
| 5242 /** | |
| 5243 * A list containing the strongly connected component in the import/export | |
| 5244 * graph in which the current library resides. Computed on demand, null | |
| 5245 * if not present. If _libraryCycle is set, then the _libraryCycle field | |
| 5246 * for all libraries reachable from this library in the import/export graph | |
| 5247 * is also set. | |
| 5248 */ | |
| 5249 List<LibraryElement> _libraryCycle = null; | |
| 5250 | |
| 5251 /** | |
| 5252 * A list containing all of the compilation units that are included in this | |
| 5253 * library using a `part` directive. | |
| 5254 */ | |
| 5255 List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST; | |
| 5256 | |
| 5257 /** | |
| 5258 * The element representing the synthetic function `loadLibrary` that is | |
| 5259 * defined for this library, or `null` if the element has not yet been created
. | |
| 5260 */ | |
| 5261 FunctionElement _loadLibraryFunction; | |
| 5262 | |
| 5263 @override | |
| 5264 final int nameLength; | |
| 5265 | |
| 5266 /** | |
| 5267 * The export [Namespace] of this library, `null` if it has not been | |
| 5268 * computed yet. | |
| 5269 */ | |
| 5270 @override | |
| 5271 Namespace exportNamespace; | |
| 5272 | |
| 5273 /** | |
| 5274 * The public [Namespace] of this library, `null` if it has not been | |
| 5275 * computed yet. | |
| 5276 */ | |
| 5277 @override | |
| 5278 Namespace publicNamespace; | |
| 5279 | |
| 5280 /** | |
| 5281 * Initialize a newly created library element in the given [context] to have | |
| 5282 * the given [name] and [offset]. | |
| 5283 */ | |
| 5284 LibraryElementImpl(this.context, String name, int offset, this.nameLength) | |
| 5285 : super(name, offset); | |
| 5286 | |
| 5287 /** | |
| 5288 * Initialize a newly created library element in the given [context] to have | |
| 5289 * the given [name]. | |
| 5290 */ | |
| 5291 LibraryElementImpl.forNode(this.context, LibraryIdentifier name) | |
| 5292 : super.forNode(name), | |
| 5293 nameLength = name != null ? name.length : 0; | |
| 5294 | |
| 5295 @override | |
| 5296 CompilationUnitElement get definingCompilationUnit => | |
| 5297 _definingCompilationUnit; | |
| 5298 | |
| 5299 /** | |
| 5300 * Set the compilation unit that defines this library to the given compilation | |
| 5301 * [unit]. | |
| 5302 */ | |
| 5303 void set definingCompilationUnit(CompilationUnitElement unit) { | |
| 5304 assert((unit as CompilationUnitElementImpl).librarySource == unit.source); | |
| 5305 (unit as CompilationUnitElementImpl).enclosingElement = this; | |
| 5306 this._definingCompilationUnit = unit; | |
| 5307 } | |
| 5308 | |
| 5309 @override | |
| 5310 List<LibraryElement> get exportedLibraries { | |
| 5311 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); | |
| 5312 for (ExportElement element in _exports) { | |
| 5313 LibraryElement library = element.exportedLibrary; | |
| 5314 if (library != null) { | |
| 5315 libraries.add(library); | |
| 5316 } | |
| 5317 } | |
| 5318 return new List.from(libraries); | |
| 5319 } | |
| 5320 | |
| 5321 @override | |
| 5322 List<ExportElement> get exports => _exports; | |
| 5323 | |
| 5324 /** | |
| 5325 * Set the specifications of all of the exports defined in this library to the | |
| 5326 * given list of [exports]. | |
| 5327 */ | |
| 5328 void set exports(List<ExportElement> exports) { | |
| 5329 for (ExportElement exportElement in exports) { | |
| 5330 (exportElement as ExportElementImpl).enclosingElement = this; | |
| 5331 } | |
| 5332 this._exports = exports; | |
| 5333 } | |
| 5334 | |
| 5335 @override | |
| 5336 bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI); | |
| 5337 | |
| 5338 /** | |
| 5339 * Set whether this library has an import of a "dart-ext" URI. | |
| 5340 */ | |
| 5341 void set hasExtUri(bool hasExtUri) { | |
| 5342 setModifier(Modifier.HAS_EXT_URI, hasExtUri); | |
| 5343 } | |
| 5344 | |
| 5345 @override | |
| 5346 int get hashCode => _definingCompilationUnit.hashCode; | |
| 5347 | |
| 5348 @override | |
| 5349 bool get hasLoadLibraryFunction { | |
| 5350 if (_definingCompilationUnit.hasLoadLibraryFunction) { | |
| 5351 return true; | |
| 5352 } | |
| 5353 for (int i = 0; i < _parts.length; i++) { | |
| 5354 if (_parts[i].hasLoadLibraryFunction) { | |
| 5355 return true; | |
| 5356 } | |
| 5357 } | |
| 5358 return false; | |
| 5359 } | |
| 5360 | |
| 5361 @override | |
| 5362 String get identifier => _definingCompilationUnit.source.encoding; | |
| 5363 | |
| 5364 @override | |
| 5365 List<LibraryElement> get importedLibraries { | |
| 5366 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); | |
| 5367 for (ImportElement element in _imports) { | |
| 5368 LibraryElement library = element.importedLibrary; | |
| 5369 if (library != null) { | |
| 5370 libraries.add(library); | |
| 5371 } | |
| 5372 } | |
| 5373 return new List.from(libraries); | |
| 5374 } | |
| 5375 | |
| 5376 @override | |
| 5377 List<ImportElement> get imports => _imports; | |
| 5378 | |
| 5379 /** | |
| 5380 * Set the specifications of all of the imports defined in this library to the | |
| 5381 * given list of [imports]. | |
| 5382 */ | |
| 5383 void set imports(List<ImportElement> imports) { | |
| 5384 for (ImportElement importElement in imports) { | |
| 5385 (importElement as ImportElementImpl).enclosingElement = this; | |
| 5386 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; | |
| 5387 if (prefix != null) { | |
| 5388 prefix.enclosingElement = this; | |
| 5389 } | |
| 5390 } | |
| 5391 this._imports = imports; | |
| 5392 } | |
| 5393 | |
| 5394 @override | |
| 5395 bool get isBrowserApplication => | |
| 5396 entryPoint != null && isOrImportsBrowserLibrary; | |
| 5397 | |
| 5398 @override | |
| 5399 bool get isDartCore => name == "dart.core"; | |
| 5400 | |
| 5401 @override | |
| 5402 bool get isInSdk => | |
| 5403 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); | |
| 5404 | |
| 5405 /** | |
| 5406 * Return `true` if the receiver directly or indirectly imports the | |
| 5407 * 'dart:html' libraries. | |
| 5408 */ | |
| 5409 bool get isOrImportsBrowserLibrary { | |
| 5410 List<LibraryElement> visited = new List<LibraryElement>(); | |
| 5411 Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML); | |
| 5412 visited.add(this); | |
| 5413 for (int index = 0; index < visited.length; index++) { | |
| 5414 LibraryElement library = visited[index]; | |
| 5415 Source source = library.definingCompilationUnit.source; | |
| 5416 if (source == htmlLibSource) { | |
| 5417 return true; | |
| 5418 } | |
| 5419 for (LibraryElement importedLibrary in library.importedLibraries) { | |
| 5420 if (!visited.contains(importedLibrary)) { | |
| 5421 visited.add(importedLibrary); | |
| 5422 } | |
| 5423 } | |
| 5424 for (LibraryElement exportedLibrary in library.exportedLibraries) { | |
| 5425 if (!visited.contains(exportedLibrary)) { | |
| 5426 visited.add(exportedLibrary); | |
| 5427 } | |
| 5428 } | |
| 5429 } | |
| 5430 return false; | |
| 5431 } | |
| 5432 | |
| 5433 @override | |
| 5434 ElementKind get kind => ElementKind.LIBRARY; | |
| 5435 | |
| 5436 @override | |
| 5437 LibraryElement get library => this; | |
| 5438 | |
| 5439 List<LibraryElement> get libraryCycle { | |
| 5440 if (_libraryCycle != null) { | |
| 5441 return _libraryCycle; | |
| 5442 } | |
| 5443 | |
| 5444 // Global counter for this run of the algorithm | |
| 5445 int counter = 0; | |
| 5446 // The discovery times of each library | |
| 5447 Map<LibraryElementImpl, int> indices = {}; | |
| 5448 // The set of scc candidates | |
| 5449 Set<LibraryElementImpl> active = new Set(); | |
| 5450 // The stack of discovered elements | |
| 5451 List<LibraryElementImpl> stack = []; | |
| 5452 // For a given library that has not yet been processed by this run of the | |
| 5453 // algorithm, compute the strongly connected components. | |
| 5454 int scc(LibraryElementImpl library) { | |
| 5455 int index = counter++; | |
| 5456 int root = index; | |
| 5457 indices[library] = index; | |
| 5458 active.add(library); | |
| 5459 stack.add(library); | |
| 5460 void recurse(LibraryElementImpl child) { | |
| 5461 if (!indices.containsKey(child)) { | |
| 5462 // We haven't visited this child yet, so recurse on the child, | |
| 5463 // returning the lowest numbered node reachable from the child. If | |
| 5464 // the child can reach a root which is lower numbered than anything | |
| 5465 // we've reached so far, update the root. | |
| 5466 root = min(root, scc(child)); | |
| 5467 } else if (active.contains(child)) { | |
| 5468 // The child has been visited, but has not yet been placed into a | |
| 5469 // component. If the child is higher than anything we've seen so far | |
| 5470 // update the root appropriately. | |
| 5471 root = min(root, indices[child]); | |
| 5472 } | |
| 5473 } | |
| 5474 // Recurse on all of the children in the import/export graph, filtering | |
| 5475 // out those for which library cycles have already been computed. | |
| 5476 library.exportedLibraries | |
| 5477 .where((l) => l._libraryCycle == null) | |
| 5478 .forEach(recurse); | |
| 5479 library.importedLibraries | |
| 5480 .where((l) => l._libraryCycle == null) | |
| 5481 .forEach(recurse); | |
| 5482 | |
| 5483 if (root == index) { | |
| 5484 // This is the root of a strongly connected component. | |
| 5485 // Pop the elements, and share the component across all | |
| 5486 // of the elements. | |
| 5487 List<LibraryElement> component = <LibraryElement>[]; | |
| 5488 LibraryElementImpl cur = null; | |
| 5489 do { | |
| 5490 cur = stack.removeLast(); | |
| 5491 active.remove(cur); | |
| 5492 component.add(cur); | |
| 5493 cur._libraryCycle = component; | |
| 5494 } while (cur != library); | |
| 5495 } | |
| 5496 return root; | |
| 5497 } | |
| 5498 scc(library); | |
| 5499 return _libraryCycle; | |
| 5500 } | |
| 5501 | |
| 5502 @override | |
| 5503 FunctionElement get loadLibraryFunction { | |
| 5504 assert(_loadLibraryFunction != null); | |
| 5505 return _loadLibraryFunction; | |
| 5506 } | |
| 5507 | |
| 5508 @override | |
| 5509 List<CompilationUnitElement> get parts => _parts; | |
| 5510 | |
| 5511 /** | |
| 5512 * Set the compilation units that are included in this library using a `part` | |
| 5513 * directive to the given list of [parts]. | |
| 5514 */ | |
| 5515 void set parts(List<CompilationUnitElement> parts) { | |
| 5516 for (CompilationUnitElement compilationUnit in parts) { | |
| 5517 assert((compilationUnit as CompilationUnitElementImpl).librarySource == | |
| 5518 source); | |
| 5519 (compilationUnit as CompilationUnitElementImpl).enclosingElement = this; | |
| 5520 } | |
| 5521 this._parts = parts; | |
| 5522 } | |
| 5523 | |
| 5524 @override | |
| 5525 List<PrefixElement> get prefixes { | |
| 5526 HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>(); | |
| 5527 for (ImportElement element in _imports) { | |
| 5528 PrefixElement prefix = element.prefix; | |
| 5529 if (prefix != null) { | |
| 5530 prefixes.add(prefix); | |
| 5531 } | |
| 5532 } | |
| 5533 return new List.from(prefixes); | |
| 5534 } | |
| 5535 | |
| 5536 @override | |
| 5537 Source get source { | |
| 5538 if (_definingCompilationUnit == null) { | |
| 5539 return null; | |
| 5540 } | |
| 5541 return _definingCompilationUnit.source; | |
| 5542 } | |
| 5543 | |
| 5544 @override | |
| 5545 List<CompilationUnitElement> get units { | |
| 5546 List<CompilationUnitElement> units = new List<CompilationUnitElement>(); | |
| 5547 units.add(_definingCompilationUnit); | |
| 5548 units.addAll(_parts); | |
| 5549 return units; | |
| 5550 } | |
| 5551 | |
| 5552 @override | |
| 5553 List<LibraryElement> get visibleLibraries { | |
| 5554 Set<LibraryElement> visibleLibraries = new Set(); | |
| 5555 _addVisibleLibraries(visibleLibraries, false); | |
| 5556 return new List.from(visibleLibraries); | |
| 5557 } | |
| 5558 | |
| 5559 @override | |
| 5560 bool operator ==(Object object) => | |
| 5561 object is LibraryElementImpl && | |
| 5562 _definingCompilationUnit == object.definingCompilationUnit; | |
| 5563 | |
| 5564 @override | |
| 5565 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); | |
| 5566 | |
| 5567 /** | |
| 5568 * Create the [FunctionElement] to be returned by [loadLibraryFunction], | |
| 5569 * using types provided by [typeProvider]. | |
| 5570 */ | |
| 5571 void createLoadLibraryFunction(TypeProvider typeProvider) { | |
| 5572 FunctionElementImpl function = | |
| 5573 new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1); | |
| 5574 function.synthetic = true; | |
| 5575 function.enclosingElement = this; | |
| 5576 function.returnType = typeProvider.futureDynamicType; | |
| 5577 function.type = new FunctionTypeImpl(function); | |
| 5578 _loadLibraryFunction = function; | |
| 5579 } | |
| 5580 | |
| 5581 @override | |
| 5582 ElementImpl getChild(String identifier) { | |
| 5583 if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == | |
| 5584 identifier) { | |
| 5585 return _definingCompilationUnit as CompilationUnitElementImpl; | |
| 5586 } | |
| 5587 for (CompilationUnitElement part in _parts) { | |
| 5588 if ((part as CompilationUnitElementImpl).identifier == identifier) { | |
| 5589 return part as CompilationUnitElementImpl; | |
| 5590 } | |
| 5591 } | |
| 5592 for (ImportElement importElement in _imports) { | |
| 5593 if ((importElement as ImportElementImpl).identifier == identifier) { | |
| 5594 return importElement as ImportElementImpl; | |
| 5595 } | |
| 5596 } | |
| 5597 for (ExportElement exportElement in _exports) { | |
| 5598 if ((exportElement as ExportElementImpl).identifier == identifier) { | |
| 5599 return exportElement as ExportElementImpl; | |
| 5600 } | |
| 5601 } | |
| 5602 return null; | |
| 5603 } | |
| 5604 | |
| 5605 @override | |
| 5606 List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) { | |
| 5607 int count = _imports.length; | |
| 5608 List<ImportElement> importList = new List<ImportElement>(); | |
| 5609 for (int i = 0; i < count; i++) { | |
| 5610 if (identical(_imports[i].prefix, prefixElement)) { | |
| 5611 importList.add(_imports[i]); | |
| 5612 } | |
| 5613 } | |
| 5614 return importList; | |
| 5615 } | |
| 5616 | |
| 5617 @override | |
| 5618 ClassElement getType(String className) { | |
| 5619 ClassElement type = _definingCompilationUnit.getType(className); | |
| 5620 if (type != null) { | |
| 5621 return type; | |
| 5622 } | |
| 5623 for (CompilationUnitElement part in _parts) { | |
| 5624 type = part.getType(className); | |
| 5625 if (type != null) { | |
| 5626 return type; | |
| 5627 } | |
| 5628 } | |
| 5629 return null; | |
| 5630 } | |
| 5631 | |
| 5632 /** Given an update to this library which may have added or deleted edges | |
| 5633 * in the import/export graph originating from this node only, remove any | |
| 5634 * cached library cycles in the element model which may have been invalidated. | |
| 5635 */ | |
| 5636 void invalidateLibraryCycles() { | |
| 5637 if (_libraryCycle == null) { | |
| 5638 // We have already invalidated this node, or we have never computed | |
| 5639 // library cycle information for it. In the former case, we're done. In | |
| 5640 // the latter case, this node cannot be reachable from any node for which | |
| 5641 // we have computed library cycle information. Therefore, any edges added | |
| 5642 // or deleted in the update causing this invalidation can only be edges to | |
| 5643 // nodes which either have no library cycle information (and hence do not | |
| 5644 // need invalidation), or which do not reach this node by any path. | |
| 5645 // In either case, no further invalidation is needed. | |
| 5646 return; | |
| 5647 } | |
| 5648 // If we have pre-computed library cycle information, then we must | |
| 5649 // invalidate the information both on this element, and on certain | |
| 5650 // other elements. Edges originating at this node may have been | |
| 5651 // added or deleted. A deleted edge that points outside of this cycle | |
| 5652 // cannot change the cycle information for anything outside of this cycle, | |
| 5653 // and so it is sufficient to delete the cached library information on this | |
| 5654 // cycle. An added edge which points to another node within the cycle | |
| 5655 // only invalidates the cycle. An added edge which points to a node earlier | |
| 5656 // in the topological sort of cycles induces no invalidation (since there | |
| 5657 // are by definition no back edges from earlier cycles in the topological | |
| 5658 // order, and hence no possible cycle can have been introduced. The only | |
| 5659 // remaining case is that we have added an edge to a node which is later | |
| 5660 // in the topological sort of cycles. This can induce cycles, since it | |
| 5661 // represents a new back edge. It would be sufficient to invalidate the | |
| 5662 // cycle information for all nodes that are between the target and the | |
| 5663 // node in the topological order. For simplicity, we simply invalidate | |
| 5664 // all nodes which are reachable from the the source node. | |
| 5665 // Note that in the invalidation phase, we do not cut off when we encounter | |
| 5666 // a node with no library cycle information, since we do not know whether | |
| 5667 // we are in the case where invalidation has already been performed, or we | |
| 5668 // are in the case where library cycles have simply never been computed from | |
| 5669 // a newly reachable node. | |
| 5670 Set<LibraryElementImpl> active = new HashSet(); | |
| 5671 void invalidate(LibraryElementImpl library) { | |
| 5672 if (!active.add(library)) return; | |
| 5673 if (library._libraryCycle != null) { | |
| 5674 library._libraryCycle.forEach(invalidate); | |
| 5675 library._libraryCycle = null; | |
| 5676 } | |
| 5677 library.exportedLibraries.forEach(invalidate); | |
| 5678 library.importedLibraries.forEach(invalidate); | |
| 5679 } | |
| 5680 invalidate(this); | |
| 5681 } | |
| 5682 | |
| 5683 @override | |
| 5684 bool isUpToDate(int timeStamp) { | |
| 5685 Set<LibraryElement> visitedLibraries = new Set(); | |
| 5686 return _safeIsUpToDate(this, timeStamp, visitedLibraries); | |
| 5687 } | |
| 5688 | |
| 5689 @override | |
| 5690 void visitChildren(ElementVisitor visitor) { | |
| 5691 super.visitChildren(visitor); | |
| 5692 safelyVisitChild(_definingCompilationUnit, visitor); | |
| 5693 safelyVisitChildren(_exports, visitor); | |
| 5694 safelyVisitChildren(_imports, visitor); | |
| 5695 safelyVisitChildren(_parts, visitor); | |
| 5696 } | |
| 5697 | |
| 5698 /** | |
| 5699 * Recursively fills set of visible libraries for | |
| 5700 * [getVisibleElementsLibraries]. | |
| 5701 */ | |
| 5702 void _addVisibleLibraries( | |
| 5703 Set<LibraryElement> visibleLibraries, bool includeExports) { | |
| 5704 // maybe already processed | |
| 5705 if (!visibleLibraries.add(this)) { | |
| 5706 return; | |
| 5707 } | |
| 5708 // add imported libraries | |
| 5709 for (ImportElement importElement in _imports) { | |
| 5710 LibraryElement importedLibrary = importElement.importedLibrary; | |
| 5711 if (importedLibrary != null) { | |
| 5712 (importedLibrary as LibraryElementImpl) | |
| 5713 ._addVisibleLibraries(visibleLibraries, true); | |
| 5714 } | |
| 5715 } | |
| 5716 // add exported libraries | |
| 5717 if (includeExports) { | |
| 5718 for (ExportElement exportElement in _exports) { | |
| 5719 LibraryElement exportedLibrary = exportElement.exportedLibrary; | |
| 5720 if (exportedLibrary != null) { | |
| 5721 (exportedLibrary as LibraryElementImpl) | |
| 5722 ._addVisibleLibraries(visibleLibraries, true); | |
| 5723 } | |
| 5724 } | |
| 5725 } | |
| 5726 } | |
| 5727 | |
| 5728 /** | |
| 5729 * Return `true` if the given [library] is up to date with respect to the | |
| 5730 * given [timeStamp]. The set of [visitedLibraries] is used to prevent | |
| 5731 * infinite recursion in the case of mutually dependent libraries. | |
| 5732 */ | |
| 5733 static bool _safeIsUpToDate(LibraryElement library, int timeStamp, | |
| 5734 Set<LibraryElement> visitedLibraries) { | |
| 5735 if (!visitedLibraries.contains(library)) { | |
| 5736 visitedLibraries.add(library); | |
| 5737 AnalysisContext context = library.context; | |
| 5738 // Check the defining compilation unit. | |
| 5739 if (timeStamp < | |
| 5740 context | |
| 5741 .getModificationStamp(library.definingCompilationUnit.source)) { | |
| 5742 return false; | |
| 5743 } | |
| 5744 // Check the parted compilation units. | |
| 5745 for (CompilationUnitElement element in library.parts) { | |
| 5746 if (timeStamp < context.getModificationStamp(element.source)) { | |
| 5747 return false; | |
| 5748 } | |
| 5749 } | |
| 5750 // Check the imported libraries. | |
| 5751 for (LibraryElement importedLibrary in library.importedLibraries) { | |
| 5752 if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) { | |
| 5753 return false; | |
| 5754 } | |
| 5755 } | |
| 5756 // Check the exported libraries. | |
| 5757 for (LibraryElement exportedLibrary in library.exportedLibraries) { | |
| 5758 if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) { | |
| 5759 return false; | |
| 5760 } | |
| 5761 } | |
| 5762 } | |
| 5763 return true; | |
| 5764 } | |
| 5765 } | |
| 5766 | |
| 5767 /** | |
| 5768 * A concrete implementation of a [LocalVariableElement]. | |
| 5769 */ | |
| 5770 class LocalVariableElementImpl extends VariableElementImpl | |
| 5771 implements LocalVariableElement { | |
| 5772 /** | |
| 5773 * The offset to the beginning of the visible range for this element. | |
| 5774 */ | |
| 5775 int _visibleRangeOffset = 0; | |
| 5776 | |
| 5777 /** | |
| 5778 * The length of the visible range for this element, or `-1` if this element | |
| 5779 * does not have a visible range. | |
| 5780 */ | |
| 5781 int _visibleRangeLength = -1; | |
| 5782 | |
| 5783 /** | |
| 5784 * Initialize a newly created method element to have the given [name] and | |
| 5785 * [offset]. | |
| 5786 */ | |
| 5787 LocalVariableElementImpl(String name, int offset) : super(name, offset); | |
| 5788 | |
| 5789 /** | |
| 5790 * Initialize a newly created local variable element to have the given [name]. | |
| 5791 */ | |
| 5792 LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 5793 | |
| 5794 @override | |
| 5795 String get identifier { | |
| 5796 int enclosingOffset = | |
| 5797 enclosingElement != null ? enclosingElement.nameOffset : 0; | |
| 5798 int delta = nameOffset - enclosingOffset; | |
| 5799 return '${super.identifier}@$delta'; | |
| 5800 } | |
| 5801 | |
| 5802 @override | |
| 5803 bool get isPotentiallyMutatedInClosure => | |
| 5804 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); | |
| 5805 | |
| 5806 @override | |
| 5807 bool get isPotentiallyMutatedInScope => | |
| 5808 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); | |
| 5809 | |
| 5810 @override | |
| 5811 ElementKind get kind => ElementKind.LOCAL_VARIABLE; | |
| 5812 | |
| 5813 @override | |
| 5814 SourceRange get visibleRange { | |
| 5815 if (_visibleRangeLength < 0) { | |
| 5816 return null; | |
| 5817 } | |
| 5818 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 5819 } | |
| 5820 | |
| 5821 @override | |
| 5822 accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this); | |
| 5823 | |
| 5824 @override | |
| 5825 void appendTo(StringBuffer buffer) { | |
| 5826 buffer.write(type); | |
| 5827 buffer.write(" "); | |
| 5828 buffer.write(displayName); | |
| 5829 } | |
| 5830 | |
| 5831 @override | |
| 5832 VariableDeclaration computeNode() => | |
| 5833 getNodeMatching((node) => node is VariableDeclaration); | |
| 5834 | |
| 5835 /** | |
| 5836 * Specifies that this variable is potentially mutated somewhere in closure. | |
| 5837 */ | |
| 5838 void markPotentiallyMutatedInClosure() { | |
| 5839 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); | |
| 5840 } | |
| 5841 | |
| 5842 /** | |
| 5843 * Specifies that this variable is potentially mutated somewhere in its scope. | |
| 5844 */ | |
| 5845 void markPotentiallyMutatedInScope() { | |
| 5846 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); | |
| 5847 } | |
| 5848 | |
| 5849 /** | |
| 5850 * Set the visible range for this element to the range starting at the given | |
| 5851 * [offset] with the given [length]. | |
| 5852 */ | |
| 5853 void setVisibleRange(int offset, int length) { | |
| 5854 _visibleRangeOffset = offset; | |
| 5855 _visibleRangeLength = length; | |
| 5856 } | |
| 5857 } | |
| 5858 | |
| 5859 /** | |
| 5860 * An element defined in a parameterized type where the values of the type | |
| 5861 * parameters are known. | |
| 5862 */ | |
| 5863 abstract class Member implements Element { | |
| 5864 /** | |
| 5865 * The element on which the parameterized element was created. | |
| 5866 */ | |
| 5867 final Element _baseElement; | |
| 5868 | |
| 5869 /** | |
| 5870 * The type in which the element is defined. | |
| 5871 */ | |
| 5872 final ParameterizedType _definingType; | |
| 5873 | |
| 5874 /** | |
| 5875 * Initialize a newly created element to represent a member, based on the | |
| 5876 * [baseElement], defined by the [definingType]. | |
| 5877 */ | |
| 5878 Member(this._baseElement, this._definingType); | |
| 5879 | |
| 5880 /** | |
| 5881 * Return the element on which the parameterized element was created. | |
| 5882 */ | |
| 5883 Element get baseElement => _baseElement; | |
| 5884 | |
| 5885 @override | |
| 5886 AnalysisContext get context => _baseElement.context; | |
| 5887 | |
| 5888 /** | |
| 5889 * Return the type in which the element is defined. | |
| 5890 */ | |
| 5891 ParameterizedType get definingType => _definingType; | |
| 5892 | |
| 5893 @override | |
| 5894 String get displayName => _baseElement.displayName; | |
| 5895 | |
| 5896 @override | |
| 5897 SourceRange get docRange => _baseElement.docRange; | |
| 5898 | |
| 5899 int get id => _baseElement.id; | |
| 5900 | |
| 5901 @override | |
| 5902 bool get isDeprecated => _baseElement.isDeprecated; | |
| 5903 | |
| 5904 @override | |
| 5905 bool get isOverride => _baseElement.isOverride; | |
| 5906 | |
| 5907 @override | |
| 5908 bool get isPrivate => _baseElement.isPrivate; | |
| 5909 | |
| 5910 @override | |
| 5911 bool get isPublic => _baseElement.isPublic; | |
| 5912 | |
| 5913 @override | |
| 5914 bool get isSynthetic => _baseElement.isSynthetic; | |
| 5915 | |
| 5916 @override | |
| 5917 ElementKind get kind => _baseElement.kind; | |
| 5918 | |
| 5919 @override | |
| 5920 LibraryElement get library => _baseElement.library; | |
| 5921 | |
| 5922 @override | |
| 5923 ElementLocation get location => _baseElement.location; | |
| 5924 | |
| 5925 @override | |
| 5926 List<ElementAnnotation> get metadata => _baseElement.metadata; | |
| 5927 | |
| 5928 @override | |
| 5929 String get name => _baseElement.name; | |
| 5930 | |
| 5931 @override | |
| 5932 int get nameLength => _baseElement.nameLength; | |
| 5933 | |
| 5934 @override | |
| 5935 int get nameOffset => _baseElement.nameOffset; | |
| 5936 | |
| 5937 @override | |
| 5938 Source get source => _baseElement.source; | |
| 5939 | |
| 5940 @override | |
| 5941 CompilationUnit get unit => _baseElement.unit; | |
| 5942 | |
| 5943 @override | |
| 5944 String computeDocumentationComment() => | |
| 5945 _baseElement.computeDocumentationComment(); | |
| 5946 | |
| 5947 @override | |
| 5948 AstNode computeNode() => _baseElement.computeNode(); | |
| 5949 | |
| 5950 @override | |
| 5951 Element getAncestor(Predicate<Element> predicate) => | |
| 5952 baseElement.getAncestor(predicate); | |
| 5953 | |
| 5954 @override | |
| 5955 String getExtendedDisplayName(String shortName) => | |
| 5956 _baseElement.getExtendedDisplayName(shortName); | |
| 5957 | |
| 5958 @override | |
| 5959 bool isAccessibleIn(LibraryElement library) => | |
| 5960 _baseElement.isAccessibleIn(library); | |
| 5961 | |
| 5962 /** | |
| 5963 * If the given [child] is not `null`, use the given [visitor] to visit it. | |
| 5964 */ | |
| 5965 void safelyVisitChild(Element child, ElementVisitor visitor) { | |
| 5966 // TODO(brianwilkerson) Make this private | |
| 5967 if (child != null) { | |
| 5968 child.accept(visitor); | |
| 5969 } | |
| 5970 } | |
| 5971 | |
| 5972 /** | |
| 5973 * Use the given [visitor] to visit all of the [children]. | |
| 5974 */ | |
| 5975 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { | |
| 5976 // TODO(brianwilkerson) Make this private | |
| 5977 if (children != null) { | |
| 5978 for (Element child in children) { | |
| 5979 child.accept(visitor); | |
| 5980 } | |
| 5981 } | |
| 5982 } | |
| 5983 | |
| 5984 /** | |
| 5985 * Return the type that results from replacing the type parameters in the | |
| 5986 * given [type] with the type arguments associated with this member. | |
| 5987 */ | |
| 5988 DartType substituteFor(DartType type) { | |
| 5989 if (type == null) { | |
| 5990 return null; | |
| 5991 } | |
| 5992 List<DartType> argumentTypes = _definingType.typeArguments; | |
| 5993 List<DartType> parameterTypes = | |
| 5994 TypeParameterTypeImpl.getTypes(_definingType.typeParameters); | |
| 5995 return type.substitute2(argumentTypes, parameterTypes); | |
| 5996 } | |
| 5997 | |
| 5998 @override | |
| 5999 void visitChildren(ElementVisitor visitor) { | |
| 6000 // There are no children to visit | |
| 6001 } | |
| 6002 } | |
| 6003 | |
| 6004 /** | |
| 6005 * A concrete implementation of a [MethodElement]. | |
| 6006 */ | |
| 6007 class MethodElementImpl extends ExecutableElementImpl implements MethodElement { | |
| 6008 /** | |
| 6009 * Initialize a newly created method element to have the given [name] at the | |
| 6010 * given [offset]. | |
| 6011 */ | |
| 6012 MethodElementImpl(String name, int offset) : super(name, offset); | |
| 6013 | |
| 6014 /** | |
| 6015 * Initialize a newly created method element to have the given [name]. | |
| 6016 */ | |
| 6017 MethodElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 6018 | |
| 6019 /** | |
| 6020 * Set whether this method is abstract. | |
| 6021 */ | |
| 6022 void set abstract(bool isAbstract) { | |
| 6023 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 6024 } | |
| 6025 | |
| 6026 @override | |
| 6027 String get displayName { | |
| 6028 String displayName = super.displayName; | |
| 6029 if ("unary-" == displayName) { | |
| 6030 return "-"; | |
| 6031 } | |
| 6032 return displayName; | |
| 6033 } | |
| 6034 | |
| 6035 @override | |
| 6036 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 6037 | |
| 6038 @override | |
| 6039 bool get isOperator { | |
| 6040 String name = displayName; | |
| 6041 if (name.isEmpty) { | |
| 6042 return false; | |
| 6043 } | |
| 6044 int first = name.codeUnitAt(0); | |
| 6045 return !((0x61 <= first && first <= 0x7A) || | |
| 6046 (0x41 <= first && first <= 0x5A) || | |
| 6047 first == 0x5F || | |
| 6048 first == 0x24); | |
| 6049 } | |
| 6050 | |
| 6051 @override | |
| 6052 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 6053 | |
| 6054 @override | |
| 6055 ElementKind get kind => ElementKind.METHOD; | |
| 6056 | |
| 6057 @override | |
| 6058 String get name { | |
| 6059 String name = super.name; | |
| 6060 if (isOperator && name == "-") { | |
| 6061 if (parameters.length == 0) { | |
| 6062 return "unary-"; | |
| 6063 } | |
| 6064 } | |
| 6065 return super.name; | |
| 6066 } | |
| 6067 | |
| 6068 /** | |
| 6069 * Set whether this method is static. | |
| 6070 */ | |
| 6071 void set static(bool isStatic) { | |
| 6072 setModifier(Modifier.STATIC, isStatic); | |
| 6073 } | |
| 6074 | |
| 6075 @override | |
| 6076 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); | |
| 6077 | |
| 6078 @override | |
| 6079 void appendTo(StringBuffer buffer) { | |
| 6080 buffer.write(displayName); | |
| 6081 super.appendTo(buffer); | |
| 6082 } | |
| 6083 | |
| 6084 @override | |
| 6085 MethodDeclaration computeNode() => | |
| 6086 getNodeMatching((node) => node is MethodDeclaration); | |
| 6087 } | |
| 6088 | |
| 6089 /** | |
| 6090 * A method element defined in a parameterized type where the values of the type | |
| 6091 * parameters are known. | |
| 6092 */ | |
| 6093 class MethodMember extends ExecutableMember implements MethodElement { | |
| 6094 /** | |
| 6095 * Initialize a newly created element to represent a method, based on the | |
| 6096 * [baseElement], defined by the [definingType]. If [type] is passed, it | |
| 6097 * represents the full type of the member, and will take precedence over | |
| 6098 * the [definingType]. | |
| 6099 */ | |
| 6100 MethodMember(MethodElement baseElement, InterfaceType definingType, | |
| 6101 [DartType type]) | |
| 6102 : super(baseElement, definingType, type); | |
| 6103 | |
| 6104 @override | |
| 6105 MethodElement get baseElement => super.baseElement as MethodElement; | |
| 6106 | |
| 6107 @override | |
| 6108 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 6109 | |
| 6110 @override | |
| 6111 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); | |
| 6112 | |
| 6113 @override | |
| 6114 MethodDeclaration computeNode() => baseElement.computeNode(); | |
| 6115 | |
| 6116 @override | |
| 6117 String toString() { | |
| 6118 MethodElement baseElement = this.baseElement; | |
| 6119 List<ParameterElement> parameters = this.parameters; | |
| 6120 FunctionType type = this.type; | |
| 6121 StringBuffer buffer = new StringBuffer(); | |
| 6122 buffer.write(baseElement.enclosingElement.displayName); | |
| 6123 buffer.write("."); | |
| 6124 buffer.write(baseElement.displayName); | |
| 6125 buffer.write("("); | |
| 6126 int parameterCount = parameters.length; | |
| 6127 for (int i = 0; i < parameterCount; i++) { | |
| 6128 if (i > 0) { | |
| 6129 buffer.write(", "); | |
| 6130 } | |
| 6131 buffer.write(parameters[i]); | |
| 6132 } | |
| 6133 buffer.write(")"); | |
| 6134 if (type != null) { | |
| 6135 buffer.write(ElementImpl.RIGHT_ARROW); | |
| 6136 buffer.write(type.returnType); | |
| 6137 } | |
| 6138 return buffer.toString(); | |
| 6139 } | |
| 6140 | |
| 6141 /** | |
| 6142 * If the given [method]'s type is different when any type parameters from the | |
| 6143 * defining type's declaration are replaced with the actual type arguments | |
| 6144 * from the [definingType], create a method member representing the given | |
| 6145 * method. Return the member that was created, or the base method if no member | |
| 6146 * was created. | |
| 6147 */ | |
| 6148 static MethodElement from(MethodElement method, InterfaceType definingType) { | |
| 6149 if (method == null || definingType.typeArguments.length == 0) { | |
| 6150 return method; | |
| 6151 } | |
| 6152 FunctionType baseType = method.type; | |
| 6153 List<DartType> argumentTypes = definingType.typeArguments; | |
| 6154 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 6155 FunctionType substitutedType = | |
| 6156 baseType.substitute2(argumentTypes, parameterTypes); | |
| 6157 if (baseType == substitutedType) { | |
| 6158 return method; | |
| 6159 } | |
| 6160 return new MethodMember(method, definingType, substitutedType); | |
| 6161 } | |
| 6162 } | |
| 6163 | |
| 6164 /** | |
| 6165 * A concrete implementation of a [MultiplyDefinedElement]. | |
| 6166 */ | |
| 6167 class MultiplyDefinedElementImpl implements MultiplyDefinedElement { | |
| 6168 /** | |
| 6169 * The unique integer identifier of this element. | |
| 6170 */ | |
| 6171 final int id = ElementImpl._NEXT_ID++; | |
| 6172 | |
| 6173 /** | |
| 6174 * The analysis context in which the multiply defined elements are defined. | |
| 6175 */ | |
| 6176 final AnalysisContext context; | |
| 6177 | |
| 6178 /** | |
| 6179 * The name of the conflicting elements. | |
| 6180 */ | |
| 6181 String _name; | |
| 6182 | |
| 6183 /** | |
| 6184 * A list containing all of the elements that conflict. | |
| 6185 */ | |
| 6186 final List<Element> conflictingElements; | |
| 6187 | |
| 6188 /** | |
| 6189 * Initialize a newly created element in the given [context] to represent a | |
| 6190 * list of [conflictingElements]. | |
| 6191 */ | |
| 6192 MultiplyDefinedElementImpl(this.context, this.conflictingElements) { | |
| 6193 _name = conflictingElements[0].name; | |
| 6194 } | |
| 6195 | |
| 6196 @override | |
| 6197 String get displayName => _name; | |
| 6198 | |
| 6199 @override | |
| 6200 SourceRange get docRange => null; | |
| 6201 | |
| 6202 @override | |
| 6203 Element get enclosingElement => null; | |
| 6204 | |
| 6205 @override | |
| 6206 bool get isDeprecated => false; | |
| 6207 | |
| 6208 @override | |
| 6209 bool get isOverride => false; | |
| 6210 | |
| 6211 @override | |
| 6212 bool get isPrivate { | |
| 6213 String name = displayName; | |
| 6214 if (name == null) { | |
| 6215 return false; | |
| 6216 } | |
| 6217 return Identifier.isPrivateName(name); | |
| 6218 } | |
| 6219 | |
| 6220 @override | |
| 6221 bool get isPublic => !isPrivate; | |
| 6222 | |
| 6223 @override | |
| 6224 bool get isSynthetic => true; | |
| 6225 | |
| 6226 @override | |
| 6227 ElementKind get kind => ElementKind.ERROR; | |
| 6228 | |
| 6229 @override | |
| 6230 LibraryElement get library => null; | |
| 6231 | |
| 6232 @override | |
| 6233 ElementLocation get location => null; | |
| 6234 | |
| 6235 @override | |
| 6236 List<ElementAnnotation> get metadata => ElementAnnotation.EMPTY_LIST; | |
| 6237 | |
| 6238 @override | |
| 6239 String get name => _name; | |
| 6240 | |
| 6241 @override | |
| 6242 int get nameLength => displayName != null ? displayName.length : 0; | |
| 6243 | |
| 6244 @override | |
| 6245 int get nameOffset => -1; | |
| 6246 | |
| 6247 @override | |
| 6248 Source get source => null; | |
| 6249 | |
| 6250 @override | |
| 6251 DartType get type => DynamicTypeImpl.instance; | |
| 6252 | |
| 6253 @override | |
| 6254 CompilationUnit get unit => null; | |
| 6255 | |
| 6256 @override | |
| 6257 accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this); | |
| 6258 | |
| 6259 @override | |
| 6260 String computeDocumentationComment() => null; | |
| 6261 | |
| 6262 @override | |
| 6263 AstNode computeNode() => null; | |
| 6264 | |
| 6265 @override | |
| 6266 Element getAncestor(Predicate<Element> predicate) => null; | |
| 6267 | |
| 6268 @override | |
| 6269 String getExtendedDisplayName(String shortName) { | |
| 6270 if (shortName != null) { | |
| 6271 return shortName; | |
| 6272 } | |
| 6273 return displayName; | |
| 6274 } | |
| 6275 | |
| 6276 @override | |
| 6277 bool isAccessibleIn(LibraryElement library) { | |
| 6278 for (Element element in conflictingElements) { | |
| 6279 if (element.isAccessibleIn(library)) { | |
| 6280 return true; | |
| 6281 } | |
| 6282 } | |
| 6283 return false; | |
| 6284 } | |
| 6285 | |
| 6286 @override | |
| 6287 String toString() { | |
| 6288 StringBuffer buffer = new StringBuffer(); | |
| 6289 buffer.write("["); | |
| 6290 int count = conflictingElements.length; | |
| 6291 for (int i = 0; i < count; i++) { | |
| 6292 if (i > 0) { | |
| 6293 buffer.write(", "); | |
| 6294 } | |
| 6295 (conflictingElements[i] as ElementImpl).appendTo(buffer); | |
| 6296 } | |
| 6297 buffer.write("]"); | |
| 6298 return buffer.toString(); | |
| 6299 } | |
| 6300 | |
| 6301 @override | |
| 6302 void visitChildren(ElementVisitor visitor) { | |
| 6303 // There are no children to visit | |
| 6304 } | |
| 6305 | |
| 6306 /** | |
| 6307 * Return an element in the given [context] that represents the fact that the | |
| 6308 * [firstElement] and [secondElement] conflict. (If the elements are the same, | |
| 6309 * then one of the two will be returned directly.) | |
| 6310 */ | |
| 6311 static Element fromElements( | |
| 6312 AnalysisContext context, Element firstElement, Element secondElement) { | |
| 6313 List<Element> conflictingElements = | |
| 6314 _computeConflictingElements(firstElement, secondElement); | |
| 6315 int length = conflictingElements.length; | |
| 6316 if (length == 0) { | |
| 6317 return null; | |
| 6318 } else if (length == 1) { | |
| 6319 return conflictingElements[0]; | |
| 6320 } | |
| 6321 return new MultiplyDefinedElementImpl(context, conflictingElements); | |
| 6322 } | |
| 6323 | |
| 6324 /** | |
| 6325 * Add the given [element] to the list of [elements]. If the element is a | |
| 6326 * multiply-defined element, add all of the conflicting elements that it | |
| 6327 * represents. | |
| 6328 */ | |
| 6329 static void _add(HashSet<Element> elements, Element element) { | |
| 6330 if (element is MultiplyDefinedElementImpl) { | |
| 6331 for (Element conflictingElement in element.conflictingElements) { | |
| 6332 elements.add(conflictingElement); | |
| 6333 } | |
| 6334 } else { | |
| 6335 elements.add(element); | |
| 6336 } | |
| 6337 } | |
| 6338 | |
| 6339 /** | |
| 6340 * Use the given elements to construct a list of conflicting elements. If | |
| 6341 * either the [firstElement] or [secondElement] are multiply-defined elements | |
| 6342 * then the conflicting elements they represent will be included in the array. | |
| 6343 * Otherwise, the element itself will be included. | |
| 6344 */ | |
| 6345 static List<Element> _computeConflictingElements( | |
| 6346 Element firstElement, Element secondElement) { | |
| 6347 HashSet<Element> elements = new HashSet<Element>(); | |
| 6348 _add(elements, firstElement); | |
| 6349 _add(elements, secondElement); | |
| 6350 return new List.from(elements); | |
| 6351 } | |
| 6352 } | |
| 6353 | |
| 6354 /** | |
| 6355 * A [MethodElementImpl], with the additional information of a list of | |
| 6356 * [ExecutableElement]s from which this element was composed. | |
| 6357 */ | |
| 6358 class MultiplyInheritedMethodElementImpl extends MethodElementImpl | |
| 6359 implements MultiplyInheritedExecutableElement { | |
| 6360 /** | |
| 6361 * A list the array of executable elements that were used to compose this | |
| 6362 * element. | |
| 6363 */ | |
| 6364 List<ExecutableElement> _elements = MethodElement.EMPTY_LIST; | |
| 6365 | |
| 6366 MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) { | |
| 6367 synthetic = true; | |
| 6368 } | |
| 6369 | |
| 6370 @override | |
| 6371 List<ExecutableElement> get inheritedElements => _elements; | |
| 6372 | |
| 6373 void set inheritedElements(List<ExecutableElement> elements) { | |
| 6374 this._elements = elements; | |
| 6375 } | |
| 6376 } | |
| 6377 | |
| 6378 /** | |
| 6379 * A [PropertyAccessorElementImpl], with the additional information of a list of | |
| 6380 * [ExecutableElement]s from which this element was composed. | |
| 6381 */ | |
| 6382 class MultiplyInheritedPropertyAccessorElementImpl | |
| 6383 extends PropertyAccessorElementImpl | |
| 6384 implements MultiplyInheritedExecutableElement { | |
| 6385 /** | |
| 6386 * A list the array of executable elements that were used to compose this | |
| 6387 * element. | |
| 6388 */ | |
| 6389 List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST; | |
| 6390 | |
| 6391 MultiplyInheritedPropertyAccessorElementImpl(Identifier name) | |
| 6392 : super.forNode(name) { | |
| 6393 synthetic = true; | |
| 6394 } | |
| 6395 | |
| 6396 @override | |
| 6397 List<ExecutableElement> get inheritedElements => _elements; | |
| 6398 | |
| 6399 void set inheritedElements(List<ExecutableElement> elements) { | |
| 6400 this._elements = elements; | |
| 6401 } | |
| 6402 } | |
| 6403 | |
| 6404 /** | |
| 6405 * A concrete implementation of a [ParameterElement]. | |
| 6406 */ | |
| 6407 class ParameterElementImpl extends VariableElementImpl | |
| 6408 with ParameterElementMixin | |
| 6409 implements ParameterElement { | |
| 6410 /** | |
| 6411 * A list containing all of the parameters defined by this parameter element. | |
| 6412 * There will only be parameters if this parameter is a function typed | |
| 6413 * parameter. | |
| 6414 */ | |
| 6415 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 6416 | |
| 6417 /** | |
| 6418 * A list containing all of the type parameters defined for this parameter | |
| 6419 * element. There will only be parameters if this parameter is a function | |
| 6420 * typed parameter. | |
| 6421 */ | |
| 6422 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 6423 | |
| 6424 /** | |
| 6425 * The kind of this parameter. | |
| 6426 */ | |
| 6427 ParameterKind parameterKind; | |
| 6428 | |
| 6429 /** | |
| 6430 * The Dart code of the default value. | |
| 6431 */ | |
| 6432 String _defaultValueCode; | |
| 6433 | |
| 6434 /** | |
| 6435 * The offset to the beginning of the visible range for this element. | |
| 6436 */ | |
| 6437 int _visibleRangeOffset = 0; | |
| 6438 | |
| 6439 /** | |
| 6440 * The length of the visible range for this element, or `-1` if this element | |
| 6441 * does not have a visible range. | |
| 6442 */ | |
| 6443 int _visibleRangeLength = -1; | |
| 6444 | |
| 6445 /** | |
| 6446 * Initialize a newly created parameter element to have the given [name] and | |
| 6447 * [offset]. | |
| 6448 */ | |
| 6449 ParameterElementImpl(String name, int nameOffset) : super(name, nameOffset); | |
| 6450 | |
| 6451 /** | |
| 6452 * Initialize a newly created parameter element to have the given [name]. | |
| 6453 */ | |
| 6454 ParameterElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 6455 | |
| 6456 @override | |
| 6457 String get defaultValueCode => _defaultValueCode; | |
| 6458 | |
| 6459 /** | |
| 6460 * Set Dart code of the default value. | |
| 6461 */ | |
| 6462 void set defaultValueCode(String defaultValueCode) { | |
| 6463 this._defaultValueCode = StringUtilities.intern(defaultValueCode); | |
| 6464 } | |
| 6465 | |
| 6466 @override | |
| 6467 bool get isInitializingFormal => false; | |
| 6468 | |
| 6469 @override | |
| 6470 bool get isPotentiallyMutatedInClosure => | |
| 6471 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); | |
| 6472 | |
| 6473 @override | |
| 6474 bool get isPotentiallyMutatedInScope => | |
| 6475 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); | |
| 6476 | |
| 6477 @override | |
| 6478 ElementKind get kind => ElementKind.PARAMETER; | |
| 6479 | |
| 6480 @override | |
| 6481 List<ParameterElement> get parameters => _parameters; | |
| 6482 | |
| 6483 /** | |
| 6484 * Set the parameters defined by this executable element to the given | |
| 6485 * [parameters]. | |
| 6486 */ | |
| 6487 void set parameters(List<ParameterElement> parameters) { | |
| 6488 for (ParameterElement parameter in parameters) { | |
| 6489 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 6490 } | |
| 6491 this._parameters = parameters; | |
| 6492 } | |
| 6493 | |
| 6494 @override | |
| 6495 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 6496 | |
| 6497 /** | |
| 6498 * Set the type parameters defined by this parameter element to the given | |
| 6499 * [typeParameters]. | |
| 6500 */ | |
| 6501 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 6502 for (TypeParameterElement parameter in typeParameters) { | |
| 6503 (parameter as TypeParameterElementImpl).enclosingElement = this; | |
| 6504 } | |
| 6505 this._typeParameters = typeParameters; | |
| 6506 } | |
| 6507 | |
| 6508 @override | |
| 6509 SourceRange get visibleRange { | |
| 6510 if (_visibleRangeLength < 0) { | |
| 6511 return null; | |
| 6512 } | |
| 6513 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 6514 } | |
| 6515 | |
| 6516 @override | |
| 6517 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); | |
| 6518 | |
| 6519 @override | |
| 6520 void appendTo(StringBuffer buffer) { | |
| 6521 String left = ""; | |
| 6522 String right = ""; | |
| 6523 while (true) { | |
| 6524 if (parameterKind == ParameterKind.NAMED) { | |
| 6525 left = "{"; | |
| 6526 right = "}"; | |
| 6527 } else if (parameterKind == ParameterKind.POSITIONAL) { | |
| 6528 left = "["; | |
| 6529 right = "]"; | |
| 6530 } else if (parameterKind == ParameterKind.REQUIRED) {} | |
| 6531 break; | |
| 6532 } | |
| 6533 buffer.write(left); | |
| 6534 appendToWithoutDelimiters(buffer); | |
| 6535 buffer.write(right); | |
| 6536 } | |
| 6537 | |
| 6538 @override | |
| 6539 FormalParameter computeNode() => | |
| 6540 getNodeMatching((node) => node is FormalParameter); | |
| 6541 | |
| 6542 @override | |
| 6543 ElementImpl getChild(String identifier) { | |
| 6544 for (ParameterElement parameter in _parameters) { | |
| 6545 if ((parameter as ParameterElementImpl).identifier == identifier) { | |
| 6546 return parameter as ParameterElementImpl; | |
| 6547 } | |
| 6548 } | |
| 6549 return null; | |
| 6550 } | |
| 6551 | |
| 6552 /** | |
| 6553 * Specifies that this variable is potentially mutated somewhere in closure. | |
| 6554 */ | |
| 6555 void markPotentiallyMutatedInClosure() { | |
| 6556 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); | |
| 6557 } | |
| 6558 | |
| 6559 /** | |
| 6560 * Specifies that this variable is potentially mutated somewhere in its scope. | |
| 6561 */ | |
| 6562 void markPotentiallyMutatedInScope() { | |
| 6563 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); | |
| 6564 } | |
| 6565 | |
| 6566 /** | |
| 6567 * Set the visible range for this element to the range starting at the given | |
| 6568 * [offset] with the given [length]. | |
| 6569 */ | |
| 6570 void setVisibleRange(int offset, int length) { | |
| 6571 _visibleRangeOffset = offset; | |
| 6572 _visibleRangeLength = length; | |
| 6573 } | |
| 6574 | |
| 6575 @override | |
| 6576 void visitChildren(ElementVisitor visitor) { | |
| 6577 super.visitChildren(visitor); | |
| 6578 safelyVisitChildren(_parameters, visitor); | |
| 6579 } | |
| 6580 } | |
| 6581 | |
| 6582 /** | |
| 6583 * A mixin that provides a common implementation for methods defined in | |
| 6584 * [ParameterElement]. | |
| 6585 */ | |
| 6586 abstract class ParameterElementMixin implements ParameterElement { | |
| 6587 @override | |
| 6588 void appendToWithoutDelimiters(StringBuffer buffer) { | |
| 6589 buffer.write(type); | |
| 6590 buffer.write(" "); | |
| 6591 buffer.write(displayName); | |
| 6592 if (defaultValueCode != null) { | |
| 6593 if (parameterKind == ParameterKind.NAMED) { | |
| 6594 buffer.write(": "); | |
| 6595 } | |
| 6596 if (parameterKind == ParameterKind.POSITIONAL) { | |
| 6597 buffer.write(" = "); | |
| 6598 } | |
| 6599 buffer.write(defaultValueCode); | |
| 6600 } | |
| 6601 } | |
| 6602 } | |
| 6603 | |
| 6604 /** | |
| 6605 * A parameter element defined in a parameterized type where the values of the | |
| 6606 * type parameters are known. | |
| 6607 */ | |
| 6608 class ParameterMember extends VariableMember | |
| 6609 with ParameterElementMixin | |
| 6610 implements ParameterElement { | |
| 6611 /** | |
| 6612 * Initialize a newly created element to represent a parameter, based on the | |
| 6613 * [baseElement], defined by the [definingType]. If [type] is passed it will | |
| 6614 * represent the already substituted type. | |
| 6615 */ | |
| 6616 ParameterMember(ParameterElement baseElement, ParameterizedType definingType, | |
| 6617 [DartType type]) | |
| 6618 : super._(baseElement, definingType, type); | |
| 6619 | |
| 6620 @override | |
| 6621 ParameterElement get baseElement => super.baseElement as ParameterElement; | |
| 6622 | |
| 6623 @override | |
| 6624 String get defaultValueCode => baseElement.defaultValueCode; | |
| 6625 | |
| 6626 @override | |
| 6627 Element get enclosingElement => baseElement.enclosingElement; | |
| 6628 | |
| 6629 @override | |
| 6630 int get hashCode => baseElement.hashCode; | |
| 6631 | |
| 6632 @override | |
| 6633 bool get isInitializingFormal => baseElement.isInitializingFormal; | |
| 6634 | |
| 6635 @override | |
| 6636 ParameterKind get parameterKind => baseElement.parameterKind; | |
| 6637 | |
| 6638 @override | |
| 6639 List<ParameterElement> get parameters { | |
| 6640 DartType type = this.type; | |
| 6641 if (type is FunctionType) { | |
| 6642 return type.parameters; | |
| 6643 } | |
| 6644 return ParameterElement.EMPTY_LIST; | |
| 6645 } | |
| 6646 | |
| 6647 @override | |
| 6648 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; | |
| 6649 | |
| 6650 @override | |
| 6651 SourceRange get visibleRange => baseElement.visibleRange; | |
| 6652 | |
| 6653 // TODO(jmesserly): this equality is broken. It should consider the defining | |
| 6654 // type as well, otherwise we're dropping the substitution. | |
| 6655 @override | |
| 6656 bool operator ==(Object object) => | |
| 6657 object is ParameterMember && baseElement == object.baseElement; | |
| 6658 | |
| 6659 @override | |
| 6660 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); | |
| 6661 | |
| 6662 @override | |
| 6663 FormalParameter computeNode() => baseElement.computeNode(); | |
| 6664 | |
| 6665 @override | |
| 6666 Element getAncestor(Predicate<Element> predicate) { | |
| 6667 Element element = baseElement.getAncestor(predicate); | |
| 6668 ParameterizedType definingType = this.definingType; | |
| 6669 if (definingType is InterfaceType) { | |
| 6670 InterfaceType definingInterfaceType = definingType; | |
| 6671 if (element is ConstructorElement) { | |
| 6672 return ConstructorMember.from(element, definingInterfaceType); | |
| 6673 } else if (element is MethodElement) { | |
| 6674 return MethodMember.from(element, definingInterfaceType); | |
| 6675 } else if (element is PropertyAccessorElement) { | |
| 6676 return PropertyAccessorMember.from(element, definingInterfaceType); | |
| 6677 } | |
| 6678 } | |
| 6679 return element; | |
| 6680 } | |
| 6681 | |
| 6682 @override | |
| 6683 String toString() { | |
| 6684 ParameterElement baseElement = this.baseElement; | |
| 6685 String left = ""; | |
| 6686 String right = ""; | |
| 6687 while (true) { | |
| 6688 if (baseElement.parameterKind == ParameterKind.NAMED) { | |
| 6689 left = "{"; | |
| 6690 right = "}"; | |
| 6691 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) { | |
| 6692 left = "["; | |
| 6693 right = "]"; | |
| 6694 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {} | |
| 6695 break; | |
| 6696 } | |
| 6697 return '$left$type ${baseElement.displayName}$right'; | |
| 6698 } | |
| 6699 | |
| 6700 @override | |
| 6701 void visitChildren(ElementVisitor visitor) { | |
| 6702 super.visitChildren(visitor); | |
| 6703 safelyVisitChildren(parameters, visitor); | |
| 6704 } | |
| 6705 | |
| 6706 /** | |
| 6707 * If the given [parameter]'s type is different when any type parameters from | |
| 6708 * the defining type's declaration are replaced with the actual type | |
| 6709 * arguments from the [definingType], create a parameter member representing | |
| 6710 * the given parameter. Return the member that was created, or the base | |
| 6711 * parameter if no member was created. | |
| 6712 */ | |
| 6713 static ParameterElement from( | |
| 6714 ParameterElement parameter, ParameterizedType definingType) { | |
| 6715 if (parameter == null || definingType.typeArguments.length == 0) { | |
| 6716 return parameter; | |
| 6717 } | |
| 6718 // Check if parameter type depends on defining type type arguments. | |
| 6719 // It is possible that we did not resolve field formal parameter yet, | |
| 6720 // so skip this check for it. | |
| 6721 if (parameter is FieldFormalParameterElement) { | |
| 6722 return new FieldFormalParameterMember(parameter, definingType); | |
| 6723 } else { | |
| 6724 DartType baseType = parameter.type; | |
| 6725 List<DartType> argumentTypes = definingType.typeArguments; | |
| 6726 List<DartType> parameterTypes = | |
| 6727 TypeParameterTypeImpl.getTypes(definingType.typeParameters); | |
| 6728 DartType substitutedType = | |
| 6729 baseType.substitute2(argumentTypes, parameterTypes); | |
| 6730 if (baseType == substitutedType) { | |
| 6731 return parameter; | |
| 6732 } | |
| 6733 return new ParameterMember(parameter, definingType, substitutedType); | |
| 6734 } | |
| 6735 } | |
| 6736 } | |
| 6737 | |
| 6738 /** | |
| 6739 * A concrete implementation of a [PrefixElement]. | |
| 6740 */ | |
| 6741 class PrefixElementImpl extends ElementImpl implements PrefixElement { | |
| 6742 /** | |
| 6743 * A list containing all of the libraries that are imported using this prefix. | |
| 6744 */ | |
| 6745 List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST; | |
| 6746 | |
| 6747 /** | |
| 6748 * Initialize a newly created method element to have the given [name] and | |
| 6749 * [offset]. | |
| 6750 */ | |
| 6751 PrefixElementImpl(String name, int nameOffset) : super(name, nameOffset); | |
| 6752 | |
| 6753 /** | |
| 6754 * Initialize a newly created prefix element to have the given [name]. | |
| 6755 */ | |
| 6756 PrefixElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 6757 | |
| 6758 @override | |
| 6759 LibraryElement get enclosingElement => | |
| 6760 super.enclosingElement as LibraryElement; | |
| 6761 | |
| 6762 @override | |
| 6763 String get identifier => "_${super.identifier}"; | |
| 6764 | |
| 6765 @override | |
| 6766 List<LibraryElement> get importedLibraries => _importedLibraries; | |
| 6767 | |
| 6768 /** | |
| 6769 * Set the libraries that are imported using this prefix to the given | |
| 6770 * [libraries]. | |
| 6771 */ | |
| 6772 void set importedLibraries(List<LibraryElement> libraries) { | |
| 6773 for (LibraryElement library in libraries) { | |
| 6774 (library as LibraryElementImpl).enclosingElement = this; | |
| 6775 } | |
| 6776 _importedLibraries = libraries; | |
| 6777 } | |
| 6778 | |
| 6779 @override | |
| 6780 ElementKind get kind => ElementKind.PREFIX; | |
| 6781 | |
| 6782 @override | |
| 6783 accept(ElementVisitor visitor) => visitor.visitPrefixElement(this); | |
| 6784 | |
| 6785 @override | |
| 6786 void appendTo(StringBuffer buffer) { | |
| 6787 buffer.write("as "); | |
| 6788 super.appendTo(buffer); | |
| 6789 } | |
| 6790 } | |
| 6791 | |
| 6792 /** | |
| 6793 * A concrete implementation of a [PropertyAccessorElement]. | |
| 6794 */ | |
| 6795 class PropertyAccessorElementImpl extends ExecutableElementImpl | |
| 6796 implements PropertyAccessorElement { | |
| 6797 /** | |
| 6798 * The variable associated with this accessor. | |
| 6799 */ | |
| 6800 PropertyInducingElement variable; | |
| 6801 | |
| 6802 /** | |
| 6803 * Initialize a newly created property accessor element to have the given | |
| 6804 * [name]. | |
| 6805 */ | |
| 6806 PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 6807 | |
| 6808 /** | |
| 6809 * Initialize a newly created synthetic property accessor element to be | |
| 6810 * associated with the given [variable]. | |
| 6811 */ | |
| 6812 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable) | |
| 6813 : super(variable.name, variable.nameOffset) { | |
| 6814 this.variable = variable; | |
| 6815 static = variable.isStatic; | |
| 6816 synthetic = true; | |
| 6817 } | |
| 6818 | |
| 6819 /** | |
| 6820 * Set whether this accessor is abstract. | |
| 6821 */ | |
| 6822 void set abstract(bool isAbstract) { | |
| 6823 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 6824 } | |
| 6825 | |
| 6826 @override | |
| 6827 PropertyAccessorElement get correspondingGetter { | |
| 6828 if (isGetter || variable == null) { | |
| 6829 return null; | |
| 6830 } | |
| 6831 return variable.getter; | |
| 6832 } | |
| 6833 | |
| 6834 @override | |
| 6835 PropertyAccessorElement get correspondingSetter { | |
| 6836 if (isSetter || variable == null) { | |
| 6837 return null; | |
| 6838 } | |
| 6839 return variable.setter; | |
| 6840 } | |
| 6841 | |
| 6842 /** | |
| 6843 * Set whether this accessor is a getter. | |
| 6844 */ | |
| 6845 void set getter(bool isGetter) { | |
| 6846 setModifier(Modifier.GETTER, isGetter); | |
| 6847 } | |
| 6848 | |
| 6849 @override | |
| 6850 int get hashCode => JenkinsSmiHash.hash2(super.hashCode, isGetter ? 1 : 2); | |
| 6851 | |
| 6852 @override | |
| 6853 String get identifier { | |
| 6854 String name = displayName; | |
| 6855 String suffix = isGetter ? "?" : "="; | |
| 6856 return "$name$suffix"; | |
| 6857 } | |
| 6858 | |
| 6859 @override | |
| 6860 bool get isGetter => hasModifier(Modifier.GETTER); | |
| 6861 | |
| 6862 @override | |
| 6863 bool get isSetter => hasModifier(Modifier.SETTER); | |
| 6864 | |
| 6865 @override | |
| 6866 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 6867 | |
| 6868 @override | |
| 6869 ElementKind get kind { | |
| 6870 if (isGetter) { | |
| 6871 return ElementKind.GETTER; | |
| 6872 } | |
| 6873 return ElementKind.SETTER; | |
| 6874 } | |
| 6875 | |
| 6876 @override | |
| 6877 String get name { | |
| 6878 if (isSetter) { | |
| 6879 return "${super.name}="; | |
| 6880 } | |
| 6881 return super.name; | |
| 6882 } | |
| 6883 | |
| 6884 /** | |
| 6885 * Set whether this accessor is a setter. | |
| 6886 */ | |
| 6887 void set setter(bool isSetter) { | |
| 6888 setModifier(Modifier.SETTER, isSetter); | |
| 6889 } | |
| 6890 | |
| 6891 /** | |
| 6892 * Set whether this accessor is static. | |
| 6893 */ | |
| 6894 void set static(bool isStatic) { | |
| 6895 setModifier(Modifier.STATIC, isStatic); | |
| 6896 } | |
| 6897 | |
| 6898 @override | |
| 6899 bool operator ==(Object object) => | |
| 6900 super == object && | |
| 6901 isGetter == (object as PropertyAccessorElement).isGetter; | |
| 6902 | |
| 6903 @override | |
| 6904 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); | |
| 6905 | |
| 6906 @override | |
| 6907 void appendTo(StringBuffer buffer) { | |
| 6908 buffer.write(isGetter ? "get " : "set "); | |
| 6909 buffer.write(variable.displayName); | |
| 6910 super.appendTo(buffer); | |
| 6911 } | |
| 6912 | |
| 6913 @override | |
| 6914 AstNode computeNode() { | |
| 6915 if (isSynthetic) { | |
| 6916 return null; | |
| 6917 } | |
| 6918 if (enclosingElement is ClassElement) { | |
| 6919 return getNodeMatching((node) => node is MethodDeclaration); | |
| 6920 } | |
| 6921 if (enclosingElement is CompilationUnitElement) { | |
| 6922 return getNodeMatching((node) => node is FunctionDeclaration); | |
| 6923 } | |
| 6924 return null; | |
| 6925 } | |
| 6926 } | |
| 6927 | |
| 6928 /** | |
| 6929 * A property accessor element defined in a parameterized type where the values | |
| 6930 * of the type parameters are known. | |
| 6931 */ | |
| 6932 class PropertyAccessorMember extends ExecutableMember | |
| 6933 implements PropertyAccessorElement { | |
| 6934 /** | |
| 6935 * Initialize a newly created element to represent a property, based on the | |
| 6936 * [baseElement], defined by the [definingType]. | |
| 6937 */ | |
| 6938 PropertyAccessorMember( | |
| 6939 PropertyAccessorElement baseElement, InterfaceType definingType) | |
| 6940 : super(baseElement, definingType); | |
| 6941 | |
| 6942 @override | |
| 6943 PropertyAccessorElement get baseElement => | |
| 6944 super.baseElement as PropertyAccessorElement; | |
| 6945 | |
| 6946 @override | |
| 6947 PropertyAccessorElement get correspondingGetter => | |
| 6948 from(baseElement.correspondingGetter, definingType); | |
| 6949 | |
| 6950 @override | |
| 6951 PropertyAccessorElement get correspondingSetter => | |
| 6952 from(baseElement.correspondingSetter, definingType); | |
| 6953 | |
| 6954 @override | |
| 6955 InterfaceType get definingType => super.definingType as InterfaceType; | |
| 6956 | |
| 6957 @override | |
| 6958 Element get enclosingElement => baseElement.enclosingElement; | |
| 6959 | |
| 6960 @override | |
| 6961 bool get isGetter => baseElement.isGetter; | |
| 6962 | |
| 6963 @override | |
| 6964 bool get isSetter => baseElement.isSetter; | |
| 6965 | |
| 6966 @override | |
| 6967 PropertyInducingElement get variable { | |
| 6968 PropertyInducingElement variable = baseElement.variable; | |
| 6969 if (variable is FieldElement) { | |
| 6970 return FieldMember.from(variable, definingType); | |
| 6971 } | |
| 6972 return variable; | |
| 6973 } | |
| 6974 | |
| 6975 @override | |
| 6976 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); | |
| 6977 | |
| 6978 @override | |
| 6979 String toString() { | |
| 6980 PropertyAccessorElement baseElement = this.baseElement; | |
| 6981 List<ParameterElement> parameters = this.parameters; | |
| 6982 FunctionType type = this.type; | |
| 6983 StringBuffer builder = new StringBuffer(); | |
| 6984 if (isGetter) { | |
| 6985 builder.write("get "); | |
| 6986 } else { | |
| 6987 builder.write("set "); | |
| 6988 } | |
| 6989 builder.write(baseElement.enclosingElement.displayName); | |
| 6990 builder.write("."); | |
| 6991 builder.write(baseElement.displayName); | |
| 6992 builder.write("("); | |
| 6993 int parameterCount = parameters.length; | |
| 6994 for (int i = 0; i < parameterCount; i++) { | |
| 6995 if (i > 0) { | |
| 6996 builder.write(", "); | |
| 6997 } | |
| 6998 builder.write(parameters[i]); | |
| 6999 } | |
| 7000 builder.write(")"); | |
| 7001 if (type != null) { | |
| 7002 builder.write(ElementImpl.RIGHT_ARROW); | |
| 7003 builder.write(type.returnType); | |
| 7004 } | |
| 7005 return builder.toString(); | |
| 7006 } | |
| 7007 | |
| 7008 /** | |
| 7009 * If the given [accessor]'s type is different when any type parameters from | |
| 7010 * the defining type's declaration are replaced with the actual type | |
| 7011 * arguments from the [definingType], create an accessor member representing | |
| 7012 * the given accessor. Return the member that was created, or the base | |
| 7013 * accessor if no member was created. | |
| 7014 */ | |
| 7015 static PropertyAccessorElement from( | |
| 7016 PropertyAccessorElement accessor, InterfaceType definingType) { | |
| 7017 if (!_isChangedByTypeSubstitution(accessor, definingType)) { | |
| 7018 return accessor; | |
| 7019 } | |
| 7020 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 7021 // instance. It would use more memory but speed up some operations. | |
| 7022 // We need to see how often the type is being re-computed. | |
| 7023 return new PropertyAccessorMember(accessor, definingType); | |
| 7024 } | |
| 7025 | |
| 7026 /** | |
| 7027 * Determine whether the given property [accessor]'s type is changed when type | |
| 7028 * parameters from the defining type's declaration are replaced with the | |
| 7029 * actual type arguments from the [definingType]. | |
| 7030 */ | |
| 7031 static bool _isChangedByTypeSubstitution( | |
| 7032 PropertyAccessorElement accessor, InterfaceType definingType) { | |
| 7033 List<DartType> argumentTypes = definingType.typeArguments; | |
| 7034 if (accessor != null && argumentTypes.length != 0) { | |
| 7035 FunctionType baseType = accessor.type; | |
| 7036 if (baseType == null) { | |
| 7037 AnalysisEngine.instance.logger.logInformation( | |
| 7038 'Type of $accessor is null in PropertyAccessorMember._isChangedByTyp
eSubstitution'); | |
| 7039 return false; | |
| 7040 } | |
| 7041 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 7042 FunctionType substitutedType = | |
| 7043 baseType.substitute2(argumentTypes, parameterTypes); | |
| 7044 if (baseType != substitutedType) { | |
| 7045 return true; | |
| 7046 } | |
| 7047 // If this property accessor is based on a field, that field might have a | |
| 7048 // propagated type. In which case we need to check whether the propagated | |
| 7049 // type of the field needs substitution. | |
| 7050 PropertyInducingElement field = accessor.variable; | |
| 7051 if (!field.isSynthetic) { | |
| 7052 DartType baseFieldType = field.propagatedType; | |
| 7053 if (baseFieldType != null) { | |
| 7054 DartType substitutedFieldType = | |
| 7055 baseFieldType.substitute2(argumentTypes, parameterTypes); | |
| 7056 if (baseFieldType != substitutedFieldType) { | |
| 7057 return true; | |
| 7058 } | |
| 7059 } | |
| 7060 } | |
| 7061 } | |
| 7062 return false; | |
| 7063 } | |
| 7064 } | |
| 7065 | |
| 7066 /** | |
| 7067 * A concrete implementation of a [PropertyInducingElement]. | |
| 7068 */ | |
| 7069 abstract class PropertyInducingElementImpl extends VariableElementImpl | |
| 7070 implements PropertyInducingElement { | |
| 7071 /** | |
| 7072 * The getter associated with this element. | |
| 7073 */ | |
| 7074 PropertyAccessorElement getter; | |
| 7075 | |
| 7076 /** | |
| 7077 * The setter associated with this element, or `null` if the element is | |
| 7078 * effectively `final` and therefore does not have a setter associated with | |
| 7079 * it. | |
| 7080 */ | |
| 7081 PropertyAccessorElement setter; | |
| 7082 | |
| 7083 /** | |
| 7084 * The propagated type of this variable, or `null` if type propagation has not | |
| 7085 * been performed. | |
| 7086 */ | |
| 7087 DartType propagatedType; | |
| 7088 | |
| 7089 /** | |
| 7090 * Initialize a newly created synthetic element to have the given [name] and | |
| 7091 * [offset]. | |
| 7092 */ | |
| 7093 PropertyInducingElementImpl(String name, int offset) : super(name, offset); | |
| 7094 | |
| 7095 /** | |
| 7096 * Initialize a newly created element to have the given [name]. | |
| 7097 */ | |
| 7098 PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 7099 } | |
| 7100 | |
| 7101 /** | |
| 7102 * A concrete implementation of a [ShowElementCombinator]. | |
| 7103 */ | |
| 7104 class ShowElementCombinatorImpl implements ShowElementCombinator { | |
| 7105 /** | |
| 7106 * The names that are to be made visible in the importing library if they are | |
| 7107 * defined in the imported library. | |
| 7108 */ | |
| 7109 List<String> shownNames = StringUtilities.EMPTY_ARRAY; | |
| 7110 | |
| 7111 /** | |
| 7112 * The offset of the character immediately following the last character of | |
| 7113 * this node. | |
| 7114 */ | |
| 7115 int end = -1; | |
| 7116 | |
| 7117 /** | |
| 7118 * The offset of the 'show' keyword of this element. | |
| 7119 */ | |
| 7120 int offset = 0; | |
| 7121 | |
| 7122 @override | |
| 7123 String toString() { | |
| 7124 StringBuffer buffer = new StringBuffer(); | |
| 7125 buffer.write("show "); | |
| 7126 int count = shownNames.length; | |
| 7127 for (int i = 0; i < count; i++) { | |
| 7128 if (i > 0) { | |
| 7129 buffer.write(", "); | |
| 7130 } | |
| 7131 buffer.write(shownNames[i]); | |
| 7132 } | |
| 7133 return buffer.toString(); | |
| 7134 } | |
| 7135 } | |
| 7136 | |
| 7137 /** | |
| 7138 * A concrete implementation of a [TopLevelVariableElement]. | |
| 7139 */ | |
| 7140 class TopLevelVariableElementImpl extends PropertyInducingElementImpl | |
| 7141 implements TopLevelVariableElement { | |
| 7142 /** | |
| 7143 * Initialize a newly created synthetic top-level variable element to have the | |
| 7144 * given [name] and [offset]. | |
| 7145 */ | |
| 7146 TopLevelVariableElementImpl(String name, int offset) : super(name, offset); | |
| 7147 | |
| 7148 /** | |
| 7149 * Initialize a newly created top-level variable element to have the given | |
| 7150 * [name]. | |
| 7151 */ | |
| 7152 TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 7153 | |
| 7154 @override | |
| 7155 bool get isStatic => true; | |
| 7156 | |
| 7157 @override | |
| 7158 ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE; | |
| 7159 | |
| 7160 @override | |
| 7161 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this); | |
| 7162 | |
| 7163 @override | |
| 7164 VariableDeclaration computeNode() => | |
| 7165 getNodeMatching((node) => node is VariableDeclaration); | |
| 7166 } | |
| 7167 | |
| 7168 /** | |
| 7169 * The abstract class `TypeImpl` implements the behavior common to objects | |
| 7170 * representing the declared type of elements in the element model. | |
| 7171 */ | |
| 7172 abstract class TypeImpl implements DartType { | |
| 7173 /** | |
| 7174 * The element representing the declaration of this type, or `null` if the | |
| 7175 * type has not, or cannot, be associated with an element. | |
| 7176 */ | |
| 7177 final Element _element; | |
| 7178 | |
| 7179 /** | |
| 7180 * The name of this type, or `null` if the type does not have a name. | |
| 7181 */ | |
| 7182 final String name; | |
| 7183 | |
| 7184 /** | |
| 7185 * Initialize a newly created type to be declared by the given [element] and | |
| 7186 * to have the given [name]. | |
| 7187 */ | |
| 7188 TypeImpl(this._element, this.name); | |
| 7189 | |
| 7190 @override | |
| 7191 String get displayName => name; | |
| 7192 | |
| 7193 @override | |
| 7194 Element get element => _element; | |
| 7195 | |
| 7196 @override | |
| 7197 bool get isBottom => false; | |
| 7198 | |
| 7199 @override | |
| 7200 bool get isDartCoreFunction => false; | |
| 7201 | |
| 7202 @override | |
| 7203 bool get isDynamic => false; | |
| 7204 | |
| 7205 @override | |
| 7206 bool get isObject => false; | |
| 7207 | |
| 7208 @override | |
| 7209 bool get isUndefined => false; | |
| 7210 | |
| 7211 @override | |
| 7212 bool get isVoid => false; | |
| 7213 | |
| 7214 /** | |
| 7215 * Append a textual representation of this type to the given [buffer]. The set | |
| 7216 * of [visitedTypes] is used to prevent infinite recursion. | |
| 7217 */ | |
| 7218 void appendTo(StringBuffer buffer) { | |
| 7219 if (name == null) { | |
| 7220 buffer.write("<unnamed type>"); | |
| 7221 } else { | |
| 7222 buffer.write(name); | |
| 7223 } | |
| 7224 } | |
| 7225 | |
| 7226 /** | |
| 7227 * Return `true` if this type is assignable to the given [type] (written in | |
| 7228 * the spec as "T <=> S", where T=[this] and S=[type]). | |
| 7229 * | |
| 7230 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of | |
| 7231 * function type aliases that have been expanded so far in the process of | |
| 7232 * reaching [this] and [type], respectively. These are used to avoid | |
| 7233 * infinite regress when analyzing invalid code; since the language spec | |
| 7234 * forbids a typedef from referring to itself directly or indirectly, we can | |
| 7235 * use these as sets of function type aliases that don't need to be expanded. | |
| 7236 */ | |
| 7237 @override | |
| 7238 bool isAssignableTo(DartType type) { | |
| 7239 // An interface type T may be assigned to a type S, written T <=> S, iff | |
| 7240 // either T <: S or S <: T. | |
| 7241 return isSubtypeOf(type) || (type as TypeImpl).isSubtypeOf(this); | |
| 7242 } | |
| 7243 | |
| 7244 /** | |
| 7245 * Return `true` if this type is more specific than the given [type] (written | |
| 7246 * in the spec as "T << S", where T=[this] and S=[type]). | |
| 7247 * | |
| 7248 * If [withDynamic] is `true`, then "dynamic" should be considered as a | |
| 7249 * subtype of any type (as though "dynamic" had been replaced with bottom). | |
| 7250 * | |
| 7251 * The set [visitedElements], if given, is the set of classes and type | |
| 7252 * parameters that have been visited so far while examining the class | |
| 7253 * hierarchy of [this]. This is used to avoid infinite regress when | |
| 7254 * analyzing invalid code; since the language spec forbids loops in the class | |
| 7255 * hierarchy, we can use this as a set of classes that don't need to be | |
| 7256 * examined when walking the class hierarchy. | |
| 7257 */ | |
| 7258 @override | |
| 7259 bool isMoreSpecificThan(DartType type, | |
| 7260 [bool withDynamic = false, Set<Element> visitedElements]); | |
| 7261 | |
| 7262 /** | |
| 7263 * Return `true` if this type is a subtype of the given [type] (written in | |
| 7264 * the spec as "T <: S", where T=[this] and S=[type]). | |
| 7265 * | |
| 7266 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of | |
| 7267 * function type aliases that have been expanded so far in the process of | |
| 7268 * reaching [this] and [type], respectively. These are used to avoid | |
| 7269 * infinite regress when analyzing invalid code; since the language spec | |
| 7270 * forbids a typedef from referring to itself directly or indirectly, we can | |
| 7271 * use these as sets of function type aliases that don't need to be expanded. | |
| 7272 */ | |
| 7273 @override | |
| 7274 bool isSubtypeOf(DartType type) { | |
| 7275 // For non-function types, T <: S iff [_|_/dynamic]T << S. | |
| 7276 return isMoreSpecificThan(type, true); | |
| 7277 } | |
| 7278 | |
| 7279 @override | |
| 7280 bool isSupertypeOf(DartType type) => type.isSubtypeOf(this); | |
| 7281 | |
| 7282 /** | |
| 7283 * Create a new [TypeImpl] that is identical to [this] except that when | |
| 7284 * visiting type parameters, function parameter types, and function return | |
| 7285 * types, function types listed in [prune] will not be expanded. This is | |
| 7286 * used to avoid creating infinite types in the presence of circular | |
| 7287 * typedefs. | |
| 7288 * | |
| 7289 * If [prune] is null, then [this] is returned unchanged. | |
| 7290 * | |
| 7291 * Only legal to call on a [TypeImpl] that is not already subject to pruning. | |
| 7292 */ | |
| 7293 TypeImpl pruned(List<FunctionTypeAliasElement> prune); | |
| 7294 | |
| 7295 /** | |
| 7296 * Return the type resulting from substituting the given [argumentTypes] for | |
| 7297 * the given [parameterTypes] in this type. | |
| 7298 * | |
| 7299 * In all classes derived from [TypeImpl], a new optional argument | |
| 7300 * [prune] is added. If specified, it is a list of function typdefs | |
| 7301 * which should not be expanded. This is used to avoid creating infinite | |
| 7302 * types in response to self-referential typedefs. | |
| 7303 */ | |
| 7304 @override | |
| 7305 DartType substitute2( | |
| 7306 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 7307 [List<FunctionTypeAliasElement> prune]); | |
| 7308 | |
| 7309 @override | |
| 7310 String toString() { | |
| 7311 StringBuffer buffer = new StringBuffer(); | |
| 7312 appendTo(buffer); | |
| 7313 return buffer.toString(); | |
| 7314 } | |
| 7315 | |
| 7316 /** | |
| 7317 * Return `true` if corresponding elements of the [first] and [second] lists | |
| 7318 * of type arguments are all equal. | |
| 7319 */ | |
| 7320 static bool equalArrays(List<DartType> first, List<DartType> second) { | |
| 7321 if (first.length != second.length) { | |
| 7322 return false; | |
| 7323 } | |
| 7324 for (int i = 0; i < first.length; i++) { | |
| 7325 if (first[i] == null) { | |
| 7326 AnalysisEngine.instance.logger | |
| 7327 .logInformation('Found null type argument in TypeImpl.equalArrays'); | |
| 7328 return second[i] == null; | |
| 7329 } else if (second[i] == null) { | |
| 7330 AnalysisEngine.instance.logger | |
| 7331 .logInformation('Found null type argument in TypeImpl.equalArrays'); | |
| 7332 return false; | |
| 7333 } | |
| 7334 if (first[i] != second[i]) { | |
| 7335 return false; | |
| 7336 } | |
| 7337 } | |
| 7338 return true; | |
| 7339 } | |
| 7340 | |
| 7341 /** | |
| 7342 * Return a list containing the results of using the given [argumentTypes] and | |
| 7343 * [parameterTypes] to perform a substitution on all of the given [types]. | |
| 7344 * | |
| 7345 * If [prune] is specified, it is a list of function typdefs which should not | |
| 7346 * be expanded. This is used to avoid creating infinite types in response to | |
| 7347 * self-referential typedefs. | |
| 7348 */ | |
| 7349 static List<DartType> substitute(List<DartType> types, | |
| 7350 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 7351 [List<FunctionTypeAliasElement> prune]) { | |
| 7352 int length = types.length; | |
| 7353 if (length == 0) { | |
| 7354 return types; | |
| 7355 } | |
| 7356 List<DartType> newTypes = new List<DartType>(length); | |
| 7357 for (int i = 0; i < length; i++) { | |
| 7358 newTypes[i] = (types[i] as TypeImpl) | |
| 7359 .substitute2(argumentTypes, parameterTypes, prune); | |
| 7360 } | |
| 7361 return newTypes; | |
| 7362 } | |
| 7363 } | |
| 7364 | |
| 7365 /** | |
| 7366 * A concrete implementation of a [TypeParameterElement]. | |
| 7367 */ | |
| 7368 class TypeParameterElementImpl extends ElementImpl | |
| 7369 implements TypeParameterElement { | |
| 7370 /** | |
| 7371 * The type defined by this type parameter. | |
| 7372 */ | |
| 7373 TypeParameterType type; | |
| 7374 | |
| 7375 /** | |
| 7376 * The type representing the bound associated with this parameter, or `null` | |
| 7377 * if this parameter does not have an explicit bound. | |
| 7378 */ | |
| 7379 DartType bound; | |
| 7380 | |
| 7381 /** | |
| 7382 * Initialize a newly created method element to have the given [name] and | |
| 7383 * [offset]. | |
| 7384 */ | |
| 7385 TypeParameterElementImpl(String name, int offset) : super(name, offset); | |
| 7386 | |
| 7387 /** | |
| 7388 * Initialize a newly created type parameter element to have the given [name]. | |
| 7389 */ | |
| 7390 TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 7391 | |
| 7392 @override | |
| 7393 ElementKind get kind => ElementKind.TYPE_PARAMETER; | |
| 7394 | |
| 7395 @override | |
| 7396 accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this); | |
| 7397 | |
| 7398 @override | |
| 7399 void appendTo(StringBuffer buffer) { | |
| 7400 buffer.write(displayName); | |
| 7401 if (bound != null) { | |
| 7402 buffer.write(" extends "); | |
| 7403 buffer.write(bound); | |
| 7404 } | |
| 7405 } | |
| 7406 } | |
| 7407 | |
| 7408 /** | |
| 7409 * A concrete implementation of a [TypeParameterType]. | |
| 7410 */ | |
| 7411 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { | |
| 7412 /** | |
| 7413 * Initialize a newly created type parameter type to be declared by the given | |
| 7414 * [element] and to have the given name. | |
| 7415 */ | |
| 7416 TypeParameterTypeImpl(TypeParameterElement element) | |
| 7417 : super(element, element.name); | |
| 7418 | |
| 7419 @override | |
| 7420 TypeParameterElement get element => super.element as TypeParameterElement; | |
| 7421 | |
| 7422 @override | |
| 7423 int get hashCode => element.hashCode; | |
| 7424 | |
| 7425 @override | |
| 7426 bool operator ==(Object object) => | |
| 7427 object is TypeParameterTypeImpl && (element == object.element); | |
| 7428 | |
| 7429 @override | |
| 7430 bool isMoreSpecificThan(DartType s, | |
| 7431 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 7432 // | |
| 7433 // A type T is more specific than a type S, written T << S, | |
| 7434 // if one of the following conditions is met: | |
| 7435 // | |
| 7436 // Reflexivity: T is S. | |
| 7437 // | |
| 7438 if (this == s) { | |
| 7439 return true; | |
| 7440 } | |
| 7441 // S is dynamic. | |
| 7442 // | |
| 7443 if (s.isDynamic) { | |
| 7444 return true; | |
| 7445 } | |
| 7446 // | |
| 7447 // T is a type parameter and S is the upper bound of T. | |
| 7448 // | |
| 7449 TypeImpl bound = element.bound; | |
| 7450 if (s == bound) { | |
| 7451 return true; | |
| 7452 } | |
| 7453 // | |
| 7454 // T is a type parameter and S is Object. | |
| 7455 // | |
| 7456 if (s.isObject) { | |
| 7457 return true; | |
| 7458 } | |
| 7459 // We need upper bound to continue. | |
| 7460 if (bound == null) { | |
| 7461 return false; | |
| 7462 } | |
| 7463 // | |
| 7464 // Transitivity: T << U and U << S. | |
| 7465 // | |
| 7466 // First check for infinite loops | |
| 7467 if (element == null) { | |
| 7468 return false; | |
| 7469 } | |
| 7470 if (visitedElements == null) { | |
| 7471 visitedElements = new HashSet<Element>(); | |
| 7472 } else if (visitedElements.contains(element)) { | |
| 7473 return false; | |
| 7474 } | |
| 7475 visitedElements.add(element); | |
| 7476 try { | |
| 7477 return bound.isMoreSpecificThan(s, withDynamic, visitedElements); | |
| 7478 } finally { | |
| 7479 visitedElements.remove(element); | |
| 7480 } | |
| 7481 } | |
| 7482 | |
| 7483 @override | |
| 7484 bool isSubtypeOf(DartType type) => isMoreSpecificThan(type, true); | |
| 7485 | |
| 7486 @override | |
| 7487 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 7488 | |
| 7489 @override | |
| 7490 DartType substitute2( | |
| 7491 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 7492 [List<FunctionTypeAliasElement> prune]) { | |
| 7493 int length = parameterTypes.length; | |
| 7494 for (int i = 0; i < length; i++) { | |
| 7495 if (parameterTypes[i] == this) { | |
| 7496 return argumentTypes[i]; | |
| 7497 } | |
| 7498 } | |
| 7499 return this; | |
| 7500 } | |
| 7501 | |
| 7502 /** | |
| 7503 * Return a list containing the type parameter types defined by the given | |
| 7504 * array of type parameter elements ([typeParameters]). | |
| 7505 */ | |
| 7506 static List<TypeParameterType> getTypes( | |
| 7507 List<TypeParameterElement> typeParameters) { | |
| 7508 int count = typeParameters.length; | |
| 7509 if (count == 0) { | |
| 7510 return TypeParameterType.EMPTY_LIST; | |
| 7511 } | |
| 7512 List<TypeParameterType> types = new List<TypeParameterType>(count); | |
| 7513 for (int i = 0; i < count; i++) { | |
| 7514 types[i] = typeParameters[i].type; | |
| 7515 } | |
| 7516 return types; | |
| 7517 } | |
| 7518 } | |
| 7519 | |
| 7520 /** | |
| 7521 * The unique instance of the class `UndefinedTypeImpl` implements the type of | |
| 7522 * type names that couldn't be resolved. | |
| 7523 * | |
| 7524 * This class behaves like DynamicTypeImpl in almost every respect, to reduce | |
| 7525 * cascading errors. | |
| 7526 */ | |
| 7527 class UndefinedTypeImpl extends TypeImpl { | |
| 7528 /** | |
| 7529 * The unique instance of this class. | |
| 7530 */ | |
| 7531 static UndefinedTypeImpl _INSTANCE = new UndefinedTypeImpl._(); | |
| 7532 | |
| 7533 /** | |
| 7534 * Return the unique instance of this class. | |
| 7535 */ | |
| 7536 static UndefinedTypeImpl get instance => _INSTANCE; | |
| 7537 | |
| 7538 /** | |
| 7539 * Prevent the creation of instances of this class. | |
| 7540 */ | |
| 7541 UndefinedTypeImpl._() | |
| 7542 : super(DynamicElementImpl.instance, Keyword.DYNAMIC.syntax); | |
| 7543 | |
| 7544 @override | |
| 7545 int get hashCode => 1; | |
| 7546 | |
| 7547 @override | |
| 7548 bool get isDynamic => true; | |
| 7549 | |
| 7550 @override | |
| 7551 bool get isUndefined => true; | |
| 7552 | |
| 7553 @override | |
| 7554 bool operator ==(Object object) => identical(object, this); | |
| 7555 | |
| 7556 @override | |
| 7557 bool isMoreSpecificThan(DartType type, | |
| 7558 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 7559 // T is S | |
| 7560 if (identical(this, type)) { | |
| 7561 return true; | |
| 7562 } | |
| 7563 // else | |
| 7564 return withDynamic; | |
| 7565 } | |
| 7566 | |
| 7567 @override | |
| 7568 bool isSubtypeOf(DartType type) => true; | |
| 7569 | |
| 7570 @override | |
| 7571 bool isSupertypeOf(DartType type) => true; | |
| 7572 | |
| 7573 @override | |
| 7574 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 7575 | |
| 7576 @override | |
| 7577 DartType substitute2( | |
| 7578 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 7579 [List<FunctionTypeAliasElement> prune]) { | |
| 7580 int length = parameterTypes.length; | |
| 7581 for (int i = 0; i < length; i++) { | |
| 7582 if (parameterTypes[i] == this) { | |
| 7583 return argumentTypes[i]; | |
| 7584 } | |
| 7585 } | |
| 7586 return this; | |
| 7587 } | |
| 7588 } | |
| 7589 | |
| 7590 /** | |
| 7591 * A concrete implementation of a [UriReferencedElement]. | |
| 7592 */ | |
| 7593 abstract class UriReferencedElementImpl extends ElementImpl | |
| 7594 implements UriReferencedElement { | |
| 7595 /** | |
| 7596 * The offset of the URI in the file, may be `-1` if synthetic. | |
| 7597 */ | |
| 7598 int uriOffset = -1; | |
| 7599 | |
| 7600 /** | |
| 7601 * The offset of the character immediately following the last character of | |
| 7602 * this node's URI, may be `-1` if synthetic. | |
| 7603 */ | |
| 7604 int uriEnd = -1; | |
| 7605 | |
| 7606 /** | |
| 7607 * The URI that is specified by this directive. | |
| 7608 */ | |
| 7609 String uri; | |
| 7610 | |
| 7611 /** | |
| 7612 * Initialize a newly created import element to have the given [name] and | |
| 7613 * [offset]. The offset may be `-1` if the element is synthetic. | |
| 7614 */ | |
| 7615 UriReferencedElementImpl(String name, int offset) : super(name, offset); | |
| 7616 } | |
| 7617 | |
| 7618 /** | |
| 7619 * A concrete implementation of a [VariableElement]. | |
| 7620 */ | |
| 7621 abstract class VariableElementImpl extends ElementImpl | |
| 7622 implements VariableElement { | |
| 7623 /** | |
| 7624 * The declared type of this variable. | |
| 7625 */ | |
| 7626 DartType type; | |
| 7627 | |
| 7628 /** | |
| 7629 * A synthetic function representing this variable's initializer, or `null` if | |
| 7630 * this variable does not have an initializer. | |
| 7631 */ | |
| 7632 FunctionElement _initializer; | |
| 7633 | |
| 7634 /** | |
| 7635 * Initialize a newly created variable element to have the given [name] and | |
| 7636 * [offset]. | |
| 7637 */ | |
| 7638 VariableElementImpl(String name, int offset) : super(name, offset); | |
| 7639 | |
| 7640 /** | |
| 7641 * Initialize a newly created variable element to have the given [name]. | |
| 7642 */ | |
| 7643 VariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 7644 | |
| 7645 /** | |
| 7646 * Set whether this variable is const. | |
| 7647 */ | |
| 7648 void set const3(bool isConst) { | |
| 7649 setModifier(Modifier.CONST, isConst); | |
| 7650 } | |
| 7651 | |
| 7652 /** | |
| 7653 * If this element represents a constant variable, and it has an initializer, | |
| 7654 * a copy of the initializer for the constant. Otherwise `null`. | |
| 7655 * | |
| 7656 * Note that in correct Dart code, all constant variables must have | |
| 7657 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 7658 * in which case there might be some constant variables that lack | |
| 7659 * initializers. | |
| 7660 */ | |
| 7661 Expression get constantInitializer => null; | |
| 7662 | |
| 7663 @override | |
| 7664 DartObject get constantValue => null; | |
| 7665 | |
| 7666 /** | |
| 7667 * Return the result of evaluating this variable's initializer as a | |
| 7668 * compile-time constant expression, or `null` if this variable is not a | |
| 7669 * 'const' variable, if it does not have an initializer, or if the compilation | |
| 7670 * unit containing the variable has not been resolved. | |
| 7671 */ | |
| 7672 EvaluationResultImpl get evaluationResult => null; | |
| 7673 | |
| 7674 /** | |
| 7675 * Set the result of evaluating this variable's initializer as a compile-time | |
| 7676 * constant expression to the given [result]. | |
| 7677 */ | |
| 7678 void set evaluationResult(EvaluationResultImpl result) { | |
| 7679 throw new IllegalStateException( | |
| 7680 "Invalid attempt to set a compile-time constant result"); | |
| 7681 } | |
| 7682 | |
| 7683 /** | |
| 7684 * Set whether this variable is final. | |
| 7685 */ | |
| 7686 void set final2(bool isFinal) { | |
| 7687 setModifier(Modifier.FINAL, isFinal); | |
| 7688 } | |
| 7689 | |
| 7690 @override | |
| 7691 bool get hasImplicitType => hasModifier(Modifier.IMPLICIT_TYPE); | |
| 7692 | |
| 7693 /** | |
| 7694 * Set whether this variable element has an implicit type. | |
| 7695 */ | |
| 7696 void set hasImplicitType(bool hasImplicitType) { | |
| 7697 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType); | |
| 7698 } | |
| 7699 | |
| 7700 @override | |
| 7701 FunctionElement get initializer => _initializer; | |
| 7702 | |
| 7703 /** | |
| 7704 * Set the function representing this variable's initializer to the given | |
| 7705 * [function]. | |
| 7706 */ | |
| 7707 void set initializer(FunctionElement function) { | |
| 7708 if (function != null) { | |
| 7709 (function as FunctionElementImpl).enclosingElement = this; | |
| 7710 } | |
| 7711 this._initializer = function; | |
| 7712 } | |
| 7713 | |
| 7714 @override | |
| 7715 bool get isConst => hasModifier(Modifier.CONST); | |
| 7716 | |
| 7717 @override | |
| 7718 bool get isFinal => hasModifier(Modifier.FINAL); | |
| 7719 | |
| 7720 @override | |
| 7721 bool get isPotentiallyMutatedInClosure => false; | |
| 7722 | |
| 7723 @override | |
| 7724 bool get isPotentiallyMutatedInScope => false; | |
| 7725 | |
| 7726 @override | |
| 7727 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 7728 | |
| 7729 @override | |
| 7730 void appendTo(StringBuffer buffer) { | |
| 7731 buffer.write(type); | |
| 7732 buffer.write(" "); | |
| 7733 buffer.write(displayName); | |
| 7734 } | |
| 7735 | |
| 7736 @override | |
| 7737 void visitChildren(ElementVisitor visitor) { | |
| 7738 super.visitChildren(visitor); | |
| 7739 safelyVisitChild(_initializer, visitor); | |
| 7740 } | |
| 7741 } | |
| 7742 | |
| 7743 /** | |
| 7744 * A variable element defined in a parameterized type where the values of the | |
| 7745 * type parameters are known. | |
| 7746 */ | |
| 7747 abstract class VariableMember extends Member implements VariableElement { | |
| 7748 @override | |
| 7749 final DartType type; | |
| 7750 | |
| 7751 /** | |
| 7752 * Initialize a newly created element to represent a variable, based on the | |
| 7753 * [baseElement], defined by the [definingType]. | |
| 7754 */ | |
| 7755 VariableMember(VariableElement baseElement, ParameterizedType definingType, | |
| 7756 [DartType type]) | |
| 7757 : type = type ?? | |
| 7758 baseElement.type.substitute2(definingType.typeArguments, | |
| 7759 TypeParameterTypeImpl.getTypes(definingType.typeParameters)), | |
| 7760 super(baseElement, definingType); | |
| 7761 | |
| 7762 // TODO(jmesserly): this is temporary to allow the ParameterMember subclass. | |
| 7763 // Apparently mixins don't work with optional params. | |
| 7764 VariableMember._(VariableElement baseElement, ParameterizedType definingType, | |
| 7765 DartType type) | |
| 7766 : this(baseElement, definingType, type); | |
| 7767 | |
| 7768 @override | |
| 7769 VariableElement get baseElement => super.baseElement as VariableElement; | |
| 7770 | |
| 7771 @override | |
| 7772 DartObject get constantValue => baseElement.constantValue; | |
| 7773 | |
| 7774 @override | |
| 7775 bool get hasImplicitType => baseElement.hasImplicitType; | |
| 7776 | |
| 7777 @override | |
| 7778 FunctionElement get initializer { | |
| 7779 // | |
| 7780 // Elements within this element should have type parameters substituted, | |
| 7781 // just like this element. | |
| 7782 // | |
| 7783 throw new UnsupportedOperationException(); | |
| 7784 // return getBaseElement().getInitializer(); | |
| 7785 } | |
| 7786 | |
| 7787 @override | |
| 7788 bool get isConst => baseElement.isConst; | |
| 7789 | |
| 7790 @override | |
| 7791 bool get isFinal => baseElement.isFinal; | |
| 7792 | |
| 7793 @override | |
| 7794 bool get isPotentiallyMutatedInClosure => | |
| 7795 baseElement.isPotentiallyMutatedInClosure; | |
| 7796 | |
| 7797 @override | |
| 7798 bool get isPotentiallyMutatedInScope => | |
| 7799 baseElement.isPotentiallyMutatedInScope; | |
| 7800 | |
| 7801 @override | |
| 7802 bool get isStatic => baseElement.isStatic; | |
| 7803 | |
| 7804 @override | |
| 7805 void visitChildren(ElementVisitor visitor) { | |
| 7806 // TODO(brianwilkerson) We need to finish implementing the accessors used | |
| 7807 // below so that we can safely invoke them. | |
| 7808 super.visitChildren(visitor); | |
| 7809 safelyVisitChild(baseElement.initializer, visitor); | |
| 7810 } | |
| 7811 } | |
| 7812 | |
| 7813 /** | |
| 7814 * The type `void`. | |
| 7815 */ | |
| 7816 abstract class VoidType implements DartType { | |
| 7817 @override | |
| 7818 VoidType substitute2( | |
| 7819 List<DartType> argumentTypes, List<DartType> parameterTypes); | |
| 7820 } | |
| 7821 | |
| 7822 /** | |
| 7823 * A concrete implementation of a [VoidType]. | |
| 7824 */ | |
| 7825 class VoidTypeImpl extends TypeImpl implements VoidType { | |
| 7826 /** | |
| 7827 * The unique instance of this class. | |
| 7828 */ | |
| 7829 static VoidTypeImpl _INSTANCE = new VoidTypeImpl(); | |
| 7830 | |
| 7831 /** | |
| 7832 * Return the unique instance of this class. | |
| 7833 */ | |
| 7834 static VoidTypeImpl get instance => _INSTANCE; | |
| 7835 | |
| 7836 /** | |
| 7837 * Prevent the creation of instances of this class. | |
| 7838 */ | |
| 7839 VoidTypeImpl() : super(null, Keyword.VOID.syntax); | |
| 7840 | |
| 7841 @override | |
| 7842 int get hashCode => 2; | |
| 7843 | |
| 7844 @override | |
| 7845 bool get isVoid => true; | |
| 7846 | |
| 7847 @override | |
| 7848 bool operator ==(Object object) => identical(object, this); | |
| 7849 | |
| 7850 @override | |
| 7851 bool isMoreSpecificThan(DartType type, | |
| 7852 [bool withDynamic = false, Set<Element> visitedElements]) => | |
| 7853 isSubtypeOf(type); | |
| 7854 | |
| 7855 @override | |
| 7856 bool isSubtypeOf(DartType type) { | |
| 7857 // The only subtype relations that pertain to void are therefore: | |
| 7858 // void <: void (by reflexivity) | |
| 7859 // bottom <: void (as bottom is a subtype of all types). | |
| 7860 // void <: dynamic (as dynamic is a supertype of all types) | |
| 7861 return identical(type, this) || type.isDynamic; | |
| 7862 } | |
| 7863 | |
| 7864 @override | |
| 7865 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 7866 | |
| 7867 @override | |
| 7868 VoidTypeImpl substitute2( | |
| 7869 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 7870 [List<FunctionTypeAliasElement> prune]) => | |
| 7871 this; | |
| 7872 } | |
| 7873 | |
| 7874 /** | |
| 7875 * A visitor that visit all the elements recursively and fill the given [map]. | |
| 7876 */ | |
| 7877 class _BuildOffsetToElementMap extends GeneralizingElementVisitor { | |
| 7878 final Map<int, Element> map; | |
| 7879 | |
| 7880 _BuildOffsetToElementMap(this.map); | |
| 7881 | |
| 7882 @override | |
| 7883 void visitElement(Element element) { | |
| 7884 int offset = element.nameOffset; | |
| 7885 if (offset != -1) { | |
| 7886 map[offset] = element; | |
| 7887 } | |
| 7888 super.visitElement(element); | |
| 7889 } | |
| 7890 } | |
| OLD | NEW |