OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library engine.element; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 10 import 'package:analyzer/src/task/dart.dart'; |
| 11 import 'package:analyzer/task/model.dart' |
| 12 show AnalysisTarget, ConstantEvaluationTarget; |
| 13 |
| 14 import 'ast.dart'; |
| 15 import 'constant.dart' show EvaluationResultImpl; |
| 16 import 'engine.dart' show AnalysisContext, AnalysisEngine, AnalysisException; |
| 17 import 'html.dart' show XmlAttributeNode, XmlTagNode; |
| 18 import 'java_core.dart'; |
| 19 import 'java_engine.dart'; |
| 20 import 'resolver.dart'; |
| 21 import 'scanner.dart' show Keyword; |
| 22 import 'sdk.dart' show DartSdk; |
| 23 import 'source.dart'; |
| 24 import 'utilities_collection.dart'; |
| 25 import 'utilities_dart.dart'; |
| 26 |
| 27 /** |
| 28 * For AST nodes that could be in both the getter and setter contexts |
| 29 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved |
| 30 * elements are stored in the AST node, in an [AuxiliaryElements]. Because |
| 31 * resolved elements are either statically resolved or resolved using propagated |
| 32 * type information, this class is a wrapper for a pair of [ExecutableElement]s, |
| 33 * not just a single [ExecutableElement]. |
| 34 */ |
| 35 class AuxiliaryElements { |
| 36 /** |
| 37 * The element based on propagated type information, or `null` if the AST |
| 38 * structure has not been resolved or if the node could not be resolved. |
| 39 */ |
| 40 final ExecutableElement propagatedElement; |
| 41 |
| 42 /** |
| 43 * The element based on static type information, or `null` if the AST |
| 44 * structure has not been resolved or if the node could not be resolved. |
| 45 */ |
| 46 final ExecutableElement staticElement; |
| 47 |
| 48 /** |
| 49 * Initialize a newly created pair to have both the [staticElement] and the |
| 50 * [propagatedElement]. |
| 51 */ |
| 52 AuxiliaryElements(this.staticElement, this.propagatedElement); |
| 53 } |
| 54 |
| 55 /** |
| 56 * A [Type] that represents the type 'bottom'. |
| 57 */ |
| 58 class BottomTypeImpl extends TypeImpl { |
| 59 /** |
| 60 * The unique instance of this class. |
| 61 */ |
| 62 static BottomTypeImpl _INSTANCE = new BottomTypeImpl._(); |
| 63 |
| 64 /** |
| 65 * Return the unique instance of this class. |
| 66 */ |
| 67 static BottomTypeImpl get instance => _INSTANCE; |
| 68 |
| 69 /** |
| 70 * Prevent the creation of instances of this class. |
| 71 */ |
| 72 BottomTypeImpl._() : super(null, "<bottom>"); |
| 73 |
| 74 @override |
| 75 int get hashCode => 0; |
| 76 |
| 77 @override |
| 78 bool get isBottom => true; |
| 79 |
| 80 @override |
| 81 bool operator ==(Object object) => identical(object, this); |
| 82 |
| 83 @override |
| 84 bool isMoreSpecificThan(DartType type, |
| 85 [bool withDynamic = false, Set<Element> visitedElements]) => |
| 86 true; |
| 87 |
| 88 @override |
| 89 bool isSubtypeOf(DartType type) => true; |
| 90 |
| 91 @override |
| 92 bool isSupertypeOf(DartType type) => false; |
| 93 |
| 94 @override |
| 95 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 96 |
| 97 @override |
| 98 BottomTypeImpl substitute2( |
| 99 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 100 [List<FunctionTypeAliasElement> prune]) => |
| 101 this; |
| 102 } |
| 103 |
| 104 /** |
| 105 * Type created internally if a circular reference is ever detected. Behaves |
| 106 * like `dynamic`, except that when converted to a string it is displayed as |
| 107 * `...`. |
| 108 */ |
| 109 class CircularTypeImpl extends DynamicTypeImpl { |
| 110 CircularTypeImpl() : super._circular(); |
| 111 |
| 112 @override |
| 113 int get hashCode => 1; |
| 114 |
| 115 @override |
| 116 bool operator ==(Object object) => object is CircularTypeImpl; |
| 117 |
| 118 @override |
| 119 void appendTo(StringBuffer buffer) { |
| 120 buffer.write('...'); |
| 121 } |
| 122 |
| 123 @override |
| 124 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 125 } |
| 126 |
| 127 /** |
| 128 * An element that represents a class. |
| 129 */ |
| 130 abstract class ClassElement implements TypeDefiningElement { |
| 131 /** |
| 132 * An empty list of class elements. |
| 133 */ |
| 134 static const List<ClassElement> EMPTY_LIST = const <ClassElement>[]; |
| 135 |
| 136 /** |
| 137 * Return a list containing all of the accessors (getters and setters) |
| 138 * declared in this class. |
| 139 */ |
| 140 List<PropertyAccessorElement> get accessors; |
| 141 |
| 142 /** |
| 143 * Return a list containing all the supertypes defined for this class and its |
| 144 * supertypes. This includes superclasses, mixins and interfaces. |
| 145 */ |
| 146 List<InterfaceType> get allSupertypes; |
| 147 |
| 148 /** |
| 149 * Return a list containing all of the constructors declared in this class. |
| 150 */ |
| 151 List<ConstructorElement> get constructors; |
| 152 |
| 153 /** |
| 154 * Return a list containing all of the fields declared in this class. |
| 155 */ |
| 156 List<FieldElement> get fields; |
| 157 |
| 158 /** |
| 159 * Return `true` if this class or its superclass declares a non-final instance |
| 160 * field. |
| 161 */ |
| 162 bool get hasNonFinalField; |
| 163 |
| 164 /** |
| 165 * Return `true` if this class has reference to super (so, for example, cannot |
| 166 * be used as a mixin). |
| 167 */ |
| 168 bool get hasReferenceToSuper; |
| 169 |
| 170 /** |
| 171 * Return `true` if this class declares a static member. |
| 172 */ |
| 173 bool get hasStaticMember; |
| 174 |
| 175 /** |
| 176 * Return a list containing all of the interfaces that are implemented by this |
| 177 * class. |
| 178 * |
| 179 * <b>Note:</b> Because the element model represents the state of the code, it |
| 180 * is possible for it to be semantically invalid. In particular, it is not |
| 181 * safe to assume that the inheritance structure of a class does not contain a |
| 182 * cycle. Clients that traverse the inheritance structure must explicitly |
| 183 * guard against infinite loops. |
| 184 */ |
| 185 List<InterfaceType> get interfaces; |
| 186 |
| 187 /** |
| 188 * Return `true` if this class is abstract. A class is abstract if it has an |
| 189 * explicit `abstract` modifier. Note, that this definition of <i>abstract</i> |
| 190 * is different from <i>has unimplemented members</i>. |
| 191 */ |
| 192 bool get isAbstract; |
| 193 |
| 194 /** |
| 195 * Return `true` if this class is defined by an enum declaration. |
| 196 */ |
| 197 bool get isEnum; |
| 198 |
| 199 /** |
| 200 * Return `true` if this class is a mixin application. A class is a mixin |
| 201 * application if it was declared using the syntax "class A = B with C;". |
| 202 */ |
| 203 bool get isMixinApplication; |
| 204 |
| 205 /** |
| 206 * Return `true` if this class [isProxy], or if it inherits the proxy |
| 207 * annotation from a supertype. |
| 208 */ |
| 209 bool get isOrInheritsProxy; |
| 210 |
| 211 /** |
| 212 * Return `true` if this element has an annotation of the form '@proxy'. |
| 213 */ |
| 214 bool get isProxy; |
| 215 |
| 216 /** |
| 217 * Return `true` if this class is a mixin application. Deprecated--please |
| 218 * use [isMixinApplication] instead. |
| 219 */ |
| 220 @deprecated |
| 221 bool get isTypedef; |
| 222 |
| 223 /** |
| 224 * Return `true` if this class can validly be used as a mixin when defining |
| 225 * another class. The behavior of this method is defined by the Dart Language |
| 226 * Specification in section 9: |
| 227 * <blockquote> |
| 228 * It is a compile-time error if a declared or derived mixin refers to super. |
| 229 * It is a compile-time error if a declared or derived mixin explicitly |
| 230 * declares a constructor. It is a compile-time error if a mixin is derived |
| 231 * from a class whose superclass is not Object. |
| 232 * </blockquote> |
| 233 */ |
| 234 bool get isValidMixin; |
| 235 |
| 236 /** |
| 237 * Return a list containing all of the methods declared in this class. |
| 238 */ |
| 239 List<MethodElement> get methods; |
| 240 |
| 241 /** |
| 242 * Return a list containing all of the mixins that are applied to the class |
| 243 * being extended in order to derive the superclass of this class. |
| 244 * |
| 245 * <b>Note:</b> Because the element model represents the state of the code, it |
| 246 * is possible for it to be semantically invalid. In particular, it is not |
| 247 * safe to assume that the inheritance structure of a class does not contain a |
| 248 * cycle. Clients that traverse the inheritance structure must explicitly |
| 249 * guard against infinite loops. |
| 250 */ |
| 251 List<InterfaceType> get mixins; |
| 252 |
| 253 /** |
| 254 * Return the superclass of this class, or `null` if the class represents the |
| 255 * class 'Object'. All other classes will have a non-`null` superclass. If the |
| 256 * superclass was not explicitly declared then the implicit superclass |
| 257 * 'Object' will be returned. |
| 258 * |
| 259 * <b>Note:</b> Because the element model represents the state of the code, it |
| 260 * is possible for it to be semantically invalid. In particular, it is not |
| 261 * safe to assume that the inheritance structure of a class does not contain a |
| 262 * cycle. Clients that traverse the inheritance structure must explicitly |
| 263 * guard against infinite loops. |
| 264 */ |
| 265 InterfaceType get supertype; |
| 266 |
| 267 @override |
| 268 InterfaceType get type; |
| 269 |
| 270 /** |
| 271 * Return a list containing all of the type parameters declared for this |
| 272 * class. |
| 273 */ |
| 274 List<TypeParameterElement> get typeParameters; |
| 275 |
| 276 /** |
| 277 * Return the unnamed constructor declared in this class, or `null` if this |
| 278 * class does not declare an unnamed constructor but does declare named |
| 279 * constructors. The returned constructor will be synthetic if this class does |
| 280 * not declare any constructors, in which case it will represent the default |
| 281 * constructor for the class. |
| 282 */ |
| 283 ConstructorElement get unnamedConstructor; |
| 284 |
| 285 /** |
| 286 * Return the resolved [ClassDeclaration] or [EnumDeclaration] node that |
| 287 * declares this [ClassElement]. |
| 288 * |
| 289 * This method is expensive, because resolved AST might be evicted from cache, |
| 290 * so parsing and resolving will be performed. |
| 291 */ |
| 292 @override |
| 293 NamedCompilationUnitMember computeNode(); |
| 294 |
| 295 /** |
| 296 * Return the field (synthetic or explicit) defined in this class that has the |
| 297 * given [name], or `null` if this class does not define a field with the |
| 298 * given name. |
| 299 */ |
| 300 FieldElement getField(String name); |
| 301 |
| 302 /** |
| 303 * Return the element representing the getter with the given [name] that is |
| 304 * declared in this class, or `null` if this class does not declare a getter |
| 305 * with the given name. |
| 306 */ |
| 307 PropertyAccessorElement getGetter(String name); |
| 308 |
| 309 /** |
| 310 * Return the element representing the method with the given [name] that is |
| 311 * declared in this class, or `null` if this class does not declare a method |
| 312 * with the given name. |
| 313 */ |
| 314 MethodElement getMethod(String name); |
| 315 |
| 316 /** |
| 317 * Return the named constructor declared in this class with the given [name], |
| 318 * or `null` if this class does not declare a named constructor with the given |
| 319 * name. |
| 320 */ |
| 321 ConstructorElement getNamedConstructor(String name); |
| 322 |
| 323 /** |
| 324 * Return the element representing the setter with the given [name] that is |
| 325 * declared in this class, or `null` if this class does not declare a setter |
| 326 * with the given name. |
| 327 */ |
| 328 PropertyAccessorElement getSetter(String name); |
| 329 |
| 330 /** |
| 331 * Determine whether the given [constructor], which exists in the superclass |
| 332 * of this class, is accessible to constructors in this class. |
| 333 */ |
| 334 bool isSuperConstructorAccessible(ConstructorElement constructor); |
| 335 |
| 336 /** |
| 337 * Return the element representing the method that results from looking up the |
| 338 * given [methodName] in this class with respect to the given [library], |
| 339 * ignoring abstract methods, or `null` if the look up fails. The behavior of |
| 340 * this method is defined by the Dart Language Specification in section |
| 341 * 16.15.1: |
| 342 * <blockquote> |
| 343 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 344 * library <i>L</i> is: If <i>C</i> declares an instance method named <i>m</i> |
| 345 * that is accessible to <i>L</i>, then that method is the result of the |
| 346 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result |
| 347 * of the lookup is the result of looking up method <i>m</i> in <i>S</i> with |
| 348 * respect to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 349 * </blockquote> |
| 350 */ |
| 351 MethodElement lookUpConcreteMethod(String methodName, LibraryElement library); |
| 352 |
| 353 /** |
| 354 * Return the element representing the getter that results from looking up the |
| 355 * given [getterName] in this class with respect to the given [library], or |
| 356 * `null` if the look up fails. The behavior of this method is defined by the |
| 357 * Dart Language Specification in section 16.15.2: |
| 358 * <blockquote> |
| 359 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 360 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an |
| 361 * instance getter (respectively setter) named <i>m</i> that is accessible to |
| 362 * <i>L</i>, then that getter (respectively setter) is the result of the |
| 363 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result |
| 364 * of the lookup is the result of looking up getter (respectively setter) |
| 365 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the |
| 366 * lookup has failed. |
| 367 * </blockquote> |
| 368 */ |
| 369 PropertyAccessorElement lookUpGetter( |
| 370 String getterName, LibraryElement library); |
| 371 |
| 372 /** |
| 373 * Return the element representing the getter that results from looking up the |
| 374 * given [getterName] in the superclass of this class with respect to the |
| 375 * given [library], ignoring abstract getters, or `null` if the look up fails. |
| 376 * The behavior of this method is defined by the Dart Language Specification |
| 377 * in section 16.15.2: |
| 378 * <blockquote> |
| 379 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 380 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an |
| 381 * instance getter (respectively setter) named <i>m</i> that is accessible to |
| 382 * <i>L</i>, then that getter (respectively setter) is the result of the |
| 383 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result |
| 384 * of the lookup is the result of looking up getter (respectively setter) |
| 385 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the |
| 386 * lookup has failed. |
| 387 * </blockquote> |
| 388 */ |
| 389 PropertyAccessorElement lookUpInheritedConcreteGetter( |
| 390 String getterName, LibraryElement library); |
| 391 |
| 392 /** |
| 393 * Return the element representing the method that results from looking up the |
| 394 * given [methodName] in the superclass of this class with respect to the |
| 395 * given [library], ignoring abstract methods, or `null` if the look up fails. |
| 396 * The behavior of this method is defined by the Dart Language Specification |
| 397 * in section 16.15.1: |
| 398 * <blockquote> |
| 399 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 400 * library <i>L</i> is: If <i>C</i> declares an instance method named |
| 401 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of |
| 402 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the |
| 403 * result of the lookup is the result of looking up method <i>m</i> in |
| 404 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has |
| 405 * failed. |
| 406 * </blockquote> |
| 407 */ |
| 408 MethodElement lookUpInheritedConcreteMethod( |
| 409 String methodName, LibraryElement library); |
| 410 |
| 411 /** |
| 412 * Return the element representing the setter that results from looking up the |
| 413 * given [setterName] in the superclass of this class with respect to the |
| 414 * given [library], ignoring abstract setters, or `null` if the look up fails. |
| 415 * The behavior of this method is defined by the Dart Language Specification |
| 416 * in section 16.15.2: |
| 417 * <blockquote> |
| 418 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 419 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an |
| 420 * instance getter (respectively setter) named <i>m</i> that is accessible to |
| 421 * <i>L</i>, then that getter (respectively setter) is the result of the |
| 422 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result |
| 423 * of the lookup is the result of looking up getter (respectively setter) |
| 424 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the |
| 425 * lookup has failed. |
| 426 * </blockquote> |
| 427 */ |
| 428 PropertyAccessorElement lookUpInheritedConcreteSetter( |
| 429 String setterName, LibraryElement library); |
| 430 |
| 431 /** |
| 432 * Return the element representing the method that results from looking up the |
| 433 * given [methodName] in the superclass of this class with respect to the |
| 434 * given [library], or `null` if the look up fails. The behavior of this |
| 435 * method is defined by the Dart Language Specification in section 16.15.1: |
| 436 * <blockquote> |
| 437 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 438 * library <i>L</i> is: If <i>C</i> declares an instance method named |
| 439 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of |
| 440 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the |
| 441 * result of the lookup is the result of looking up method <i>m</i> in |
| 442 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has |
| 443 * failed. |
| 444 * </blockquote> |
| 445 */ |
| 446 MethodElement lookUpInheritedMethod( |
| 447 String methodName, LibraryElement library); |
| 448 |
| 449 /** |
| 450 * Return the element representing the method that results from looking up the |
| 451 * given [methodName] in this class with respect to the given [library], or |
| 452 * `null` if the look up fails. The behavior of this method is defined by the |
| 453 * Dart Language Specification in section 16.15.1: |
| 454 * <blockquote> |
| 455 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 456 * library <i>L</i> is: If <i>C</i> declares an instance method named |
| 457 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of |
| 458 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the |
| 459 * result of the lookup is the result of looking up method <i>m</i> in |
| 460 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has |
| 461 * failed. |
| 462 * </blockquote> |
| 463 */ |
| 464 MethodElement lookUpMethod(String methodName, LibraryElement library); |
| 465 |
| 466 /** |
| 467 * Return the element representing the setter that results from looking up the |
| 468 * given [setterName] in this class with respect to the given [library], or |
| 469 * `null` if the look up fails. The behavior of this method is defined by the |
| 470 * Dart Language Specification in section 16.15.2: |
| 471 * <blockquote> |
| 472 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 473 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an |
| 474 * instance getter (respectively setter) named <i>m</i> that is accessible to |
| 475 * <i>L</i>, then that getter (respectively setter) is the result of the |
| 476 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result |
| 477 * of the lookup is the result of looking up getter (respectively setter) |
| 478 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the |
| 479 * lookup has failed. |
| 480 * </blockquote> |
| 481 */ |
| 482 PropertyAccessorElement lookUpSetter( |
| 483 String setterName, LibraryElement library); |
| 484 } |
| 485 |
| 486 /** |
| 487 * A concrete implementation of a [ClassElement]. |
| 488 */ |
| 489 class ClassElementImpl extends ElementImpl implements ClassElement { |
| 490 /** |
| 491 * An empty list of class elements. |
| 492 */ |
| 493 @deprecated // Use ClassElement.EMPTY_LIST |
| 494 static const List<ClassElement> EMPTY_ARRAY = const <ClassElement>[]; |
| 495 |
| 496 /** |
| 497 * A list containing all of the accessors (getters and setters) contained in |
| 498 * this class. |
| 499 */ |
| 500 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; |
| 501 |
| 502 /** |
| 503 * For classes which are not mixin applications, a list containing all of the |
| 504 * constructors contained in this class, or `null` if the list of |
| 505 * constructors has not yet been built. |
| 506 * |
| 507 * For classes which are mixin applications, the list of constructors is |
| 508 * computed on the fly by the [constructors] getter, and this field is |
| 509 * `null`. |
| 510 */ |
| 511 List<ConstructorElement> _constructors; |
| 512 |
| 513 /** |
| 514 * A list containing all of the fields contained in this class. |
| 515 */ |
| 516 List<FieldElement> _fields = FieldElement.EMPTY_LIST; |
| 517 |
| 518 /** |
| 519 * A list containing all of the mixins that are applied to the class being |
| 520 * extended in order to derive the superclass of this class. |
| 521 */ |
| 522 List<InterfaceType> mixins = InterfaceType.EMPTY_LIST; |
| 523 |
| 524 /** |
| 525 * A list containing all of the interfaces that are implemented by this class. |
| 526 */ |
| 527 List<InterfaceType> interfaces = InterfaceType.EMPTY_LIST; |
| 528 |
| 529 /** |
| 530 * A list containing all of the methods contained in this class. |
| 531 */ |
| 532 List<MethodElement> _methods = MethodElement.EMPTY_LIST; |
| 533 |
| 534 /** |
| 535 * The superclass of the class, or `null` if the class does not have an |
| 536 * explicit superclass. |
| 537 */ |
| 538 InterfaceType supertype; |
| 539 |
| 540 /** |
| 541 * The type defined by the class. |
| 542 */ |
| 543 InterfaceType type; |
| 544 |
| 545 /** |
| 546 * A list containing all of the type parameters defined for this class. |
| 547 */ |
| 548 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| 549 |
| 550 /** |
| 551 * The [SourceRange] of the `with` clause, `null` if there is no one. |
| 552 */ |
| 553 SourceRange withClauseRange; |
| 554 |
| 555 /** |
| 556 * A flag indicating whether the types associated with the instance members of |
| 557 * this class have been inferred. |
| 558 */ |
| 559 bool hasBeenInferred = false; |
| 560 |
| 561 /** |
| 562 * Initialize a newly created class element to have the given [name] at the |
| 563 * given [offset] in the file that contains the declaration of this element. |
| 564 */ |
| 565 ClassElementImpl(String name, int offset) : super(name, offset); |
| 566 |
| 567 /** |
| 568 * Initialize a newly created class element to have the given [name]. |
| 569 */ |
| 570 ClassElementImpl.forNode(Identifier name) : super.forNode(name); |
| 571 |
| 572 /** |
| 573 * Set whether this class is abstract. |
| 574 */ |
| 575 void set abstract(bool isAbstract) { |
| 576 setModifier(Modifier.ABSTRACT, isAbstract); |
| 577 } |
| 578 |
| 579 @override |
| 580 List<PropertyAccessorElement> get accessors => _accessors; |
| 581 |
| 582 /** |
| 583 * Set the accessors contained in this class to the given [accessors]. |
| 584 */ |
| 585 void set accessors(List<PropertyAccessorElement> accessors) { |
| 586 for (PropertyAccessorElement accessor in accessors) { |
| 587 (accessor as PropertyAccessorElementImpl).enclosingElement = this; |
| 588 } |
| 589 this._accessors = accessors; |
| 590 } |
| 591 |
| 592 @override |
| 593 List<InterfaceType> get allSupertypes { |
| 594 List<InterfaceType> list = new List<InterfaceType>(); |
| 595 _collectAllSupertypes(list); |
| 596 return list; |
| 597 } |
| 598 |
| 599 @override |
| 600 List<ConstructorElement> get constructors { |
| 601 if (!isMixinApplication) { |
| 602 assert(_constructors != null); |
| 603 return _constructors == null |
| 604 ? ConstructorElement.EMPTY_LIST |
| 605 : _constructors; |
| 606 } |
| 607 |
| 608 return _computeMixinAppConstructors(); |
| 609 } |
| 610 |
| 611 /** |
| 612 * Set the constructors contained in this class to the given [constructors]. |
| 613 * |
| 614 * Should only be used for class elements that are not mixin applications. |
| 615 */ |
| 616 void set constructors(List<ConstructorElement> constructors) { |
| 617 assert(!isMixinApplication); |
| 618 for (ConstructorElement constructor in constructors) { |
| 619 (constructor as ConstructorElementImpl).enclosingElement = this; |
| 620 } |
| 621 this._constructors = constructors; |
| 622 } |
| 623 |
| 624 /** |
| 625 * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should |
| 626 * be reported for this class. |
| 627 */ |
| 628 bool get doesMixinLackConstructors { |
| 629 if (!isMixinApplication && mixins.isEmpty) { |
| 630 // This class is not a mixin application and it doesn't have a "with" |
| 631 // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is |
| 632 // inapplicable. |
| 633 return false; |
| 634 } |
| 635 if (supertype == null) { |
| 636 // Should never happen, since Object is the only class that has no |
| 637 // supertype, and it should have been caught by the test above. |
| 638 assert(false); |
| 639 return false; |
| 640 } |
| 641 // Find the nearest class in the supertype chain that is not a mixin |
| 642 // application. |
| 643 ClassElement nearestNonMixinClass = supertype.element; |
| 644 if (nearestNonMixinClass.isMixinApplication) { |
| 645 // Use a list to keep track of the classes we've seen, so that we won't |
| 646 // go into an infinite loop in the event of a non-trivial loop in the |
| 647 // class hierarchy. |
| 648 List<ClassElementImpl> classesSeen = <ClassElementImpl>[this]; |
| 649 while (nearestNonMixinClass.isMixinApplication) { |
| 650 if (classesSeen.contains(nearestNonMixinClass)) { |
| 651 // Loop in the class hierarchy (which is reported elsewhere). Don't |
| 652 // confuse the user with further errors. |
| 653 return false; |
| 654 } |
| 655 classesSeen.add(nearestNonMixinClass); |
| 656 if (nearestNonMixinClass.supertype == null) { |
| 657 // Should never happen, since Object is the only class that has no |
| 658 // supertype, and it is not a mixin application. |
| 659 assert(false); |
| 660 return false; |
| 661 } |
| 662 nearestNonMixinClass = nearestNonMixinClass.supertype.element; |
| 663 } |
| 664 } |
| 665 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); |
| 666 } |
| 667 |
| 668 /** |
| 669 * Set whether this class is defined by an enum declaration. |
| 670 */ |
| 671 void set enum2(bool isEnum) { |
| 672 setModifier(Modifier.ENUM, isEnum); |
| 673 } |
| 674 |
| 675 @override |
| 676 List<FieldElement> get fields => _fields; |
| 677 |
| 678 /** |
| 679 * Set the fields contained in this class to the given [fields]. |
| 680 */ |
| 681 void set fields(List<FieldElement> fields) { |
| 682 for (FieldElement field in fields) { |
| 683 (field as FieldElementImpl).enclosingElement = this; |
| 684 } |
| 685 this._fields = fields; |
| 686 } |
| 687 |
| 688 @override |
| 689 bool get hasNonFinalField { |
| 690 List<ClassElement> classesToVisit = new List<ClassElement>(); |
| 691 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 692 classesToVisit.add(this); |
| 693 while (!classesToVisit.isEmpty) { |
| 694 ClassElement currentElement = classesToVisit.removeAt(0); |
| 695 if (visitedClasses.add(currentElement)) { |
| 696 // check fields |
| 697 for (FieldElement field in currentElement.fields) { |
| 698 if (!field.isFinal && |
| 699 !field.isConst && |
| 700 !field.isStatic && |
| 701 !field.isSynthetic) { |
| 702 return true; |
| 703 } |
| 704 } |
| 705 // check mixins |
| 706 for (InterfaceType mixinType in currentElement.mixins) { |
| 707 ClassElement mixinElement = mixinType.element; |
| 708 classesToVisit.add(mixinElement); |
| 709 } |
| 710 // check super |
| 711 InterfaceType supertype = currentElement.supertype; |
| 712 if (supertype != null) { |
| 713 ClassElement superElement = supertype.element; |
| 714 if (superElement != null) { |
| 715 classesToVisit.add(superElement); |
| 716 } |
| 717 } |
| 718 } |
| 719 } |
| 720 // not found |
| 721 return false; |
| 722 } |
| 723 |
| 724 @override |
| 725 bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); |
| 726 |
| 727 /** |
| 728 * Set whether this class references 'super'. |
| 729 */ |
| 730 void set hasReferenceToSuper(bool isReferencedSuper) { |
| 731 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); |
| 732 } |
| 733 |
| 734 @override |
| 735 bool get hasStaticMember { |
| 736 for (MethodElement method in _methods) { |
| 737 if (method.isStatic) { |
| 738 return true; |
| 739 } |
| 740 } |
| 741 for (PropertyAccessorElement accessor in _accessors) { |
| 742 if (accessor.isStatic) { |
| 743 return true; |
| 744 } |
| 745 } |
| 746 return false; |
| 747 } |
| 748 |
| 749 @override |
| 750 bool get isAbstract => hasModifier(Modifier.ABSTRACT); |
| 751 |
| 752 @override |
| 753 bool get isEnum => hasModifier(Modifier.ENUM); |
| 754 |
| 755 @override |
| 756 bool get isMixinApplication => hasModifier(Modifier.MIXIN_APPLICATION); |
| 757 |
| 758 @override |
| 759 bool get isOrInheritsProxy => |
| 760 _safeIsOrInheritsProxy(this, new HashSet<ClassElement>()); |
| 761 |
| 762 @override |
| 763 bool get isProxy { |
| 764 for (ElementAnnotation annotation in metadata) { |
| 765 if (annotation.isProxy) { |
| 766 return true; |
| 767 } |
| 768 } |
| 769 return false; |
| 770 } |
| 771 |
| 772 @override |
| 773 @deprecated |
| 774 bool get isTypedef => isMixinApplication; |
| 775 |
| 776 @override |
| 777 bool get isValidMixin => hasModifier(Modifier.MIXIN); |
| 778 |
| 779 @override |
| 780 ElementKind get kind => ElementKind.CLASS; |
| 781 |
| 782 @override |
| 783 List<MethodElement> get methods => _methods; |
| 784 |
| 785 /** |
| 786 * Set the methods contained in this class to the given [methods]. |
| 787 */ |
| 788 void set methods(List<MethodElement> methods) { |
| 789 for (MethodElement method in methods) { |
| 790 (method as MethodElementImpl).enclosingElement = this; |
| 791 } |
| 792 this._methods = methods; |
| 793 } |
| 794 |
| 795 /** |
| 796 * Set whether this class is a mixin application. |
| 797 */ |
| 798 void set mixinApplication(bool isMixinApplication) { |
| 799 setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); |
| 800 } |
| 801 |
| 802 @override |
| 803 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 804 |
| 805 /** |
| 806 * Set the type parameters defined for this class to the given |
| 807 * [typeParameters]. |
| 808 */ |
| 809 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 810 for (TypeParameterElement typeParameter in typeParameters) { |
| 811 (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| 812 } |
| 813 this._typeParameters = typeParameters; |
| 814 } |
| 815 |
| 816 @override |
| 817 ConstructorElement get unnamedConstructor { |
| 818 for (ConstructorElement element in constructors) { |
| 819 String name = element.displayName; |
| 820 if (name == null || name.isEmpty) { |
| 821 return element; |
| 822 } |
| 823 } |
| 824 return null; |
| 825 } |
| 826 |
| 827 /** |
| 828 * Set whether this class is a valid mixin. |
| 829 */ |
| 830 void set validMixin(bool isValidMixin) { |
| 831 setModifier(Modifier.MIXIN, isValidMixin); |
| 832 } |
| 833 |
| 834 @override |
| 835 accept(ElementVisitor visitor) => visitor.visitClassElement(this); |
| 836 |
| 837 @override |
| 838 void appendTo(StringBuffer buffer) { |
| 839 String name = displayName; |
| 840 if (name == null) { |
| 841 buffer.write("{unnamed class}"); |
| 842 } else { |
| 843 buffer.write(name); |
| 844 } |
| 845 int variableCount = _typeParameters.length; |
| 846 if (variableCount > 0) { |
| 847 buffer.write("<"); |
| 848 for (int i = 0; i < variableCount; i++) { |
| 849 if (i > 0) { |
| 850 buffer.write(", "); |
| 851 } |
| 852 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); |
| 853 } |
| 854 buffer.write(">"); |
| 855 } |
| 856 } |
| 857 |
| 858 @override |
| 859 NamedCompilationUnitMember computeNode() { |
| 860 if (isEnum) { |
| 861 return getNodeMatching((node) => node is EnumDeclaration); |
| 862 } else { |
| 863 return getNodeMatching( |
| 864 (node) => node is ClassDeclaration || node is ClassTypeAlias); |
| 865 } |
| 866 } |
| 867 |
| 868 @override |
| 869 ElementImpl getChild(String identifier) { |
| 870 // |
| 871 // The casts in this method are safe because the set methods would have |
| 872 // thrown a CCE if any of the elements in the arrays were not of the |
| 873 // expected types. |
| 874 // |
| 875 for (PropertyAccessorElement accessor in _accessors) { |
| 876 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { |
| 877 return accessor as PropertyAccessorElementImpl; |
| 878 } |
| 879 } |
| 880 for (ConstructorElement constructor in _constructors) { |
| 881 if ((constructor as ConstructorElementImpl).identifier == identifier) { |
| 882 return constructor as ConstructorElementImpl; |
| 883 } |
| 884 } |
| 885 for (FieldElement field in _fields) { |
| 886 if ((field as FieldElementImpl).identifier == identifier) { |
| 887 return field as FieldElementImpl; |
| 888 } |
| 889 } |
| 890 for (MethodElement method in _methods) { |
| 891 if ((method as MethodElementImpl).identifier == identifier) { |
| 892 return method as MethodElementImpl; |
| 893 } |
| 894 } |
| 895 for (TypeParameterElement typeParameter in _typeParameters) { |
| 896 if ((typeParameter as TypeParameterElementImpl).identifier == |
| 897 identifier) { |
| 898 return typeParameter as TypeParameterElementImpl; |
| 899 } |
| 900 } |
| 901 return null; |
| 902 } |
| 903 |
| 904 @override |
| 905 FieldElement getField(String name) { |
| 906 for (FieldElement fieldElement in _fields) { |
| 907 if (name == fieldElement.name) { |
| 908 return fieldElement; |
| 909 } |
| 910 } |
| 911 return null; |
| 912 } |
| 913 |
| 914 @override |
| 915 PropertyAccessorElement getGetter(String getterName) { |
| 916 for (PropertyAccessorElement accessor in _accessors) { |
| 917 if (accessor.isGetter && accessor.name == getterName) { |
| 918 return accessor; |
| 919 } |
| 920 } |
| 921 return null; |
| 922 } |
| 923 |
| 924 @override |
| 925 MethodElement getMethod(String methodName) { |
| 926 for (MethodElement method in _methods) { |
| 927 if (method.name == methodName) { |
| 928 return method; |
| 929 } |
| 930 } |
| 931 return null; |
| 932 } |
| 933 |
| 934 @override |
| 935 ConstructorElement getNamedConstructor(String name) { |
| 936 for (ConstructorElement element in constructors) { |
| 937 String elementName = element.name; |
| 938 if (elementName != null && elementName == name) { |
| 939 return element; |
| 940 } |
| 941 } |
| 942 return null; |
| 943 } |
| 944 |
| 945 @override |
| 946 PropertyAccessorElement getSetter(String setterName) { |
| 947 // TODO (jwren) revisit- should we append '=' here or require clients to |
| 948 // include it? |
| 949 // Do we need the check for isSetter below? |
| 950 if (!StringUtilities.endsWithChar(setterName, 0x3D)) { |
| 951 setterName += '='; |
| 952 } |
| 953 for (PropertyAccessorElement accessor in _accessors) { |
| 954 if (accessor.isSetter && accessor.name == setterName) { |
| 955 return accessor; |
| 956 } |
| 957 } |
| 958 return null; |
| 959 } |
| 960 |
| 961 @override |
| 962 bool isSuperConstructorAccessible(ConstructorElement constructor) { |
| 963 // If this class has no mixins, then all superclass constructors are |
| 964 // accessible. |
| 965 if (mixins.isEmpty) { |
| 966 return true; |
| 967 } |
| 968 // Otherwise only constructors that lack optional parameters are |
| 969 // accessible (see dartbug.com/19576). |
| 970 for (ParameterElement parameter in constructor.parameters) { |
| 971 if (parameter.parameterKind != ParameterKind.REQUIRED) { |
| 972 return false; |
| 973 } |
| 974 } |
| 975 return true; |
| 976 } |
| 977 |
| 978 @override |
| 979 MethodElement lookUpConcreteMethod( |
| 980 String methodName, LibraryElement library) => |
| 981 _internalLookUpConcreteMethod(methodName, library, true); |
| 982 |
| 983 @override |
| 984 PropertyAccessorElement lookUpGetter( |
| 985 String getterName, LibraryElement library) => |
| 986 _internalLookUpGetter(getterName, library, true); |
| 987 |
| 988 @override |
| 989 PropertyAccessorElement lookUpInheritedConcreteGetter( |
| 990 String getterName, LibraryElement library) => |
| 991 _internalLookUpConcreteGetter(getterName, library, false); |
| 992 |
| 993 @override |
| 994 MethodElement lookUpInheritedConcreteMethod( |
| 995 String methodName, LibraryElement library) => |
| 996 _internalLookUpConcreteMethod(methodName, library, false); |
| 997 |
| 998 @override |
| 999 PropertyAccessorElement lookUpInheritedConcreteSetter( |
| 1000 String setterName, LibraryElement library) => |
| 1001 _internalLookUpConcreteSetter(setterName, library, false); |
| 1002 |
| 1003 @override |
| 1004 MethodElement lookUpInheritedMethod( |
| 1005 String methodName, LibraryElement library) => |
| 1006 _internalLookUpMethod(methodName, library, false); |
| 1007 |
| 1008 @override |
| 1009 MethodElement lookUpMethod(String methodName, LibraryElement library) => |
| 1010 _internalLookUpMethod(methodName, library, true); |
| 1011 |
| 1012 @override |
| 1013 PropertyAccessorElement lookUpSetter( |
| 1014 String setterName, LibraryElement library) => |
| 1015 _internalLookUpSetter(setterName, library, true); |
| 1016 |
| 1017 @override |
| 1018 void visitChildren(ElementVisitor visitor) { |
| 1019 super.visitChildren(visitor); |
| 1020 safelyVisitChildren(_accessors, visitor); |
| 1021 safelyVisitChildren(_constructors, visitor); |
| 1022 safelyVisitChildren(_fields, visitor); |
| 1023 safelyVisitChildren(_methods, visitor); |
| 1024 safelyVisitChildren(_typeParameters, visitor); |
| 1025 } |
| 1026 |
| 1027 void _collectAllSupertypes(List<InterfaceType> supertypes) { |
| 1028 List<InterfaceType> typesToVisit = new List<InterfaceType>(); |
| 1029 List<ClassElement> visitedClasses = new List<ClassElement>(); |
| 1030 typesToVisit.add(this.type); |
| 1031 while (!typesToVisit.isEmpty) { |
| 1032 InterfaceType currentType = typesToVisit.removeAt(0); |
| 1033 ClassElement currentElement = currentType.element; |
| 1034 if (!visitedClasses.contains(currentElement)) { |
| 1035 visitedClasses.add(currentElement); |
| 1036 if (!identical(currentType, this.type)) { |
| 1037 supertypes.add(currentType); |
| 1038 } |
| 1039 InterfaceType supertype = currentType.superclass; |
| 1040 if (supertype != null) { |
| 1041 typesToVisit.add(supertype); |
| 1042 } |
| 1043 for (InterfaceType type in currentElement.interfaces) { |
| 1044 typesToVisit.add(type); |
| 1045 } |
| 1046 for (InterfaceType type in currentElement.mixins) { |
| 1047 ClassElement element = type.element; |
| 1048 if (!visitedClasses.contains(element)) { |
| 1049 supertypes.add(type); |
| 1050 } |
| 1051 } |
| 1052 } |
| 1053 } |
| 1054 } |
| 1055 |
| 1056 /** |
| 1057 * Compute a list of constructors for this class, which is a mixin |
| 1058 * application. If specified, [visitedClasses] is a list of the other mixin |
| 1059 * application classes which have been visited on the way to reaching this |
| 1060 * one (this is used to detect circularities). |
| 1061 */ |
| 1062 List<ConstructorElement> _computeMixinAppConstructors( |
| 1063 [List<ClassElementImpl> visitedClasses = null]) { |
| 1064 // First get the list of constructors of the superclass which need to be |
| 1065 // forwarded to this class. |
| 1066 Iterable<ConstructorElement> constructorsToForward; |
| 1067 if (supertype == null) { |
| 1068 // Shouldn't ever happen, since the only class with no supertype is |
| 1069 // Object, and it isn't a mixin application. But for safety's sake just |
| 1070 // assume an empty list. |
| 1071 assert(false); |
| 1072 constructorsToForward = <ConstructorElement>[]; |
| 1073 } else if (!supertype.element.isMixinApplication) { |
| 1074 List<ConstructorElement> superclassConstructors = |
| 1075 supertype.element.constructors; |
| 1076 // Filter out any constructors with optional parameters (see |
| 1077 // dartbug.com/15101). |
| 1078 constructorsToForward = |
| 1079 superclassConstructors.where(isSuperConstructorAccessible); |
| 1080 } else { |
| 1081 if (visitedClasses == null) { |
| 1082 visitedClasses = <ClassElementImpl>[this]; |
| 1083 } else { |
| 1084 if (visitedClasses.contains(this)) { |
| 1085 // Loop in the class hierarchy. Don't try to forward any |
| 1086 // constructors. |
| 1087 return <ConstructorElement>[]; |
| 1088 } |
| 1089 visitedClasses.add(this); |
| 1090 } |
| 1091 try { |
| 1092 ClassElementImpl superclass = supertype.element; |
| 1093 constructorsToForward = |
| 1094 superclass._computeMixinAppConstructors(visitedClasses); |
| 1095 } finally { |
| 1096 visitedClasses.removeLast(); |
| 1097 } |
| 1098 } |
| 1099 |
| 1100 // Figure out the type parameter substitution we need to perform in order |
| 1101 // to produce constructors for this class. We want to be robust in the |
| 1102 // face of errors, so drop any extra type arguments and fill in any missing |
| 1103 // ones with `dynamic`. |
| 1104 List<DartType> parameterTypes = |
| 1105 TypeParameterTypeImpl.getTypes(supertype.typeParameters); |
| 1106 List<DartType> argumentTypes = new List<DartType>.filled( |
| 1107 parameterTypes.length, DynamicTypeImpl.instance); |
| 1108 for (int i = 0; i < supertype.typeArguments.length; i++) { |
| 1109 if (i >= argumentTypes.length) { |
| 1110 break; |
| 1111 } |
| 1112 argumentTypes[i] = supertype.typeArguments[i]; |
| 1113 } |
| 1114 |
| 1115 // Now create an implicit constructor for every constructor found above, |
| 1116 // substituting type parameters as appropriate. |
| 1117 return constructorsToForward |
| 1118 .map((ConstructorElement superclassConstructor) { |
| 1119 ConstructorElementImpl implicitConstructor = |
| 1120 new ConstructorElementImpl(superclassConstructor.name, -1); |
| 1121 implicitConstructor.synthetic = true; |
| 1122 implicitConstructor.redirectedConstructor = superclassConstructor; |
| 1123 implicitConstructor.const2 = superclassConstructor.isConst; |
| 1124 implicitConstructor.returnType = type; |
| 1125 List<ParameterElement> superParameters = superclassConstructor.parameters; |
| 1126 int count = superParameters.length; |
| 1127 if (count > 0) { |
| 1128 List<ParameterElement> implicitParameters = |
| 1129 new List<ParameterElement>(count); |
| 1130 for (int i = 0; i < count; i++) { |
| 1131 ParameterElement superParameter = superParameters[i]; |
| 1132 ParameterElementImpl implicitParameter = |
| 1133 new ParameterElementImpl(superParameter.name, -1); |
| 1134 implicitParameter.const3 = superParameter.isConst; |
| 1135 implicitParameter.final2 = superParameter.isFinal; |
| 1136 implicitParameter.parameterKind = superParameter.parameterKind; |
| 1137 implicitParameter.synthetic = true; |
| 1138 implicitParameter.type = |
| 1139 superParameter.type.substitute2(argumentTypes, parameterTypes); |
| 1140 implicitParameters[i] = implicitParameter; |
| 1141 } |
| 1142 implicitConstructor.parameters = implicitParameters; |
| 1143 } |
| 1144 FunctionTypeImpl constructorType = |
| 1145 new FunctionTypeImpl(implicitConstructor); |
| 1146 constructorType.typeArguments = type.typeArguments; |
| 1147 implicitConstructor.type = constructorType; |
| 1148 implicitConstructor.enclosingElement = this; |
| 1149 return implicitConstructor; |
| 1150 }).toList(); |
| 1151 } |
| 1152 |
| 1153 PropertyAccessorElement _internalLookUpConcreteGetter( |
| 1154 String getterName, LibraryElement library, bool includeThisClass) { |
| 1155 PropertyAccessorElement getter = |
| 1156 _internalLookUpGetter(getterName, library, includeThisClass); |
| 1157 while (getter != null && getter.isAbstract) { |
| 1158 Element definingClass = getter.enclosingElement; |
| 1159 if (definingClass is! ClassElementImpl) { |
| 1160 return null; |
| 1161 } |
| 1162 getter = (definingClass as ClassElementImpl) |
| 1163 ._internalLookUpGetter(getterName, library, false); |
| 1164 } |
| 1165 return getter; |
| 1166 } |
| 1167 |
| 1168 MethodElement _internalLookUpConcreteMethod( |
| 1169 String methodName, LibraryElement library, bool includeThisClass) { |
| 1170 MethodElement method = |
| 1171 _internalLookUpMethod(methodName, library, includeThisClass); |
| 1172 while (method != null && method.isAbstract) { |
| 1173 ClassElement definingClass = method.enclosingElement; |
| 1174 if (definingClass == null) { |
| 1175 return null; |
| 1176 } |
| 1177 method = definingClass.lookUpInheritedMethod(methodName, library); |
| 1178 } |
| 1179 return method; |
| 1180 } |
| 1181 |
| 1182 PropertyAccessorElement _internalLookUpConcreteSetter( |
| 1183 String setterName, LibraryElement library, bool includeThisClass) { |
| 1184 PropertyAccessorElement setter = |
| 1185 _internalLookUpSetter(setterName, library, includeThisClass); |
| 1186 while (setter != null && setter.isAbstract) { |
| 1187 Element definingClass = setter.enclosingElement; |
| 1188 if (definingClass is! ClassElementImpl) { |
| 1189 return null; |
| 1190 } |
| 1191 setter = (definingClass as ClassElementImpl) |
| 1192 ._internalLookUpSetter(setterName, library, false); |
| 1193 } |
| 1194 return setter; |
| 1195 } |
| 1196 |
| 1197 PropertyAccessorElement _internalLookUpGetter( |
| 1198 String getterName, LibraryElement library, bool includeThisClass) { |
| 1199 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1200 ClassElement currentElement = this; |
| 1201 if (includeThisClass) { |
| 1202 PropertyAccessorElement element = currentElement.getGetter(getterName); |
| 1203 if (element != null && element.isAccessibleIn(library)) { |
| 1204 return element; |
| 1205 } |
| 1206 } |
| 1207 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1208 for (InterfaceType mixin in currentElement.mixins.reversed) { |
| 1209 ClassElement mixinElement = mixin.element; |
| 1210 if (mixinElement != null) { |
| 1211 PropertyAccessorElement element = mixinElement.getGetter(getterName); |
| 1212 if (element != null && element.isAccessibleIn(library)) { |
| 1213 return element; |
| 1214 } |
| 1215 } |
| 1216 } |
| 1217 InterfaceType supertype = currentElement.supertype; |
| 1218 if (supertype == null) { |
| 1219 return null; |
| 1220 } |
| 1221 currentElement = supertype.element; |
| 1222 PropertyAccessorElement element = currentElement.getGetter(getterName); |
| 1223 if (element != null && element.isAccessibleIn(library)) { |
| 1224 return element; |
| 1225 } |
| 1226 } |
| 1227 return null; |
| 1228 } |
| 1229 |
| 1230 MethodElement _internalLookUpMethod( |
| 1231 String methodName, LibraryElement library, bool includeThisClass) { |
| 1232 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1233 ClassElement currentElement = this; |
| 1234 if (includeThisClass) { |
| 1235 MethodElement element = currentElement.getMethod(methodName); |
| 1236 if (element != null && element.isAccessibleIn(library)) { |
| 1237 return element; |
| 1238 } |
| 1239 } |
| 1240 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1241 for (InterfaceType mixin in currentElement.mixins.reversed) { |
| 1242 ClassElement mixinElement = mixin.element; |
| 1243 if (mixinElement != null) { |
| 1244 MethodElement element = mixinElement.getMethod(methodName); |
| 1245 if (element != null && element.isAccessibleIn(library)) { |
| 1246 return element; |
| 1247 } |
| 1248 } |
| 1249 } |
| 1250 InterfaceType supertype = currentElement.supertype; |
| 1251 if (supertype == null) { |
| 1252 return null; |
| 1253 } |
| 1254 currentElement = supertype.element; |
| 1255 MethodElement element = currentElement.getMethod(methodName); |
| 1256 if (element != null && element.isAccessibleIn(library)) { |
| 1257 return element; |
| 1258 } |
| 1259 } |
| 1260 return null; |
| 1261 } |
| 1262 |
| 1263 PropertyAccessorElement _internalLookUpSetter( |
| 1264 String setterName, LibraryElement library, bool includeThisClass) { |
| 1265 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 1266 ClassElement currentElement = this; |
| 1267 if (includeThisClass) { |
| 1268 PropertyAccessorElement element = currentElement.getSetter(setterName); |
| 1269 if (element != null && element.isAccessibleIn(library)) { |
| 1270 return element; |
| 1271 } |
| 1272 } |
| 1273 while (currentElement != null && visitedClasses.add(currentElement)) { |
| 1274 for (InterfaceType mixin in currentElement.mixins.reversed) { |
| 1275 ClassElement mixinElement = mixin.element; |
| 1276 if (mixinElement != null) { |
| 1277 PropertyAccessorElement element = mixinElement.getSetter(setterName); |
| 1278 if (element != null && element.isAccessibleIn(library)) { |
| 1279 return element; |
| 1280 } |
| 1281 } |
| 1282 } |
| 1283 InterfaceType supertype = currentElement.supertype; |
| 1284 if (supertype == null) { |
| 1285 return null; |
| 1286 } |
| 1287 currentElement = supertype.element; |
| 1288 PropertyAccessorElement element = currentElement.getSetter(setterName); |
| 1289 if (element != null && element.isAccessibleIn(library)) { |
| 1290 return element; |
| 1291 } |
| 1292 } |
| 1293 return null; |
| 1294 } |
| 1295 |
| 1296 bool _safeIsOrInheritsProxy( |
| 1297 ClassElement classElt, HashSet<ClassElement> visitedClassElts) { |
| 1298 if (visitedClassElts.contains(classElt)) { |
| 1299 return false; |
| 1300 } |
| 1301 visitedClassElts.add(classElt); |
| 1302 if (classElt.isProxy) { |
| 1303 return true; |
| 1304 } else if (classElt.supertype != null && |
| 1305 _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { |
| 1306 return true; |
| 1307 } |
| 1308 List<InterfaceType> supertypes = classElt.interfaces; |
| 1309 for (int i = 0; i < supertypes.length; i++) { |
| 1310 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| 1311 return true; |
| 1312 } |
| 1313 } |
| 1314 supertypes = classElt.mixins; |
| 1315 for (int i = 0; i < supertypes.length; i++) { |
| 1316 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { |
| 1317 return true; |
| 1318 } |
| 1319 } |
| 1320 return false; |
| 1321 } |
| 1322 } |
| 1323 |
| 1324 /** |
| 1325 * An element that is contained within a [ClassElement]. |
| 1326 */ |
| 1327 abstract class ClassMemberElement implements Element { |
| 1328 /** |
| 1329 * Return the type in which this member is defined. |
| 1330 */ |
| 1331 @override |
| 1332 ClassElement get enclosingElement; |
| 1333 |
| 1334 /** |
| 1335 * Return `true` if this element is a static element. A static element is an |
| 1336 * element that is not associated with a particular instance, but rather with |
| 1337 * an entire library or class. |
| 1338 */ |
| 1339 bool get isStatic; |
| 1340 } |
| 1341 |
| 1342 /** |
| 1343 * An element representing a compilation unit. |
| 1344 */ |
| 1345 abstract class CompilationUnitElement implements Element, UriReferencedElement { |
| 1346 /** |
| 1347 * An empty list of compilation unit elements. |
| 1348 */ |
| 1349 static const List<CompilationUnitElement> EMPTY_LIST = |
| 1350 const <CompilationUnitElement>[]; |
| 1351 |
| 1352 /** |
| 1353 * Return a list containing all of the top-level accessors (getters and |
| 1354 * setters) contained in this compilation unit. |
| 1355 */ |
| 1356 List<PropertyAccessorElement> get accessors; |
| 1357 |
| 1358 /** |
| 1359 * Return the library in which this compilation unit is defined. |
| 1360 */ |
| 1361 @override |
| 1362 LibraryElement get enclosingElement; |
| 1363 |
| 1364 /** |
| 1365 * Return a list containing all of the enums contained in this compilation |
| 1366 * unit. |
| 1367 */ |
| 1368 List<ClassElement> get enums; |
| 1369 |
| 1370 /** |
| 1371 * Return a list containing all of the top-level functions contained in this |
| 1372 * compilation unit. |
| 1373 */ |
| 1374 List<FunctionElement> get functions; |
| 1375 |
| 1376 /** |
| 1377 * Return a list containing all of the function type aliases contained in this |
| 1378 * compilation unit. |
| 1379 */ |
| 1380 List<FunctionTypeAliasElement> get functionTypeAliases; |
| 1381 |
| 1382 /** |
| 1383 * Return `true` if this compilation unit defines a top-level function named |
| 1384 * `loadLibrary`. |
| 1385 */ |
| 1386 bool get hasLoadLibraryFunction; |
| 1387 |
| 1388 /** |
| 1389 * Return a list containing all of the top-level variables contained in this |
| 1390 * compilation unit. |
| 1391 */ |
| 1392 List<TopLevelVariableElement> get topLevelVariables; |
| 1393 |
| 1394 /** |
| 1395 * Return a list containing all of the classes contained in this compilation |
| 1396 * unit. |
| 1397 */ |
| 1398 List<ClassElement> get types; |
| 1399 |
| 1400 /** |
| 1401 * Return the resolved [CompilationUnit] node that declares this element. |
| 1402 * |
| 1403 * This method is expensive, because resolved AST might be evicted from cache, |
| 1404 * so parsing and resolving will be performed. |
| 1405 */ |
| 1406 @override |
| 1407 CompilationUnit computeNode(); |
| 1408 |
| 1409 /** |
| 1410 * Return the element at the given [offset], maybe `null` if no such element. |
| 1411 */ |
| 1412 Element getElementAt(int offset); |
| 1413 |
| 1414 /** |
| 1415 * Return the enum defined in this compilation unit that has the given [name], |
| 1416 * or `null` if this compilation unit does not define an enum with the given |
| 1417 * name. |
| 1418 */ |
| 1419 ClassElement getEnum(String name); |
| 1420 |
| 1421 /** |
| 1422 * Return the class defined in this compilation unit that has the given |
| 1423 * [name], or `null` if this compilation unit does not define a class with the |
| 1424 * given name. |
| 1425 */ |
| 1426 ClassElement getType(String name); |
| 1427 } |
| 1428 |
| 1429 /** |
| 1430 * A concrete implementation of a [CompilationUnitElement]. |
| 1431 */ |
| 1432 class CompilationUnitElementImpl extends UriReferencedElementImpl |
| 1433 implements CompilationUnitElement { |
| 1434 /** |
| 1435 * An empty list of compilation unit elements. |
| 1436 */ |
| 1437 @deprecated // Use CompilationUnitElement.EMPTY_LIST |
| 1438 static const List<CompilationUnitElement> EMPTY_ARRAY = |
| 1439 const <CompilationUnitElement>[]; |
| 1440 |
| 1441 /** |
| 1442 * The source that corresponds to this compilation unit. |
| 1443 */ |
| 1444 Source source; |
| 1445 |
| 1446 /** |
| 1447 * The source of the library containing this compilation unit. |
| 1448 * |
| 1449 * This is the same as the source of the containing [LibraryElement], |
| 1450 * except that it does not require the containing [LibraryElement] to be |
| 1451 * computed. |
| 1452 */ |
| 1453 Source librarySource; |
| 1454 |
| 1455 /** |
| 1456 * A list containing all of the top-level accessors (getters and setters) |
| 1457 * contained in this compilation unit. |
| 1458 */ |
| 1459 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; |
| 1460 |
| 1461 /** |
| 1462 * A list containing all of the enums contained in this compilation unit. |
| 1463 */ |
| 1464 List<ClassElement> _enums = ClassElement.EMPTY_LIST; |
| 1465 |
| 1466 /** |
| 1467 * A list containing all of the top-level functions contained in this |
| 1468 * compilation unit. |
| 1469 */ |
| 1470 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; |
| 1471 |
| 1472 /** |
| 1473 * A list containing all of the function type aliases contained in this |
| 1474 * compilation unit. |
| 1475 */ |
| 1476 List<FunctionTypeAliasElement> _typeAliases = |
| 1477 FunctionTypeAliasElement.EMPTY_LIST; |
| 1478 |
| 1479 /** |
| 1480 * A list containing all of the types contained in this compilation unit. |
| 1481 */ |
| 1482 List<ClassElement> _types = ClassElement.EMPTY_LIST; |
| 1483 |
| 1484 /** |
| 1485 * A list containing all of the variables contained in this compilation unit. |
| 1486 */ |
| 1487 List<TopLevelVariableElement> _variables = TopLevelVariableElement.EMPTY_LIST; |
| 1488 |
| 1489 /** |
| 1490 * A map from offsets to elements of this unit at these offsets. |
| 1491 */ |
| 1492 final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>(); |
| 1493 |
| 1494 /** |
| 1495 * Initialize a newly created compilation unit element to have the given |
| 1496 * [name]. |
| 1497 */ |
| 1498 CompilationUnitElementImpl(String name) : super(name, -1); |
| 1499 |
| 1500 @override |
| 1501 List<PropertyAccessorElement> get accessors => _accessors; |
| 1502 |
| 1503 /** |
| 1504 * Set the top-level accessors (getters and setters) contained in this |
| 1505 * compilation unit to the given [accessors]. |
| 1506 */ |
| 1507 void set accessors(List<PropertyAccessorElement> accessors) { |
| 1508 for (PropertyAccessorElement accessor in accessors) { |
| 1509 (accessor as PropertyAccessorElementImpl).enclosingElement = this; |
| 1510 } |
| 1511 this._accessors = accessors; |
| 1512 } |
| 1513 |
| 1514 @override |
| 1515 LibraryElement get enclosingElement => |
| 1516 super.enclosingElement as LibraryElement; |
| 1517 |
| 1518 @override |
| 1519 List<ClassElement> get enums => _enums; |
| 1520 |
| 1521 /** |
| 1522 * Set the enums contained in this compilation unit to the given [enums]. |
| 1523 */ |
| 1524 void set enums(List<ClassElement> enums) { |
| 1525 for (ClassElement enumDeclaration in enums) { |
| 1526 (enumDeclaration as ClassElementImpl).enclosingElement = this; |
| 1527 } |
| 1528 this._enums = enums; |
| 1529 } |
| 1530 |
| 1531 @override |
| 1532 List<FunctionElement> get functions => _functions; |
| 1533 |
| 1534 /** |
| 1535 * Set the top-level functions contained in this compilation unit to the given |
| 1536 * [functions]. |
| 1537 */ |
| 1538 void set functions(List<FunctionElement> functions) { |
| 1539 for (FunctionElement function in functions) { |
| 1540 (function as FunctionElementImpl).enclosingElement = this; |
| 1541 } |
| 1542 this._functions = functions; |
| 1543 } |
| 1544 |
| 1545 @override |
| 1546 List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases; |
| 1547 |
| 1548 @override |
| 1549 int get hashCode => source.hashCode; |
| 1550 |
| 1551 @override |
| 1552 bool get hasLoadLibraryFunction { |
| 1553 for (int i = 0; i < _functions.length; i++) { |
| 1554 if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) { |
| 1555 return true; |
| 1556 } |
| 1557 } |
| 1558 return false; |
| 1559 } |
| 1560 |
| 1561 @override |
| 1562 String get identifier => source.encoding; |
| 1563 |
| 1564 @override |
| 1565 ElementKind get kind => ElementKind.COMPILATION_UNIT; |
| 1566 |
| 1567 @override |
| 1568 List<TopLevelVariableElement> get topLevelVariables => _variables; |
| 1569 |
| 1570 /** |
| 1571 * Set the top-level variables contained in this compilation unit to the given |
| 1572 * [variables]. |
| 1573 */ |
| 1574 void set topLevelVariables(List<TopLevelVariableElement> variables) { |
| 1575 for (TopLevelVariableElement field in variables) { |
| 1576 (field as TopLevelVariableElementImpl).enclosingElement = this; |
| 1577 } |
| 1578 this._variables = variables; |
| 1579 } |
| 1580 |
| 1581 /** |
| 1582 * Set the function type aliases contained in this compilation unit to the |
| 1583 * given [typeAliases]. |
| 1584 */ |
| 1585 void set typeAliases(List<FunctionTypeAliasElement> typeAliases) { |
| 1586 for (FunctionTypeAliasElement typeAlias in typeAliases) { |
| 1587 (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this; |
| 1588 } |
| 1589 this._typeAliases = typeAliases; |
| 1590 } |
| 1591 |
| 1592 @override |
| 1593 List<ClassElement> get types => _types; |
| 1594 |
| 1595 /** |
| 1596 * Set the types contained in this compilation unit to the given [types]. |
| 1597 */ |
| 1598 void set types(List<ClassElement> types) { |
| 1599 for (ClassElement type in types) { |
| 1600 (type as ClassElementImpl).enclosingElement = this; |
| 1601 } |
| 1602 this._types = types; |
| 1603 } |
| 1604 |
| 1605 @override |
| 1606 bool operator ==(Object object) => |
| 1607 object is CompilationUnitElementImpl && source == object.source; |
| 1608 |
| 1609 @override |
| 1610 accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this); |
| 1611 |
| 1612 /** |
| 1613 * This method is invoked after this unit was incrementally resolved. |
| 1614 */ |
| 1615 void afterIncrementalResolution() { |
| 1616 _offsetToElementMap.clear(); |
| 1617 } |
| 1618 |
| 1619 @override |
| 1620 void appendTo(StringBuffer buffer) { |
| 1621 if (source == null) { |
| 1622 buffer.write("{compilation unit}"); |
| 1623 } else { |
| 1624 buffer.write(source.fullName); |
| 1625 } |
| 1626 } |
| 1627 |
| 1628 @override |
| 1629 CompilationUnit computeNode() => unit; |
| 1630 |
| 1631 @override |
| 1632 ElementImpl getChild(String identifier) { |
| 1633 // |
| 1634 // The casts in this method are safe because the set methods would have |
| 1635 // thrown a CCE if any of the elements in the arrays were not of the |
| 1636 // expected types. |
| 1637 // |
| 1638 for (PropertyAccessorElement accessor in _accessors) { |
| 1639 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { |
| 1640 return accessor as PropertyAccessorElementImpl; |
| 1641 } |
| 1642 } |
| 1643 for (VariableElement variable in _variables) { |
| 1644 if ((variable as VariableElementImpl).identifier == identifier) { |
| 1645 return variable as VariableElementImpl; |
| 1646 } |
| 1647 } |
| 1648 for (ExecutableElement function in _functions) { |
| 1649 if ((function as ExecutableElementImpl).identifier == identifier) { |
| 1650 return function as ExecutableElementImpl; |
| 1651 } |
| 1652 } |
| 1653 for (FunctionTypeAliasElement typeAlias in _typeAliases) { |
| 1654 if ((typeAlias as FunctionTypeAliasElementImpl).identifier == |
| 1655 identifier) { |
| 1656 return typeAlias as FunctionTypeAliasElementImpl; |
| 1657 } |
| 1658 } |
| 1659 for (ClassElement type in _types) { |
| 1660 if ((type as ClassElementImpl).identifier == identifier) { |
| 1661 return type as ClassElementImpl; |
| 1662 } |
| 1663 } |
| 1664 for (ClassElement type in _enums) { |
| 1665 if ((type as ClassElementImpl).identifier == identifier) { |
| 1666 return type as ClassElementImpl; |
| 1667 } |
| 1668 } |
| 1669 return null; |
| 1670 } |
| 1671 |
| 1672 @override |
| 1673 Element getElementAt(int offset) { |
| 1674 if (_offsetToElementMap.isEmpty) { |
| 1675 accept(new _BuildOffsetToElementMap(_offsetToElementMap)); |
| 1676 } |
| 1677 return _offsetToElementMap[offset]; |
| 1678 } |
| 1679 |
| 1680 @override |
| 1681 ClassElement getEnum(String enumName) { |
| 1682 for (ClassElement enumDeclaration in _enums) { |
| 1683 if (enumDeclaration.name == enumName) { |
| 1684 return enumDeclaration; |
| 1685 } |
| 1686 } |
| 1687 return null; |
| 1688 } |
| 1689 |
| 1690 @override |
| 1691 ClassElement getType(String className) { |
| 1692 for (ClassElement type in _types) { |
| 1693 if (type.name == className) { |
| 1694 return type; |
| 1695 } |
| 1696 } |
| 1697 return null; |
| 1698 } |
| 1699 |
| 1700 /** |
| 1701 * Replace the given [from] top-level variable with [to] in this compilation u
nit. |
| 1702 */ |
| 1703 void replaceTopLevelVariable( |
| 1704 TopLevelVariableElement from, TopLevelVariableElement to) { |
| 1705 int index = _variables.indexOf(from); |
| 1706 _variables[index] = to; |
| 1707 } |
| 1708 |
| 1709 @override |
| 1710 void visitChildren(ElementVisitor visitor) { |
| 1711 super.visitChildren(visitor); |
| 1712 safelyVisitChildren(_accessors, visitor); |
| 1713 safelyVisitChildren(_enums, visitor); |
| 1714 safelyVisitChildren(_functions, visitor); |
| 1715 safelyVisitChildren(_typeAliases, visitor); |
| 1716 safelyVisitChildren(_types, visitor); |
| 1717 safelyVisitChildren(_variables, visitor); |
| 1718 } |
| 1719 } |
| 1720 |
| 1721 /** |
| 1722 * A [FieldElement] for a 'const' or 'final' field that has an initializer. |
| 1723 * |
| 1724 * TODO(paulberry): we should rename this class to reflect the fact that it's |
| 1725 * used for both const and final fields. However, we shouldn't do so until |
| 1726 * we've created an API for reading the values of constants; until that API is |
| 1727 * available, clients are likely to read constant values by casting to |
| 1728 * ConstFieldElementImpl, so it would be a breaking change to rename this |
| 1729 * class. |
| 1730 */ |
| 1731 class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement { |
| 1732 /** |
| 1733 * The result of evaluating this variable's initializer. |
| 1734 */ |
| 1735 EvaluationResultImpl _result; |
| 1736 |
| 1737 /** |
| 1738 * Initialize a newly created synthetic field element to have the given |
| 1739 * [name] and [offset]. |
| 1740 */ |
| 1741 ConstFieldElementImpl(String name, int offset) : super(name, offset); |
| 1742 |
| 1743 /** |
| 1744 * Initialize a newly created field element to have the given [name]. |
| 1745 */ |
| 1746 @deprecated // Use new ConstFieldElementImpl.forNode(name) |
| 1747 ConstFieldElementImpl.con1(Identifier name) : super.forNode(name); |
| 1748 |
| 1749 /** |
| 1750 * Initialize a newly created synthetic field element to have the given |
| 1751 * [name] and [offset]. |
| 1752 */ |
| 1753 @deprecated // Use new ConstFieldElementImpl(name, offset) |
| 1754 ConstFieldElementImpl.con2(String name, int offset) : super(name, offset); |
| 1755 |
| 1756 /** |
| 1757 * Initialize a newly created field element to have the given [name]. |
| 1758 */ |
| 1759 ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name); |
| 1760 |
| 1761 @override |
| 1762 EvaluationResultImpl get evaluationResult => _result; |
| 1763 |
| 1764 @override |
| 1765 void set evaluationResult(EvaluationResultImpl result) { |
| 1766 this._result = result; |
| 1767 } |
| 1768 } |
| 1769 |
| 1770 /** |
| 1771 * A [LocalVariableElement] for a local 'const' variable that has an |
| 1772 * initializer. |
| 1773 */ |
| 1774 class ConstLocalVariableElementImpl extends LocalVariableElementImpl |
| 1775 with ConstVariableElement { |
| 1776 /** |
| 1777 * The result of evaluating this variable's initializer. |
| 1778 */ |
| 1779 EvaluationResultImpl _result; |
| 1780 |
| 1781 /** |
| 1782 * Initialize a newly created local variable element to have the given [name] |
| 1783 * and [offset]. |
| 1784 */ |
| 1785 ConstLocalVariableElementImpl(String name, int offset) : super(name, offset); |
| 1786 |
| 1787 /** |
| 1788 * Initialize a newly created local variable element to have the given [name]. |
| 1789 */ |
| 1790 ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 1791 |
| 1792 @override |
| 1793 EvaluationResultImpl get evaluationResult => _result; |
| 1794 |
| 1795 @override |
| 1796 void set evaluationResult(EvaluationResultImpl result) { |
| 1797 this._result = result; |
| 1798 } |
| 1799 } |
| 1800 |
| 1801 /** |
| 1802 * An element representing a constructor or a factory method defined within a |
| 1803 * class. |
| 1804 */ |
| 1805 abstract class ConstructorElement |
| 1806 implements ClassMemberElement, ExecutableElement, ConstantEvaluationTarget { |
| 1807 /** |
| 1808 * An empty list of constructor elements. |
| 1809 */ |
| 1810 static const List<ConstructorElement> EMPTY_LIST = |
| 1811 const <ConstructorElement>[]; |
| 1812 |
| 1813 /** |
| 1814 * Return `true` if this constructor is a const constructor. |
| 1815 */ |
| 1816 bool get isConst; |
| 1817 |
| 1818 /** |
| 1819 * Return `true` if this constructor can be used as a default constructor - |
| 1820 * unnamed and has no required parameters. |
| 1821 */ |
| 1822 bool get isDefaultConstructor; |
| 1823 |
| 1824 /** |
| 1825 * Return `true` if this constructor represents a factory constructor. |
| 1826 */ |
| 1827 bool get isFactory; |
| 1828 |
| 1829 /** |
| 1830 * Return the offset of the character immediately following the last character |
| 1831 * of this constructor's name, or `null` if not named. |
| 1832 */ |
| 1833 int get nameEnd; |
| 1834 |
| 1835 /** |
| 1836 * Return the offset of the `.` before this constructor name, or `null` if |
| 1837 * not named. |
| 1838 */ |
| 1839 int get periodOffset; |
| 1840 |
| 1841 /** |
| 1842 * Return the constructor to which this constructor is redirecting, or `null` |
| 1843 * if this constructor does not redirect to another constructor or if the |
| 1844 * library containing this constructor has not yet been resolved. |
| 1845 */ |
| 1846 ConstructorElement get redirectedConstructor; |
| 1847 |
| 1848 /** |
| 1849 * Return the resolved [ConstructorDeclaration] node that declares this |
| 1850 * [ConstructorElement] . |
| 1851 * |
| 1852 * This method is expensive, because resolved AST might be evicted from cache, |
| 1853 * so parsing and resolving will be performed. |
| 1854 */ |
| 1855 @override |
| 1856 ConstructorDeclaration computeNode(); |
| 1857 } |
| 1858 |
| 1859 /** |
| 1860 * A concrete implementation of a [ConstructorElement]. |
| 1861 */ |
| 1862 class ConstructorElementImpl extends ExecutableElementImpl |
| 1863 implements ConstructorElement { |
| 1864 /** |
| 1865 * An empty list of constructor elements. |
| 1866 */ |
| 1867 @deprecated // Use ConstructorElement.EMPTY_LIST |
| 1868 static const List<ConstructorElement> EMPTY_ARRAY = |
| 1869 const <ConstructorElement>[]; |
| 1870 |
| 1871 /** |
| 1872 * The constructor to which this constructor is redirecting. |
| 1873 */ |
| 1874 ConstructorElement redirectedConstructor; |
| 1875 |
| 1876 /** |
| 1877 * The initializers for this constructor (used for evaluating constant |
| 1878 * instance creation expressions). |
| 1879 */ |
| 1880 List<ConstructorInitializer> constantInitializers; |
| 1881 |
| 1882 /** |
| 1883 * The offset of the `.` before this constructor name or `null` if not named. |
| 1884 */ |
| 1885 int periodOffset; |
| 1886 |
| 1887 /** |
| 1888 * Return the offset of the character immediately following the last character |
| 1889 * of this constructor's name, or `null` if not named. |
| 1890 */ |
| 1891 int nameEnd; |
| 1892 |
| 1893 /** |
| 1894 * True if this constructor has been found by constant evaluation to be free |
| 1895 * of redirect cycles, and is thus safe to evaluate. |
| 1896 */ |
| 1897 bool isCycleFree = false; |
| 1898 |
| 1899 /** |
| 1900 * Initialize a newly created constructor element to have the given [name] and |
| 1901 * [offset]. |
| 1902 */ |
| 1903 ConstructorElementImpl(String name, int offset) : super(name, offset); |
| 1904 |
| 1905 /** |
| 1906 * Initialize a newly created constructor element to have the given [name]. |
| 1907 */ |
| 1908 ConstructorElementImpl.forNode(Identifier name) : super.forNode(name); |
| 1909 |
| 1910 /** |
| 1911 * Set whether this constructor represents a 'const' constructor. |
| 1912 */ |
| 1913 void set const2(bool isConst) { |
| 1914 setModifier(Modifier.CONST, isConst); |
| 1915 } |
| 1916 |
| 1917 @override |
| 1918 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 1919 |
| 1920 /** |
| 1921 * Set whether this constructor represents a factory method. |
| 1922 */ |
| 1923 void set factory(bool isFactory) { |
| 1924 setModifier(Modifier.FACTORY, isFactory); |
| 1925 } |
| 1926 |
| 1927 @override |
| 1928 bool get isConst => hasModifier(Modifier.CONST); |
| 1929 |
| 1930 @override |
| 1931 bool get isDefaultConstructor { |
| 1932 // unnamed |
| 1933 String name = this.name; |
| 1934 if (name != null && name.length != 0) { |
| 1935 return false; |
| 1936 } |
| 1937 // no required parameters |
| 1938 for (ParameterElement parameter in parameters) { |
| 1939 if (parameter.parameterKind == ParameterKind.REQUIRED) { |
| 1940 return false; |
| 1941 } |
| 1942 } |
| 1943 // OK, can be used as default constructor |
| 1944 return true; |
| 1945 } |
| 1946 |
| 1947 @override |
| 1948 bool get isFactory => hasModifier(Modifier.FACTORY); |
| 1949 |
| 1950 @override |
| 1951 bool get isStatic => false; |
| 1952 |
| 1953 @override |
| 1954 ElementKind get kind => ElementKind.CONSTRUCTOR; |
| 1955 |
| 1956 @override |
| 1957 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); |
| 1958 |
| 1959 @override |
| 1960 void appendTo(StringBuffer buffer) { |
| 1961 if (enclosingElement == null) { |
| 1962 String message; |
| 1963 String name = displayName; |
| 1964 if (name != null && !name.isEmpty) { |
| 1965 message = |
| 1966 'Found constructor element named $name with no enclosing element'; |
| 1967 } else { |
| 1968 message = 'Found unnamed constructor element with no enclosing element'; |
| 1969 } |
| 1970 AnalysisEngine.instance.logger.logError(message); |
| 1971 buffer.write('<unknown class>'); |
| 1972 } else { |
| 1973 buffer.write(enclosingElement.displayName); |
| 1974 } |
| 1975 String name = displayName; |
| 1976 if (name != null && !name.isEmpty) { |
| 1977 buffer.write("."); |
| 1978 buffer.write(name); |
| 1979 } |
| 1980 super.appendTo(buffer); |
| 1981 } |
| 1982 |
| 1983 @override |
| 1984 ConstructorDeclaration computeNode() => |
| 1985 getNodeMatching((node) => node is ConstructorDeclaration); |
| 1986 } |
| 1987 |
| 1988 /** |
| 1989 * A constructor element defined in a parameterized type where the values of the |
| 1990 * type parameters are known. |
| 1991 */ |
| 1992 class ConstructorMember extends ExecutableMember implements ConstructorElement { |
| 1993 /** |
| 1994 * Initialize a newly created element to represent a constructor, based on the |
| 1995 * [baseElement], defined by the [definingType]. |
| 1996 */ |
| 1997 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType) |
| 1998 : super(baseElement, definingType); |
| 1999 |
| 2000 @override |
| 2001 ConstructorElement get baseElement => super.baseElement as ConstructorElement; |
| 2002 |
| 2003 @override |
| 2004 InterfaceType get definingType => super.definingType as InterfaceType; |
| 2005 |
| 2006 @override |
| 2007 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 2008 |
| 2009 @override |
| 2010 bool get isConst => baseElement.isConst; |
| 2011 |
| 2012 @override |
| 2013 bool get isDefaultConstructor => baseElement.isDefaultConstructor; |
| 2014 |
| 2015 @override |
| 2016 bool get isFactory => baseElement.isFactory; |
| 2017 |
| 2018 @override |
| 2019 int get nameEnd => baseElement.nameEnd; |
| 2020 |
| 2021 @override |
| 2022 int get periodOffset => baseElement.periodOffset; |
| 2023 |
| 2024 @override |
| 2025 ConstructorElement get redirectedConstructor => |
| 2026 from(baseElement.redirectedConstructor, definingType); |
| 2027 |
| 2028 @override |
| 2029 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); |
| 2030 |
| 2031 @override |
| 2032 ConstructorDeclaration computeNode() => baseElement.computeNode(); |
| 2033 |
| 2034 @override |
| 2035 String toString() { |
| 2036 ConstructorElement baseElement = this.baseElement; |
| 2037 List<ParameterElement> parameters = this.parameters; |
| 2038 FunctionType type = this.type; |
| 2039 StringBuffer buffer = new StringBuffer(); |
| 2040 buffer.write(baseElement.enclosingElement.displayName); |
| 2041 String name = displayName; |
| 2042 if (name != null && !name.isEmpty) { |
| 2043 buffer.write("."); |
| 2044 buffer.write(name); |
| 2045 } |
| 2046 buffer.write("("); |
| 2047 int parameterCount = parameters.length; |
| 2048 for (int i = 0; i < parameterCount; i++) { |
| 2049 if (i > 0) { |
| 2050 buffer.write(", "); |
| 2051 } |
| 2052 buffer.write(parameters[i]); |
| 2053 } |
| 2054 buffer.write(")"); |
| 2055 if (type != null) { |
| 2056 buffer.write(Element.RIGHT_ARROW); |
| 2057 buffer.write(type.returnType); |
| 2058 } |
| 2059 return buffer.toString(); |
| 2060 } |
| 2061 |
| 2062 /** |
| 2063 * If the given [constructor]'s type is different when any type parameters |
| 2064 * from the defining type's declaration are replaced with the actual type |
| 2065 * arguments from the [definingType], create a constructor member representing |
| 2066 * the given constructor. Return the member that was created, or the original |
| 2067 * constructor if no member was created. |
| 2068 */ |
| 2069 static ConstructorElement from( |
| 2070 ConstructorElement constructor, InterfaceType definingType) { |
| 2071 if (constructor == null || definingType.typeArguments.length == 0) { |
| 2072 return constructor; |
| 2073 } |
| 2074 FunctionType baseType = constructor.type; |
| 2075 if (baseType == null) { |
| 2076 // TODO(brianwilkerson) We need to understand when this can happen. |
| 2077 return constructor; |
| 2078 } |
| 2079 List<DartType> argumentTypes = definingType.typeArguments; |
| 2080 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 2081 FunctionType substitutedType = |
| 2082 baseType.substitute2(argumentTypes, parameterTypes); |
| 2083 if (baseType == substitutedType) { |
| 2084 return constructor; |
| 2085 } |
| 2086 // TODO(brianwilkerson) Consider caching the substituted type in the |
| 2087 // instance. It would use more memory but speed up some operations. |
| 2088 // We need to see how often the type is being re-computed. |
| 2089 return new ConstructorMember(constructor, definingType); |
| 2090 } |
| 2091 } |
| 2092 |
| 2093 /** |
| 2094 * A [TopLevelVariableElement] for a top-level 'const' variable that has an |
| 2095 * initializer. |
| 2096 */ |
| 2097 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl |
| 2098 with ConstVariableElement { |
| 2099 /** |
| 2100 * The result of evaluating this variable's initializer. |
| 2101 */ |
| 2102 EvaluationResultImpl _result; |
| 2103 |
| 2104 /** |
| 2105 * Initialize a newly created top-level variable element to have the given |
| 2106 * [name]. |
| 2107 */ |
| 2108 ConstTopLevelVariableElementImpl(Identifier name) : super.forNode(name); |
| 2109 |
| 2110 @override |
| 2111 EvaluationResultImpl get evaluationResult => _result; |
| 2112 |
| 2113 @override |
| 2114 void set evaluationResult(EvaluationResultImpl result) { |
| 2115 this._result = result; |
| 2116 } |
| 2117 } |
| 2118 |
| 2119 /** |
| 2120 * Mixin used by elements that represent constant variables and have |
| 2121 * initializers. |
| 2122 * |
| 2123 * Note that in correct Dart code, all constant variables must have |
| 2124 * initializers. However, analyzer also needs to handle incorrect Dart code, |
| 2125 * in which case there might be some constant variables that lack initializers. |
| 2126 * This interface is only used for constant variables that have initializers. |
| 2127 * |
| 2128 * This class is not intended to be part of the public API for analyzer. |
| 2129 */ |
| 2130 abstract class ConstVariableElement implements PotentiallyConstVariableElement { |
| 2131 /** |
| 2132 * If this element represents a constant variable, and it has an initializer, |
| 2133 * a copy of the initializer for the constant. Otherwise `null`. |
| 2134 * |
| 2135 * Note that in correct Dart code, all constant variables must have |
| 2136 * initializers. However, analyzer also needs to handle incorrect Dart code, |
| 2137 * in which case there might be some constant variables that lack |
| 2138 * initializers. |
| 2139 */ |
| 2140 Expression constantInitializer; |
| 2141 } |
| 2142 |
| 2143 /** |
| 2144 * The type associated with elements in the element model. |
| 2145 */ |
| 2146 abstract class DartType { |
| 2147 /** |
| 2148 * An empty list of types. |
| 2149 */ |
| 2150 static const List<DartType> EMPTY_LIST = const <DartType>[]; |
| 2151 |
| 2152 /** |
| 2153 * Return the name of this type as it should appear when presented to users in |
| 2154 * contexts such as error messages. |
| 2155 */ |
| 2156 String get displayName; |
| 2157 |
| 2158 /** |
| 2159 * Return the element representing the declaration of this type, or `null` if |
| 2160 * the type has not, or cannot, be associated with an element. The former case |
| 2161 * will occur if the element model is not yet complete; the latter case will |
| 2162 * occur if this object represents an undefined type. |
| 2163 */ |
| 2164 Element get element; |
| 2165 |
| 2166 /** |
| 2167 * Return `true` if this type represents the bottom type. |
| 2168 */ |
| 2169 bool get isBottom; |
| 2170 |
| 2171 /** |
| 2172 * Return `true` if this type represents the type 'Function' defined in the |
| 2173 * dart:core library. |
| 2174 */ |
| 2175 bool get isDartCoreFunction; |
| 2176 |
| 2177 /** |
| 2178 * Return `true` if this type represents the type 'dynamic'. |
| 2179 */ |
| 2180 bool get isDynamic; |
| 2181 |
| 2182 /** |
| 2183 * Return `true` if this type represents the type 'Object'. |
| 2184 */ |
| 2185 bool get isObject; |
| 2186 |
| 2187 /** |
| 2188 * Return `true` if this type represents a typename that couldn't be resolved. |
| 2189 */ |
| 2190 bool get isUndefined; |
| 2191 |
| 2192 /** |
| 2193 * Return `true` if this type represents the type 'void'. |
| 2194 */ |
| 2195 bool get isVoid; |
| 2196 |
| 2197 /** |
| 2198 * Return the name of this type, or `null` if the type does not have a name, |
| 2199 * such as when the type represents the type of an unnamed function. |
| 2200 */ |
| 2201 String get name; |
| 2202 |
| 2203 /** |
| 2204 * Return the least upper bound of this type and the given [type], or `null` |
| 2205 * if there is no least upper bound. |
| 2206 * |
| 2207 * Deprecated, since it is impossible to implement the correct algorithm |
| 2208 * without access to a [TypeProvider]. Please use |
| 2209 * [TypeSystem.getLeastUpperBound] instead. |
| 2210 */ |
| 2211 @deprecated |
| 2212 DartType getLeastUpperBound(DartType type); |
| 2213 |
| 2214 /** |
| 2215 * Return `true` if this type is assignable to the given [type]. A type |
| 2216 * <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> ⇔ |
| 2217 * <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i>. |
| 2218 */ |
| 2219 bool isAssignableTo(DartType type); |
| 2220 |
| 2221 /** |
| 2222 * Return `true` if this type is more specific than the given [type]. |
| 2223 */ |
| 2224 bool isMoreSpecificThan(DartType type); |
| 2225 |
| 2226 /** |
| 2227 * Return `true` if this type is a subtype of the given [type]. |
| 2228 */ |
| 2229 bool isSubtypeOf(DartType type); |
| 2230 |
| 2231 /** |
| 2232 * Return `true` if this type is a supertype of the given [type]. A type |
| 2233 * <i>S</i> is a supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff |
| 2234 * <i>T</i> is a subtype of <i>S</i>. |
| 2235 */ |
| 2236 bool isSupertypeOf(DartType type); |
| 2237 |
| 2238 /** |
| 2239 * Return the type resulting from substituting the given [argumentTypes] for |
| 2240 * the given [parameterTypes] in this type. The specification defines this |
| 2241 * operation in section 2: |
| 2242 * <blockquote> |
| 2243 * The notation <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ..., |
| 2244 * y<sub>n</sub>]E</i> denotes a copy of <i>E</i> in which all occurrences of |
| 2245 * <i>y<sub>i</sub>, 1 <= i <= n</i> have been replaced with |
| 2246 * <i>x<sub>i</sub></i>. |
| 2247 * </blockquote> |
| 2248 * Note that, contrary to the specification, this method will not create a |
| 2249 * copy of this type if no substitutions were required, but will return this |
| 2250 * type directly. |
| 2251 * |
| 2252 * Note too that the current implementation of this method is only guaranteed |
| 2253 * to work when the parameter types are type variables. |
| 2254 */ |
| 2255 DartType substitute2( |
| 2256 List<DartType> argumentTypes, List<DartType> parameterTypes); |
| 2257 } |
| 2258 |
| 2259 /** |
| 2260 * A [FieldFormalParameterElementImpl] for parameters that have an initializer. |
| 2261 */ |
| 2262 class DefaultFieldFormalParameterElementImpl |
| 2263 extends FieldFormalParameterElementImpl with ConstVariableElement { |
| 2264 /** |
| 2265 * The result of evaluating this variable's initializer. |
| 2266 */ |
| 2267 EvaluationResultImpl _result; |
| 2268 |
| 2269 /** |
| 2270 * Initialize a newly created parameter element to have the given [name]. |
| 2271 */ |
| 2272 DefaultFieldFormalParameterElementImpl(Identifier name) : super(name); |
| 2273 |
| 2274 @override |
| 2275 EvaluationResultImpl get evaluationResult => _result; |
| 2276 |
| 2277 @override |
| 2278 void set evaluationResult(EvaluationResultImpl result) { |
| 2279 this._result = result; |
| 2280 } |
| 2281 } |
| 2282 |
| 2283 /** |
| 2284 * A [ParameterElement] for parameters that have an initializer. |
| 2285 */ |
| 2286 class DefaultParameterElementImpl extends ParameterElementImpl |
| 2287 with ConstVariableElement { |
| 2288 /** |
| 2289 * The result of evaluating this variable's initializer. |
| 2290 */ |
| 2291 EvaluationResultImpl _result; |
| 2292 |
| 2293 /** |
| 2294 * Initialize a newly created parameter element to have the given [name]. |
| 2295 */ |
| 2296 DefaultParameterElementImpl(Identifier name) : super.forNode(name); |
| 2297 |
| 2298 @override |
| 2299 EvaluationResultImpl get evaluationResult => _result; |
| 2300 |
| 2301 @override |
| 2302 void set evaluationResult(EvaluationResultImpl result) { |
| 2303 this._result = result; |
| 2304 } |
| 2305 |
| 2306 @override |
| 2307 DefaultFormalParameter computeNode() => |
| 2308 getNodeMatching((node) => node is DefaultFormalParameter); |
| 2309 } |
| 2310 |
| 2311 /** |
| 2312 * The synthetic element representing the declaration of the type `dynamic`. |
| 2313 */ |
| 2314 class DynamicElementImpl extends ElementImpl implements TypeDefiningElement { |
| 2315 /** |
| 2316 * Return the unique instance of this class. |
| 2317 */ |
| 2318 static DynamicElementImpl get instance => |
| 2319 DynamicTypeImpl.instance.element as DynamicElementImpl; |
| 2320 |
| 2321 @override |
| 2322 DynamicTypeImpl type; |
| 2323 |
| 2324 /** |
| 2325 * Initialize a newly created instance of this class. Instances of this class |
| 2326 * should <b>not</b> be created except as part of creating the type associated |
| 2327 * with this element. The single instance of this class should be accessed |
| 2328 * through the method [getInstance]. |
| 2329 */ |
| 2330 DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) { |
| 2331 setModifier(Modifier.SYNTHETIC, true); |
| 2332 } |
| 2333 |
| 2334 @override |
| 2335 ElementKind get kind => ElementKind.DYNAMIC; |
| 2336 |
| 2337 @override |
| 2338 accept(ElementVisitor visitor) => null; |
| 2339 } |
| 2340 |
| 2341 /** |
| 2342 * The [Type] representing the type `dynamic`. |
| 2343 */ |
| 2344 class DynamicTypeImpl extends TypeImpl { |
| 2345 /** |
| 2346 * The unique instance of this class. |
| 2347 */ |
| 2348 static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl._(); |
| 2349 |
| 2350 /** |
| 2351 * Return the unique instance of this class. |
| 2352 */ |
| 2353 static DynamicTypeImpl get instance => _INSTANCE; |
| 2354 |
| 2355 /** |
| 2356 * Prevent the creation of instances of this class. |
| 2357 */ |
| 2358 DynamicTypeImpl._() |
| 2359 : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) { |
| 2360 (element as DynamicElementImpl).type = this; |
| 2361 } |
| 2362 |
| 2363 /** |
| 2364 * Constructor used by [CircularTypeImpl]. |
| 2365 */ |
| 2366 DynamicTypeImpl._circular() |
| 2367 : super(_INSTANCE.element, Keyword.DYNAMIC.syntax); |
| 2368 |
| 2369 @override |
| 2370 int get hashCode => 1; |
| 2371 |
| 2372 @override |
| 2373 bool get isDynamic => true; |
| 2374 |
| 2375 @override |
| 2376 bool operator ==(Object object) => identical(object, this); |
| 2377 |
| 2378 @override |
| 2379 bool isMoreSpecificThan(DartType type, |
| 2380 [bool withDynamic = false, Set<Element> visitedElements]) { |
| 2381 // T is S |
| 2382 if (identical(this, type)) { |
| 2383 return true; |
| 2384 } |
| 2385 // else |
| 2386 return withDynamic; |
| 2387 } |
| 2388 |
| 2389 @override |
| 2390 bool isSubtypeOf(DartType type) => true; |
| 2391 |
| 2392 @override |
| 2393 bool isSupertypeOf(DartType type) => true; |
| 2394 |
| 2395 @override |
| 2396 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 2397 |
| 2398 @override |
| 2399 DartType substitute2( |
| 2400 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 2401 [List<FunctionTypeAliasElement> prune]) { |
| 2402 int length = parameterTypes.length; |
| 2403 for (int i = 0; i < length; i++) { |
| 2404 if (parameterTypes[i] == this) { |
| 2405 return argumentTypes[i]; |
| 2406 } |
| 2407 } |
| 2408 return this; |
| 2409 } |
| 2410 } |
| 2411 |
| 2412 /** |
| 2413 * The base class for all of the elements in the element model. Generally |
| 2414 * speaking, the element model is a semantic model of the program that |
| 2415 * represents things that are declared with a name and hence can be referenced |
| 2416 * elsewhere in the code. |
| 2417 * |
| 2418 * There are two exceptions to the general case. First, there are elements in |
| 2419 * the element model that are created for the convenience of various kinds of |
| 2420 * analysis but that do not have any corresponding declaration within the source |
| 2421 * code. Such elements are marked as being <i>synthetic</i>. Examples of |
| 2422 * synthetic elements include |
| 2423 * * default constructors in classes that do not define any explicit |
| 2424 * constructors, |
| 2425 * * getters and setters that are induced by explicit field declarations, |
| 2426 * * fields that are induced by explicit declarations of getters and setters, |
| 2427 * and |
| 2428 * * functions representing the initialization expression for a variable. |
| 2429 * |
| 2430 * Second, there are elements in the element model that do not have a name. |
| 2431 * These correspond to unnamed functions and exist in order to more accurately |
| 2432 * represent the semantic structure of the program. |
| 2433 */ |
| 2434 abstract class Element implements AnalysisTarget { |
| 2435 /** |
| 2436 * An Unicode right arrow. |
| 2437 */ |
| 2438 static final String RIGHT_ARROW = " \u2192 "; |
| 2439 |
| 2440 /** |
| 2441 * A comparator that can be used to sort elements by their name offset. |
| 2442 * Elements with a smaller offset will be sorted to be before elements with a |
| 2443 * larger name offset. |
| 2444 */ |
| 2445 static final Comparator<Element> SORT_BY_OFFSET = (Element firstElement, |
| 2446 Element secondElement) => |
| 2447 firstElement.nameOffset - secondElement.nameOffset; |
| 2448 |
| 2449 /** |
| 2450 * Return the analysis context in which this element is defined. |
| 2451 */ |
| 2452 AnalysisContext get context; |
| 2453 |
| 2454 /** |
| 2455 * Return the display name of this element, or `null` if this element does not |
| 2456 * have a name. |
| 2457 * |
| 2458 * In most cases the name and the display name are the same. Differences |
| 2459 * though are cases such as setters where the name of some setter `set f(x)` |
| 2460 * is `f=`, instead of `f`. |
| 2461 */ |
| 2462 String get displayName; |
| 2463 |
| 2464 /** |
| 2465 * Return the element that either physically or logically encloses this |
| 2466 * element. This will be `null` if this element is a library because libraries |
| 2467 * are the top-level elements in the model. |
| 2468 */ |
| 2469 Element get enclosingElement; |
| 2470 |
| 2471 /** |
| 2472 * The unique integer identifier of this element. |
| 2473 */ |
| 2474 int get id; |
| 2475 |
| 2476 /** |
| 2477 * Return `true` if this element has an annotation of the form '@deprecated' |
| 2478 * or '@Deprecated('..')'. |
| 2479 */ |
| 2480 bool get isDeprecated; |
| 2481 |
| 2482 /** |
| 2483 * Return `true` if this element has an annotation of the form '@override'. |
| 2484 */ |
| 2485 bool get isOverride; |
| 2486 |
| 2487 /** |
| 2488 * Return `true` if this element is private. Private elements are visible only |
| 2489 * within the library in which they are declared. |
| 2490 */ |
| 2491 bool get isPrivate; |
| 2492 |
| 2493 /** |
| 2494 * Return `true` if this element is public. Public elements are visible within |
| 2495 * any library that imports the library in which they are declared. |
| 2496 */ |
| 2497 bool get isPublic; |
| 2498 |
| 2499 /** |
| 2500 * Return `true` if this element is synthetic. A synthetic element is an |
| 2501 * element that is not represented in the source code explicitly, but is |
| 2502 * implied by the source code, such as the default constructor for a class |
| 2503 * that does not explicitly define any constructors. |
| 2504 */ |
| 2505 bool get isSynthetic; |
| 2506 |
| 2507 /** |
| 2508 * Return the kind of element that this is. |
| 2509 */ |
| 2510 ElementKind get kind; |
| 2511 |
| 2512 /** |
| 2513 * Return the library that contains this element. This will be the element |
| 2514 * itself if it is a library element. This will be `null` if this element is |
| 2515 * an HTML file because HTML files are not contained in libraries. |
| 2516 */ |
| 2517 LibraryElement get library; |
| 2518 |
| 2519 /** |
| 2520 * Return an object representing the location of this element in the element |
| 2521 * model. The object can be used to locate this element at a later time. |
| 2522 */ |
| 2523 ElementLocation get location; |
| 2524 |
| 2525 /** |
| 2526 * Return a list containing all of the metadata associated with this element. |
| 2527 * The array will be empty if the element does not have any metadata or if the |
| 2528 * library containing this element has not yet been resolved. |
| 2529 */ |
| 2530 List<ElementAnnotation> get metadata; |
| 2531 |
| 2532 /** |
| 2533 * Return the name of this element, or `null` if this element does not have a |
| 2534 * name. |
| 2535 */ |
| 2536 String get name; |
| 2537 |
| 2538 /** |
| 2539 * Return the offset of the name of this element in the file that contains the |
| 2540 * declaration of this element, or `-1` if this element is synthetic, does not |
| 2541 * have a name, or otherwise does not have an offset. |
| 2542 */ |
| 2543 int get nameOffset; |
| 2544 |
| 2545 /** |
| 2546 * **DEPRECATED** Use `computeNode()` instead. |
| 2547 * |
| 2548 * Return the resolved [AstNode] node that declares this element, or `null` if |
| 2549 * this element is synthetic or isn't contained in a compilation unit, such as |
| 2550 * a [LibraryElement]. |
| 2551 * |
| 2552 * This method is expensive, because resolved AST might be evicted from cache, |
| 2553 * so parsing and resolving will be performed. |
| 2554 * |
| 2555 * <b>Note:</b> This method cannot be used in an async environment. |
| 2556 */ |
| 2557 @deprecated |
| 2558 AstNode get node; |
| 2559 |
| 2560 /** |
| 2561 * Return the source that contains this element, or `null` if this element is |
| 2562 * not contained in a source. |
| 2563 */ |
| 2564 Source get source; |
| 2565 |
| 2566 /** |
| 2567 * Return the resolved [CompilationUnit] that declares this element, or `null` |
| 2568 * if this element is synthetic. |
| 2569 * |
| 2570 * This method is expensive, because resolved AST might have been already |
| 2571 * evicted from cache, so parsing and resolving will be performed. |
| 2572 */ |
| 2573 CompilationUnit get unit; |
| 2574 |
| 2575 /** |
| 2576 * Use the given [visitor] to visit this element. Return the value returned by |
| 2577 * the visitor as a result of visiting this element. |
| 2578 */ |
| 2579 accept(ElementVisitor visitor); |
| 2580 |
| 2581 /** |
| 2582 * Return the documentation comment for this element as it appears in the |
| 2583 * original source (complete with the beginning and ending delimiters), or |
| 2584 * `null` if this element does not have a documentation comment associated |
| 2585 * with it. This can be a long-running operation if the information needed to |
| 2586 * access the comment is not cached. |
| 2587 * |
| 2588 * Throws [AnalysisException] if the documentation comment could not be |
| 2589 * determined because the analysis could not be performed |
| 2590 */ |
| 2591 String computeDocumentationComment(); |
| 2592 |
| 2593 /** |
| 2594 * Return the resolved [AstNode] node that declares this element, or `null` if |
| 2595 * this element is synthetic or isn't contained in a compilation unit, such as |
| 2596 * a [LibraryElement]. |
| 2597 * |
| 2598 * This method is expensive, because resolved AST might be evicted from cache, |
| 2599 * so parsing and resolving will be performed. |
| 2600 * |
| 2601 * <b>Note:</b> This method cannot be used in an async environment. |
| 2602 */ |
| 2603 AstNode computeNode(); |
| 2604 |
| 2605 /** |
| 2606 * Return the most immediate ancestor of this element for which the |
| 2607 * [predicate] returns `true`, or `null` if there is no such ancestor. Note |
| 2608 * that this element will never be returned. |
| 2609 */ |
| 2610 Element getAncestor(Predicate<Element> predicate); |
| 2611 |
| 2612 /** |
| 2613 * Return a display name for the given element that includes the path to the |
| 2614 * compilation unit in which the type is defined. If [shortName] is `null` |
| 2615 * then [getDisplayName] will be used as the name of this element. Otherwise |
| 2616 * the provided name will be used. |
| 2617 */ |
| 2618 // TODO(brianwilkerson) Make the parameter optional. |
| 2619 String getExtendedDisplayName(String shortName); |
| 2620 |
| 2621 /** |
| 2622 * Return `true` if this element, assuming that it is within scope, is |
| 2623 * accessible to code in the given [library]. This is defined by the Dart |
| 2624 * Language Specification in section 3.2: |
| 2625 * <blockquote> |
| 2626 * A declaration <i>m</i> is accessible to library <i>L</i> if <i>m</i> is |
| 2627 * declared in <i>L</i> or if <i>m</i> is public. |
| 2628 * </blockquote> |
| 2629 */ |
| 2630 bool isAccessibleIn(LibraryElement library); |
| 2631 |
| 2632 /** |
| 2633 * Use the given [visitor] to visit all of the children of this element. There |
| 2634 * is no guarantee of the order in which the children will be visited. |
| 2635 */ |
| 2636 void visitChildren(ElementVisitor visitor); |
| 2637 } |
| 2638 |
| 2639 /** |
| 2640 * A single annotation associated with an element. |
| 2641 */ |
| 2642 abstract class ElementAnnotation { |
| 2643 /** |
| 2644 * An empty list of annotations. |
| 2645 */ |
| 2646 static const List<ElementAnnotation> EMPTY_LIST = const <ElementAnnotation>[]; |
| 2647 |
| 2648 /** |
| 2649 * Return the element representing the field, variable, or const constructor |
| 2650 * being used as an annotation. |
| 2651 */ |
| 2652 Element get element; |
| 2653 |
| 2654 /** |
| 2655 * Return `true` if this annotation marks the associated element as being |
| 2656 * deprecated. |
| 2657 */ |
| 2658 bool get isDeprecated; |
| 2659 |
| 2660 /** |
| 2661 * Return `true` if this annotation marks the associated method as being |
| 2662 * expected to override an inherited method. |
| 2663 */ |
| 2664 bool get isOverride; |
| 2665 |
| 2666 /** |
| 2667 * Return `true` if this annotation marks the associated class as implementing |
| 2668 * a proxy object. |
| 2669 */ |
| 2670 bool get isProxy; |
| 2671 } |
| 2672 |
| 2673 /** |
| 2674 * A concrete implementation of an [ElementAnnotation]. |
| 2675 */ |
| 2676 class ElementAnnotationImpl implements ElementAnnotation { |
| 2677 /** |
| 2678 * An empty list of annotations. |
| 2679 */ |
| 2680 @deprecated // Use ElementAnnotation.EMPTY_LIST |
| 2681 static const List<ElementAnnotationImpl> EMPTY_ARRAY = |
| 2682 const <ElementAnnotationImpl>[]; |
| 2683 |
| 2684 /** |
| 2685 * The name of the class used to mark an element as being deprecated. |
| 2686 */ |
| 2687 static String _DEPRECATED_CLASS_NAME = "Deprecated"; |
| 2688 |
| 2689 /** |
| 2690 * The name of the top-level variable used to mark an element as being |
| 2691 * deprecated. |
| 2692 */ |
| 2693 static String _DEPRECATED_VARIABLE_NAME = "deprecated"; |
| 2694 |
| 2695 /** |
| 2696 * The name of the top-level variable used to mark a method as being expected |
| 2697 * to override an inherited method. |
| 2698 */ |
| 2699 static String _OVERRIDE_VARIABLE_NAME = "override"; |
| 2700 |
| 2701 /** |
| 2702 * The name of the top-level variable used to mark a class as implementing a |
| 2703 * proxy object. |
| 2704 */ |
| 2705 static String PROXY_VARIABLE_NAME = "proxy"; |
| 2706 |
| 2707 /** |
| 2708 * The element representing the field, variable, or constructor being used as |
| 2709 * an annotation. |
| 2710 */ |
| 2711 final Element element; |
| 2712 |
| 2713 /** |
| 2714 * The result of evaluating this annotation as a compile-time constant |
| 2715 * expression, or `null` if the compilation unit containing the variable has |
| 2716 * not been resolved. |
| 2717 */ |
| 2718 EvaluationResultImpl evaluationResult; |
| 2719 |
| 2720 /** |
| 2721 * Initialize a newly created annotation. The given [element] is the element |
| 2722 * representing the field, variable, or constructor being used as an |
| 2723 * annotation. |
| 2724 */ |
| 2725 ElementAnnotationImpl(this.element); |
| 2726 |
| 2727 @override |
| 2728 bool get isDeprecated { |
| 2729 if (element != null) { |
| 2730 LibraryElement library = element.library; |
| 2731 if (library != null && library.isDartCore) { |
| 2732 if (element is ConstructorElement) { |
| 2733 ConstructorElement constructorElement = element as ConstructorElement; |
| 2734 if (constructorElement.enclosingElement.name == |
| 2735 _DEPRECATED_CLASS_NAME) { |
| 2736 return true; |
| 2737 } |
| 2738 } else if (element is PropertyAccessorElement && |
| 2739 element.name == _DEPRECATED_VARIABLE_NAME) { |
| 2740 return true; |
| 2741 } |
| 2742 } |
| 2743 } |
| 2744 return false; |
| 2745 } |
| 2746 |
| 2747 @override |
| 2748 bool get isOverride { |
| 2749 if (element != null) { |
| 2750 LibraryElement library = element.library; |
| 2751 if (library != null && library.isDartCore) { |
| 2752 if (element is PropertyAccessorElement && |
| 2753 element.name == _OVERRIDE_VARIABLE_NAME) { |
| 2754 return true; |
| 2755 } |
| 2756 } |
| 2757 } |
| 2758 return false; |
| 2759 } |
| 2760 |
| 2761 @override |
| 2762 bool get isProxy { |
| 2763 if (element != null) { |
| 2764 LibraryElement library = element.library; |
| 2765 if (library != null && library.isDartCore) { |
| 2766 if (element is PropertyAccessorElement && |
| 2767 element.name == PROXY_VARIABLE_NAME) { |
| 2768 return true; |
| 2769 } |
| 2770 } |
| 2771 } |
| 2772 return false; |
| 2773 } |
| 2774 |
| 2775 @override |
| 2776 String toString() => '@$element'; |
| 2777 } |
| 2778 |
| 2779 /** |
| 2780 * A base class for concrete implementations of an [Element]. |
| 2781 */ |
| 2782 abstract class ElementImpl implements Element { |
| 2783 static int _NEXT_ID = 0; |
| 2784 |
| 2785 final int id = _NEXT_ID++; |
| 2786 |
| 2787 /** |
| 2788 * The enclosing element of this element, or `null` if this element is at the |
| 2789 * root of the element structure. |
| 2790 */ |
| 2791 ElementImpl _enclosingElement; |
| 2792 |
| 2793 /** |
| 2794 * The name of this element. |
| 2795 */ |
| 2796 String _name; |
| 2797 |
| 2798 /** |
| 2799 * The offset of the name of this element in the file that contains the |
| 2800 * declaration of this element. |
| 2801 */ |
| 2802 int _nameOffset = 0; |
| 2803 |
| 2804 /** |
| 2805 * A bit-encoded form of the modifiers associated with this element. |
| 2806 */ |
| 2807 int _modifiers = 0; |
| 2808 |
| 2809 /** |
| 2810 * A list containing all of the metadata associated with this element. |
| 2811 */ |
| 2812 List<ElementAnnotation> metadata = ElementAnnotation.EMPTY_LIST; |
| 2813 |
| 2814 /** |
| 2815 * A cached copy of the calculated hashCode for this element. |
| 2816 */ |
| 2817 int _cachedHashCode; |
| 2818 |
| 2819 /** |
| 2820 * A cached copy of the calculated location for this element. |
| 2821 */ |
| 2822 ElementLocation _cachedLocation; |
| 2823 |
| 2824 /** |
| 2825 * Initialize a newly created element to have the given [name] at the given |
| 2826 * [_nameOffset]. |
| 2827 */ |
| 2828 ElementImpl(String name, this._nameOffset) { |
| 2829 this._name = StringUtilities.intern(name); |
| 2830 } |
| 2831 |
| 2832 /** |
| 2833 * Initialize a newly created element to have the given [name]. |
| 2834 */ |
| 2835 ElementImpl.forNode(Identifier name) |
| 2836 : this(name == null ? "" : name.name, name == null ? -1 : name.offset); |
| 2837 |
| 2838 @override |
| 2839 AnalysisContext get context { |
| 2840 if (_enclosingElement == null) { |
| 2841 return null; |
| 2842 } |
| 2843 return _enclosingElement.context; |
| 2844 } |
| 2845 |
| 2846 @override |
| 2847 String get displayName => _name; |
| 2848 |
| 2849 @override |
| 2850 Element get enclosingElement => _enclosingElement; |
| 2851 |
| 2852 /** |
| 2853 * Set the enclosing element of this element to the given [element]. |
| 2854 */ |
| 2855 void set enclosingElement(Element element) { |
| 2856 _enclosingElement = element as ElementImpl; |
| 2857 _cachedLocation = null; |
| 2858 _cachedHashCode = null; |
| 2859 } |
| 2860 |
| 2861 @override |
| 2862 int get hashCode { |
| 2863 // TODO: We might want to re-visit this optimization in the future. |
| 2864 // We cache the hash code value as this is a very frequently called method. |
| 2865 if (_cachedHashCode == null) { |
| 2866 int hashIdentifier = identifier.hashCode; |
| 2867 Element enclosing = enclosingElement; |
| 2868 if (enclosing != null) { |
| 2869 _cachedHashCode = hashIdentifier + enclosing.hashCode; |
| 2870 } else { |
| 2871 _cachedHashCode = hashIdentifier; |
| 2872 } |
| 2873 } |
| 2874 return _cachedHashCode; |
| 2875 } |
| 2876 |
| 2877 /** |
| 2878 * Return an identifier that uniquely identifies this element among the |
| 2879 * children of this element's parent. |
| 2880 */ |
| 2881 String get identifier => name; |
| 2882 |
| 2883 @override |
| 2884 bool get isDeprecated { |
| 2885 for (ElementAnnotation annotation in metadata) { |
| 2886 if (annotation.isDeprecated) { |
| 2887 return true; |
| 2888 } |
| 2889 } |
| 2890 return false; |
| 2891 } |
| 2892 |
| 2893 @override |
| 2894 bool get isOverride { |
| 2895 for (ElementAnnotation annotation in metadata) { |
| 2896 if (annotation.isOverride) { |
| 2897 return true; |
| 2898 } |
| 2899 } |
| 2900 return false; |
| 2901 } |
| 2902 |
| 2903 @override |
| 2904 bool get isPrivate { |
| 2905 String name = displayName; |
| 2906 if (name == null) { |
| 2907 return true; |
| 2908 } |
| 2909 return Identifier.isPrivateName(name); |
| 2910 } |
| 2911 |
| 2912 @override |
| 2913 bool get isPublic => !isPrivate; |
| 2914 |
| 2915 @override |
| 2916 bool get isSynthetic => hasModifier(Modifier.SYNTHETIC); |
| 2917 |
| 2918 @override |
| 2919 LibraryElement get library => |
| 2920 getAncestor((element) => element is LibraryElement); |
| 2921 |
| 2922 @override |
| 2923 ElementLocation get location { |
| 2924 if (_cachedLocation == null) { |
| 2925 _cachedLocation = new ElementLocationImpl.con1(this); |
| 2926 } |
| 2927 return _cachedLocation; |
| 2928 } |
| 2929 |
| 2930 @override |
| 2931 String get name => _name; |
| 2932 |
| 2933 void set name(String name) { |
| 2934 this._name = name; |
| 2935 _cachedLocation = null; |
| 2936 _cachedHashCode = null; |
| 2937 } |
| 2938 |
| 2939 /** |
| 2940 * The offset of the name of this element in the file that contains the |
| 2941 * declaration of this element. |
| 2942 */ |
| 2943 int get nameOffset => _nameOffset; |
| 2944 |
| 2945 /** |
| 2946 * Sets the offset of the name of this element in the file that contains the |
| 2947 * declaration of this element. |
| 2948 */ |
| 2949 void set nameOffset(int offset) { |
| 2950 _nameOffset = offset; |
| 2951 _cachedHashCode = null; |
| 2952 _cachedLocation = null; |
| 2953 } |
| 2954 |
| 2955 @deprecated |
| 2956 @override |
| 2957 AstNode get node => computeNode(); |
| 2958 |
| 2959 @override |
| 2960 Source get source { |
| 2961 if (_enclosingElement == null) { |
| 2962 return null; |
| 2963 } |
| 2964 return _enclosingElement.source; |
| 2965 } |
| 2966 |
| 2967 /** |
| 2968 * Set whether this element is synthetic. |
| 2969 */ |
| 2970 void set synthetic(bool isSynthetic) { |
| 2971 setModifier(Modifier.SYNTHETIC, isSynthetic); |
| 2972 } |
| 2973 |
| 2974 @override |
| 2975 CompilationUnit get unit => context.resolveCompilationUnit(source, library); |
| 2976 |
| 2977 @override |
| 2978 bool operator ==(Object object) { |
| 2979 if (identical(this, object)) { |
| 2980 return true; |
| 2981 } |
| 2982 if (object == null || hashCode != object.hashCode) { |
| 2983 return false; |
| 2984 } |
| 2985 return object.runtimeType == runtimeType && |
| 2986 (object as Element).location == location; |
| 2987 } |
| 2988 |
| 2989 /** |
| 2990 * Append a textual representation of this element to the given [buffer]. |
| 2991 */ |
| 2992 void appendTo(StringBuffer buffer) { |
| 2993 if (_name == null) { |
| 2994 buffer.write("<unnamed "); |
| 2995 buffer.write(runtimeType.toString()); |
| 2996 buffer.write(">"); |
| 2997 } else { |
| 2998 buffer.write(_name); |
| 2999 } |
| 3000 } |
| 3001 |
| 3002 @override |
| 3003 String computeDocumentationComment() { |
| 3004 AnalysisContext context = this.context; |
| 3005 if (context == null) { |
| 3006 return null; |
| 3007 } |
| 3008 return context.computeDocumentationComment(this); |
| 3009 } |
| 3010 |
| 3011 @override |
| 3012 AstNode computeNode() => getNodeMatching((node) => node is AstNode); |
| 3013 |
| 3014 /** |
| 3015 * Set this element as the enclosing element for given [element]. |
| 3016 */ |
| 3017 void encloseElement(ElementImpl element) { |
| 3018 element.enclosingElement = this; |
| 3019 } |
| 3020 |
| 3021 @override |
| 3022 Element getAncestor(Predicate<Element> predicate) { |
| 3023 Element ancestor = _enclosingElement; |
| 3024 while (ancestor != null && !predicate(ancestor)) { |
| 3025 ancestor = ancestor.enclosingElement; |
| 3026 } |
| 3027 return ancestor; |
| 3028 } |
| 3029 |
| 3030 /** |
| 3031 * Return the child of this element that is uniquely identified by the given |
| 3032 * [identifier], or `null` if there is no such child. |
| 3033 */ |
| 3034 ElementImpl getChild(String identifier) => null; |
| 3035 |
| 3036 @override |
| 3037 String getExtendedDisplayName(String shortName) { |
| 3038 if (shortName == null) { |
| 3039 shortName = displayName; |
| 3040 } |
| 3041 Source source = this.source; |
| 3042 if (source != null) { |
| 3043 return "$shortName (${source.fullName})"; |
| 3044 } |
| 3045 return shortName; |
| 3046 } |
| 3047 |
| 3048 /** |
| 3049 * Return the resolved [AstNode] of the given type enclosing [getNameOffset]. |
| 3050 */ |
| 3051 AstNode getNodeMatching(Predicate<AstNode> predicate) { |
| 3052 CompilationUnit unit = this.unit; |
| 3053 if (unit == null) { |
| 3054 return null; |
| 3055 } |
| 3056 int offset = nameOffset; |
| 3057 AstNode node = new NodeLocator(offset).searchWithin(unit); |
| 3058 if (node == null) { |
| 3059 return null; |
| 3060 } |
| 3061 return node.getAncestor(predicate); |
| 3062 } |
| 3063 |
| 3064 /** |
| 3065 * Return `true` if this element has the given [modifier] associated with it. |
| 3066 */ |
| 3067 bool hasModifier(Modifier modifier) => |
| 3068 BooleanArray.getEnum(_modifiers, modifier); |
| 3069 |
| 3070 @override |
| 3071 bool isAccessibleIn(LibraryElement library) { |
| 3072 if (Identifier.isPrivateName(_name)) { |
| 3073 return library == this.library; |
| 3074 } |
| 3075 return true; |
| 3076 } |
| 3077 |
| 3078 /** |
| 3079 * If the given [child] is not `null`, use the given [visitor] to visit it. |
| 3080 */ |
| 3081 void safelyVisitChild(Element child, ElementVisitor visitor) { |
| 3082 if (child != null) { |
| 3083 child.accept(visitor); |
| 3084 } |
| 3085 } |
| 3086 |
| 3087 /** |
| 3088 * Use the given [visitor] to visit all of the [children] in the given array. |
| 3089 */ |
| 3090 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { |
| 3091 if (children != null) { |
| 3092 for (Element child in children) { |
| 3093 child.accept(visitor); |
| 3094 } |
| 3095 } |
| 3096 } |
| 3097 |
| 3098 /** |
| 3099 * Set whether the given [modifier] is associated with this element to |
| 3100 * correspond to the given [value]. |
| 3101 */ |
| 3102 void setModifier(Modifier modifier, bool value) { |
| 3103 _modifiers = BooleanArray.setEnum(_modifiers, modifier, value); |
| 3104 } |
| 3105 |
| 3106 @override |
| 3107 String toString() { |
| 3108 StringBuffer buffer = new StringBuffer(); |
| 3109 appendTo(buffer); |
| 3110 return buffer.toString(); |
| 3111 } |
| 3112 |
| 3113 @override |
| 3114 void visitChildren(ElementVisitor visitor) { |
| 3115 // There are no children to visit |
| 3116 } |
| 3117 } |
| 3118 |
| 3119 /** |
| 3120 * The enumeration `ElementKind` defines the various kinds of elements in the |
| 3121 * element model. |
| 3122 */ |
| 3123 class ElementKind extends Enum<ElementKind> { |
| 3124 static const ElementKind CLASS = const ElementKind('CLASS', 0, "class"); |
| 3125 |
| 3126 static const ElementKind COMPILATION_UNIT = |
| 3127 const ElementKind('COMPILATION_UNIT', 1, "compilation unit"); |
| 3128 |
| 3129 static const ElementKind CONSTRUCTOR = |
| 3130 const ElementKind('CONSTRUCTOR', 2, "constructor"); |
| 3131 |
| 3132 static const ElementKind DYNAMIC = |
| 3133 const ElementKind('DYNAMIC', 3, "<dynamic>"); |
| 3134 |
| 3135 static const ElementKind EMBEDDED_HTML_SCRIPT = |
| 3136 const ElementKind('EMBEDDED_HTML_SCRIPT', 4, "embedded html script"); |
| 3137 |
| 3138 static const ElementKind ERROR = const ElementKind('ERROR', 5, "<error>"); |
| 3139 |
| 3140 static const ElementKind EXPORT = |
| 3141 const ElementKind('EXPORT', 6, "export directive"); |
| 3142 |
| 3143 static const ElementKind EXTERNAL_HTML_SCRIPT = |
| 3144 const ElementKind('EXTERNAL_HTML_SCRIPT', 7, "external html script"); |
| 3145 |
| 3146 static const ElementKind FIELD = const ElementKind('FIELD', 8, "field"); |
| 3147 |
| 3148 static const ElementKind FUNCTION = |
| 3149 const ElementKind('FUNCTION', 9, "function"); |
| 3150 |
| 3151 static const ElementKind GETTER = const ElementKind('GETTER', 10, "getter"); |
| 3152 |
| 3153 static const ElementKind HTML = const ElementKind('HTML', 11, "html"); |
| 3154 |
| 3155 static const ElementKind IMPORT = |
| 3156 const ElementKind('IMPORT', 12, "import directive"); |
| 3157 |
| 3158 static const ElementKind LABEL = const ElementKind('LABEL', 13, "label"); |
| 3159 |
| 3160 static const ElementKind LIBRARY = |
| 3161 const ElementKind('LIBRARY', 14, "library"); |
| 3162 |
| 3163 static const ElementKind LOCAL_VARIABLE = |
| 3164 const ElementKind('LOCAL_VARIABLE', 15, "local variable"); |
| 3165 |
| 3166 static const ElementKind METHOD = const ElementKind('METHOD', 16, "method"); |
| 3167 |
| 3168 static const ElementKind NAME = const ElementKind('NAME', 17, "<name>"); |
| 3169 |
| 3170 static const ElementKind PARAMETER = |
| 3171 const ElementKind('PARAMETER', 18, "parameter"); |
| 3172 |
| 3173 static const ElementKind PREFIX = |
| 3174 const ElementKind('PREFIX', 19, "import prefix"); |
| 3175 |
| 3176 static const ElementKind SETTER = const ElementKind('SETTER', 20, "setter"); |
| 3177 |
| 3178 static const ElementKind TOP_LEVEL_VARIABLE = |
| 3179 const ElementKind('TOP_LEVEL_VARIABLE', 21, "top level variable"); |
| 3180 |
| 3181 static const ElementKind FUNCTION_TYPE_ALIAS = |
| 3182 const ElementKind('FUNCTION_TYPE_ALIAS', 22, "function type alias"); |
| 3183 |
| 3184 static const ElementKind TYPE_PARAMETER = |
| 3185 const ElementKind('TYPE_PARAMETER', 23, "type parameter"); |
| 3186 |
| 3187 static const ElementKind UNIVERSE = |
| 3188 const ElementKind('UNIVERSE', 24, "<universe>"); |
| 3189 |
| 3190 static const List<ElementKind> values = const [ |
| 3191 CLASS, |
| 3192 COMPILATION_UNIT, |
| 3193 CONSTRUCTOR, |
| 3194 DYNAMIC, |
| 3195 EMBEDDED_HTML_SCRIPT, |
| 3196 ERROR, |
| 3197 EXPORT, |
| 3198 EXTERNAL_HTML_SCRIPT, |
| 3199 FIELD, |
| 3200 FUNCTION, |
| 3201 GETTER, |
| 3202 HTML, |
| 3203 IMPORT, |
| 3204 LABEL, |
| 3205 LIBRARY, |
| 3206 LOCAL_VARIABLE, |
| 3207 METHOD, |
| 3208 NAME, |
| 3209 PARAMETER, |
| 3210 PREFIX, |
| 3211 SETTER, |
| 3212 TOP_LEVEL_VARIABLE, |
| 3213 FUNCTION_TYPE_ALIAS, |
| 3214 TYPE_PARAMETER, |
| 3215 UNIVERSE |
| 3216 ]; |
| 3217 |
| 3218 /** |
| 3219 * The name displayed in the UI for this kind of element. |
| 3220 */ |
| 3221 final String displayName; |
| 3222 |
| 3223 /** |
| 3224 * Initialize a newly created element kind to have the given [displayName]. |
| 3225 */ |
| 3226 const ElementKind(String name, int ordinal, this.displayName) |
| 3227 : super(name, ordinal); |
| 3228 |
| 3229 /** |
| 3230 * Return the kind of the given [element], or [ERROR] if the element is |
| 3231 * `null`. This is a utility method that can reduce the need for null checks |
| 3232 * in other places. |
| 3233 */ |
| 3234 static ElementKind of(Element element) { |
| 3235 if (element == null) { |
| 3236 return ERROR; |
| 3237 } |
| 3238 return element.kind; |
| 3239 } |
| 3240 } |
| 3241 |
| 3242 /** |
| 3243 * The location of an element within the element model. |
| 3244 */ |
| 3245 abstract class ElementLocation { |
| 3246 /** |
| 3247 * Return the path to the element whose location is represented by this |
| 3248 * object. Clients must not modify the returned array. |
| 3249 */ |
| 3250 List<String> get components; |
| 3251 |
| 3252 /** |
| 3253 * Return an encoded representation of this location that can be used to |
| 3254 * create a location that is equal to this location. |
| 3255 */ |
| 3256 String get encoding; |
| 3257 } |
| 3258 |
| 3259 /** |
| 3260 * A concrete implementation of an [ElementLocation]. |
| 3261 */ |
| 3262 class ElementLocationImpl implements ElementLocation { |
| 3263 /** |
| 3264 * The character used to separate components in the encoded form. |
| 3265 */ |
| 3266 static int _SEPARATOR_CHAR = 0x3B; |
| 3267 |
| 3268 /** |
| 3269 * The path to the element whose location is represented by this object. |
| 3270 */ |
| 3271 List<String> _components; |
| 3272 |
| 3273 /** |
| 3274 * The object managing [indexKeyId] and [indexLocationId]. |
| 3275 */ |
| 3276 Object indexOwner; |
| 3277 |
| 3278 /** |
| 3279 * A cached id of this location in index. |
| 3280 */ |
| 3281 int indexKeyId; |
| 3282 |
| 3283 /** |
| 3284 * A cached id of this location in index. |
| 3285 */ |
| 3286 int indexLocationId; |
| 3287 |
| 3288 /** |
| 3289 * Initialize a newly created location to represent the given [element]. |
| 3290 */ |
| 3291 ElementLocationImpl.con1(Element element) { |
| 3292 List<String> components = new List<String>(); |
| 3293 Element ancestor = element; |
| 3294 while (ancestor != null) { |
| 3295 components.insert(0, (ancestor as ElementImpl).identifier); |
| 3296 ancestor = ancestor.enclosingElement; |
| 3297 } |
| 3298 this._components = components; |
| 3299 } |
| 3300 |
| 3301 /** |
| 3302 * Initialize a newly created location from the given [encoding]. |
| 3303 */ |
| 3304 ElementLocationImpl.con2(String encoding) { |
| 3305 this._components = _decode(encoding); |
| 3306 } |
| 3307 |
| 3308 /** |
| 3309 * Initialize a newly created location from the given [components]. |
| 3310 */ |
| 3311 ElementLocationImpl.con3(List<String> components) { |
| 3312 this._components = components; |
| 3313 } |
| 3314 |
| 3315 @override |
| 3316 List<String> get components => _components; |
| 3317 |
| 3318 @override |
| 3319 String get encoding { |
| 3320 StringBuffer buffer = new StringBuffer(); |
| 3321 int length = _components.length; |
| 3322 for (int i = 0; i < length; i++) { |
| 3323 if (i > 0) { |
| 3324 buffer.writeCharCode(_SEPARATOR_CHAR); |
| 3325 } |
| 3326 _encode(buffer, _components[i]); |
| 3327 } |
| 3328 return buffer.toString(); |
| 3329 } |
| 3330 |
| 3331 @override |
| 3332 int get hashCode { |
| 3333 int result = 1; |
| 3334 for (int i = 0; i < _components.length; i++) { |
| 3335 String component = _components[i]; |
| 3336 result = 31 * result + component.hashCode; |
| 3337 } |
| 3338 return result; |
| 3339 } |
| 3340 |
| 3341 @override |
| 3342 bool operator ==(Object object) { |
| 3343 if (identical(this, object)) { |
| 3344 return true; |
| 3345 } |
| 3346 if (object is! ElementLocationImpl) { |
| 3347 return false; |
| 3348 } |
| 3349 ElementLocationImpl location = object as ElementLocationImpl; |
| 3350 List<String> otherComponents = location._components; |
| 3351 int length = _components.length; |
| 3352 if (otherComponents.length != length) { |
| 3353 return false; |
| 3354 } |
| 3355 for (int i = 0; i < length; i++) { |
| 3356 if (_components[i] != otherComponents[i]) { |
| 3357 return false; |
| 3358 } |
| 3359 } |
| 3360 return true; |
| 3361 } |
| 3362 |
| 3363 @override |
| 3364 String toString() => encoding; |
| 3365 |
| 3366 /** |
| 3367 * Decode the [encoding] of a location into a list of components and return |
| 3368 * the components. |
| 3369 */ |
| 3370 List<String> _decode(String encoding) { |
| 3371 List<String> components = new List<String>(); |
| 3372 StringBuffer buffer = new StringBuffer(); |
| 3373 int index = 0; |
| 3374 int length = encoding.length; |
| 3375 while (index < length) { |
| 3376 int currentChar = encoding.codeUnitAt(index); |
| 3377 if (currentChar == _SEPARATOR_CHAR) { |
| 3378 if (index + 1 < length && |
| 3379 encoding.codeUnitAt(index + 1) == _SEPARATOR_CHAR) { |
| 3380 buffer.writeCharCode(_SEPARATOR_CHAR); |
| 3381 index += 2; |
| 3382 } else { |
| 3383 components.add(buffer.toString()); |
| 3384 buffer = new StringBuffer(); |
| 3385 index++; |
| 3386 } |
| 3387 } else { |
| 3388 buffer.writeCharCode(currentChar); |
| 3389 index++; |
| 3390 } |
| 3391 } |
| 3392 components.add(buffer.toString()); |
| 3393 return components; |
| 3394 } |
| 3395 |
| 3396 /** |
| 3397 * Append an encoded form of the given [component] to the given [buffer]. |
| 3398 */ |
| 3399 void _encode(StringBuffer buffer, String component) { |
| 3400 int length = component.length; |
| 3401 for (int i = 0; i < length; i++) { |
| 3402 int currentChar = component.codeUnitAt(i); |
| 3403 if (currentChar == _SEPARATOR_CHAR) { |
| 3404 buffer.writeCharCode(_SEPARATOR_CHAR); |
| 3405 } |
| 3406 buffer.writeCharCode(currentChar); |
| 3407 } |
| 3408 } |
| 3409 } |
| 3410 |
| 3411 /** |
| 3412 * An object that can be used to visit an element structure. |
| 3413 */ |
| 3414 abstract class ElementVisitor<R> { |
| 3415 R visitClassElement(ClassElement element); |
| 3416 |
| 3417 R visitCompilationUnitElement(CompilationUnitElement element); |
| 3418 |
| 3419 R visitConstructorElement(ConstructorElement element); |
| 3420 |
| 3421 @deprecated |
| 3422 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element); |
| 3423 |
| 3424 R visitExportElement(ExportElement element); |
| 3425 |
| 3426 @deprecated |
| 3427 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element); |
| 3428 |
| 3429 R visitFieldElement(FieldElement element); |
| 3430 |
| 3431 R visitFieldFormalParameterElement(FieldFormalParameterElement element); |
| 3432 |
| 3433 R visitFunctionElement(FunctionElement element); |
| 3434 |
| 3435 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element); |
| 3436 |
| 3437 @deprecated |
| 3438 R visitHtmlElement(HtmlElement element); |
| 3439 |
| 3440 R visitImportElement(ImportElement element); |
| 3441 |
| 3442 R visitLabelElement(LabelElement element); |
| 3443 |
| 3444 R visitLibraryElement(LibraryElement element); |
| 3445 |
| 3446 R visitLocalVariableElement(LocalVariableElement element); |
| 3447 |
| 3448 R visitMethodElement(MethodElement element); |
| 3449 |
| 3450 R visitMultiplyDefinedElement(MultiplyDefinedElement element); |
| 3451 |
| 3452 R visitParameterElement(ParameterElement element); |
| 3453 |
| 3454 R visitPrefixElement(PrefixElement element); |
| 3455 |
| 3456 R visitPropertyAccessorElement(PropertyAccessorElement element); |
| 3457 |
| 3458 R visitTopLevelVariableElement(TopLevelVariableElement element); |
| 3459 |
| 3460 R visitTypeParameterElement(TypeParameterElement element); |
| 3461 } |
| 3462 |
| 3463 /** |
| 3464 * A script tag in an HTML file having content that defines a Dart library. |
| 3465 */ |
| 3466 @deprecated |
| 3467 abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement { |
| 3468 /** |
| 3469 * Return the library element defined by the content of the script tag. |
| 3470 */ |
| 3471 LibraryElement get scriptLibrary; |
| 3472 } |
| 3473 |
| 3474 /** |
| 3475 * A concrete implementation of an [EmbeddedHtmlScriptElement]. |
| 3476 */ |
| 3477 @deprecated |
| 3478 class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl |
| 3479 implements EmbeddedHtmlScriptElement { |
| 3480 /** |
| 3481 * The library defined by the script tag's content. |
| 3482 */ |
| 3483 LibraryElement _scriptLibrary; |
| 3484 |
| 3485 /** |
| 3486 * Initialize a newly created script element to represent the given [node]. |
| 3487 */ |
| 3488 EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node); |
| 3489 |
| 3490 @override |
| 3491 ElementKind get kind => ElementKind.EMBEDDED_HTML_SCRIPT; |
| 3492 |
| 3493 @override |
| 3494 LibraryElement get scriptLibrary => _scriptLibrary; |
| 3495 |
| 3496 /** |
| 3497 * Set the script library defined by the script tag's content to the given |
| 3498 * [library]. |
| 3499 */ |
| 3500 void set scriptLibrary(LibraryElementImpl library) { |
| 3501 library.enclosingElement = this; |
| 3502 _scriptLibrary = library; |
| 3503 } |
| 3504 |
| 3505 @override |
| 3506 accept(ElementVisitor visitor) => |
| 3507 visitor.visitEmbeddedHtmlScriptElement(this); |
| 3508 |
| 3509 @override |
| 3510 void visitChildren(ElementVisitor visitor) { |
| 3511 safelyVisitChild(_scriptLibrary, visitor); |
| 3512 } |
| 3513 } |
| 3514 |
| 3515 /** |
| 3516 * An element representing an executable object, including functions, methods, |
| 3517 * constructors, getters, and setters. |
| 3518 */ |
| 3519 abstract class ExecutableElement implements Element { |
| 3520 /** |
| 3521 * An empty list of executable elements. |
| 3522 */ |
| 3523 static const List<ExecutableElement> EMPTY_LIST = const <ExecutableElement>[]; |
| 3524 |
| 3525 /** |
| 3526 * Return a list containing all of the functions defined within this |
| 3527 * executable element. |
| 3528 */ |
| 3529 List<FunctionElement> get functions; |
| 3530 |
| 3531 /** |
| 3532 * Return `true` if this executable element did not have an explicit return |
| 3533 * type specified for it in the original source. Note that if there was no |
| 3534 * explicit return type, and if the element model is fully populated, then |
| 3535 * the [returnType] will not be `null`. |
| 3536 */ |
| 3537 bool get hasImplicitReturnType; |
| 3538 |
| 3539 /** |
| 3540 * Return `true` if this executable element is abstract. Executable elements |
| 3541 * are abstract if they are not external and have no body. |
| 3542 */ |
| 3543 bool get isAbstract; |
| 3544 |
| 3545 /** |
| 3546 * Return `true` if this executable element has body marked as being |
| 3547 * asynchronous. |
| 3548 */ |
| 3549 bool get isAsynchronous; |
| 3550 |
| 3551 /** |
| 3552 * Return `true` if this executable element is external. Executable elements |
| 3553 * are external if they are explicitly marked as such using the 'external' |
| 3554 * keyword. |
| 3555 */ |
| 3556 bool get isExternal; |
| 3557 |
| 3558 /** |
| 3559 * Return `true` if this executable element has a body marked as being a |
| 3560 * generator. |
| 3561 */ |
| 3562 bool get isGenerator; |
| 3563 |
| 3564 /** |
| 3565 * Return `true` if this executable element is an operator. The test may be |
| 3566 * based on the name of the executable element, in which case the result will |
| 3567 * be correct when the name is legal. |
| 3568 */ |
| 3569 bool get isOperator; |
| 3570 |
| 3571 /** |
| 3572 * Return `true` if this element is a static element. A static element is an |
| 3573 * element that is not associated with a particular instance, but rather with |
| 3574 * an entire library or class. |
| 3575 */ |
| 3576 bool get isStatic; |
| 3577 |
| 3578 /** |
| 3579 * Return `true` if this executable element has a body marked as being |
| 3580 * synchronous. |
| 3581 */ |
| 3582 bool get isSynchronous; |
| 3583 |
| 3584 /** |
| 3585 * Return a list containing all of the labels defined within this executable |
| 3586 * element. |
| 3587 */ |
| 3588 List<LabelElement> get labels; |
| 3589 |
| 3590 /** |
| 3591 * Return a list containing all of the local variables defined within this |
| 3592 * executable element. |
| 3593 */ |
| 3594 List<LocalVariableElement> get localVariables; |
| 3595 |
| 3596 /** |
| 3597 * Return a list containing all of the parameters defined by this executable |
| 3598 * element. |
| 3599 */ |
| 3600 List<ParameterElement> get parameters; |
| 3601 |
| 3602 /** |
| 3603 * Return the return type defined by this executable element. If the element |
| 3604 * model is fully populated, then the [returnType] will not be `null`, even |
| 3605 * if no return type was explicitly specified. |
| 3606 */ |
| 3607 DartType get returnType; |
| 3608 |
| 3609 /** |
| 3610 * Return the type of function defined by this executable element. |
| 3611 */ |
| 3612 FunctionType get type; |
| 3613 |
| 3614 /** |
| 3615 * Return a list containing all of the type parameters defined for this |
| 3616 * executable element. |
| 3617 */ |
| 3618 List<TypeParameterElement> get typeParameters; |
| 3619 } |
| 3620 |
| 3621 /** |
| 3622 * A base class for concrete implementations of an [ExecutableElement]. |
| 3623 */ |
| 3624 abstract class ExecutableElementImpl extends ElementImpl |
| 3625 implements ExecutableElement { |
| 3626 /** |
| 3627 * An empty list of executable elements. |
| 3628 */ |
| 3629 @deprecated // Use ExecutableElement.EMPTY_LIST |
| 3630 static const List<ExecutableElement> EMPTY_ARRAY = |
| 3631 const <ExecutableElement>[]; |
| 3632 |
| 3633 /** |
| 3634 * A list containing all of the functions defined within this executable |
| 3635 * element. |
| 3636 */ |
| 3637 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; |
| 3638 |
| 3639 /** |
| 3640 * A list containing all of the labels defined within this executable element. |
| 3641 */ |
| 3642 List<LabelElement> _labels = LabelElement.EMPTY_LIST; |
| 3643 |
| 3644 /** |
| 3645 * A list containing all of the local variables defined within this executable |
| 3646 * element. |
| 3647 */ |
| 3648 List<LocalVariableElement> _localVariables = LocalVariableElement.EMPTY_LIST; |
| 3649 |
| 3650 /** |
| 3651 * A list containing all of the parameters defined by this executable element. |
| 3652 */ |
| 3653 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; |
| 3654 |
| 3655 /** |
| 3656 * A list containing all of the type parameters defined for this executable |
| 3657 * element. |
| 3658 */ |
| 3659 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| 3660 |
| 3661 /** |
| 3662 * The return type defined by this executable element. |
| 3663 */ |
| 3664 DartType returnType; |
| 3665 |
| 3666 /** |
| 3667 * The type of function defined by this executable element. |
| 3668 */ |
| 3669 FunctionType type; |
| 3670 |
| 3671 /** |
| 3672 * Initialize a newly created executable element to have the given [name] and |
| 3673 * [offset]. |
| 3674 */ |
| 3675 ExecutableElementImpl(String name, int offset) : super(name, offset); |
| 3676 |
| 3677 /** |
| 3678 * Initialize a newly created executable element to have the given [name]. |
| 3679 */ |
| 3680 ExecutableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 3681 |
| 3682 /** |
| 3683 * Set whether this executable element's body is asynchronous. |
| 3684 */ |
| 3685 void set asynchronous(bool isAsynchronous) { |
| 3686 setModifier(Modifier.ASYNCHRONOUS, isAsynchronous); |
| 3687 } |
| 3688 |
| 3689 /** |
| 3690 * Set whether this executable element is external. |
| 3691 */ |
| 3692 void set external(bool isExternal) { |
| 3693 setModifier(Modifier.EXTERNAL, isExternal); |
| 3694 } |
| 3695 |
| 3696 @override |
| 3697 List<FunctionElement> get functions => _functions; |
| 3698 |
| 3699 /** |
| 3700 * Set the functions defined within this executable element to the given |
| 3701 * [functions]. |
| 3702 */ |
| 3703 void set functions(List<FunctionElement> functions) { |
| 3704 for (FunctionElement function in functions) { |
| 3705 (function as FunctionElementImpl).enclosingElement = this; |
| 3706 } |
| 3707 this._functions = functions; |
| 3708 } |
| 3709 |
| 3710 /** |
| 3711 * Set whether this method's body is a generator. |
| 3712 */ |
| 3713 void set generator(bool isGenerator) { |
| 3714 setModifier(Modifier.GENERATOR, isGenerator); |
| 3715 } |
| 3716 |
| 3717 @override |
| 3718 bool get hasImplicitReturnType => hasModifier(Modifier.IMPLICIT_TYPE); |
| 3719 |
| 3720 /** |
| 3721 * Set whether this executable element has an implicit return type. |
| 3722 */ |
| 3723 void set hasImplicitReturnType(bool hasImplicitReturnType) { |
| 3724 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType); |
| 3725 } |
| 3726 |
| 3727 @override |
| 3728 bool get isAbstract => hasModifier(Modifier.ABSTRACT); |
| 3729 |
| 3730 @override |
| 3731 bool get isAsynchronous => hasModifier(Modifier.ASYNCHRONOUS); |
| 3732 |
| 3733 @override |
| 3734 bool get isExternal => hasModifier(Modifier.EXTERNAL); |
| 3735 |
| 3736 @override |
| 3737 bool get isGenerator => hasModifier(Modifier.GENERATOR); |
| 3738 |
| 3739 @override |
| 3740 bool get isOperator => false; |
| 3741 |
| 3742 @override |
| 3743 bool get isSynchronous => !hasModifier(Modifier.ASYNCHRONOUS); |
| 3744 |
| 3745 @override |
| 3746 List<LabelElement> get labels => _labels; |
| 3747 |
| 3748 /** |
| 3749 * Set the labels defined within this executable element to the given |
| 3750 * [labels]. |
| 3751 */ |
| 3752 void set labels(List<LabelElement> labels) { |
| 3753 for (LabelElement label in labels) { |
| 3754 (label as LabelElementImpl).enclosingElement = this; |
| 3755 } |
| 3756 this._labels = labels; |
| 3757 } |
| 3758 |
| 3759 @override |
| 3760 List<LocalVariableElement> get localVariables => _localVariables; |
| 3761 |
| 3762 /** |
| 3763 * Set the local variables defined within this executable element to the given |
| 3764 * [variables]. |
| 3765 */ |
| 3766 void set localVariables(List<LocalVariableElement> variables) { |
| 3767 for (LocalVariableElement variable in variables) { |
| 3768 (variable as LocalVariableElementImpl).enclosingElement = this; |
| 3769 } |
| 3770 this._localVariables = variables; |
| 3771 } |
| 3772 |
| 3773 @override |
| 3774 List<ParameterElement> get parameters => _parameters; |
| 3775 |
| 3776 /** |
| 3777 * Set the parameters defined by this executable element to the given |
| 3778 * [parameters]. |
| 3779 */ |
| 3780 void set parameters(List<ParameterElement> parameters) { |
| 3781 for (ParameterElement parameter in parameters) { |
| 3782 (parameter as ParameterElementImpl).enclosingElement = this; |
| 3783 } |
| 3784 this._parameters = parameters; |
| 3785 } |
| 3786 |
| 3787 @override |
| 3788 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 3789 |
| 3790 /** |
| 3791 * Set the type parameters defined by this executable element to the given |
| 3792 * [typeParameters]. |
| 3793 */ |
| 3794 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 3795 for (TypeParameterElement parameter in typeParameters) { |
| 3796 (parameter as TypeParameterElementImpl).enclosingElement = this; |
| 3797 } |
| 3798 this._typeParameters = typeParameters; |
| 3799 } |
| 3800 |
| 3801 @override |
| 3802 void appendTo(StringBuffer buffer) { |
| 3803 if (this.kind != ElementKind.GETTER) { |
| 3804 int typeParameterCount = _typeParameters.length; |
| 3805 if (typeParameterCount > 0) { |
| 3806 buffer.write('<'); |
| 3807 for (int i = 0; i < typeParameterCount; i++) { |
| 3808 if (i > 0) { |
| 3809 buffer.write(", "); |
| 3810 } |
| 3811 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); |
| 3812 } |
| 3813 buffer.write('>'); |
| 3814 } |
| 3815 buffer.write("("); |
| 3816 String closing = null; |
| 3817 ParameterKind kind = ParameterKind.REQUIRED; |
| 3818 int parameterCount = _parameters.length; |
| 3819 for (int i = 0; i < parameterCount; i++) { |
| 3820 if (i > 0) { |
| 3821 buffer.write(", "); |
| 3822 } |
| 3823 ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl; |
| 3824 ParameterKind parameterKind = parameter.parameterKind; |
| 3825 if (parameterKind != kind) { |
| 3826 if (closing != null) { |
| 3827 buffer.write(closing); |
| 3828 } |
| 3829 if (parameterKind == ParameterKind.POSITIONAL) { |
| 3830 buffer.write("["); |
| 3831 closing = "]"; |
| 3832 } else if (parameterKind == ParameterKind.NAMED) { |
| 3833 buffer.write("{"); |
| 3834 closing = "}"; |
| 3835 } else { |
| 3836 closing = null; |
| 3837 } |
| 3838 } |
| 3839 kind = parameterKind; |
| 3840 parameter.appendToWithoutDelimiters(buffer); |
| 3841 } |
| 3842 if (closing != null) { |
| 3843 buffer.write(closing); |
| 3844 } |
| 3845 buffer.write(")"); |
| 3846 } |
| 3847 if (type != null) { |
| 3848 buffer.write(Element.RIGHT_ARROW); |
| 3849 buffer.write(type.returnType); |
| 3850 } |
| 3851 } |
| 3852 |
| 3853 @override |
| 3854 ElementImpl getChild(String identifier) { |
| 3855 for (ExecutableElement function in _functions) { |
| 3856 if ((function as ExecutableElementImpl).identifier == identifier) { |
| 3857 return function as ExecutableElementImpl; |
| 3858 } |
| 3859 } |
| 3860 for (LabelElement label in _labels) { |
| 3861 if ((label as LabelElementImpl).identifier == identifier) { |
| 3862 return label as LabelElementImpl; |
| 3863 } |
| 3864 } |
| 3865 for (VariableElement variable in _localVariables) { |
| 3866 if ((variable as VariableElementImpl).identifier == identifier) { |
| 3867 return variable as VariableElementImpl; |
| 3868 } |
| 3869 } |
| 3870 for (ParameterElement parameter in _parameters) { |
| 3871 if ((parameter as ParameterElementImpl).identifier == identifier) { |
| 3872 return parameter as ParameterElementImpl; |
| 3873 } |
| 3874 } |
| 3875 return null; |
| 3876 } |
| 3877 |
| 3878 @override |
| 3879 void visitChildren(ElementVisitor visitor) { |
| 3880 super.visitChildren(visitor); |
| 3881 safelyVisitChildren(_functions, visitor); |
| 3882 safelyVisitChildren(_labels, visitor); |
| 3883 safelyVisitChildren(_localVariables, visitor); |
| 3884 safelyVisitChildren(_parameters, visitor); |
| 3885 } |
| 3886 } |
| 3887 |
| 3888 /** |
| 3889 * An executable element defined in a parameterized type where the values of the |
| 3890 * type parameters are known. |
| 3891 */ |
| 3892 abstract class ExecutableMember extends Member implements ExecutableElement { |
| 3893 /** |
| 3894 * Initialize a newly created element to represent a constructor, based on the |
| 3895 * [baseElement], defined by the [definingType]. |
| 3896 */ |
| 3897 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType) |
| 3898 : super(baseElement, definingType); |
| 3899 |
| 3900 @override |
| 3901 ExecutableElement get baseElement => super.baseElement as ExecutableElement; |
| 3902 |
| 3903 @override |
| 3904 List<FunctionElement> get functions { |
| 3905 // |
| 3906 // Elements within this element should have type parameters substituted, |
| 3907 // just like this element. |
| 3908 // |
| 3909 throw new UnsupportedOperationException(); |
| 3910 // return getBaseElement().getFunctions(); |
| 3911 } |
| 3912 |
| 3913 @override |
| 3914 bool get hasImplicitReturnType => baseElement.hasImplicitReturnType; |
| 3915 |
| 3916 @override |
| 3917 bool get isAbstract => baseElement.isAbstract; |
| 3918 |
| 3919 @override |
| 3920 bool get isAsynchronous => baseElement.isAsynchronous; |
| 3921 |
| 3922 @override |
| 3923 bool get isExternal => baseElement.isExternal; |
| 3924 |
| 3925 @override |
| 3926 bool get isGenerator => baseElement.isGenerator; |
| 3927 |
| 3928 @override |
| 3929 bool get isOperator => baseElement.isOperator; |
| 3930 |
| 3931 @override |
| 3932 bool get isStatic => baseElement.isStatic; |
| 3933 |
| 3934 @override |
| 3935 bool get isSynchronous => baseElement.isSynchronous; |
| 3936 |
| 3937 @override |
| 3938 List<LabelElement> get labels => baseElement.labels; |
| 3939 |
| 3940 @override |
| 3941 List<LocalVariableElement> get localVariables { |
| 3942 // |
| 3943 // Elements within this element should have type parameters substituted, |
| 3944 // just like this element. |
| 3945 // |
| 3946 throw new UnsupportedOperationException(); |
| 3947 // return getBaseElement().getLocalVariables(); |
| 3948 } |
| 3949 |
| 3950 @override |
| 3951 List<ParameterElement> get parameters { |
| 3952 List<ParameterElement> baseParameters = baseElement.parameters; |
| 3953 int parameterCount = baseParameters.length; |
| 3954 if (parameterCount == 0) { |
| 3955 return baseParameters; |
| 3956 } |
| 3957 List<ParameterElement> parameterizedParameters = |
| 3958 new List<ParameterElement>(parameterCount); |
| 3959 for (int i = 0; i < parameterCount; i++) { |
| 3960 parameterizedParameters[i] = |
| 3961 ParameterMember.from(baseParameters[i], definingType); |
| 3962 } |
| 3963 return parameterizedParameters; |
| 3964 } |
| 3965 |
| 3966 @override |
| 3967 DartType get returnType => substituteFor(baseElement.returnType); |
| 3968 |
| 3969 @override |
| 3970 FunctionType get type => substituteFor(baseElement.type); |
| 3971 |
| 3972 @override |
| 3973 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; |
| 3974 |
| 3975 @override |
| 3976 void visitChildren(ElementVisitor visitor) { |
| 3977 // TODO(brianwilkerson) We need to finish implementing the accessors used |
| 3978 // below so that we can safely invoke them. |
| 3979 super.visitChildren(visitor); |
| 3980 safelyVisitChildren(baseElement.functions, visitor); |
| 3981 safelyVisitChildren(labels, visitor); |
| 3982 safelyVisitChildren(baseElement.localVariables, visitor); |
| 3983 safelyVisitChildren(parameters, visitor); |
| 3984 } |
| 3985 } |
| 3986 |
| 3987 /** |
| 3988 * An export directive within a library. |
| 3989 */ |
| 3990 abstract class ExportElement implements Element, UriReferencedElement { |
| 3991 /** |
| 3992 * An empty list of export elements. |
| 3993 */ |
| 3994 @deprecated // Use ExportElement.EMPTY_LIST |
| 3995 static const List<ExportElement> EMPTY_ARRAY = const <ExportElement>[]; |
| 3996 |
| 3997 /** |
| 3998 * An empty list of export elements. |
| 3999 */ |
| 4000 static const List<ExportElement> EMPTY_LIST = const <ExportElement>[]; |
| 4001 |
| 4002 /** |
| 4003 * Return a list containing the combinators that were specified as part of the |
| 4004 * export directive in the order in which they were specified. |
| 4005 */ |
| 4006 List<NamespaceCombinator> get combinators; |
| 4007 |
| 4008 /** |
| 4009 * Return the library that is exported from this library by this export |
| 4010 * directive. |
| 4011 */ |
| 4012 LibraryElement get exportedLibrary; |
| 4013 } |
| 4014 |
| 4015 /** |
| 4016 * A concrete implementation of an [ExportElement]. |
| 4017 */ |
| 4018 class ExportElementImpl extends UriReferencedElementImpl |
| 4019 implements ExportElement { |
| 4020 /** |
| 4021 * The library that is exported from this library by this export directive. |
| 4022 */ |
| 4023 LibraryElement exportedLibrary; |
| 4024 |
| 4025 /** |
| 4026 * The combinators that were specified as part of the export directive in the |
| 4027 * order in which they were specified. |
| 4028 */ |
| 4029 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; |
| 4030 |
| 4031 /** |
| 4032 * Initialize a newly created export element at the given [offset]. |
| 4033 */ |
| 4034 ExportElementImpl(int offset) : super(null, offset); |
| 4035 |
| 4036 @override |
| 4037 String get identifier => exportedLibrary.name; |
| 4038 |
| 4039 @override |
| 4040 ElementKind get kind => ElementKind.EXPORT; |
| 4041 |
| 4042 @override |
| 4043 accept(ElementVisitor visitor) => visitor.visitExportElement(this); |
| 4044 |
| 4045 @override |
| 4046 void appendTo(StringBuffer buffer) { |
| 4047 buffer.write("export "); |
| 4048 (exportedLibrary as LibraryElementImpl).appendTo(buffer); |
| 4049 } |
| 4050 } |
| 4051 |
| 4052 /** |
| 4053 * A script tag in an HTML file having a `source` attribute that references a |
| 4054 * Dart library source file. |
| 4055 */ |
| 4056 @deprecated |
| 4057 abstract class ExternalHtmlScriptElement implements HtmlScriptElement { |
| 4058 /** |
| 4059 * Return the source referenced by this element, or `null` if this element |
| 4060 * does not reference a Dart library source file. |
| 4061 */ |
| 4062 Source get scriptSource; |
| 4063 } |
| 4064 |
| 4065 /** |
| 4066 * A concrete implementation of an [ExternalHtmlScriptElement]. |
| 4067 */ |
| 4068 @deprecated |
| 4069 class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl |
| 4070 implements ExternalHtmlScriptElement { |
| 4071 /** |
| 4072 * The source specified in the `source` attribute or `null` if unspecified. |
| 4073 */ |
| 4074 Source scriptSource; |
| 4075 |
| 4076 /** |
| 4077 * Initialize a newly created script element to correspond to the given |
| 4078 * [node]. |
| 4079 */ |
| 4080 ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node); |
| 4081 |
| 4082 @override |
| 4083 ElementKind get kind => ElementKind.EXTERNAL_HTML_SCRIPT; |
| 4084 |
| 4085 @override |
| 4086 accept(ElementVisitor visitor) => |
| 4087 visitor.visitExternalHtmlScriptElement(this); |
| 4088 } |
| 4089 |
| 4090 /** |
| 4091 * A field defined within a type. |
| 4092 */ |
| 4093 abstract class FieldElement |
| 4094 implements ClassMemberElement, PropertyInducingElement { |
| 4095 /** |
| 4096 * An empty list of field elements. |
| 4097 */ |
| 4098 static const List<FieldElement> EMPTY_LIST = const <FieldElement>[]; |
| 4099 |
| 4100 /** |
| 4101 * Return {@code true} if this element is an enum constant. |
| 4102 */ |
| 4103 bool get isEnumConstant; |
| 4104 |
| 4105 /** |
| 4106 * Return the resolved [VariableDeclaration] or [EnumConstantDeclaration] |
| 4107 * node that declares this [FieldElement]. |
| 4108 * |
| 4109 * This method is expensive, because resolved AST might be evicted from cache, |
| 4110 * so parsing and resolving will be performed. |
| 4111 */ |
| 4112 @override |
| 4113 AstNode computeNode(); |
| 4114 } |
| 4115 |
| 4116 /** |
| 4117 * A concrete implementation of a [FieldElement]. |
| 4118 */ |
| 4119 class FieldElementImpl extends PropertyInducingElementImpl |
| 4120 with PotentiallyConstVariableElement |
| 4121 implements FieldElement { |
| 4122 /** |
| 4123 * An empty list of field elements. |
| 4124 */ |
| 4125 @deprecated // Use FieldElement.EMPTY_LIST |
| 4126 static const List<FieldElement> EMPTY_ARRAY = const <FieldElement>[]; |
| 4127 |
| 4128 /** |
| 4129 * Initialize a newly created synthetic field element to have the given [name] |
| 4130 * at the given [offset]. |
| 4131 */ |
| 4132 FieldElementImpl(String name, int offset) : super(name, offset); |
| 4133 |
| 4134 /** |
| 4135 * Initialize a newly created field element to have the given [name]. |
| 4136 */ |
| 4137 FieldElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4138 |
| 4139 @override |
| 4140 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 4141 |
| 4142 @override |
| 4143 bool get isEnumConstant => |
| 4144 enclosingElement != null ? enclosingElement.isEnum : false; |
| 4145 |
| 4146 @override |
| 4147 ElementKind get kind => ElementKind.FIELD; |
| 4148 |
| 4149 /** |
| 4150 * Set whether this field is static. |
| 4151 */ |
| 4152 void set static(bool isStatic) { |
| 4153 setModifier(Modifier.STATIC, isStatic); |
| 4154 } |
| 4155 |
| 4156 @override |
| 4157 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); |
| 4158 |
| 4159 @override |
| 4160 AstNode computeNode() { |
| 4161 if (isEnumConstant) { |
| 4162 return getNodeMatching((node) => node is EnumConstantDeclaration); |
| 4163 } else { |
| 4164 return getNodeMatching((node) => node is VariableDeclaration); |
| 4165 } |
| 4166 } |
| 4167 } |
| 4168 |
| 4169 /** |
| 4170 * A field formal parameter defined within a constructor element. |
| 4171 */ |
| 4172 abstract class FieldFormalParameterElement implements ParameterElement { |
| 4173 /** |
| 4174 * Return the field element associated with this field formal parameter, or |
| 4175 * `null` if the parameter references a field that doesn't exist. |
| 4176 */ |
| 4177 FieldElement get field; |
| 4178 } |
| 4179 |
| 4180 /** |
| 4181 * A [ParameterElementImpl] that has the additional information of the |
| 4182 * [FieldElement] associated with the parameter. |
| 4183 */ |
| 4184 class FieldFormalParameterElementImpl extends ParameterElementImpl |
| 4185 implements FieldFormalParameterElement { |
| 4186 /** |
| 4187 * The field associated with this field formal parameter. |
| 4188 */ |
| 4189 FieldElement field; |
| 4190 |
| 4191 /** |
| 4192 * Initialize a newly created parameter element to have the given [name]. |
| 4193 */ |
| 4194 FieldFormalParameterElementImpl(Identifier name) : super.forNode(name); |
| 4195 |
| 4196 @override |
| 4197 bool get isInitializingFormal => true; |
| 4198 |
| 4199 @override |
| 4200 accept(ElementVisitor visitor) => |
| 4201 visitor.visitFieldFormalParameterElement(this); |
| 4202 } |
| 4203 |
| 4204 /** |
| 4205 * A parameter element defined in a parameterized type where the values of the |
| 4206 * type parameters are known. |
| 4207 */ |
| 4208 class FieldFormalParameterMember extends ParameterMember |
| 4209 implements FieldFormalParameterElement { |
| 4210 /** |
| 4211 * Initialize a newly created element to represent a constructor, based on the |
| 4212 * [baseElement], defined by the [definingType]. |
| 4213 */ |
| 4214 FieldFormalParameterMember( |
| 4215 FieldFormalParameterElement baseElement, ParameterizedType definingType) |
| 4216 : super(baseElement, definingType); |
| 4217 |
| 4218 @override |
| 4219 FieldElement get field { |
| 4220 FieldElement field = (baseElement as FieldFormalParameterElement).field; |
| 4221 if (field is FieldElement) { |
| 4222 return FieldMember.from(field, definingType); |
| 4223 } |
| 4224 return field; |
| 4225 } |
| 4226 |
| 4227 @override |
| 4228 accept(ElementVisitor visitor) => |
| 4229 visitor.visitFieldFormalParameterElement(this); |
| 4230 } |
| 4231 |
| 4232 /** |
| 4233 * A field element defined in a parameterized type where the values of the type |
| 4234 * parameters are known. |
| 4235 */ |
| 4236 class FieldMember extends VariableMember implements FieldElement { |
| 4237 /** |
| 4238 * Initialize a newly created element to represent a constructor, based on the |
| 4239 * [baseElement], defined by the [definingType]. |
| 4240 */ |
| 4241 FieldMember(FieldElement baseElement, InterfaceType definingType) |
| 4242 : super(baseElement, definingType); |
| 4243 |
| 4244 @override |
| 4245 FieldElement get baseElement => super.baseElement as FieldElement; |
| 4246 |
| 4247 @override |
| 4248 InterfaceType get definingType => super.definingType as InterfaceType; |
| 4249 |
| 4250 @override |
| 4251 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 4252 |
| 4253 @override |
| 4254 PropertyAccessorElement get getter => |
| 4255 PropertyAccessorMember.from(baseElement.getter, definingType); |
| 4256 |
| 4257 @override |
| 4258 bool get isEnumConstant => baseElement.isEnumConstant; |
| 4259 |
| 4260 @override |
| 4261 DartType get propagatedType => substituteFor(baseElement.propagatedType); |
| 4262 |
| 4263 @override |
| 4264 PropertyAccessorElement get setter => |
| 4265 PropertyAccessorMember.from(baseElement.setter, definingType); |
| 4266 |
| 4267 @override |
| 4268 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); |
| 4269 |
| 4270 @override |
| 4271 VariableDeclaration computeNode() => baseElement.computeNode(); |
| 4272 |
| 4273 @override |
| 4274 String toString() => '$type $displayName'; |
| 4275 |
| 4276 /** |
| 4277 * If the given [field]'s type is different when any type parameters from the |
| 4278 * defining type's declaration are replaced with the actual type arguments |
| 4279 * from the [definingType], create a field member representing the given |
| 4280 * field. Return the member that was created, or the base field if no member |
| 4281 * was created. |
| 4282 */ |
| 4283 static FieldElement from(FieldElement field, InterfaceType definingType) { |
| 4284 if (!_isChangedByTypeSubstitution(field, definingType)) { |
| 4285 return field; |
| 4286 } |
| 4287 // TODO(brianwilkerson) Consider caching the substituted type in the |
| 4288 // instance. It would use more memory but speed up some operations. |
| 4289 // We need to see how often the type is being re-computed. |
| 4290 return new FieldMember(field, definingType); |
| 4291 } |
| 4292 |
| 4293 /** |
| 4294 * Determine whether the given [field]'s type is changed when type parameters |
| 4295 * from the [definingType]'s declaration are replaced with the actual type |
| 4296 * arguments from the defining type. |
| 4297 */ |
| 4298 static bool _isChangedByTypeSubstitution( |
| 4299 FieldElement field, InterfaceType definingType) { |
| 4300 List<DartType> argumentTypes = definingType.typeArguments; |
| 4301 if (field != null && argumentTypes.length != 0) { |
| 4302 DartType baseType = field.type; |
| 4303 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 4304 if (baseType != null) { |
| 4305 DartType substitutedType = |
| 4306 baseType.substitute2(argumentTypes, parameterTypes); |
| 4307 if (baseType != substitutedType) { |
| 4308 return true; |
| 4309 } |
| 4310 } |
| 4311 // If the field has a propagated type, then we need to check whether the |
| 4312 // propagated type needs substitution. |
| 4313 DartType basePropagatedType = field.propagatedType; |
| 4314 if (basePropagatedType != null) { |
| 4315 DartType substitutedPropagatedType = |
| 4316 basePropagatedType.substitute2(argumentTypes, parameterTypes); |
| 4317 if (basePropagatedType != substitutedPropagatedType) { |
| 4318 return true; |
| 4319 } |
| 4320 } |
| 4321 } |
| 4322 return false; |
| 4323 } |
| 4324 } |
| 4325 |
| 4326 /** |
| 4327 * A (non-method) function. This can be either a top-level function, a local |
| 4328 * function, a closure, or the initialization expression for a field or |
| 4329 * variable. |
| 4330 */ |
| 4331 abstract class FunctionElement implements ExecutableElement, LocalElement { |
| 4332 /** |
| 4333 * An empty list of function elements. |
| 4334 */ |
| 4335 static const List<FunctionElement> EMPTY_LIST = const <FunctionElement>[]; |
| 4336 |
| 4337 /** |
| 4338 * The name of the method that can be implemented by a class to allow its |
| 4339 * instances to be invoked as if they were a function. |
| 4340 */ |
| 4341 static final String CALL_METHOD_NAME = "call"; |
| 4342 |
| 4343 /** |
| 4344 * The name of the synthetic function defined for libraries that are deferred. |
| 4345 */ |
| 4346 static final String LOAD_LIBRARY_NAME = "loadLibrary"; |
| 4347 |
| 4348 /** |
| 4349 * The name of the function used as an entry point. |
| 4350 */ |
| 4351 static const String MAIN_FUNCTION_NAME = "main"; |
| 4352 |
| 4353 /** |
| 4354 * The name of the method that will be invoked if an attempt is made to invoke |
| 4355 * an undefined method on an object. |
| 4356 */ |
| 4357 static final String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod"; |
| 4358 |
| 4359 /** |
| 4360 * Return `true` if the function is an entry point, i.e. a top-level function |
| 4361 * and has the name `main`. |
| 4362 */ |
| 4363 bool get isEntryPoint; |
| 4364 |
| 4365 /** |
| 4366 * Return the resolved function declaration node that declares this element. |
| 4367 * |
| 4368 * This method is expensive, because resolved AST might be evicted from cache, |
| 4369 * so parsing and resolving will be performed. |
| 4370 */ |
| 4371 @override |
| 4372 FunctionDeclaration computeNode(); |
| 4373 } |
| 4374 |
| 4375 /** |
| 4376 * A concrete implementation of a [FunctionElement]. |
| 4377 */ |
| 4378 class FunctionElementImpl extends ExecutableElementImpl |
| 4379 implements FunctionElement { |
| 4380 /** |
| 4381 * An empty list of function elements. |
| 4382 */ |
| 4383 @deprecated // Use FunctionElement.EMPTY_LIST |
| 4384 static const List<FunctionElement> EMPTY_ARRAY = const <FunctionElement>[]; |
| 4385 |
| 4386 /** |
| 4387 * The offset to the beginning of the visible range for this element. |
| 4388 */ |
| 4389 int _visibleRangeOffset = 0; |
| 4390 |
| 4391 /** |
| 4392 * The length of the visible range for this element, or `-1` if this element |
| 4393 * does not have a visible range. |
| 4394 */ |
| 4395 int _visibleRangeLength = -1; |
| 4396 |
| 4397 /** |
| 4398 * Initialize a newly created function element to have the given [name] and |
| 4399 * [offset]. |
| 4400 */ |
| 4401 FunctionElementImpl(String name, int offset) : super(name, offset); |
| 4402 |
| 4403 /** |
| 4404 * Initialize a newly created function element to have the given [name]. |
| 4405 */ |
| 4406 FunctionElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4407 |
| 4408 /** |
| 4409 * Initialize a newly created function element to have no name and the given |
| 4410 * [offset]. This is used for function expressions, that have no name. |
| 4411 */ |
| 4412 FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset); |
| 4413 |
| 4414 @override |
| 4415 String get identifier { |
| 4416 String identifier = super.identifier; |
| 4417 if (!isStatic) { |
| 4418 identifier += "@$nameOffset"; |
| 4419 } |
| 4420 return identifier; |
| 4421 } |
| 4422 |
| 4423 @override |
| 4424 bool get isEntryPoint { |
| 4425 return isStatic && displayName == FunctionElement.MAIN_FUNCTION_NAME; |
| 4426 } |
| 4427 |
| 4428 @override |
| 4429 bool get isStatic => enclosingElement is CompilationUnitElement; |
| 4430 |
| 4431 @override |
| 4432 ElementKind get kind => ElementKind.FUNCTION; |
| 4433 |
| 4434 @override |
| 4435 SourceRange get visibleRange { |
| 4436 if (_visibleRangeLength < 0) { |
| 4437 return null; |
| 4438 } |
| 4439 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 4440 } |
| 4441 |
| 4442 @override |
| 4443 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this); |
| 4444 |
| 4445 @override |
| 4446 void appendTo(StringBuffer buffer) { |
| 4447 String name = displayName; |
| 4448 if (name != null) { |
| 4449 buffer.write(name); |
| 4450 } |
| 4451 super.appendTo(buffer); |
| 4452 } |
| 4453 |
| 4454 @override |
| 4455 FunctionDeclaration computeNode() => |
| 4456 getNodeMatching((node) => node is FunctionDeclaration); |
| 4457 |
| 4458 /** |
| 4459 * Set the visible range for this element to the range starting at the given |
| 4460 * [offset] with the given [length]. |
| 4461 */ |
| 4462 void setVisibleRange(int offset, int length) { |
| 4463 _visibleRangeOffset = offset; |
| 4464 _visibleRangeLength = length; |
| 4465 } |
| 4466 } |
| 4467 |
| 4468 /** |
| 4469 * The type of a function, method, constructor, getter, or setter. Function |
| 4470 * types come in three variations: |
| 4471 * |
| 4472 * * The types of functions that only have required parameters. These have the |
| 4473 * general form <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i>. |
| 4474 * * The types of functions with optional positional parameters. These have the |
| 4475 * general form <i>(T<sub>1</sub>, …, T<sub>n</sub>, [T<sub>n+1</sub> |
| 4476 * …, T<sub>n+k</sub>]) → T</i>. |
| 4477 * * The types of functions with named parameters. These have the general form |
| 4478 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>x1</sub> x1, …, |
| 4479 * T<sub>xk</sub> xk}) → T</i>. |
| 4480 */ |
| 4481 abstract class FunctionType implements ParameterizedType { |
| 4482 /** |
| 4483 * Return a map from the names of named parameters to the types of the named |
| 4484 * parameters of this type of function. The entries in the map will be |
| 4485 * iterated in the same order as the order in which the named parameters were |
| 4486 * defined. If there were no named parameters declared then the map will be |
| 4487 * empty. |
| 4488 */ |
| 4489 Map<String, DartType> get namedParameterTypes; |
| 4490 |
| 4491 /** |
| 4492 * Return a list containing the types of the normal parameters of this type of |
| 4493 * function. The parameter types are in the same order as they appear in the |
| 4494 * declaration of the function. |
| 4495 */ |
| 4496 List<DartType> get normalParameterTypes; |
| 4497 |
| 4498 /** |
| 4499 * Return a map from the names of optional (positional) parameters to the |
| 4500 * types of the optional parameters of this type of function. The entries in |
| 4501 * the map will be iterated in the same order as the order in which the |
| 4502 * optional parameters were defined. If there were no optional parameters |
| 4503 * declared then the map will be empty. |
| 4504 */ |
| 4505 List<DartType> get optionalParameterTypes; |
| 4506 |
| 4507 /** |
| 4508 * Return a list containing the parameters elements of this type of function. |
| 4509 * The parameter types are in the same order as they appear in the declaration |
| 4510 * of the function. |
| 4511 */ |
| 4512 List<ParameterElement> get parameters; |
| 4513 |
| 4514 /** |
| 4515 * Return the type of object returned by this type of function. |
| 4516 */ |
| 4517 DartType get returnType; |
| 4518 |
| 4519 /** |
| 4520 * Return `true` if this type is a subtype of the given [type]. |
| 4521 * |
| 4522 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i> is |
| 4523 * a subtype of the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>) |
| 4524 * → S</i>, if all of the following conditions are met: |
| 4525 * |
| 4526 * * Either |
| 4527 * * <i>S</i> is void, or |
| 4528 * * <i>T ⇔ S</i>. |
| 4529 * |
| 4530 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ |
| 4531 * S<sub>i</sub></i>. |
| 4532 * |
| 4533 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, |
| 4534 * [T<sub>n+1</sub>, …, T<sub>n+k</sub>]) → T</i> is a subtype of |
| 4535 * the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>, |
| 4536 * [S<sub>n+1</sub>, …, S<sub>n+m</sub>]) → S</i>, if all of the |
| 4537 * following conditions are met: |
| 4538 * |
| 4539 * * Either |
| 4540 * * <i>S</i> is void, or |
| 4541 * * <i>T ⇔ S</i>. |
| 4542 * |
| 4543 * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, |
| 4544 * <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>. |
| 4545 * |
| 4546 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, |
| 4547 * {T<sub>x1</sub> x1, …, T<sub>xk</sub> xk}) → T</i> is a subtype |
| 4548 * of the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>, |
| 4549 * {S<sub>y1</sub> y1, …, S<sub>ym</sub> ym}) → S</i>, if all of |
| 4550 * the following conditions are met: |
| 4551 * * Either |
| 4552 * * <i>S</i> is void, |
| 4553 * * or <i>T ⇔ S</i>. |
| 4554 * |
| 4555 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ |
| 4556 * S<sub>i</sub></i>. |
| 4557 * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, |
| 4558 * …, x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>. |
| 4559 * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, …, |
| 4560 * y<sub>m</sub>}</i>, <i>y<sub>i</sub> = x<sub>j</sub> => Tj ⇔ Si</i>. |
| 4561 * |
| 4562 * In addition, the following subtype rules apply: |
| 4563 * |
| 4564 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, []) → T <: (T<sub>1</sub>, |
| 4565 * …, T<sub>n</sub>) → T.</i><br> |
| 4566 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, |
| 4567 * …, T<sub>n</sub>, {}) → T.</i><br> |
| 4568 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, {}) → T <: (T<sub>1</sub>, |
| 4569 * …, T<sub>n</sub>) → T.</i><br> |
| 4570 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, |
| 4571 * …, T<sub>n</sub>, []) → T.</i> |
| 4572 * |
| 4573 * All functions implement the class `Function`. However not all function |
| 4574 * types are a subtype of `Function`. If an interface type <i>I</i> includes a |
| 4575 * method named `call()`, and the type of `call()` is the function type |
| 4576 * <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>. |
| 4577 */ |
| 4578 @override |
| 4579 bool isSubtypeOf(DartType type); |
| 4580 |
| 4581 @override |
| 4582 FunctionType substitute2( |
| 4583 List<DartType> argumentTypes, List<DartType> parameterTypes); |
| 4584 |
| 4585 /** |
| 4586 * Return the type resulting from substituting the given [argumentTypes] for |
| 4587 * this type's parameters. This is fully equivalent to |
| 4588 * `substitute(argumentTypes, getTypeArguments())`. |
| 4589 */ |
| 4590 FunctionType substitute3(List<DartType> argumentTypes); |
| 4591 } |
| 4592 |
| 4593 /** |
| 4594 * A function type alias (`typedef`). |
| 4595 */ |
| 4596 abstract class FunctionTypeAliasElement implements TypeDefiningElement { |
| 4597 /** |
| 4598 * An empty array of type alias elements. |
| 4599 */ |
| 4600 static List<FunctionTypeAliasElement> EMPTY_LIST = |
| 4601 new List<FunctionTypeAliasElement>(0); |
| 4602 |
| 4603 /** |
| 4604 * Return the compilation unit in which this type alias is defined. |
| 4605 */ |
| 4606 @override |
| 4607 CompilationUnitElement get enclosingElement; |
| 4608 |
| 4609 /** |
| 4610 * Return a list containing all of the parameters defined by this type alias. |
| 4611 */ |
| 4612 List<ParameterElement> get parameters; |
| 4613 |
| 4614 /** |
| 4615 * Return the return type defined by this type alias. |
| 4616 */ |
| 4617 DartType get returnType; |
| 4618 |
| 4619 @override |
| 4620 FunctionType get type; |
| 4621 |
| 4622 /** |
| 4623 * Return a list containing all of the type parameters defined for this type. |
| 4624 */ |
| 4625 List<TypeParameterElement> get typeParameters; |
| 4626 |
| 4627 /** |
| 4628 * Return the resolved function type alias node that declares this element. |
| 4629 * |
| 4630 * This method is expensive, because resolved AST might be evicted from cache, |
| 4631 * so parsing and resolving will be performed. |
| 4632 */ |
| 4633 @override |
| 4634 FunctionTypeAlias computeNode(); |
| 4635 } |
| 4636 |
| 4637 /** |
| 4638 * A concrete implementation of a [FunctionTypeAliasElement]. |
| 4639 */ |
| 4640 class FunctionTypeAliasElementImpl extends ElementImpl |
| 4641 implements FunctionTypeAliasElement { |
| 4642 /** |
| 4643 * An empty array of type alias elements. |
| 4644 */ |
| 4645 @deprecated // Use FunctionTypeAliasElement.EMPTY_LIST |
| 4646 static List<FunctionTypeAliasElement> EMPTY_ARRAY = |
| 4647 new List<FunctionTypeAliasElement>(0); |
| 4648 |
| 4649 /** |
| 4650 * A list containing all of the parameters defined by this type alias. |
| 4651 */ |
| 4652 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; |
| 4653 |
| 4654 /** |
| 4655 * The return type defined by this type alias. |
| 4656 */ |
| 4657 DartType returnType; |
| 4658 |
| 4659 /** |
| 4660 * The type of function defined by this type alias. |
| 4661 */ |
| 4662 FunctionType type; |
| 4663 |
| 4664 /** |
| 4665 * A list containing all of the type parameters defined for this type. |
| 4666 */ |
| 4667 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| 4668 |
| 4669 /** |
| 4670 * Initialize a newly created type alias element to have the given name. |
| 4671 * |
| 4672 * [name] the name of this element |
| 4673 * [nameOffset] the offset of the name of this element in the file that |
| 4674 * contains the declaration of this element |
| 4675 */ |
| 4676 FunctionTypeAliasElementImpl(String name, int nameOffset) |
| 4677 : super(name, nameOffset); |
| 4678 |
| 4679 /** |
| 4680 * Initialize a newly created type alias element to have the given [name]. |
| 4681 */ |
| 4682 FunctionTypeAliasElementImpl.forNode(Identifier name) : super.forNode(name); |
| 4683 |
| 4684 @override |
| 4685 CompilationUnitElement get enclosingElement => |
| 4686 super.enclosingElement as CompilationUnitElement; |
| 4687 |
| 4688 @override |
| 4689 ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS; |
| 4690 |
| 4691 @override |
| 4692 List<ParameterElement> get parameters => _parameters; |
| 4693 |
| 4694 /** |
| 4695 * Set the parameters defined by this type alias to the given [parameters]. |
| 4696 */ |
| 4697 void set parameters(List<ParameterElement> parameters) { |
| 4698 if (parameters != null) { |
| 4699 for (ParameterElement parameter in parameters) { |
| 4700 (parameter as ParameterElementImpl).enclosingElement = this; |
| 4701 } |
| 4702 } |
| 4703 this._parameters = parameters; |
| 4704 } |
| 4705 |
| 4706 @override |
| 4707 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 4708 |
| 4709 /** |
| 4710 * Set the type parameters defined for this type to the given |
| 4711 * [typeParameters]. |
| 4712 */ |
| 4713 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 4714 for (TypeParameterElement typeParameter in typeParameters) { |
| 4715 (typeParameter as TypeParameterElementImpl).enclosingElement = this; |
| 4716 } |
| 4717 this._typeParameters = typeParameters; |
| 4718 } |
| 4719 |
| 4720 @override |
| 4721 accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this); |
| 4722 |
| 4723 @override |
| 4724 void appendTo(StringBuffer buffer) { |
| 4725 buffer.write("typedef "); |
| 4726 buffer.write(displayName); |
| 4727 int typeParameterCount = _typeParameters.length; |
| 4728 if (typeParameterCount > 0) { |
| 4729 buffer.write("<"); |
| 4730 for (int i = 0; i < typeParameterCount; i++) { |
| 4731 if (i > 0) { |
| 4732 buffer.write(", "); |
| 4733 } |
| 4734 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); |
| 4735 } |
| 4736 buffer.write(">"); |
| 4737 } |
| 4738 buffer.write("("); |
| 4739 int parameterCount = _parameters.length; |
| 4740 for (int i = 0; i < parameterCount; i++) { |
| 4741 if (i > 0) { |
| 4742 buffer.write(", "); |
| 4743 } |
| 4744 (_parameters[i] as ParameterElementImpl).appendTo(buffer); |
| 4745 } |
| 4746 buffer.write(")"); |
| 4747 if (type != null) { |
| 4748 buffer.write(Element.RIGHT_ARROW); |
| 4749 buffer.write(type.returnType); |
| 4750 } else if (returnType != null) { |
| 4751 buffer.write(Element.RIGHT_ARROW); |
| 4752 buffer.write(returnType); |
| 4753 } |
| 4754 } |
| 4755 |
| 4756 @override |
| 4757 FunctionTypeAlias computeNode() => |
| 4758 getNodeMatching((node) => node is FunctionTypeAlias); |
| 4759 |
| 4760 @override |
| 4761 ElementImpl getChild(String identifier) { |
| 4762 for (VariableElement parameter in _parameters) { |
| 4763 if ((parameter as VariableElementImpl).identifier == identifier) { |
| 4764 return parameter as VariableElementImpl; |
| 4765 } |
| 4766 } |
| 4767 for (TypeParameterElement typeParameter in _typeParameters) { |
| 4768 if ((typeParameter as TypeParameterElementImpl).identifier == |
| 4769 identifier) { |
| 4770 return typeParameter as TypeParameterElementImpl; |
| 4771 } |
| 4772 } |
| 4773 return null; |
| 4774 } |
| 4775 |
| 4776 /** |
| 4777 * Set the parameters defined by this type alias to the given [parameters] |
| 4778 * without becoming the parent of the parameters. This should only be used by |
| 4779 * the [TypeResolverVisitor] when creating a synthetic type alias. |
| 4780 */ |
| 4781 void shareParameters(List<ParameterElement> parameters) { |
| 4782 this._parameters = parameters; |
| 4783 } |
| 4784 |
| 4785 /** |
| 4786 * Set the type parameters defined for this type to the given [typeParameters] |
| 4787 * without becoming the parent of the parameters. This should only be used by |
| 4788 * the [TypeResolverVisitor] when creating a synthetic type alias. |
| 4789 */ |
| 4790 void shareTypeParameters(List<TypeParameterElement> typeParameters) { |
| 4791 this._typeParameters = typeParameters; |
| 4792 } |
| 4793 |
| 4794 @override |
| 4795 void visitChildren(ElementVisitor visitor) { |
| 4796 super.visitChildren(visitor); |
| 4797 safelyVisitChildren(_parameters, visitor); |
| 4798 safelyVisitChildren(_typeParameters, visitor); |
| 4799 } |
| 4800 } |
| 4801 |
| 4802 /** |
| 4803 * The type of a function, method, constructor, getter, or setter. |
| 4804 */ |
| 4805 class FunctionTypeImpl extends TypeImpl implements FunctionType { |
| 4806 /** |
| 4807 * A list containing the actual types of the type arguments. |
| 4808 */ |
| 4809 List<DartType> typeArguments = DartType.EMPTY_LIST; |
| 4810 |
| 4811 /** |
| 4812 * The set of typedefs which should not be expanded when exploring this type, |
| 4813 * to avoid creating infinite types in response to self-referential typedefs. |
| 4814 */ |
| 4815 final List<FunctionTypeAliasElement> prunedTypedefs; |
| 4816 |
| 4817 /** |
| 4818 * Initialize a newly created function type to be declared by the given |
| 4819 * [element]. |
| 4820 */ |
| 4821 FunctionTypeImpl(ExecutableElement element, [this.prunedTypedefs]) |
| 4822 : super(element, null); |
| 4823 |
| 4824 /** |
| 4825 * Initialize a newly created function type to be declared by the given |
| 4826 * [element]. |
| 4827 */ |
| 4828 @deprecated // Use new FunctionTypeImpl(element) |
| 4829 FunctionTypeImpl.con1(ExecutableElement element) |
| 4830 : prunedTypedefs = null, |
| 4831 super(element, null); |
| 4832 |
| 4833 /** |
| 4834 * Initialize a newly created function type to be declared by the given |
| 4835 * [element]. |
| 4836 */ |
| 4837 @deprecated // Use new FunctionTypeImpl.forTypedef(element) |
| 4838 FunctionTypeImpl.con2(FunctionTypeAliasElement element) |
| 4839 : prunedTypedefs = null, |
| 4840 super(element, element == null ? null : element.name); |
| 4841 |
| 4842 /** |
| 4843 * Initialize a newly created function type to be declared by the given |
| 4844 * [element]. |
| 4845 */ |
| 4846 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element, |
| 4847 [this.prunedTypedefs]) |
| 4848 : super(element, element == null ? null : element.name); |
| 4849 |
| 4850 /** |
| 4851 * Private constructor. |
| 4852 */ |
| 4853 FunctionTypeImpl._(Element element, String name, this.prunedTypedefs) |
| 4854 : super(element, name); |
| 4855 |
| 4856 /** |
| 4857 * Return the base parameter elements of this function element. |
| 4858 */ |
| 4859 List<ParameterElement> get baseParameters { |
| 4860 Element element = this.element; |
| 4861 if (element is ExecutableElement) { |
| 4862 return element.parameters; |
| 4863 } else { |
| 4864 return (element as FunctionTypeAliasElement).parameters; |
| 4865 } |
| 4866 } |
| 4867 |
| 4868 /** |
| 4869 * Return the return type defined by this function's element. |
| 4870 */ |
| 4871 DartType get baseReturnType { |
| 4872 Element element = this.element; |
| 4873 if (element is ExecutableElement) { |
| 4874 return element.returnType; |
| 4875 } else { |
| 4876 return (element as FunctionTypeAliasElement).returnType; |
| 4877 } |
| 4878 } |
| 4879 |
| 4880 @override |
| 4881 String get displayName { |
| 4882 String name = this.name; |
| 4883 if (name == null || name.length == 0) { |
| 4884 // Function types have an empty name when they are defined implicitly by |
| 4885 // either a closure or as part of a parameter declaration. |
| 4886 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 4887 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 4888 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; |
| 4889 DartType returnType = this.returnType; |
| 4890 StringBuffer buffer = new StringBuffer(); |
| 4891 buffer.write("("); |
| 4892 bool needsComma = false; |
| 4893 if (normalParameterTypes.length > 0) { |
| 4894 for (DartType type in normalParameterTypes) { |
| 4895 if (needsComma) { |
| 4896 buffer.write(", "); |
| 4897 } else { |
| 4898 needsComma = true; |
| 4899 } |
| 4900 buffer.write(type.displayName); |
| 4901 } |
| 4902 } |
| 4903 if (optionalParameterTypes.length > 0) { |
| 4904 if (needsComma) { |
| 4905 buffer.write(", "); |
| 4906 needsComma = false; |
| 4907 } |
| 4908 buffer.write("["); |
| 4909 for (DartType type in optionalParameterTypes) { |
| 4910 if (needsComma) { |
| 4911 buffer.write(", "); |
| 4912 } else { |
| 4913 needsComma = true; |
| 4914 } |
| 4915 buffer.write(type.displayName); |
| 4916 } |
| 4917 buffer.write("]"); |
| 4918 needsComma = true; |
| 4919 } |
| 4920 if (namedParameterTypes.length > 0) { |
| 4921 if (needsComma) { |
| 4922 buffer.write(", "); |
| 4923 needsComma = false; |
| 4924 } |
| 4925 buffer.write("{"); |
| 4926 namedParameterTypes.forEach((String name, DartType type) { |
| 4927 if (needsComma) { |
| 4928 buffer.write(", "); |
| 4929 } else { |
| 4930 needsComma = true; |
| 4931 } |
| 4932 buffer.write(name); |
| 4933 buffer.write(": "); |
| 4934 buffer.write(type.displayName); |
| 4935 }); |
| 4936 buffer.write("}"); |
| 4937 needsComma = true; |
| 4938 } |
| 4939 buffer.write(")"); |
| 4940 buffer.write(Element.RIGHT_ARROW); |
| 4941 if (returnType == null) { |
| 4942 buffer.write("null"); |
| 4943 } else { |
| 4944 buffer.write(returnType.displayName); |
| 4945 } |
| 4946 name = buffer.toString(); |
| 4947 } |
| 4948 return name; |
| 4949 } |
| 4950 |
| 4951 @override |
| 4952 int get hashCode { |
| 4953 if (element == null) { |
| 4954 return 0; |
| 4955 } |
| 4956 // Reference the arrays of parameters |
| 4957 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 4958 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 4959 Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values; |
| 4960 // Generate the hashCode |
| 4961 int code = (returnType as TypeImpl).hashCode; |
| 4962 for (int i = 0; i < normalParameterTypes.length; i++) { |
| 4963 code = (code << 1) + (normalParameterTypes[i] as TypeImpl).hashCode; |
| 4964 } |
| 4965 for (int i = 0; i < optionalParameterTypes.length; i++) { |
| 4966 code = (code << 1) + (optionalParameterTypes[i] as TypeImpl).hashCode; |
| 4967 } |
| 4968 for (DartType type in namedParameterTypes) { |
| 4969 code = (code << 1) + (type as TypeImpl).hashCode; |
| 4970 } |
| 4971 return code; |
| 4972 } |
| 4973 |
| 4974 @override |
| 4975 Map<String, DartType> get namedParameterTypes { |
| 4976 LinkedHashMap<String, DartType> namedParameterTypes = |
| 4977 new LinkedHashMap<String, DartType>(); |
| 4978 List<ParameterElement> parameters = baseParameters; |
| 4979 if (parameters.length == 0) { |
| 4980 return namedParameterTypes; |
| 4981 } |
| 4982 List<DartType> typeParameters = |
| 4983 TypeParameterTypeImpl.getTypes(this.typeParameters); |
| 4984 for (ParameterElement parameter in parameters) { |
| 4985 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 4986 DartType type = parameter.type; |
| 4987 if (typeArguments.length != 0 && |
| 4988 typeArguments.length == typeParameters.length) { |
| 4989 type = (type as TypeImpl) |
| 4990 .substitute2(typeArguments, typeParameters, newPrune); |
| 4991 } else { |
| 4992 type = (type as TypeImpl).pruned(newPrune); |
| 4993 } |
| 4994 namedParameterTypes[parameter.name] = type; |
| 4995 } |
| 4996 } |
| 4997 return namedParameterTypes; |
| 4998 } |
| 4999 |
| 5000 /** |
| 5001 * Determine the new set of typedefs which should be pruned when expanding |
| 5002 * this function type. |
| 5003 */ |
| 5004 List<FunctionTypeAliasElement> get newPrune { |
| 5005 Element element = this.element; |
| 5006 if (element is FunctionTypeAliasElement && !element.isSynthetic) { |
| 5007 // This typedef should be pruned, along with anything that was previously |
| 5008 // pruned. |
| 5009 if (prunedTypedefs == null) { |
| 5010 return <FunctionTypeAliasElement>[element]; |
| 5011 } else { |
| 5012 return new List<FunctionTypeAliasElement>.from(prunedTypedefs) |
| 5013 ..add(element); |
| 5014 } |
| 5015 } else { |
| 5016 // This is not a typedef, so nothing additional needs to be pruned. |
| 5017 return prunedTypedefs; |
| 5018 } |
| 5019 } |
| 5020 |
| 5021 @override |
| 5022 List<DartType> get normalParameterTypes { |
| 5023 List<ParameterElement> parameters = baseParameters; |
| 5024 if (parameters.length == 0) { |
| 5025 return DartType.EMPTY_LIST; |
| 5026 } |
| 5027 List<DartType> typeParameters = |
| 5028 TypeParameterTypeImpl.getTypes(this.typeParameters); |
| 5029 List<DartType> types = new List<DartType>(); |
| 5030 for (ParameterElement parameter in parameters) { |
| 5031 if (parameter.parameterKind == ParameterKind.REQUIRED) { |
| 5032 DartType type = parameter.type; |
| 5033 if (typeArguments.length != 0 && |
| 5034 typeArguments.length == typeParameters.length) { |
| 5035 type = (type as TypeImpl) |
| 5036 .substitute2(typeArguments, typeParameters, newPrune); |
| 5037 } else { |
| 5038 type = (type as TypeImpl).pruned(newPrune); |
| 5039 } |
| 5040 types.add(type); |
| 5041 } |
| 5042 } |
| 5043 return types; |
| 5044 } |
| 5045 |
| 5046 @override |
| 5047 List<DartType> get optionalParameterTypes { |
| 5048 List<ParameterElement> parameters = baseParameters; |
| 5049 if (parameters.length == 0) { |
| 5050 return DartType.EMPTY_LIST; |
| 5051 } |
| 5052 List<DartType> typeParameters = |
| 5053 TypeParameterTypeImpl.getTypes(this.typeParameters); |
| 5054 List<DartType> types = new List<DartType>(); |
| 5055 for (ParameterElement parameter in parameters) { |
| 5056 if (parameter.parameterKind == ParameterKind.POSITIONAL) { |
| 5057 DartType type = parameter.type; |
| 5058 if (typeArguments.length != 0 && |
| 5059 typeArguments.length == typeParameters.length) { |
| 5060 type = (type as TypeImpl) |
| 5061 .substitute2(typeArguments, typeParameters, newPrune); |
| 5062 } else { |
| 5063 type = (type as TypeImpl).pruned(newPrune); |
| 5064 } |
| 5065 types.add(type); |
| 5066 } |
| 5067 } |
| 5068 return types; |
| 5069 } |
| 5070 |
| 5071 @override |
| 5072 List<ParameterElement> get parameters { |
| 5073 List<ParameterElement> baseParameters = this.baseParameters; |
| 5074 // no parameters, quick return |
| 5075 int parameterCount = baseParameters.length; |
| 5076 if (parameterCount == 0) { |
| 5077 return baseParameters; |
| 5078 } |
| 5079 // create specialized parameters |
| 5080 List<ParameterElement> specializedParameters = |
| 5081 new List<ParameterElement>(parameterCount); |
| 5082 for (int i = 0; i < parameterCount; i++) { |
| 5083 specializedParameters[i] = ParameterMember.from(baseParameters[i], this); |
| 5084 } |
| 5085 return specializedParameters; |
| 5086 } |
| 5087 |
| 5088 @override |
| 5089 DartType get returnType { |
| 5090 DartType baseReturnType = this.baseReturnType; |
| 5091 if (baseReturnType == null) { |
| 5092 // TODO(brianwilkerson) This is a patch. The return type should never be |
| 5093 // null and we need to understand why it is and fix it. |
| 5094 return DynamicTypeImpl.instance; |
| 5095 } |
| 5096 // If there are no arguments to substitute, or if the arguments size doesn't |
| 5097 // match the parameter size, return the base return type. |
| 5098 if (typeArguments.length == 0 || |
| 5099 typeArguments.length != typeParameters.length) { |
| 5100 return (baseReturnType as TypeImpl).pruned(newPrune); |
| 5101 } |
| 5102 return (baseReturnType as TypeImpl).substitute2(typeArguments, |
| 5103 TypeParameterTypeImpl.getTypes(typeParameters), newPrune); |
| 5104 } |
| 5105 |
| 5106 @override |
| 5107 List<TypeParameterElement> get typeParameters { |
| 5108 Element element = this.element; |
| 5109 if (element is FunctionTypeAliasElement) { |
| 5110 return element.typeParameters; |
| 5111 } |
| 5112 ClassElement definingClass = |
| 5113 element.getAncestor((element) => element is ClassElement); |
| 5114 if (definingClass != null) { |
| 5115 return definingClass.typeParameters; |
| 5116 } |
| 5117 return TypeParameterElement.EMPTY_LIST; |
| 5118 } |
| 5119 |
| 5120 @override |
| 5121 bool operator ==(Object object) { |
| 5122 if (object is! FunctionTypeImpl) { |
| 5123 return false; |
| 5124 } |
| 5125 FunctionTypeImpl otherType = object as FunctionTypeImpl; |
| 5126 return returnType == otherType.returnType && |
| 5127 TypeImpl.equalArrays( |
| 5128 normalParameterTypes, otherType.normalParameterTypes) && |
| 5129 TypeImpl.equalArrays( |
| 5130 optionalParameterTypes, otherType.optionalParameterTypes) && |
| 5131 _equals(namedParameterTypes, otherType.namedParameterTypes); |
| 5132 } |
| 5133 |
| 5134 @override |
| 5135 void appendTo(StringBuffer buffer) { |
| 5136 List<DartType> normalParameterTypes = this.normalParameterTypes; |
| 5137 List<DartType> optionalParameterTypes = this.optionalParameterTypes; |
| 5138 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; |
| 5139 DartType returnType = this.returnType; |
| 5140 buffer.write("("); |
| 5141 bool needsComma = false; |
| 5142 if (normalParameterTypes.length > 0) { |
| 5143 for (DartType type in normalParameterTypes) { |
| 5144 if (needsComma) { |
| 5145 buffer.write(", "); |
| 5146 } else { |
| 5147 needsComma = true; |
| 5148 } |
| 5149 (type as TypeImpl).appendTo(buffer); |
| 5150 } |
| 5151 } |
| 5152 if (optionalParameterTypes.length > 0) { |
| 5153 if (needsComma) { |
| 5154 buffer.write(", "); |
| 5155 needsComma = false; |
| 5156 } |
| 5157 buffer.write("["); |
| 5158 for (DartType type in optionalParameterTypes) { |
| 5159 if (needsComma) { |
| 5160 buffer.write(", "); |
| 5161 } else { |
| 5162 needsComma = true; |
| 5163 } |
| 5164 (type as TypeImpl).appendTo(buffer); |
| 5165 } |
| 5166 buffer.write("]"); |
| 5167 needsComma = true; |
| 5168 } |
| 5169 if (namedParameterTypes.length > 0) { |
| 5170 if (needsComma) { |
| 5171 buffer.write(", "); |
| 5172 needsComma = false; |
| 5173 } |
| 5174 buffer.write("{"); |
| 5175 namedParameterTypes.forEach((String name, DartType type) { |
| 5176 if (needsComma) { |
| 5177 buffer.write(", "); |
| 5178 } else { |
| 5179 needsComma = true; |
| 5180 } |
| 5181 buffer.write(name); |
| 5182 buffer.write(": "); |
| 5183 (type as TypeImpl).appendTo(buffer); |
| 5184 }); |
| 5185 buffer.write("}"); |
| 5186 needsComma = true; |
| 5187 } |
| 5188 buffer.write(")"); |
| 5189 buffer.write(Element.RIGHT_ARROW); |
| 5190 if (returnType == null) { |
| 5191 buffer.write("null"); |
| 5192 } else { |
| 5193 (returnType as TypeImpl).appendTo(buffer); |
| 5194 } |
| 5195 } |
| 5196 |
| 5197 @override |
| 5198 bool isAssignableTo(DartType type) { |
| 5199 // A function type T may be assigned to a function type S, written T <=> S, |
| 5200 // iff T <: S. |
| 5201 return isSubtypeOf(type); |
| 5202 } |
| 5203 |
| 5204 @override |
| 5205 bool isMoreSpecificThan(DartType type, |
| 5206 [bool withDynamic = false, Set<Element> visitedElements]) { |
| 5207 // Note: visitedElements is only used for breaking recursion in the type |
| 5208 // hierarchy; we don't use it when recursing into the function type. |
| 5209 |
| 5210 // trivial base cases |
| 5211 if (type == null) { |
| 5212 return false; |
| 5213 } else if (identical(this, type) || |
| 5214 type.isDynamic || |
| 5215 type.isDartCoreFunction || |
| 5216 type.isObject) { |
| 5217 return true; |
| 5218 } else if (type is! FunctionType) { |
| 5219 return false; |
| 5220 } else if (this == type) { |
| 5221 return true; |
| 5222 } |
| 5223 FunctionType t = this; |
| 5224 FunctionType s = type as FunctionType; |
| 5225 List<DartType> tTypes = t.normalParameterTypes; |
| 5226 List<DartType> tOpTypes = t.optionalParameterTypes; |
| 5227 List<DartType> sTypes = s.normalParameterTypes; |
| 5228 List<DartType> sOpTypes = s.optionalParameterTypes; |
| 5229 // If one function has positional and the other has named parameters, |
| 5230 // return false. |
| 5231 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| 5232 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| 5233 return false; |
| 5234 } |
| 5235 // named parameters case |
| 5236 if (t.namedParameterTypes.length > 0) { |
| 5237 // check that the number of required parameters are equal, and check that |
| 5238 // every t_i is more specific than every s_i |
| 5239 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| 5240 return false; |
| 5241 } else if (t.normalParameterTypes.length > 0) { |
| 5242 for (int i = 0; i < tTypes.length; i++) { |
| 5243 if (!(tTypes[i] as TypeImpl) |
| 5244 .isMoreSpecificThan(sTypes[i], withDynamic)) { |
| 5245 return false; |
| 5246 } |
| 5247 } |
| 5248 } |
| 5249 Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| 5250 Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| 5251 // if k >= m is false, return false: the passed function type has more |
| 5252 // named parameter types than this |
| 5253 if (namedTypesT.length < namedTypesS.length) { |
| 5254 return false; |
| 5255 } |
| 5256 // Loop through each element in S verifying that T has a matching |
| 5257 // parameter name and that the corresponding type is more specific then |
| 5258 // the type in S. |
| 5259 for (String keyS in namedTypesS.keys) { |
| 5260 DartType typeT = namedTypesT[keyS]; |
| 5261 if (typeT == null) { |
| 5262 return false; |
| 5263 } |
| 5264 if (!(typeT as TypeImpl) |
| 5265 .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) { |
| 5266 return false; |
| 5267 } |
| 5268 } |
| 5269 } else if (s.namedParameterTypes.length > 0) { |
| 5270 return false; |
| 5271 } else { |
| 5272 // positional parameter case |
| 5273 int tArgLength = tTypes.length + tOpTypes.length; |
| 5274 int sArgLength = sTypes.length + sOpTypes.length; |
| 5275 // Check that the total number of parameters in t is greater than or equal |
| 5276 // to the number of parameters in s and that the number of required |
| 5277 // parameters in s is greater than or equal to the number of required |
| 5278 // parameters in t. |
| 5279 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| 5280 return false; |
| 5281 } |
| 5282 if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| 5283 // No positional arguments, don't copy contents to new array |
| 5284 for (int i = 0; i < sTypes.length; i++) { |
| 5285 if (!(tTypes[i] as TypeImpl) |
| 5286 .isMoreSpecificThan(sTypes[i], withDynamic)) { |
| 5287 return false; |
| 5288 } |
| 5289 } |
| 5290 } else { |
| 5291 // Else, we do have positional parameters, copy required and positional |
| 5292 // parameter types into arrays to do the compare (for loop below). |
| 5293 List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| 5294 for (int i = 0; i < tTypes.length; i++) { |
| 5295 tAllTypes[i] = tTypes[i]; |
| 5296 } |
| 5297 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5298 tAllTypes[i] = tOpTypes[j]; |
| 5299 } |
| 5300 List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| 5301 for (int i = 0; i < sTypes.length; i++) { |
| 5302 sAllTypes[i] = sTypes[i]; |
| 5303 } |
| 5304 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5305 sAllTypes[i] = sOpTypes[j]; |
| 5306 } |
| 5307 for (int i = 0; i < sAllTypes.length; i++) { |
| 5308 if (!(tAllTypes[i] as TypeImpl) |
| 5309 .isMoreSpecificThan(sAllTypes[i], withDynamic)) { |
| 5310 return false; |
| 5311 } |
| 5312 } |
| 5313 } |
| 5314 } |
| 5315 DartType tRetType = t.returnType; |
| 5316 DartType sRetType = s.returnType; |
| 5317 return sRetType.isVoid || |
| 5318 (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic); |
| 5319 } |
| 5320 |
| 5321 @override |
| 5322 bool isSubtypeOf(DartType type) { |
| 5323 // trivial base cases |
| 5324 if (type == null) { |
| 5325 return false; |
| 5326 } else if (identical(this, type) || |
| 5327 type.isDynamic || |
| 5328 type.isDartCoreFunction || |
| 5329 type.isObject) { |
| 5330 return true; |
| 5331 } else if (type is! FunctionType) { |
| 5332 return false; |
| 5333 } else if (this == type) { |
| 5334 return true; |
| 5335 } |
| 5336 FunctionType t = this; |
| 5337 FunctionType s = type as FunctionType; |
| 5338 List<DartType> tTypes = t.normalParameterTypes; |
| 5339 List<DartType> tOpTypes = t.optionalParameterTypes; |
| 5340 List<DartType> sTypes = s.normalParameterTypes; |
| 5341 List<DartType> sOpTypes = s.optionalParameterTypes; |
| 5342 // If one function has positional and the other has named parameters, |
| 5343 // return false. |
| 5344 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || |
| 5345 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { |
| 5346 return false; |
| 5347 } |
| 5348 // named parameters case |
| 5349 if (t.namedParameterTypes.length > 0) { |
| 5350 // check that the number of required parameters are equal, |
| 5351 // and check that every t_i is assignable to every s_i |
| 5352 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { |
| 5353 return false; |
| 5354 } else if (t.normalParameterTypes.length > 0) { |
| 5355 for (int i = 0; i < tTypes.length; i++) { |
| 5356 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { |
| 5357 return false; |
| 5358 } |
| 5359 } |
| 5360 } |
| 5361 Map<String, DartType> namedTypesT = t.namedParameterTypes; |
| 5362 Map<String, DartType> namedTypesS = s.namedParameterTypes; |
| 5363 // if k >= m is false, return false: the passed function type has more |
| 5364 // named parameter types than this |
| 5365 if (namedTypesT.length < namedTypesS.length) { |
| 5366 return false; |
| 5367 } |
| 5368 // Loop through each element in S verifying that T has a matching |
| 5369 // parameter name and that the corresponding type is assignable to the |
| 5370 // type in S. |
| 5371 for (String keyS in namedTypesS.keys) { |
| 5372 DartType typeT = namedTypesT[keyS]; |
| 5373 if (typeT == null) { |
| 5374 return false; |
| 5375 } |
| 5376 if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) { |
| 5377 return false; |
| 5378 } |
| 5379 } |
| 5380 } else if (s.namedParameterTypes.length > 0) { |
| 5381 return false; |
| 5382 } else { |
| 5383 // positional parameter case |
| 5384 int tArgLength = tTypes.length + tOpTypes.length; |
| 5385 int sArgLength = sTypes.length + sOpTypes.length; |
| 5386 // Check that the total number of parameters in t is greater than or |
| 5387 // equal to the number of parameters in s and that the number of |
| 5388 // required parameters in s is greater than or equal to the number of |
| 5389 // required parameters in t. |
| 5390 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
| 5391 return false; |
| 5392 } |
| 5393 if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
| 5394 // No positional arguments, don't copy contents to new array |
| 5395 for (int i = 0; i < sTypes.length; i++) { |
| 5396 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { |
| 5397 return false; |
| 5398 } |
| 5399 } |
| 5400 } else { |
| 5401 // Else, we do have positional parameters, copy required and |
| 5402 // positional parameter types into arrays to do the compare (for loop |
| 5403 // below). |
| 5404 List<DartType> tAllTypes = new List<DartType>(sArgLength); |
| 5405 for (int i = 0; i < tTypes.length; i++) { |
| 5406 tAllTypes[i] = tTypes[i]; |
| 5407 } |
| 5408 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5409 tAllTypes[i] = tOpTypes[j]; |
| 5410 } |
| 5411 List<DartType> sAllTypes = new List<DartType>(sArgLength); |
| 5412 for (int i = 0; i < sTypes.length; i++) { |
| 5413 sAllTypes[i] = sTypes[i]; |
| 5414 } |
| 5415 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
| 5416 sAllTypes[i] = sOpTypes[j]; |
| 5417 } |
| 5418 for (int i = 0; i < sAllTypes.length; i++) { |
| 5419 if (!(tAllTypes[i] as TypeImpl).isAssignableTo(sAllTypes[i])) { |
| 5420 return false; |
| 5421 } |
| 5422 } |
| 5423 } |
| 5424 } |
| 5425 DartType tRetType = t.returnType; |
| 5426 DartType sRetType = s.returnType; |
| 5427 return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType); |
| 5428 } |
| 5429 |
| 5430 @override |
| 5431 TypeImpl pruned(List<FunctionTypeAliasElement> prune) { |
| 5432 if (prune == null) { |
| 5433 return this; |
| 5434 } else if (prune.contains(element)) { |
| 5435 // Circularity found. Prune the type declaration. |
| 5436 return new CircularTypeImpl(); |
| 5437 } else { |
| 5438 // There should never be a reason to prune a type that has already been |
| 5439 // pruned, since pruning is only done when expanding a function type |
| 5440 // alias, and function type aliases are always expanded by starting with |
| 5441 // base types. |
| 5442 assert(this.prunedTypedefs == null); |
| 5443 FunctionTypeImpl result = new FunctionTypeImpl._(element, name, prune); |
| 5444 result.typeArguments = |
| 5445 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList(); |
| 5446 return result; |
| 5447 } |
| 5448 } |
| 5449 |
| 5450 @override |
| 5451 DartType substitute2( |
| 5452 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 5453 [List<FunctionTypeAliasElement> prune]) { |
| 5454 // Pruned types should only ever result from peforming type variable |
| 5455 // substitution, and it doesn't make sense to substitute again after |
| 5456 // substituting once. |
| 5457 assert(this.prunedTypedefs == null); |
| 5458 if (argumentTypes.length != parameterTypes.length) { |
| 5459 throw new IllegalArgumentException( |
| 5460 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); |
| 5461 } |
| 5462 Element element = this.element; |
| 5463 if (prune != null && prune.contains(element)) { |
| 5464 // Circularity found. Prune the type declaration. |
| 5465 return new CircularTypeImpl(); |
| 5466 } |
| 5467 if (argumentTypes.length == 0) { |
| 5468 return this.pruned(prune); |
| 5469 } |
| 5470 FunctionTypeImpl newType = (element is ExecutableElement) |
| 5471 ? new FunctionTypeImpl(element, prune) |
| 5472 : new FunctionTypeImpl.forTypedef( |
| 5473 element as FunctionTypeAliasElement, prune); |
| 5474 newType.typeArguments = |
| 5475 TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes); |
| 5476 return newType; |
| 5477 } |
| 5478 |
| 5479 @override |
| 5480 FunctionTypeImpl substitute3(List<DartType> argumentTypes) => |
| 5481 substitute2(argumentTypes, typeArguments); |
| 5482 |
| 5483 /** |
| 5484 * Compute the least upper bound of types [f] and [g], both of which are |
| 5485 * known to be function types. |
| 5486 * |
| 5487 * In the event that f and g have different numbers of required parameters, |
| 5488 * `null` is returned, in which case the least upper bound is the interface |
| 5489 * type `Function`. |
| 5490 */ |
| 5491 static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) { |
| 5492 // TODO(paulberry): implement this. |
| 5493 return null; |
| 5494 } |
| 5495 |
| 5496 /** |
| 5497 * Return `true` if all of the name/type pairs in the first map ([firstTypes]) |
| 5498 * are equal to the corresponding name/type pairs in the second map |
| 5499 * ([secondTypes]). The maps are expected to iterate over their entries in the |
| 5500 * same order in which those entries were added to the map. |
| 5501 */ |
| 5502 static bool _equals( |
| 5503 Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) { |
| 5504 if (secondTypes.length != firstTypes.length) { |
| 5505 return false; |
| 5506 } |
| 5507 Iterator<String> firstKeys = firstTypes.keys.iterator; |
| 5508 Iterator<String> secondKeys = secondTypes.keys.iterator; |
| 5509 while (firstKeys.moveNext() && secondKeys.moveNext()) { |
| 5510 String firstKey = firstKeys.current; |
| 5511 String secondKey = secondKeys.current; |
| 5512 TypeImpl firstType = firstTypes[firstKey]; |
| 5513 TypeImpl secondType = secondTypes[secondKey]; |
| 5514 if (firstKey != secondKey || firstType != secondType) { |
| 5515 return false; |
| 5516 } |
| 5517 } |
| 5518 return true; |
| 5519 } |
| 5520 } |
| 5521 |
| 5522 /** |
| 5523 * An element visitor that will recursively visit all of the elements in an |
| 5524 * element model (like instances of the class [RecursiveElementVisitor]). In |
| 5525 * addition, when an element of a specific type is visited not only will the |
| 5526 * visit method for that specific type of element be invoked, but additional |
| 5527 * methods for the supertypes of that element will also be invoked. For example, |
| 5528 * using an instance of this class to visit a [MethodElement] will cause the |
| 5529 * method [visitMethodElement] to be invoked but will also cause the methods |
| 5530 * [visitExecutableElement] and [visitElement] to be subsequently invoked. This |
| 5531 * allows visitors to be written that visit all executable elements without |
| 5532 * needing to override the visit method for each of the specific subclasses of |
| 5533 * [ExecutableElement]. |
| 5534 * |
| 5535 * Note, however, that unlike many visitors, element visitors visit objects |
| 5536 * based on the interfaces implemented by those elements. Because interfaces |
| 5537 * form a graph structure rather than a tree structure the way classes do, and |
| 5538 * because it is generally undesirable for an object to be visited more than |
| 5539 * once, this class flattens the interface graph into a pseudo-tree. In |
| 5540 * particular, this class treats elements as if the element types were |
| 5541 * structured in the following way: |
| 5542 * |
| 5543 * <pre> |
| 5544 * Element |
| 5545 * ClassElement |
| 5546 * CompilationUnitElement |
| 5547 * ExecutableElement |
| 5548 * ConstructorElement |
| 5549 * LocalElement |
| 5550 * FunctionElement |
| 5551 * MethodElement |
| 5552 * PropertyAccessorElement |
| 5553 * ExportElement |
| 5554 * HtmlElement |
| 5555 * ImportElement |
| 5556 * LabelElement |
| 5557 * LibraryElement |
| 5558 * MultiplyDefinedElement |
| 5559 * PrefixElement |
| 5560 * TypeAliasElement |
| 5561 * TypeParameterElement |
| 5562 * UndefinedElement |
| 5563 * VariableElement |
| 5564 * PropertyInducingElement |
| 5565 * FieldElement |
| 5566 * TopLevelVariableElement |
| 5567 * LocalElement |
| 5568 * LocalVariableElement |
| 5569 * ParameterElement |
| 5570 * FieldFormalParameterElement |
| 5571 * </pre> |
| 5572 * |
| 5573 * Subclasses that override a visit method must either invoke the overridden |
| 5574 * visit method or explicitly invoke the more general visit method. Failure to |
| 5575 * do so will cause the visit methods for superclasses of the element to not be |
| 5576 * invoked and will cause the children of the visited node to not be visited. |
| 5577 */ |
| 5578 class GeneralizingElementVisitor<R> implements ElementVisitor<R> { |
| 5579 @override |
| 5580 R visitClassElement(ClassElement element) => visitElement(element); |
| 5581 |
| 5582 @override |
| 5583 R visitCompilationUnitElement(CompilationUnitElement element) => |
| 5584 visitElement(element); |
| 5585 |
| 5586 @override |
| 5587 R visitConstructorElement(ConstructorElement element) => |
| 5588 visitExecutableElement(element); |
| 5589 |
| 5590 R visitElement(Element element) { |
| 5591 element.visitChildren(this); |
| 5592 return null; |
| 5593 } |
| 5594 |
| 5595 @override |
| 5596 @deprecated |
| 5597 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => |
| 5598 visitHtmlScriptElement(element); |
| 5599 |
| 5600 R visitExecutableElement(ExecutableElement element) => visitElement(element); |
| 5601 |
| 5602 @override |
| 5603 R visitExportElement(ExportElement element) => visitElement(element); |
| 5604 |
| 5605 @override |
| 5606 @deprecated |
| 5607 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => |
| 5608 visitHtmlScriptElement(element); |
| 5609 |
| 5610 @override |
| 5611 R visitFieldElement(FieldElement element) => |
| 5612 visitPropertyInducingElement(element); |
| 5613 |
| 5614 @override |
| 5615 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => |
| 5616 visitParameterElement(element); |
| 5617 |
| 5618 @override |
| 5619 R visitFunctionElement(FunctionElement element) => visitLocalElement(element); |
| 5620 |
| 5621 @override |
| 5622 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => |
| 5623 visitElement(element); |
| 5624 |
| 5625 @override |
| 5626 @deprecated |
| 5627 R visitHtmlElement(HtmlElement element) => visitElement(element); |
| 5628 |
| 5629 @deprecated |
| 5630 R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element); |
| 5631 |
| 5632 @override |
| 5633 R visitImportElement(ImportElement element) => visitElement(element); |
| 5634 |
| 5635 @override |
| 5636 R visitLabelElement(LabelElement element) => visitElement(element); |
| 5637 |
| 5638 @override |
| 5639 R visitLibraryElement(LibraryElement element) => visitElement(element); |
| 5640 |
| 5641 R visitLocalElement(LocalElement element) { |
| 5642 if (element is LocalVariableElement) { |
| 5643 return visitVariableElement(element); |
| 5644 } else if (element is ParameterElement) { |
| 5645 return visitVariableElement(element); |
| 5646 } else if (element is FunctionElement) { |
| 5647 return visitExecutableElement(element); |
| 5648 } |
| 5649 return null; |
| 5650 } |
| 5651 |
| 5652 @override |
| 5653 R visitLocalVariableElement(LocalVariableElement element) => |
| 5654 visitLocalElement(element); |
| 5655 |
| 5656 @override |
| 5657 R visitMethodElement(MethodElement element) => |
| 5658 visitExecutableElement(element); |
| 5659 |
| 5660 @override |
| 5661 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => |
| 5662 visitElement(element); |
| 5663 |
| 5664 @override |
| 5665 R visitParameterElement(ParameterElement element) => |
| 5666 visitLocalElement(element); |
| 5667 |
| 5668 @override |
| 5669 R visitPrefixElement(PrefixElement element) => visitElement(element); |
| 5670 |
| 5671 @override |
| 5672 R visitPropertyAccessorElement(PropertyAccessorElement element) => |
| 5673 visitExecutableElement(element); |
| 5674 |
| 5675 R visitPropertyInducingElement(PropertyInducingElement element) => |
| 5676 visitVariableElement(element); |
| 5677 |
| 5678 @override |
| 5679 R visitTopLevelVariableElement(TopLevelVariableElement element) => |
| 5680 visitPropertyInducingElement(element); |
| 5681 |
| 5682 @override |
| 5683 R visitTypeParameterElement(TypeParameterElement element) => |
| 5684 visitElement(element); |
| 5685 |
| 5686 R visitVariableElement(VariableElement element) => visitElement(element); |
| 5687 } |
| 5688 |
| 5689 /** |
| 5690 * A combinator that causes some of the names in a namespace to be hidden when |
| 5691 * being imported. |
| 5692 */ |
| 5693 abstract class HideElementCombinator implements NamespaceCombinator { |
| 5694 /** |
| 5695 * Return a list containing the names that are not to be made visible in the |
| 5696 * importing library even if they are defined in the imported library. |
| 5697 */ |
| 5698 List<String> get hiddenNames; |
| 5699 } |
| 5700 |
| 5701 /** |
| 5702 * A concrete implementation of a [HideElementCombinator]. |
| 5703 */ |
| 5704 class HideElementCombinatorImpl implements HideElementCombinator { |
| 5705 /** |
| 5706 * The names that are not to be made visible in the importing library even if |
| 5707 * they are defined in the imported library. |
| 5708 */ |
| 5709 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY; |
| 5710 |
| 5711 @override |
| 5712 String toString() { |
| 5713 StringBuffer buffer = new StringBuffer(); |
| 5714 buffer.write("show "); |
| 5715 int count = hiddenNames.length; |
| 5716 for (int i = 0; i < count; i++) { |
| 5717 if (i > 0) { |
| 5718 buffer.write(", "); |
| 5719 } |
| 5720 buffer.write(hiddenNames[i]); |
| 5721 } |
| 5722 return buffer.toString(); |
| 5723 } |
| 5724 } |
| 5725 |
| 5726 /** |
| 5727 * An HTML file. |
| 5728 */ |
| 5729 @deprecated |
| 5730 abstract class HtmlElement implements Element { |
| 5731 /** |
| 5732 * An empty list of HTML file elements. |
| 5733 */ |
| 5734 static const List<HtmlElement> EMPTY_LIST = const <HtmlElement>[]; |
| 5735 |
| 5736 /** |
| 5737 * Return a list containing all of the script elements contained in the HTML |
| 5738 * file. This includes scripts with libraries that are defined by the content |
| 5739 * of a script tag as well as libraries that are referenced in the `source` |
| 5740 * attribute of a script tag. |
| 5741 */ |
| 5742 List<HtmlScriptElement> get scripts; |
| 5743 } |
| 5744 |
| 5745 /** |
| 5746 * A concrete implementation of an [HtmlElement]. |
| 5747 */ |
| 5748 @deprecated |
| 5749 class HtmlElementImpl extends ElementImpl implements HtmlElement { |
| 5750 /** |
| 5751 * An empty list of HTML file elements. |
| 5752 */ |
| 5753 @deprecated // Use HtmlElement.EMPTY_LIST |
| 5754 static const List<HtmlElement> EMPTY_ARRAY = const <HtmlElement>[]; |
| 5755 |
| 5756 /** |
| 5757 * The analysis context in which this library is defined. |
| 5758 */ |
| 5759 final AnalysisContext context; |
| 5760 |
| 5761 /** |
| 5762 * The scripts contained in or referenced from script tags in the HTML file. |
| 5763 */ |
| 5764 List<HtmlScriptElement> _scripts = HtmlScriptElement.EMPTY_LIST; |
| 5765 |
| 5766 /** |
| 5767 * The source that corresponds to this HTML file. |
| 5768 */ |
| 5769 Source source; |
| 5770 |
| 5771 /** |
| 5772 * Initialize a newly created HTML element in the given [context] to have the |
| 5773 * given [name]. |
| 5774 */ |
| 5775 HtmlElementImpl(this.context, String name) : super(name, -1); |
| 5776 |
| 5777 @override |
| 5778 int get hashCode => source.hashCode; |
| 5779 |
| 5780 @override |
| 5781 String get identifier => source.encoding; |
| 5782 |
| 5783 @override |
| 5784 ElementKind get kind => ElementKind.HTML; |
| 5785 |
| 5786 @override |
| 5787 List<HtmlScriptElement> get scripts => _scripts; |
| 5788 |
| 5789 /** |
| 5790 * Set the scripts contained in the HTML file to the given [scripts]. |
| 5791 */ |
| 5792 void set scripts(List<HtmlScriptElement> scripts) { |
| 5793 if (scripts.length == 0) { |
| 5794 this._scripts = HtmlScriptElement.EMPTY_LIST; |
| 5795 return; |
| 5796 } |
| 5797 for (HtmlScriptElement script in scripts) { |
| 5798 (script as HtmlScriptElementImpl).enclosingElement = this; |
| 5799 } |
| 5800 this._scripts = scripts; |
| 5801 } |
| 5802 |
| 5803 @override |
| 5804 bool operator ==(Object object) { |
| 5805 if (identical(object, this)) { |
| 5806 return true; |
| 5807 } |
| 5808 return object is HtmlElementImpl && source == object.source; |
| 5809 } |
| 5810 |
| 5811 @override |
| 5812 accept(ElementVisitor visitor) => visitor.visitHtmlElement(this); |
| 5813 |
| 5814 @override |
| 5815 void appendTo(StringBuffer buffer) { |
| 5816 if (source == null) { |
| 5817 buffer.write("{HTML file}"); |
| 5818 } else { |
| 5819 buffer.write(source.fullName); |
| 5820 } |
| 5821 } |
| 5822 |
| 5823 @override |
| 5824 void visitChildren(ElementVisitor visitor) { |
| 5825 super.visitChildren(visitor); |
| 5826 safelyVisitChildren(_scripts, visitor); |
| 5827 } |
| 5828 } |
| 5829 |
| 5830 /** |
| 5831 * A script tag in an HTML file. |
| 5832 * |
| 5833 * See [EmbeddedHtmlScriptElement], and [ExternalHtmlScriptElement]. |
| 5834 */ |
| 5835 @deprecated |
| 5836 abstract class HtmlScriptElement implements Element { |
| 5837 /** |
| 5838 * An empty list of HTML script elements. |
| 5839 */ |
| 5840 static const List<HtmlScriptElement> EMPTY_LIST = const <HtmlScriptElement>[]; |
| 5841 } |
| 5842 |
| 5843 /** |
| 5844 * A concrete implementation of an [HtmlScriptElement]. |
| 5845 */ |
| 5846 @deprecated |
| 5847 abstract class HtmlScriptElementImpl extends ElementImpl |
| 5848 implements HtmlScriptElement { |
| 5849 /** |
| 5850 * An empty list of HTML script elements. |
| 5851 */ |
| 5852 @deprecated // Use HtmlScriptElement.EMPTY_LIST |
| 5853 static const List<HtmlScriptElement> EMPTY_ARRAY = |
| 5854 const <HtmlScriptElement>[]; |
| 5855 |
| 5856 /** |
| 5857 * Initialize a newly created script element corresponding to the given |
| 5858 * [node]. |
| 5859 */ |
| 5860 HtmlScriptElementImpl(XmlTagNode node) |
| 5861 : super(node.tag, node.tagToken.offset); |
| 5862 } |
| 5863 |
| 5864 /** |
| 5865 * A single import directive within a library. |
| 5866 */ |
| 5867 abstract class ImportElement implements Element, UriReferencedElement { |
| 5868 /** |
| 5869 * An empty list of import elements. |
| 5870 */ |
| 5871 @deprecated // Use ImportElement.EMPTY_LIST |
| 5872 static const List<ImportElement> EMPTY_ARRAY = const <ImportElement>[]; |
| 5873 |
| 5874 /** |
| 5875 * An empty list of import elements. |
| 5876 */ |
| 5877 static const List<ImportElement> EMPTY_LIST = const <ImportElement>[]; |
| 5878 |
| 5879 /** |
| 5880 * Return a list containing the combinators that were specified as part of the |
| 5881 * import directive in the order in which they were specified. |
| 5882 */ |
| 5883 List<NamespaceCombinator> get combinators; |
| 5884 |
| 5885 /** |
| 5886 * Return the library that is imported into this library by this import |
| 5887 * directive. |
| 5888 */ |
| 5889 LibraryElement get importedLibrary; |
| 5890 |
| 5891 /** |
| 5892 * Return `true` if this import is for a deferred library. |
| 5893 */ |
| 5894 bool get isDeferred; |
| 5895 |
| 5896 /** |
| 5897 * Return the prefix that was specified as part of the import directive, or |
| 5898 * `null` if there was no prefix specified. |
| 5899 */ |
| 5900 PrefixElement get prefix; |
| 5901 |
| 5902 /** |
| 5903 * Return the offset of the prefix of this import in the file that contains |
| 5904 * this import directive, or `-1` if this import is synthetic, does not have a |
| 5905 * prefix, or otherwise does not have an offset. |
| 5906 */ |
| 5907 int get prefixOffset; |
| 5908 } |
| 5909 |
| 5910 /** |
| 5911 * A concrete implementation of an [ImportElement]. |
| 5912 */ |
| 5913 class ImportElementImpl extends UriReferencedElementImpl |
| 5914 implements ImportElement { |
| 5915 /** |
| 5916 * The offset of the prefix of this import in the file that contains the this |
| 5917 * import directive, or `-1` if this import is synthetic. |
| 5918 */ |
| 5919 int prefixOffset = 0; |
| 5920 |
| 5921 /** |
| 5922 * The library that is imported into this library by this import directive. |
| 5923 */ |
| 5924 LibraryElement importedLibrary; |
| 5925 |
| 5926 /** |
| 5927 * The combinators that were specified as part of the import directive in the |
| 5928 * order in which they were specified. |
| 5929 */ |
| 5930 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; |
| 5931 |
| 5932 /** |
| 5933 * The prefix that was specified as part of the import directive, or `null` if |
| 5934 * there was no prefix specified. |
| 5935 */ |
| 5936 PrefixElement prefix; |
| 5937 |
| 5938 /** |
| 5939 * Initialize a newly created import element at the given [offset]. |
| 5940 * The offset may be `-1` if the import is synthetic. |
| 5941 */ |
| 5942 ImportElementImpl(int offset) : super(null, offset); |
| 5943 |
| 5944 /** |
| 5945 * Set whether this import is for a deferred library. |
| 5946 */ |
| 5947 void set deferred(bool isDeferred) { |
| 5948 setModifier(Modifier.DEFERRED, isDeferred); |
| 5949 } |
| 5950 |
| 5951 @override |
| 5952 String get identifier => |
| 5953 "${(importedLibrary as LibraryElementImpl).identifier}@$nameOffset"; |
| 5954 |
| 5955 @override |
| 5956 bool get isDeferred => hasModifier(Modifier.DEFERRED); |
| 5957 |
| 5958 @override |
| 5959 ElementKind get kind => ElementKind.IMPORT; |
| 5960 |
| 5961 @override |
| 5962 accept(ElementVisitor visitor) => visitor.visitImportElement(this); |
| 5963 |
| 5964 @override |
| 5965 void appendTo(StringBuffer buffer) { |
| 5966 buffer.write("import "); |
| 5967 (importedLibrary as LibraryElementImpl).appendTo(buffer); |
| 5968 } |
| 5969 |
| 5970 @override |
| 5971 void visitChildren(ElementVisitor visitor) { |
| 5972 super.visitChildren(visitor); |
| 5973 safelyVisitChild(prefix, visitor); |
| 5974 } |
| 5975 } |
| 5976 |
| 5977 /** |
| 5978 * The type introduced by either a class or an interface, or a reference to such |
| 5979 * a type. |
| 5980 */ |
| 5981 abstract class InterfaceType implements ParameterizedType { |
| 5982 /** |
| 5983 * An empty list of types. |
| 5984 */ |
| 5985 @deprecated // Use InterfaceType.EMPTY_LIST |
| 5986 static const List<InterfaceType> EMPTY_ARRAY = const <InterfaceType>[]; |
| 5987 |
| 5988 /** |
| 5989 * An empty list of types. |
| 5990 */ |
| 5991 static const List<InterfaceType> EMPTY_LIST = const <InterfaceType>[]; |
| 5992 |
| 5993 /** |
| 5994 * Return a list containing all of the accessors (getters and setters) |
| 5995 * declared in this type. |
| 5996 */ |
| 5997 List<PropertyAccessorElement> get accessors; |
| 5998 |
| 5999 /** |
| 6000 * Return a list containing all of the constructors declared in this type. |
| 6001 */ |
| 6002 List<ConstructorElement> get constructors; |
| 6003 |
| 6004 @override |
| 6005 ClassElement get element; |
| 6006 |
| 6007 /** |
| 6008 * Return a list containing all of the interfaces that are implemented by this |
| 6009 * interface. Note that this is <b>not</b>, in general, equivalent to getting |
| 6010 * the interfaces from this type's element because the types returned by this |
| 6011 * method will have had their type parameters replaced. |
| 6012 */ |
| 6013 List<InterfaceType> get interfaces; |
| 6014 |
| 6015 /** |
| 6016 * Return a list containing all of the methods declared in this type. |
| 6017 */ |
| 6018 List<MethodElement> get methods; |
| 6019 |
| 6020 /** |
| 6021 * Return a list containing all of the mixins that are applied to the class |
| 6022 * being extended in order to derive the superclass of this class. Note that |
| 6023 * this is <b>not</b>, in general, equivalent to getting the mixins from this |
| 6024 * type's element because the types returned by this method will have had |
| 6025 * their type parameters replaced. |
| 6026 */ |
| 6027 List<InterfaceType> get mixins; |
| 6028 |
| 6029 /** |
| 6030 * Return the type representing the superclass of this type, or null if this |
| 6031 * type represents the class 'Object'. Note that this is <b>not</b>, in |
| 6032 * general, equivalent to getting the superclass from this type's element |
| 6033 * because the type returned by this method will have had it's type parameters |
| 6034 * replaced. |
| 6035 */ |
| 6036 InterfaceType get superclass; |
| 6037 |
| 6038 /** |
| 6039 * Return the element representing the getter with the given [name] that is |
| 6040 * declared in this class, or `null` if this class does not declare a getter |
| 6041 * with the given name. |
| 6042 */ |
| 6043 PropertyAccessorElement getGetter(String name); |
| 6044 |
| 6045 /** |
| 6046 * Return the least upper bound of this type and the given [type], or `null` |
| 6047 * if there is no least upper bound. |
| 6048 * |
| 6049 * Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the |
| 6050 * set of superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of |
| 6051 * superinterfaces of <i>J</i> and let <i>S = (I ∪ S<sub>I</sub>) ∩ |
| 6052 * (J ∪ S<sub>J</sub>)</i>. Furthermore, we define <i>S<sub>n</sub> = |
| 6053 * {T | T ∈ S ∧ depth(T) = n}</i> for any finite <i>n</i>, where |
| 6054 * <i>depth(T)</i> is the number of steps in the longest inheritance path from |
| 6055 * <i>T</i> to <i>Object</i>. Let <i>q</i> be the largest number such that |
| 6056 * <i>S<sub>q</sub></i> has cardinality one. The least upper bound of <i>I</i> |
| 6057 * and <i>J</i> is the sole element of <i>S<sub>q</sub></i>. |
| 6058 */ |
| 6059 @override |
| 6060 @deprecated |
| 6061 DartType getLeastUpperBound(DartType type); |
| 6062 |
| 6063 /** |
| 6064 * Return the element representing the method with the given [name] that is |
| 6065 * declared in this class, or `null` if this class does not declare a method |
| 6066 * with the given name. |
| 6067 */ |
| 6068 MethodElement getMethod(String name); |
| 6069 |
| 6070 /** |
| 6071 * Return the element representing the setter with the given [name] that is |
| 6072 * declared in this class, or `null` if this class does not declare a setter |
| 6073 * with the given name. |
| 6074 */ |
| 6075 PropertyAccessorElement getSetter(String name); |
| 6076 |
| 6077 /** |
| 6078 * Return `true` if this type is a direct supertype of the given [type]. The |
| 6079 * implicit interface of class <i>I</i> is a direct supertype of the implicit |
| 6080 * interface of class <i>J</i> iff: |
| 6081 * |
| 6082 * * <i>I</i> is Object, and <i>J</i> has no extends clause. |
| 6083 * * <i>I</i> is listed in the extends clause of <i>J</i>. |
| 6084 * * <i>I</i> is listed in the implements clause of <i>J</i>. |
| 6085 * * <i>I</i> is listed in the with clause of <i>J</i>. |
| 6086 * * <i>J</i> is a mixin application of the mixin of <i>I</i>. |
| 6087 */ |
| 6088 bool isDirectSupertypeOf(InterfaceType type); |
| 6089 |
| 6090 /** |
| 6091 * Return `true` if this type is more specific than the given [type]. An |
| 6092 * interface type <i>T</i> is more specific than an interface type <i>S</i>, |
| 6093 * written <i>T « S</i>, if one of the following conditions is met: |
| 6094 * |
| 6095 * * Reflexivity: <i>T</i> is <i>S</i>. |
| 6096 * * <i>T</i> is bottom. |
| 6097 * * <i>S</i> is dynamic. |
| 6098 * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>. |
| 6099 * * <i>T</i> is a type parameter and <i>S</i> is the upper bound of <i>T</i>. |
| 6100 * * Covariance: <i>T</i> is of the form <i>I<T<sub>1</sub>, …, |
| 6101 * T<sub>n</sub>></i> and S</i> is of the form <i>I<S<sub>1</sub>, |
| 6102 * …, S<sub>n</sub>></i> and <i>T<sub>i</sub> « |
| 6103 * S<sub>i</sub></i>, <i>1 <= i <= n</i>. |
| 6104 * * Transitivity: <i>T « U</i> and <i>U « S</i>. |
| 6105 */ |
| 6106 @override |
| 6107 bool isMoreSpecificThan(DartType type); |
| 6108 |
| 6109 /** |
| 6110 * Return `true` if this type is a subtype of the given [type]. An interface |
| 6111 * type <i>T</i> is a subtype of an interface type <i>S</i>, written <i>T</i> |
| 6112 * <: <i>S</i>, iff <i>[bottom/dynamic]T</i> « <i>S</i> (<i>T</i> is |
| 6113 * more specific than <i>S</i>). If an interface type <i>I</i> includes a |
| 6114 * method named <i>call()</i>, and the type of <i>call()</i> is the function |
| 6115 * type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>. |
| 6116 */ |
| 6117 @override |
| 6118 bool isSubtypeOf(DartType type); |
| 6119 |
| 6120 /** |
| 6121 * Return the element representing the constructor that results from looking |
| 6122 * up the constructor with the given [name] in this class with respect to the |
| 6123 * given [library], or `null` if the look up fails. The behavior of this |
| 6124 * method is defined by the Dart Language Specification in section 12.11.1: |
| 6125 * <blockquote> |
| 6126 * If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be the |
| 6127 * constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<i>. |
| 6128 * Otherwise, if <i>q</i> is not defined or not accessible, a |
| 6129 * NoSuchMethodException is thrown. |
| 6130 * </blockquote> |
| 6131 */ |
| 6132 ConstructorElement lookUpConstructor(String name, LibraryElement library); |
| 6133 |
| 6134 /** |
| 6135 * Return the element representing the getter that results from looking up the |
| 6136 * getter with the given [name] in this class with respect to the given |
| 6137 * [library], or `null` if the look up fails. The behavior of this method is |
| 6138 * defined by the Dart Language Specification in section 12.15.1: |
| 6139 * <blockquote> |
| 6140 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 6141 * <i>C</i> with respect to library <i>L</i> is: |
| 6142 * * If <i>C</i> declares an instance getter (respectively setter) named |
| 6143 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively |
| 6144 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a |
| 6145 * superclass <i>S</i>, then the result of the lookup is the result of |
| 6146 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect |
| 6147 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6148 * </blockquote> |
| 6149 */ |
| 6150 PropertyAccessorElement lookUpGetter(String name, LibraryElement library); |
| 6151 |
| 6152 /** |
| 6153 * Return the element representing the getter that results from looking up the |
| 6154 * getter with the given [name] in the superclass of this class with respect |
| 6155 * to the given [library], or `null` if the look up fails. The behavior of |
| 6156 * this method is defined by the Dart Language Specification in section |
| 6157 * 12.15.1: |
| 6158 * <blockquote> |
| 6159 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 6160 * <i>C</i> with respect to library <i>L</i> is: |
| 6161 * * If <i>C</i> declares an instance getter (respectively setter) named |
| 6162 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively |
| 6163 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a |
| 6164 * superclass <i>S</i>, then the result of the lookup is the result of |
| 6165 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect |
| 6166 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6167 * </blockquote> |
| 6168 */ |
| 6169 PropertyAccessorElement lookUpGetterInSuperclass( |
| 6170 String name, LibraryElement library); |
| 6171 |
| 6172 /** |
| 6173 * Return the element representing the method that results from looking up the |
| 6174 * method with the given [name] in this class with respect to the given |
| 6175 * [library], or `null` if the look up fails. The behavior of this method is |
| 6176 * defined by the Dart Language Specification in section 12.15.1: |
| 6177 * <blockquote> |
| 6178 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 6179 * library <i>L</i> is: |
| 6180 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible |
| 6181 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if |
| 6182 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the |
| 6183 * result of looking up method <i>m</i> in <i>S</i> with respect to <i>L</i> |
| 6184 * Otherwise, we say that the lookup has failed. |
| 6185 * </blockquote> |
| 6186 */ |
| 6187 MethodElement lookUpMethod(String name, LibraryElement library); |
| 6188 |
| 6189 /** |
| 6190 * Return the element representing the method that results from looking up the |
| 6191 * method with the given [name] in the superclass of this class with respect |
| 6192 * to the given [library], or `null` if the look up fails. The behavior of |
| 6193 * this method is defined by the Dart Language Specification in section |
| 6194 * 12.15.1: |
| 6195 * <blockquote> |
| 6196 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 6197 * library <i>L</i> is: |
| 6198 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible |
| 6199 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if |
| 6200 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the |
| 6201 * result of looking up method <i>m</i> in <i>S</i> with respect to <i>L</i>. |
| 6202 * Otherwise, we say that the lookup has failed. |
| 6203 * </blockquote> |
| 6204 */ |
| 6205 MethodElement lookUpMethodInSuperclass(String name, LibraryElement library); |
| 6206 |
| 6207 /** |
| 6208 * Return the element representing the setter that results from looking up the |
| 6209 * setter with the given [name] in this class with respect to the given |
| 6210 * [library], or `null` if the look up fails. The behavior of this method is |
| 6211 * defined by the Dart Language Specification in section 12.16: |
| 6212 * <blockquote> |
| 6213 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 6214 * <i>C</i> with respect to library <i>L</i> is: |
| 6215 * * If <i>C</i> declares an instance getter (respectively setter) named |
| 6216 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively |
| 6217 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a |
| 6218 * superclass <i>S</i>, then the result of the lookup is the result of |
| 6219 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect |
| 6220 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6221 * </blockquote> |
| 6222 */ |
| 6223 PropertyAccessorElement lookUpSetter(String name, LibraryElement library); |
| 6224 |
| 6225 /** |
| 6226 * Return the element representing the setter that results from looking up the |
| 6227 * setter with the given [name] in the superclass of this class with respect |
| 6228 * to the given [library], or `null` if the look up fails. The behavior of |
| 6229 * this method is defined by the Dart Language Specification in section 12.16: |
| 6230 * <blockquote> |
| 6231 * The result of looking up getter (respectively setter) <i>m</i> in class |
| 6232 * <i>C</i> with respect to library <i>L</i> is: |
| 6233 * * If <i>C</i> declares an instance getter (respectively setter) named |
| 6234 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively |
| 6235 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a |
| 6236 * superclass <i>S</i>, then the result of the lookup is the result of |
| 6237 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect |
| 6238 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6239 * </blockquote> |
| 6240 */ |
| 6241 PropertyAccessorElement lookUpSetterInSuperclass( |
| 6242 String name, LibraryElement library); |
| 6243 |
| 6244 @override |
| 6245 InterfaceType substitute2( |
| 6246 List<DartType> argumentTypes, List<DartType> parameterTypes); |
| 6247 |
| 6248 /** |
| 6249 * Return the type resulting from substituting the given arguments for this |
| 6250 * type's parameters. This is fully equivalent to `substitute2(argumentTypes, |
| 6251 * getTypeArguments())`. |
| 6252 */ |
| 6253 InterfaceType substitute4(List<DartType> argumentTypes); |
| 6254 |
| 6255 /** |
| 6256 * Returns a "smart" version of the "least upper bound" of the given types. |
| 6257 * |
| 6258 * If these types have the same element and differ only in terms of the type |
| 6259 * arguments, attempts to find a compatible set of type arguments. |
| 6260 * |
| 6261 * Otherwise, calls [DartType.getLeastUpperBound]. |
| 6262 */ |
| 6263 static InterfaceType getSmartLeastUpperBound( |
| 6264 InterfaceType first, InterfaceType second) { |
| 6265 // TODO(paulberry): this needs to be deprecated and replaced with a method |
| 6266 // in [TypeSystem], since it relies on the deprecated functionality of |
| 6267 // [DartType.getLeastUpperBound]. |
| 6268 if (first.element == second.element) { |
| 6269 return _leastUpperBound(first, second); |
| 6270 } |
| 6271 return first.getLeastUpperBound(second); |
| 6272 } |
| 6273 |
| 6274 /** |
| 6275 * Return the "least upper bound" of the given types under the assumption that |
| 6276 * the types have the same element and differ only in terms of the type |
| 6277 * arguments. |
| 6278 * |
| 6279 * The resulting type is composed by comparing the corresponding type |
| 6280 * arguments, keeping those that are the same, and using 'dynamic' for those |
| 6281 * that are different. |
| 6282 */ |
| 6283 static InterfaceType _leastUpperBound( |
| 6284 InterfaceType firstType, InterfaceType secondType) { |
| 6285 ClassElement firstElement = firstType.element; |
| 6286 ClassElement secondElement = secondType.element; |
| 6287 if (firstElement != secondElement) { |
| 6288 throw new IllegalArgumentException('The same elements expected, but ' |
| 6289 '$firstElement and $secondElement are given.'); |
| 6290 } |
| 6291 if (firstType == secondType) { |
| 6292 return firstType; |
| 6293 } |
| 6294 List<DartType> firstArguments = firstType.typeArguments; |
| 6295 List<DartType> secondArguments = secondType.typeArguments; |
| 6296 int argumentCount = firstArguments.length; |
| 6297 if (argumentCount == 0) { |
| 6298 return firstType; |
| 6299 } |
| 6300 List<DartType> lubArguments = new List<DartType>(argumentCount); |
| 6301 for (int i = 0; i < argumentCount; i++) { |
| 6302 // |
| 6303 // Ideally we would take the least upper bound of the two argument types, |
| 6304 // but this can cause an infinite recursion (such as when finding the |
| 6305 // least upper bound of String and num). |
| 6306 // |
| 6307 if (firstArguments[i] == secondArguments[i]) { |
| 6308 lubArguments[i] = firstArguments[i]; |
| 6309 } |
| 6310 if (lubArguments[i] == null) { |
| 6311 lubArguments[i] = DynamicTypeImpl.instance; |
| 6312 } |
| 6313 } |
| 6314 InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement); |
| 6315 lub.typeArguments = lubArguments; |
| 6316 return lub; |
| 6317 } |
| 6318 } |
| 6319 |
| 6320 /** |
| 6321 * A concrete implementation of an [InterfaceType]. |
| 6322 */ |
| 6323 class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
| 6324 /** |
| 6325 * A list containing the actual types of the type arguments. |
| 6326 */ |
| 6327 List<DartType> typeArguments = DartType.EMPTY_LIST; |
| 6328 |
| 6329 /** |
| 6330 * The set of typedefs which should not be expanded when exploring this type, |
| 6331 * to avoid creating infinite types in response to self-referential typedefs. |
| 6332 */ |
| 6333 final List<FunctionTypeAliasElement> prunedTypedefs; |
| 6334 |
| 6335 /** |
| 6336 * Initialize a newly created type to be declared by the given [element]. |
| 6337 */ |
| 6338 InterfaceTypeImpl(ClassElement element, [this.prunedTypedefs]) |
| 6339 : super(element, element.displayName); |
| 6340 |
| 6341 /** |
| 6342 * Initialize a newly created type to be declared by the given [element]. |
| 6343 */ |
| 6344 @deprecated // Use new InterfaceTypeImpl(element) |
| 6345 InterfaceTypeImpl.con1(ClassElement element) |
| 6346 : prunedTypedefs = null, |
| 6347 super(element, element.displayName); |
| 6348 |
| 6349 /** |
| 6350 * Initialize a newly created type to have the given [name]. This constructor |
| 6351 * should only be used in cases where there is no declaration of the type. |
| 6352 */ |
| 6353 @deprecated // Use new InterfaceTypeImpl.named(name) |
| 6354 InterfaceTypeImpl.con2(String name) |
| 6355 : prunedTypedefs = null, |
| 6356 super(null, name); |
| 6357 |
| 6358 /** |
| 6359 * Initialize a newly created type to have the given [name]. This constructor |
| 6360 * should only be used in cases where there is no declaration of the type. |
| 6361 */ |
| 6362 InterfaceTypeImpl.named(String name) |
| 6363 : prunedTypedefs = null, |
| 6364 super(null, name); |
| 6365 |
| 6366 /** |
| 6367 * Private constructor. |
| 6368 */ |
| 6369 InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs) |
| 6370 : super(element, name); |
| 6371 |
| 6372 @override |
| 6373 List<PropertyAccessorElement> get accessors { |
| 6374 List<PropertyAccessorElement> accessors = element.accessors; |
| 6375 List<PropertyAccessorElement> members = |
| 6376 new List<PropertyAccessorElement>(accessors.length); |
| 6377 for (int i = 0; i < accessors.length; i++) { |
| 6378 members[i] = PropertyAccessorMember.from(accessors[i], this); |
| 6379 } |
| 6380 return members; |
| 6381 } |
| 6382 |
| 6383 @override |
| 6384 List<ConstructorElement> get constructors { |
| 6385 List<ConstructorElement> constructors = element.constructors; |
| 6386 List<ConstructorElement> members = |
| 6387 new List<ConstructorElement>(constructors.length); |
| 6388 for (int i = 0; i < constructors.length; i++) { |
| 6389 members[i] = ConstructorMember.from(constructors[i], this); |
| 6390 } |
| 6391 return members; |
| 6392 } |
| 6393 |
| 6394 @override |
| 6395 String get displayName { |
| 6396 String name = this.name; |
| 6397 List<DartType> typeArguments = this.typeArguments; |
| 6398 bool allDynamic = true; |
| 6399 for (DartType type in typeArguments) { |
| 6400 if (type != null && !type.isDynamic) { |
| 6401 allDynamic = false; |
| 6402 break; |
| 6403 } |
| 6404 } |
| 6405 // If there is at least one non-dynamic type, then list them out |
| 6406 if (!allDynamic) { |
| 6407 StringBuffer buffer = new StringBuffer(); |
| 6408 buffer.write(name); |
| 6409 buffer.write("<"); |
| 6410 for (int i = 0; i < typeArguments.length; i++) { |
| 6411 if (i != 0) { |
| 6412 buffer.write(", "); |
| 6413 } |
| 6414 DartType typeArg = typeArguments[i]; |
| 6415 buffer.write(typeArg.displayName); |
| 6416 } |
| 6417 buffer.write(">"); |
| 6418 name = buffer.toString(); |
| 6419 } |
| 6420 return name; |
| 6421 } |
| 6422 |
| 6423 @override |
| 6424 ClassElement get element => super.element as ClassElement; |
| 6425 |
| 6426 @override |
| 6427 int get hashCode { |
| 6428 ClassElement element = this.element; |
| 6429 if (element == null) { |
| 6430 return 0; |
| 6431 } |
| 6432 return element.hashCode; |
| 6433 } |
| 6434 |
| 6435 @override |
| 6436 List<InterfaceType> get interfaces { |
| 6437 ClassElement classElement = element; |
| 6438 List<InterfaceType> interfaces = classElement.interfaces; |
| 6439 List<TypeParameterElement> typeParameters = classElement.typeParameters; |
| 6440 List<DartType> parameterTypes = classElement.type.typeArguments; |
| 6441 if (typeParameters.length == 0) { |
| 6442 return interfaces; |
| 6443 } |
| 6444 int count = interfaces.length; |
| 6445 List<InterfaceType> typedInterfaces = new List<InterfaceType>(count); |
| 6446 for (int i = 0; i < count; i++) { |
| 6447 typedInterfaces[i] = |
| 6448 interfaces[i].substitute2(typeArguments, parameterTypes); |
| 6449 } |
| 6450 return typedInterfaces; |
| 6451 } |
| 6452 |
| 6453 @override |
| 6454 bool get isDartCoreFunction { |
| 6455 ClassElement element = this.element; |
| 6456 if (element == null) { |
| 6457 return false; |
| 6458 } |
| 6459 return element.name == "Function" && element.library.isDartCore; |
| 6460 } |
| 6461 |
| 6462 @override |
| 6463 bool get isObject => element.supertype == null; |
| 6464 |
| 6465 @override |
| 6466 List<MethodElement> get methods { |
| 6467 List<MethodElement> methods = element.methods; |
| 6468 List<MethodElement> members = new List<MethodElement>(methods.length); |
| 6469 for (int i = 0; i < methods.length; i++) { |
| 6470 members[i] = MethodMember.from(methods[i], this); |
| 6471 } |
| 6472 return members; |
| 6473 } |
| 6474 |
| 6475 @override |
| 6476 List<InterfaceType> get mixins { |
| 6477 ClassElement classElement = element; |
| 6478 List<InterfaceType> mixins = classElement.mixins; |
| 6479 List<TypeParameterElement> typeParameters = classElement.typeParameters; |
| 6480 List<DartType> parameterTypes = classElement.type.typeArguments; |
| 6481 if (typeParameters.length == 0) { |
| 6482 return mixins; |
| 6483 } |
| 6484 int count = mixins.length; |
| 6485 List<InterfaceType> typedMixins = new List<InterfaceType>(count); |
| 6486 for (int i = 0; i < count; i++) { |
| 6487 typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes); |
| 6488 } |
| 6489 return typedMixins; |
| 6490 } |
| 6491 |
| 6492 @override |
| 6493 InterfaceType get superclass { |
| 6494 ClassElement classElement = element; |
| 6495 InterfaceType supertype = classElement.supertype; |
| 6496 if (supertype == null) { |
| 6497 return null; |
| 6498 } |
| 6499 List<DartType> typeParameters = classElement.type.typeArguments; |
| 6500 if (typeArguments.length == 0 || |
| 6501 typeArguments.length != typeParameters.length) { |
| 6502 return supertype; |
| 6503 } |
| 6504 return supertype.substitute2(typeArguments, typeParameters); |
| 6505 } |
| 6506 |
| 6507 @override |
| 6508 List<TypeParameterElement> get typeParameters => element.typeParameters; |
| 6509 |
| 6510 @override |
| 6511 bool operator ==(Object object) { |
| 6512 if (identical(object, this)) { |
| 6513 return true; |
| 6514 } |
| 6515 if (object is! InterfaceTypeImpl) { |
| 6516 return false; |
| 6517 } |
| 6518 InterfaceTypeImpl otherType = object as InterfaceTypeImpl; |
| 6519 return (element == otherType.element) && |
| 6520 TypeImpl.equalArrays(typeArguments, otherType.typeArguments); |
| 6521 } |
| 6522 |
| 6523 @override |
| 6524 void appendTo(StringBuffer buffer) { |
| 6525 buffer.write(name); |
| 6526 int argumentCount = typeArguments.length; |
| 6527 if (argumentCount > 0) { |
| 6528 buffer.write("<"); |
| 6529 for (int i = 0; i < argumentCount; i++) { |
| 6530 if (i > 0) { |
| 6531 buffer.write(", "); |
| 6532 } |
| 6533 (typeArguments[i] as TypeImpl).appendTo(buffer); |
| 6534 } |
| 6535 buffer.write(">"); |
| 6536 } |
| 6537 } |
| 6538 |
| 6539 @override |
| 6540 PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember |
| 6541 .from((element as ClassElementImpl).getGetter(getterName), this); |
| 6542 |
| 6543 @override |
| 6544 @deprecated |
| 6545 DartType getLeastUpperBound(DartType type) { |
| 6546 // quick check for self |
| 6547 if (identical(type, this)) { |
| 6548 return this; |
| 6549 } |
| 6550 // dynamic |
| 6551 DartType dynamicType = DynamicTypeImpl.instance; |
| 6552 if (identical(this, dynamicType) || identical(type, dynamicType)) { |
| 6553 return dynamicType; |
| 6554 } |
| 6555 // TODO (jwren) opportunity here for a better, faster algorithm if this |
| 6556 // turns out to be a bottle-neck |
| 6557 if (type is! InterfaceType) { |
| 6558 return null; |
| 6559 } |
| 6560 return computeLeastUpperBound(this, type); |
| 6561 } |
| 6562 |
| 6563 @override |
| 6564 MethodElement getMethod(String methodName) => MethodMember.from( |
| 6565 (element as ClassElementImpl).getMethod(methodName), this); |
| 6566 |
| 6567 @override |
| 6568 PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember |
| 6569 .from((element as ClassElementImpl).getSetter(setterName), this); |
| 6570 |
| 6571 @override |
| 6572 bool isDirectSupertypeOf(InterfaceType type) { |
| 6573 InterfaceType i = this; |
| 6574 InterfaceType j = type; |
| 6575 ClassElement jElement = j.element; |
| 6576 InterfaceType supertype = jElement.supertype; |
| 6577 // |
| 6578 // If J has no direct supertype then it is Object, and Object has no direct |
| 6579 // supertypes. |
| 6580 // |
| 6581 if (supertype == null) { |
| 6582 return false; |
| 6583 } |
| 6584 // |
| 6585 // I is listed in the extends clause of J. |
| 6586 // |
| 6587 List<DartType> jArgs = j.typeArguments; |
| 6588 List<DartType> jVars = jElement.type.typeArguments; |
| 6589 supertype = supertype.substitute2(jArgs, jVars); |
| 6590 if (supertype == i) { |
| 6591 return true; |
| 6592 } |
| 6593 // |
| 6594 // I is listed in the implements clause of J. |
| 6595 // |
| 6596 for (InterfaceType interfaceType in jElement.interfaces) { |
| 6597 interfaceType = interfaceType.substitute2(jArgs, jVars); |
| 6598 if (interfaceType == i) { |
| 6599 return true; |
| 6600 } |
| 6601 } |
| 6602 // |
| 6603 // I is listed in the with clause of J. |
| 6604 // |
| 6605 for (InterfaceType mixinType in jElement.mixins) { |
| 6606 mixinType = mixinType.substitute2(jArgs, jVars); |
| 6607 if (mixinType == i) { |
| 6608 return true; |
| 6609 } |
| 6610 } |
| 6611 // |
| 6612 // J is a mixin application of the mixin of I. |
| 6613 // |
| 6614 // TODO(brianwilkerson) Determine whether this needs to be implemented or |
| 6615 // whether it is covered by the case above. |
| 6616 return false; |
| 6617 } |
| 6618 |
| 6619 @override |
| 6620 bool isMoreSpecificThan(DartType type, |
| 6621 [bool withDynamic = false, Set<Element> visitedElements]) { |
| 6622 // |
| 6623 // S is dynamic. |
| 6624 // The test to determine whether S is dynamic is done here because dynamic |
| 6625 // is not an instance of InterfaceType. |
| 6626 // |
| 6627 if (type.isDynamic) { |
| 6628 return true; |
| 6629 } |
| 6630 // |
| 6631 // A type T is more specific than a type S, written T << S, |
| 6632 // if one of the following conditions is met: |
| 6633 // |
| 6634 // Reflexivity: T is S. |
| 6635 // |
| 6636 if (this == type) { |
| 6637 return true; |
| 6638 } |
| 6639 if (type is InterfaceType) { |
| 6640 // |
| 6641 // T is bottom. (This case is handled by the class BottomTypeImpl.) |
| 6642 // |
| 6643 // Direct supertype: S is a direct supertype of T. |
| 6644 // |
| 6645 if (type.isDirectSupertypeOf(this)) { |
| 6646 return true; |
| 6647 } |
| 6648 // |
| 6649 // Covariance: T is of the form I<T1, ..., Tn> and S is of the form |
| 6650 // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n. |
| 6651 // |
| 6652 ClassElement tElement = this.element; |
| 6653 ClassElement sElement = type.element; |
| 6654 if (tElement == sElement) { |
| 6655 List<DartType> tArguments = typeArguments; |
| 6656 List<DartType> sArguments = type.typeArguments; |
| 6657 if (tArguments.length != sArguments.length) { |
| 6658 return false; |
| 6659 } |
| 6660 for (int i = 0; i < tArguments.length; i++) { |
| 6661 if (!(tArguments[i] as TypeImpl) |
| 6662 .isMoreSpecificThan(sArguments[i], withDynamic)) { |
| 6663 return false; |
| 6664 } |
| 6665 } |
| 6666 return true; |
| 6667 } |
| 6668 } |
| 6669 // |
| 6670 // Transitivity: T << U and U << S. |
| 6671 // |
| 6672 // First check for infinite loops |
| 6673 if (element == null) { |
| 6674 return false; |
| 6675 } |
| 6676 if (visitedElements == null) { |
| 6677 visitedElements = new HashSet<ClassElement>(); |
| 6678 } else if (visitedElements.contains(element)) { |
| 6679 return false; |
| 6680 } |
| 6681 visitedElements.add(element); |
| 6682 try { |
| 6683 // Iterate over all of the types U that are more specific than T because |
| 6684 // they are direct supertypes of T and return true if any of them are more |
| 6685 // specific than S. |
| 6686 InterfaceTypeImpl supertype = superclass; |
| 6687 if (supertype != null && |
| 6688 supertype.isMoreSpecificThan(type, withDynamic, visitedElements)) { |
| 6689 return true; |
| 6690 } |
| 6691 for (InterfaceType interfaceType in interfaces) { |
| 6692 if ((interfaceType as InterfaceTypeImpl) |
| 6693 .isMoreSpecificThan(type, withDynamic, visitedElements)) { |
| 6694 return true; |
| 6695 } |
| 6696 } |
| 6697 for (InterfaceType mixinType in mixins) { |
| 6698 if ((mixinType as InterfaceTypeImpl) |
| 6699 .isMoreSpecificThan(type, withDynamic, visitedElements)) { |
| 6700 return true; |
| 6701 } |
| 6702 } |
| 6703 // If a type I includes an instance method named `call`, and the type of |
| 6704 // `call` is the function type F, then I is considered to be more specific |
| 6705 // than F. |
| 6706 MethodElement callMethod = getMethod('call'); |
| 6707 if (callMethod != null && !callMethod.isStatic) { |
| 6708 FunctionTypeImpl callType = callMethod.type; |
| 6709 if (callType.isMoreSpecificThan(type, withDynamic, visitedElements)) { |
| 6710 return true; |
| 6711 } |
| 6712 } |
| 6713 return false; |
| 6714 } finally { |
| 6715 visitedElements.remove(element); |
| 6716 } |
| 6717 } |
| 6718 |
| 6719 @override |
| 6720 ConstructorElement lookUpConstructor( |
| 6721 String constructorName, LibraryElement library) { |
| 6722 // prepare base ConstructorElement |
| 6723 ConstructorElement constructorElement; |
| 6724 if (constructorName == null) { |
| 6725 constructorElement = element.unnamedConstructor; |
| 6726 } else { |
| 6727 constructorElement = element.getNamedConstructor(constructorName); |
| 6728 } |
| 6729 // not found or not accessible |
| 6730 if (constructorElement == null || |
| 6731 !constructorElement.isAccessibleIn(library)) { |
| 6732 return null; |
| 6733 } |
| 6734 // return member |
| 6735 return ConstructorMember.from(constructorElement, this); |
| 6736 } |
| 6737 |
| 6738 @override |
| 6739 PropertyAccessorElement lookUpGetter( |
| 6740 String getterName, LibraryElement library) { |
| 6741 PropertyAccessorElement element = getGetter(getterName); |
| 6742 if (element != null && element.isAccessibleIn(library)) { |
| 6743 return element; |
| 6744 } |
| 6745 return lookUpGetterInSuperclass(getterName, library); |
| 6746 } |
| 6747 |
| 6748 @override |
| 6749 PropertyAccessorElement lookUpGetterInSuperclass( |
| 6750 String getterName, LibraryElement library) { |
| 6751 for (InterfaceType mixin in mixins.reversed) { |
| 6752 PropertyAccessorElement element = mixin.getGetter(getterName); |
| 6753 if (element != null && element.isAccessibleIn(library)) { |
| 6754 return element; |
| 6755 } |
| 6756 } |
| 6757 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 6758 InterfaceType supertype = superclass; |
| 6759 ClassElement supertypeElement = |
| 6760 supertype == null ? null : supertype.element; |
| 6761 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 6762 visitedClasses.add(supertypeElement); |
| 6763 PropertyAccessorElement element = supertype.getGetter(getterName); |
| 6764 if (element != null && element.isAccessibleIn(library)) { |
| 6765 return element; |
| 6766 } |
| 6767 for (InterfaceType mixin in supertype.mixins.reversed) { |
| 6768 element = mixin.getGetter(getterName); |
| 6769 if (element != null && element.isAccessibleIn(library)) { |
| 6770 return element; |
| 6771 } |
| 6772 } |
| 6773 supertype = supertype.superclass; |
| 6774 supertypeElement = supertype == null ? null : supertype.element; |
| 6775 } |
| 6776 return null; |
| 6777 } |
| 6778 |
| 6779 @override |
| 6780 MethodElement lookUpMethod(String methodName, LibraryElement library) { |
| 6781 MethodElement element = getMethod(methodName); |
| 6782 if (element != null && element.isAccessibleIn(library)) { |
| 6783 return element; |
| 6784 } |
| 6785 return lookUpMethodInSuperclass(methodName, library); |
| 6786 } |
| 6787 |
| 6788 @override |
| 6789 MethodElement lookUpMethodInSuperclass( |
| 6790 String methodName, LibraryElement library) { |
| 6791 for (InterfaceType mixin in mixins.reversed) { |
| 6792 MethodElement element = mixin.getMethod(methodName); |
| 6793 if (element != null && element.isAccessibleIn(library)) { |
| 6794 return element; |
| 6795 } |
| 6796 } |
| 6797 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 6798 InterfaceType supertype = superclass; |
| 6799 ClassElement supertypeElement = |
| 6800 supertype == null ? null : supertype.element; |
| 6801 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 6802 visitedClasses.add(supertypeElement); |
| 6803 MethodElement element = supertype.getMethod(methodName); |
| 6804 if (element != null && element.isAccessibleIn(library)) { |
| 6805 return element; |
| 6806 } |
| 6807 for (InterfaceType mixin in supertype.mixins.reversed) { |
| 6808 element = mixin.getMethod(methodName); |
| 6809 if (element != null && element.isAccessibleIn(library)) { |
| 6810 return element; |
| 6811 } |
| 6812 } |
| 6813 supertype = supertype.superclass; |
| 6814 supertypeElement = supertype == null ? null : supertype.element; |
| 6815 } |
| 6816 return null; |
| 6817 } |
| 6818 |
| 6819 @override |
| 6820 PropertyAccessorElement lookUpSetter( |
| 6821 String setterName, LibraryElement library) { |
| 6822 PropertyAccessorElement element = getSetter(setterName); |
| 6823 if (element != null && element.isAccessibleIn(library)) { |
| 6824 return element; |
| 6825 } |
| 6826 return lookUpSetterInSuperclass(setterName, library); |
| 6827 } |
| 6828 |
| 6829 @override |
| 6830 PropertyAccessorElement lookUpSetterInSuperclass( |
| 6831 String setterName, LibraryElement library) { |
| 6832 for (InterfaceType mixin in mixins.reversed) { |
| 6833 PropertyAccessorElement element = mixin.getSetter(setterName); |
| 6834 if (element != null && element.isAccessibleIn(library)) { |
| 6835 return element; |
| 6836 } |
| 6837 } |
| 6838 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
| 6839 InterfaceType supertype = superclass; |
| 6840 ClassElement supertypeElement = |
| 6841 supertype == null ? null : supertype.element; |
| 6842 while (supertype != null && !visitedClasses.contains(supertypeElement)) { |
| 6843 visitedClasses.add(supertypeElement); |
| 6844 PropertyAccessorElement element = supertype.getSetter(setterName); |
| 6845 if (element != null && element.isAccessibleIn(library)) { |
| 6846 return element; |
| 6847 } |
| 6848 for (InterfaceType mixin in supertype.mixins.reversed) { |
| 6849 element = mixin.getSetter(setterName); |
| 6850 if (element != null && element.isAccessibleIn(library)) { |
| 6851 return element; |
| 6852 } |
| 6853 } |
| 6854 supertype = supertype.superclass; |
| 6855 supertypeElement = supertype == null ? null : supertype.element; |
| 6856 } |
| 6857 return null; |
| 6858 } |
| 6859 |
| 6860 @override |
| 6861 InterfaceTypeImpl pruned(List<FunctionTypeAliasElement> prune) { |
| 6862 if (prune == null) { |
| 6863 return this; |
| 6864 } else { |
| 6865 // There should never be a reason to prune a type that has already been |
| 6866 // pruned, since pruning is only done when expanding a function type |
| 6867 // alias, and function type aliases are always expanded by starting with |
| 6868 // base types. |
| 6869 assert(this.prunedTypedefs == null); |
| 6870 InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune); |
| 6871 result.typeArguments = |
| 6872 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList(); |
| 6873 return result; |
| 6874 } |
| 6875 } |
| 6876 |
| 6877 @override |
| 6878 InterfaceTypeImpl substitute2( |
| 6879 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 6880 [List<FunctionTypeAliasElement> prune]) { |
| 6881 // Pruned types should only ever result from performing type variable |
| 6882 // substitution, and it doesn't make sense to substitute again after |
| 6883 // substituting once. |
| 6884 assert(this.prunedTypedefs == null); |
| 6885 if (argumentTypes.length != parameterTypes.length) { |
| 6886 throw new IllegalArgumentException( |
| 6887 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); |
| 6888 } |
| 6889 if (argumentTypes.length == 0 || typeArguments.length == 0) { |
| 6890 return this.pruned(prune); |
| 6891 } |
| 6892 List<DartType> newTypeArguments = TypeImpl.substitute( |
| 6893 typeArguments, argumentTypes, parameterTypes, prune); |
| 6894 if (JavaArrays.equals(newTypeArguments, typeArguments)) { |
| 6895 return this; |
| 6896 } |
| 6897 InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune); |
| 6898 newType.typeArguments = newTypeArguments; |
| 6899 return newType; |
| 6900 } |
| 6901 |
| 6902 @override |
| 6903 InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => |
| 6904 substitute2(argumentTypes, typeArguments); |
| 6905 |
| 6906 /** |
| 6907 * Compute the least upper bound of types [i] and [j], both of which are |
| 6908 * known to be interface types. |
| 6909 * |
| 6910 * In the event that the algorithm fails (which might occur due to a bug in |
| 6911 * the analyzer), `null` is returned. |
| 6912 */ |
| 6913 static InterfaceType computeLeastUpperBound( |
| 6914 InterfaceType i, InterfaceType j) { |
| 6915 // compute set of supertypes |
| 6916 Set<InterfaceType> si = computeSuperinterfaceSet(i); |
| 6917 Set<InterfaceType> sj = computeSuperinterfaceSet(j); |
| 6918 // union si with i and sj with j |
| 6919 si.add(i); |
| 6920 sj.add(j); |
| 6921 // compute intersection, reference as set 's' |
| 6922 List<InterfaceType> s = _intersection(si, sj); |
| 6923 // for each element in Set s, compute the largest inheritance path to Object |
| 6924 List<int> depths = new List<int>.filled(s.length, 0); |
| 6925 int maxDepth = 0; |
| 6926 for (int n = 0; n < s.length; n++) { |
| 6927 depths[n] = computeLongestInheritancePathToObject(s[n]); |
| 6928 if (depths[n] > maxDepth) { |
| 6929 maxDepth = depths[n]; |
| 6930 } |
| 6931 } |
| 6932 // ensure that the currently computed maxDepth is unique, |
| 6933 // otherwise, decrement and test for uniqueness again |
| 6934 for (; maxDepth >= 0; maxDepth--) { |
| 6935 int indexOfLeastUpperBound = -1; |
| 6936 int numberOfTypesAtMaxDepth = 0; |
| 6937 for (int m = 0; m < depths.length; m++) { |
| 6938 if (depths[m] == maxDepth) { |
| 6939 numberOfTypesAtMaxDepth++; |
| 6940 indexOfLeastUpperBound = m; |
| 6941 } |
| 6942 } |
| 6943 if (numberOfTypesAtMaxDepth == 1) { |
| 6944 return s[indexOfLeastUpperBound]; |
| 6945 } |
| 6946 } |
| 6947 // Should be impossible--there should always be exactly one type with the |
| 6948 // maximum depth. |
| 6949 assert(false); |
| 6950 return null; |
| 6951 } |
| 6952 |
| 6953 /** |
| 6954 * Return the length of the longest inheritance path from the given [type] to |
| 6955 * Object. |
| 6956 * |
| 6957 * See [computeLeastUpperBound]. |
| 6958 */ |
| 6959 static int computeLongestInheritancePathToObject(InterfaceType type) => |
| 6960 _computeLongestInheritancePathToObject( |
| 6961 type, 0, new HashSet<ClassElement>()); |
| 6962 |
| 6963 /** |
| 6964 * Returns the set of all superinterfaces of the given [type]. |
| 6965 * |
| 6966 * See [computeLeastUpperBound]. |
| 6967 */ |
| 6968 static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => |
| 6969 _computeSuperinterfaceSet(type, new HashSet<InterfaceType>()); |
| 6970 |
| 6971 /** |
| 6972 * Return the length of the longest inheritance path from a subtype of the |
| 6973 * given [type] to Object, where the given [depth] is the length of the |
| 6974 * longest path from the subtype to this type. The set of [visitedTypes] is |
| 6975 * used to prevent infinite recursion in the case of a cyclic type structure. |
| 6976 * |
| 6977 * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound]. |
| 6978 */ |
| 6979 static int _computeLongestInheritancePathToObject( |
| 6980 InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) { |
| 6981 ClassElement classElement = type.element; |
| 6982 // Object case |
| 6983 if (classElement.supertype == null || visitedTypes.contains(classElement)) { |
| 6984 return depth; |
| 6985 } |
| 6986 int longestPath = 1; |
| 6987 try { |
| 6988 visitedTypes.add(classElement); |
| 6989 List<InterfaceType> superinterfaces = classElement.interfaces; |
| 6990 int pathLength; |
| 6991 if (superinterfaces.length > 0) { |
| 6992 // loop through each of the superinterfaces recursively calling this |
| 6993 // method and keeping track of the longest path to return |
| 6994 for (InterfaceType superinterface in superinterfaces) { |
| 6995 pathLength = _computeLongestInheritancePathToObject( |
| 6996 superinterface, depth + 1, visitedTypes); |
| 6997 if (pathLength > longestPath) { |
| 6998 longestPath = pathLength; |
| 6999 } |
| 7000 } |
| 7001 } |
| 7002 // finally, perform this same check on the super type |
| 7003 // TODO(brianwilkerson) Does this also need to add in the number of mixin |
| 7004 // classes? |
| 7005 InterfaceType supertype = classElement.supertype; |
| 7006 pathLength = _computeLongestInheritancePathToObject( |
| 7007 supertype, depth + 1, visitedTypes); |
| 7008 if (pathLength > longestPath) { |
| 7009 longestPath = pathLength; |
| 7010 } |
| 7011 } finally { |
| 7012 visitedTypes.remove(classElement); |
| 7013 } |
| 7014 return longestPath; |
| 7015 } |
| 7016 |
| 7017 /** |
| 7018 * Add all of the superinterfaces of the given [type] to the given [set]. |
| 7019 * Return the [set] as a convenience. |
| 7020 * |
| 7021 * See [computeSuperinterfaceSet], and [computeLeastUpperBound]. |
| 7022 */ |
| 7023 static Set<InterfaceType> _computeSuperinterfaceSet( |
| 7024 InterfaceType type, HashSet<InterfaceType> set) { |
| 7025 Element element = type.element; |
| 7026 if (element != null) { |
| 7027 List<InterfaceType> superinterfaces = type.interfaces; |
| 7028 for (InterfaceType superinterface in superinterfaces) { |
| 7029 if (set.add(superinterface)) { |
| 7030 _computeSuperinterfaceSet(superinterface, set); |
| 7031 } |
| 7032 } |
| 7033 InterfaceType supertype = type.superclass; |
| 7034 if (supertype != null) { |
| 7035 if (set.add(supertype)) { |
| 7036 _computeSuperinterfaceSet(supertype, set); |
| 7037 } |
| 7038 } |
| 7039 } |
| 7040 return set; |
| 7041 } |
| 7042 |
| 7043 /** |
| 7044 * Return the intersection of the [first] and [second] sets of types, where |
| 7045 * intersection is based on the equality of the types themselves. |
| 7046 */ |
| 7047 static List<InterfaceType> _intersection( |
| 7048 Set<InterfaceType> first, Set<InterfaceType> second) { |
| 7049 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); |
| 7050 result.retainAll(second); |
| 7051 return new List.from(result); |
| 7052 } |
| 7053 } |
| 7054 |
| 7055 /** |
| 7056 * A label associated with a statement. |
| 7057 */ |
| 7058 abstract class LabelElement implements Element { |
| 7059 /** |
| 7060 * An empty list of label elements. |
| 7061 */ |
| 7062 static const List<LabelElement> EMPTY_LIST = const <LabelElement>[]; |
| 7063 |
| 7064 /** |
| 7065 * Return the executable element in which this label is defined. |
| 7066 */ |
| 7067 @override |
| 7068 ExecutableElement get enclosingElement; |
| 7069 } |
| 7070 |
| 7071 /** |
| 7072 * A concrete implementation of a [LabelElement]. |
| 7073 */ |
| 7074 class LabelElementImpl extends ElementImpl implements LabelElement { |
| 7075 /** |
| 7076 * An empty list of label elements. |
| 7077 */ |
| 7078 @deprecated // Use LabelElement.EMPTY_LIST |
| 7079 static const List<LabelElement> EMPTY_ARRAY = const <LabelElement>[]; |
| 7080 |
| 7081 /** |
| 7082 * A flag indicating whether this label is associated with a `switch` |
| 7083 * statement. |
| 7084 */ |
| 7085 // TODO(brianwilkerson) Make this a modifier. |
| 7086 final bool _onSwitchStatement; |
| 7087 |
| 7088 /** |
| 7089 * A flag indicating whether this label is associated with a `switch` member |
| 7090 * (`case` or `default`). |
| 7091 */ |
| 7092 // TODO(brianwilkerson) Make this a modifier. |
| 7093 final bool _onSwitchMember; |
| 7094 |
| 7095 /** |
| 7096 * Initialize a newly created label element to have the given [name]. |
| 7097 * [onSwitchStatement] should be `true` if this label is associated with a |
| 7098 * `switch` statement and [onSwitchMember] should be `true` if this label is |
| 7099 * associated with a `switch` member. |
| 7100 */ |
| 7101 LabelElementImpl( |
| 7102 Identifier name, this._onSwitchStatement, this._onSwitchMember) |
| 7103 : super.forNode(name); |
| 7104 |
| 7105 @override |
| 7106 ExecutableElement get enclosingElement => |
| 7107 super.enclosingElement as ExecutableElement; |
| 7108 |
| 7109 /** |
| 7110 * Return `true` if this label is associated with a `switch` member (`case` or |
| 7111 * `default`). |
| 7112 */ |
| 7113 bool get isOnSwitchMember => _onSwitchMember; |
| 7114 |
| 7115 /** |
| 7116 * Return `true` if this label is associated with a `switch` statement. |
| 7117 */ |
| 7118 bool get isOnSwitchStatement => _onSwitchStatement; |
| 7119 |
| 7120 @override |
| 7121 ElementKind get kind => ElementKind.LABEL; |
| 7122 |
| 7123 @override |
| 7124 accept(ElementVisitor visitor) => visitor.visitLabelElement(this); |
| 7125 } |
| 7126 |
| 7127 /** |
| 7128 * A library. |
| 7129 */ |
| 7130 abstract class LibraryElement implements Element { |
| 7131 /** |
| 7132 * An empty list of library elements. |
| 7133 */ |
| 7134 static const List<LibraryElement> EMPTY_LIST = const <LibraryElement>[]; |
| 7135 |
| 7136 /** |
| 7137 * Return the compilation unit that defines this library. |
| 7138 */ |
| 7139 CompilationUnitElement get definingCompilationUnit; |
| 7140 |
| 7141 /** |
| 7142 * Return the entry point for this library, or `null` if this library does not |
| 7143 * have an entry point. The entry point is defined to be a zero argument |
| 7144 * top-level function whose name is `main`. |
| 7145 */ |
| 7146 FunctionElement get entryPoint; |
| 7147 |
| 7148 /** |
| 7149 * Return a list containing all of the libraries that are exported from this |
| 7150 * library. |
| 7151 */ |
| 7152 List<LibraryElement> get exportedLibraries; |
| 7153 |
| 7154 /** |
| 7155 * The export [Namespace] of this library, `null` if it has not been |
| 7156 * computed yet. |
| 7157 */ |
| 7158 Namespace get exportNamespace; |
| 7159 |
| 7160 /** |
| 7161 * Return a list containing all of the exports defined in this library. |
| 7162 */ |
| 7163 List<ExportElement> get exports; |
| 7164 |
| 7165 /** |
| 7166 * Return `true` if the defining compilation unit of this library contains at |
| 7167 * least one import directive whose URI uses the "dart-ext" scheme. |
| 7168 */ |
| 7169 bool get hasExtUri; |
| 7170 |
| 7171 /** |
| 7172 * Return `true` if this library defines a top-level function named |
| 7173 * `loadLibrary`. |
| 7174 */ |
| 7175 bool get hasLoadLibraryFunction; |
| 7176 |
| 7177 /** |
| 7178 * Return a list containing all of the libraries that are imported into this |
| 7179 * library. This includes all of the libraries that are imported using a |
| 7180 * prefix (also available through the prefixes returned by [getPrefixes]) and |
| 7181 * those that are imported without a prefix. |
| 7182 */ |
| 7183 List<LibraryElement> get importedLibraries; |
| 7184 |
| 7185 /** |
| 7186 * Return a list containing all of the imports defined in this library. |
| 7187 */ |
| 7188 List<ImportElement> get imports; |
| 7189 |
| 7190 /** |
| 7191 * Return `true` if this library is an application that can be run in the |
| 7192 * browser. |
| 7193 */ |
| 7194 bool get isBrowserApplication; |
| 7195 |
| 7196 /** |
| 7197 * Return `true` if this library is the dart:core library. |
| 7198 */ |
| 7199 bool get isDartCore; |
| 7200 |
| 7201 /** |
| 7202 * Return `true` if this library is part of the SDK. |
| 7203 */ |
| 7204 bool get isInSdk; |
| 7205 |
| 7206 /** |
| 7207 * Return the element representing the synthetic function `loadLibrary` that |
| 7208 * is implicitly defined for this library if the library is imported using a |
| 7209 * deferred import. |
| 7210 */ |
| 7211 FunctionElement get loadLibraryFunction; |
| 7212 |
| 7213 /** |
| 7214 * Return a list containing all of the compilation units that are included in |
| 7215 * this library using a `part` directive. This does not include the defining |
| 7216 * compilation unit that contains the `part` directives. |
| 7217 */ |
| 7218 List<CompilationUnitElement> get parts; |
| 7219 |
| 7220 /** |
| 7221 * Return a list containing elements for each of the prefixes used to `import` |
| 7222 * libraries into this library. Each prefix can be used in more than one |
| 7223 * `import` directive. |
| 7224 */ |
| 7225 List<PrefixElement> get prefixes; |
| 7226 |
| 7227 /** |
| 7228 * The public [Namespace] of this library, `null` if it has not been |
| 7229 * computed yet. |
| 7230 */ |
| 7231 Namespace get publicNamespace; |
| 7232 |
| 7233 /** |
| 7234 * Return a list containing all of the compilation units this library consists |
| 7235 * of. This includes the defining compilation unit and units included using |
| 7236 * the `part` directive. |
| 7237 */ |
| 7238 List<CompilationUnitElement> get units; |
| 7239 |
| 7240 /** |
| 7241 * Return a list containing all directly and indirectly imported libraries. |
| 7242 */ |
| 7243 List<LibraryElement> get visibleLibraries; |
| 7244 |
| 7245 /** |
| 7246 * Return a list containing all of the imports that share the given [prefix], |
| 7247 * or an empty array if there are no such imports. |
| 7248 */ |
| 7249 List<ImportElement> getImportsWithPrefix(PrefixElement prefix); |
| 7250 |
| 7251 /** |
| 7252 * Return the class defined in this library that has the given [name], or |
| 7253 * `null` if this library does not define a class with the given name. |
| 7254 */ |
| 7255 ClassElement getType(String className); |
| 7256 |
| 7257 /** |
| 7258 * Return `true` if this library is up to date with respect to the given |
| 7259 * [timeStamp]. If any transitively referenced Source is newer than the time |
| 7260 * stamp, this method returns false. |
| 7261 */ |
| 7262 bool isUpToDate(int timeStamp); |
| 7263 } |
| 7264 |
| 7265 /** |
| 7266 * A concrete implementation of a [LibraryElement]. |
| 7267 */ |
| 7268 class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| 7269 /** |
| 7270 * An empty list of library elements. |
| 7271 */ |
| 7272 @deprecated // Use LibraryElement.EMPTY_LIST |
| 7273 static const List<LibraryElement> EMPTY_ARRAY = const <LibraryElement>[]; |
| 7274 |
| 7275 /** |
| 7276 * The analysis context in which this library is defined. |
| 7277 */ |
| 7278 final AnalysisContext context; |
| 7279 |
| 7280 /** |
| 7281 * The compilation unit that defines this library. |
| 7282 */ |
| 7283 CompilationUnitElement _definingCompilationUnit; |
| 7284 |
| 7285 /** |
| 7286 * The entry point for this library, or `null` if this library does not have |
| 7287 * an entry point. |
| 7288 */ |
| 7289 FunctionElement entryPoint; |
| 7290 |
| 7291 /** |
| 7292 * A list containing specifications of all of the imports defined in this |
| 7293 * library. |
| 7294 */ |
| 7295 List<ImportElement> _imports = ImportElement.EMPTY_LIST; |
| 7296 |
| 7297 /** |
| 7298 * A list containing specifications of all of the exports defined in this |
| 7299 * library. |
| 7300 */ |
| 7301 List<ExportElement> _exports = ExportElement.EMPTY_LIST; |
| 7302 |
| 7303 /** |
| 7304 * A list containing all of the compilation units that are included in this |
| 7305 * library using a `part` directive. |
| 7306 */ |
| 7307 List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST; |
| 7308 |
| 7309 /** |
| 7310 * The element representing the synthetic function `loadLibrary` that is |
| 7311 * defined for this library, or `null` if the element has not yet been created
. |
| 7312 */ |
| 7313 FunctionElement _loadLibraryFunction; |
| 7314 |
| 7315 /** |
| 7316 * The export [Namespace] of this library, `null` if it has not been |
| 7317 * computed yet. |
| 7318 */ |
| 7319 @override |
| 7320 Namespace exportNamespace; |
| 7321 |
| 7322 /** |
| 7323 * The public [Namespace] of this library, `null` if it has not been |
| 7324 * computed yet. |
| 7325 */ |
| 7326 @override |
| 7327 Namespace publicNamespace; |
| 7328 |
| 7329 /** |
| 7330 * Initialize a newly created library element in the given [context] to have |
| 7331 * the given [name] and [offset]. |
| 7332 */ |
| 7333 LibraryElementImpl(this.context, String name, int offset) |
| 7334 : super(name, offset); |
| 7335 |
| 7336 /** |
| 7337 * Initialize a newly created library element in the given [context] to have |
| 7338 * the given [name]. |
| 7339 */ |
| 7340 LibraryElementImpl.forNode(this.context, LibraryIdentifier name) |
| 7341 : super.forNode(name); |
| 7342 |
| 7343 @override |
| 7344 CompilationUnitElement get definingCompilationUnit => |
| 7345 _definingCompilationUnit; |
| 7346 |
| 7347 /** |
| 7348 * Set the compilation unit that defines this library to the given compilation |
| 7349 * [unit]. |
| 7350 */ |
| 7351 void set definingCompilationUnit(CompilationUnitElement unit) { |
| 7352 assert((unit as CompilationUnitElementImpl).librarySource == unit.source); |
| 7353 (unit as CompilationUnitElementImpl).enclosingElement = this; |
| 7354 this._definingCompilationUnit = unit; |
| 7355 } |
| 7356 |
| 7357 @override |
| 7358 List<LibraryElement> get exportedLibraries { |
| 7359 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); |
| 7360 for (ExportElement element in _exports) { |
| 7361 LibraryElement library = element.exportedLibrary; |
| 7362 if (library != null) { |
| 7363 libraries.add(library); |
| 7364 } |
| 7365 } |
| 7366 return new List.from(libraries); |
| 7367 } |
| 7368 |
| 7369 @override |
| 7370 List<ExportElement> get exports => _exports; |
| 7371 |
| 7372 /** |
| 7373 * Set the specifications of all of the exports defined in this library to the |
| 7374 * given list of [exports]. |
| 7375 */ |
| 7376 void set exports(List<ExportElement> exports) { |
| 7377 for (ExportElement exportElement in exports) { |
| 7378 (exportElement as ExportElementImpl).enclosingElement = this; |
| 7379 } |
| 7380 this._exports = exports; |
| 7381 } |
| 7382 |
| 7383 @override |
| 7384 bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI); |
| 7385 |
| 7386 /** |
| 7387 * Set whether this library has an import of a "dart-ext" URI. |
| 7388 */ |
| 7389 void set hasExtUri(bool hasExtUri) { |
| 7390 setModifier(Modifier.HAS_EXT_URI, hasExtUri); |
| 7391 } |
| 7392 |
| 7393 @override |
| 7394 int get hashCode => _definingCompilationUnit.hashCode; |
| 7395 |
| 7396 @override |
| 7397 bool get hasLoadLibraryFunction { |
| 7398 if (_definingCompilationUnit.hasLoadLibraryFunction) { |
| 7399 return true; |
| 7400 } |
| 7401 for (int i = 0; i < _parts.length; i++) { |
| 7402 if (_parts[i].hasLoadLibraryFunction) { |
| 7403 return true; |
| 7404 } |
| 7405 } |
| 7406 return false; |
| 7407 } |
| 7408 |
| 7409 @override |
| 7410 String get identifier => _definingCompilationUnit.source.encoding; |
| 7411 |
| 7412 @override |
| 7413 List<LibraryElement> get importedLibraries { |
| 7414 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); |
| 7415 for (ImportElement element in _imports) { |
| 7416 LibraryElement library = element.importedLibrary; |
| 7417 if (library != null) { |
| 7418 libraries.add(library); |
| 7419 } |
| 7420 } |
| 7421 return new List.from(libraries); |
| 7422 } |
| 7423 |
| 7424 @override |
| 7425 List<ImportElement> get imports => _imports; |
| 7426 |
| 7427 /** |
| 7428 * Set the specifications of all of the imports defined in this library to the |
| 7429 * given list of [imports]. |
| 7430 */ |
| 7431 void set imports(List<ImportElement> imports) { |
| 7432 for (ImportElement importElement in imports) { |
| 7433 (importElement as ImportElementImpl).enclosingElement = this; |
| 7434 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; |
| 7435 if (prefix != null) { |
| 7436 prefix.enclosingElement = this; |
| 7437 } |
| 7438 } |
| 7439 this._imports = imports; |
| 7440 } |
| 7441 |
| 7442 @override |
| 7443 bool get isBrowserApplication => |
| 7444 entryPoint != null && isOrImportsBrowserLibrary; |
| 7445 |
| 7446 @override |
| 7447 bool get isDartCore => name == "dart.core"; |
| 7448 |
| 7449 @override |
| 7450 bool get isInSdk => |
| 7451 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); |
| 7452 |
| 7453 /** |
| 7454 * Return `true` if the receiver directly or indirectly imports the |
| 7455 * 'dart:html' libraries. |
| 7456 */ |
| 7457 bool get isOrImportsBrowserLibrary { |
| 7458 List<LibraryElement> visited = new List<LibraryElement>(); |
| 7459 Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML); |
| 7460 visited.add(this); |
| 7461 for (int index = 0; index < visited.length; index++) { |
| 7462 LibraryElement library = visited[index]; |
| 7463 Source source = library.definingCompilationUnit.source; |
| 7464 if (source == htmlLibSource) { |
| 7465 return true; |
| 7466 } |
| 7467 for (LibraryElement importedLibrary in library.importedLibraries) { |
| 7468 if (!visited.contains(importedLibrary)) { |
| 7469 visited.add(importedLibrary); |
| 7470 } |
| 7471 } |
| 7472 for (LibraryElement exportedLibrary in library.exportedLibraries) { |
| 7473 if (!visited.contains(exportedLibrary)) { |
| 7474 visited.add(exportedLibrary); |
| 7475 } |
| 7476 } |
| 7477 } |
| 7478 return false; |
| 7479 } |
| 7480 |
| 7481 @override |
| 7482 ElementKind get kind => ElementKind.LIBRARY; |
| 7483 |
| 7484 @override |
| 7485 LibraryElement get library => this; |
| 7486 |
| 7487 @override |
| 7488 FunctionElement get loadLibraryFunction { |
| 7489 if (_loadLibraryFunction == null) { |
| 7490 FunctionElementImpl function = |
| 7491 new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1); |
| 7492 function.synthetic = true; |
| 7493 function.enclosingElement = this; |
| 7494 function.returnType = loadLibraryReturnType; |
| 7495 function.type = new FunctionTypeImpl(function); |
| 7496 _loadLibraryFunction = function; |
| 7497 } |
| 7498 return _loadLibraryFunction; |
| 7499 } |
| 7500 |
| 7501 /** |
| 7502 * Return the object representing the type 'Future' from the 'dart:async' |
| 7503 * library, or the type 'void' if the type 'Future' cannot be accessed. |
| 7504 */ |
| 7505 DartType get loadLibraryReturnType { |
| 7506 try { |
| 7507 Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 7508 if (asyncSource == null) { |
| 7509 AnalysisEngine.instance.logger |
| 7510 .logError("Could not create a source for dart:async"); |
| 7511 return VoidTypeImpl.instance; |
| 7512 } |
| 7513 LibraryElement asyncElement = context.computeLibraryElement(asyncSource); |
| 7514 if (asyncElement == null) { |
| 7515 AnalysisEngine.instance.logger |
| 7516 .logError("Could not build the element model for dart:async"); |
| 7517 return VoidTypeImpl.instance; |
| 7518 } |
| 7519 ClassElement futureElement = asyncElement.getType("Future"); |
| 7520 if (futureElement == null) { |
| 7521 AnalysisEngine.instance.logger |
| 7522 .logError("Could not find type Future in dart:async"); |
| 7523 return VoidTypeImpl.instance; |
| 7524 } |
| 7525 InterfaceType futureType = futureElement.type; |
| 7526 return futureType.substitute4(<DartType>[DynamicTypeImpl.instance]); |
| 7527 } on AnalysisException catch (exception, stackTrace) { |
| 7528 AnalysisEngine.instance.logger.logError( |
| 7529 "Could not build the element model for dart:async", |
| 7530 new CaughtException(exception, stackTrace)); |
| 7531 return VoidTypeImpl.instance; |
| 7532 } |
| 7533 } |
| 7534 |
| 7535 @override |
| 7536 List<CompilationUnitElement> get parts => _parts; |
| 7537 |
| 7538 /** |
| 7539 * Set the compilation units that are included in this library using a `part` |
| 7540 * directive to the given list of [parts]. |
| 7541 */ |
| 7542 void set parts(List<CompilationUnitElement> parts) { |
| 7543 for (CompilationUnitElement compilationUnit in parts) { |
| 7544 assert((compilationUnit as CompilationUnitElementImpl).librarySource == |
| 7545 source); |
| 7546 (compilationUnit as CompilationUnitElementImpl).enclosingElement = this; |
| 7547 } |
| 7548 this._parts = parts; |
| 7549 } |
| 7550 |
| 7551 @override |
| 7552 List<PrefixElement> get prefixes { |
| 7553 HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>(); |
| 7554 for (ImportElement element in _imports) { |
| 7555 PrefixElement prefix = element.prefix; |
| 7556 if (prefix != null) { |
| 7557 prefixes.add(prefix); |
| 7558 } |
| 7559 } |
| 7560 return new List.from(prefixes); |
| 7561 } |
| 7562 |
| 7563 @override |
| 7564 Source get source { |
| 7565 if (_definingCompilationUnit == null) { |
| 7566 return null; |
| 7567 } |
| 7568 return _definingCompilationUnit.source; |
| 7569 } |
| 7570 |
| 7571 @override |
| 7572 List<CompilationUnitElement> get units { |
| 7573 List<CompilationUnitElement> units = new List<CompilationUnitElement>(); |
| 7574 units.add(_definingCompilationUnit); |
| 7575 units.addAll(_parts); |
| 7576 return units; |
| 7577 } |
| 7578 |
| 7579 @override |
| 7580 List<LibraryElement> get visibleLibraries { |
| 7581 Set<LibraryElement> visibleLibraries = new Set(); |
| 7582 _addVisibleLibraries(visibleLibraries, false); |
| 7583 return new List.from(visibleLibraries); |
| 7584 } |
| 7585 |
| 7586 @override |
| 7587 bool operator ==(Object object) => object is LibraryElementImpl && |
| 7588 _definingCompilationUnit == object.definingCompilationUnit; |
| 7589 |
| 7590 @override |
| 7591 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); |
| 7592 |
| 7593 @override |
| 7594 ElementImpl getChild(String identifier) { |
| 7595 if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == |
| 7596 identifier) { |
| 7597 return _definingCompilationUnit as CompilationUnitElementImpl; |
| 7598 } |
| 7599 for (CompilationUnitElement part in _parts) { |
| 7600 if ((part as CompilationUnitElementImpl).identifier == identifier) { |
| 7601 return part as CompilationUnitElementImpl; |
| 7602 } |
| 7603 } |
| 7604 for (ImportElement importElement in _imports) { |
| 7605 if ((importElement as ImportElementImpl).identifier == identifier) { |
| 7606 return importElement as ImportElementImpl; |
| 7607 } |
| 7608 } |
| 7609 for (ExportElement exportElement in _exports) { |
| 7610 if ((exportElement as ExportElementImpl).identifier == identifier) { |
| 7611 return exportElement as ExportElementImpl; |
| 7612 } |
| 7613 } |
| 7614 return null; |
| 7615 } |
| 7616 |
| 7617 @override |
| 7618 List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) { |
| 7619 int count = _imports.length; |
| 7620 List<ImportElement> importList = new List<ImportElement>(); |
| 7621 for (int i = 0; i < count; i++) { |
| 7622 if (identical(_imports[i].prefix, prefixElement)) { |
| 7623 importList.add(_imports[i]); |
| 7624 } |
| 7625 } |
| 7626 return importList; |
| 7627 } |
| 7628 |
| 7629 @override |
| 7630 ClassElement getType(String className) { |
| 7631 ClassElement type = _definingCompilationUnit.getType(className); |
| 7632 if (type != null) { |
| 7633 return type; |
| 7634 } |
| 7635 for (CompilationUnitElement part in _parts) { |
| 7636 type = part.getType(className); |
| 7637 if (type != null) { |
| 7638 return type; |
| 7639 } |
| 7640 } |
| 7641 return null; |
| 7642 } |
| 7643 |
| 7644 @override |
| 7645 bool isUpToDate(int timeStamp) { |
| 7646 Set<LibraryElement> visitedLibraries = new Set(); |
| 7647 return _safeIsUpToDate(this, timeStamp, visitedLibraries); |
| 7648 } |
| 7649 |
| 7650 @override |
| 7651 void visitChildren(ElementVisitor visitor) { |
| 7652 super.visitChildren(visitor); |
| 7653 safelyVisitChild(_definingCompilationUnit, visitor); |
| 7654 safelyVisitChildren(_exports, visitor); |
| 7655 safelyVisitChildren(_imports, visitor); |
| 7656 safelyVisitChildren(_parts, visitor); |
| 7657 } |
| 7658 |
| 7659 /** |
| 7660 * Recursively fills set of visible libraries for |
| 7661 * [getVisibleElementsLibraries]. |
| 7662 */ |
| 7663 void _addVisibleLibraries( |
| 7664 Set<LibraryElement> visibleLibraries, bool includeExports) { |
| 7665 // maybe already processed |
| 7666 if (!visibleLibraries.add(this)) { |
| 7667 return; |
| 7668 } |
| 7669 // add imported libraries |
| 7670 for (ImportElement importElement in _imports) { |
| 7671 LibraryElement importedLibrary = importElement.importedLibrary; |
| 7672 if (importedLibrary != null) { |
| 7673 (importedLibrary as LibraryElementImpl) |
| 7674 ._addVisibleLibraries(visibleLibraries, true); |
| 7675 } |
| 7676 } |
| 7677 // add exported libraries |
| 7678 if (includeExports) { |
| 7679 for (ExportElement exportElement in _exports) { |
| 7680 LibraryElement exportedLibrary = exportElement.exportedLibrary; |
| 7681 if (exportedLibrary != null) { |
| 7682 (exportedLibrary as LibraryElementImpl) |
| 7683 ._addVisibleLibraries(visibleLibraries, true); |
| 7684 } |
| 7685 } |
| 7686 } |
| 7687 } |
| 7688 |
| 7689 /** |
| 7690 * Return `true` if the given [library] is up to date with respect to the |
| 7691 * given [timeStamp]. The set of [visitedLibraries] is used to prevent |
| 7692 * infinite recusion in the case of mutually dependent libraries. |
| 7693 */ |
| 7694 static bool _safeIsUpToDate(LibraryElement library, int timeStamp, |
| 7695 Set<LibraryElement> visitedLibraries) { |
| 7696 if (!visitedLibraries.contains(library)) { |
| 7697 visitedLibraries.add(library); |
| 7698 AnalysisContext context = library.context; |
| 7699 // Check the defining compilation unit. |
| 7700 if (timeStamp < |
| 7701 context |
| 7702 .getModificationStamp(library.definingCompilationUnit.source)) { |
| 7703 return false; |
| 7704 } |
| 7705 // Check the parted compilation units. |
| 7706 for (CompilationUnitElement element in library.parts) { |
| 7707 if (timeStamp < context.getModificationStamp(element.source)) { |
| 7708 return false; |
| 7709 } |
| 7710 } |
| 7711 // Check the imported libraries. |
| 7712 for (LibraryElement importedLibrary in library.importedLibraries) { |
| 7713 if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) { |
| 7714 return false; |
| 7715 } |
| 7716 } |
| 7717 // Check the exported libraries. |
| 7718 for (LibraryElement exportedLibrary in library.exportedLibraries) { |
| 7719 if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) { |
| 7720 return false; |
| 7721 } |
| 7722 } |
| 7723 } |
| 7724 return true; |
| 7725 } |
| 7726 } |
| 7727 |
| 7728 /** |
| 7729 * An element that can be (but are not required to be) defined within a method |
| 7730 * or function (an [ExecutableElement]). |
| 7731 */ |
| 7732 abstract class LocalElement implements Element { |
| 7733 /** |
| 7734 * Return a source range that covers the approximate portion of the source in |
| 7735 * which the name of this element is visible, or `null` if there is no single |
| 7736 * range of characters within which the element name is visible. |
| 7737 * |
| 7738 * * For a local variable, this includes everything from the end of the |
| 7739 * variable's initializer to the end of the block that encloses the variable |
| 7740 * declaration. |
| 7741 * * For a parameter, this includes the body of the method or function that |
| 7742 * declares the parameter. |
| 7743 * * For a local function, this includes everything from the beginning of the |
| 7744 * function's body to the end of the block that encloses the function |
| 7745 * declaration. |
| 7746 * * For top-level functions, `null` will be returned because they are |
| 7747 * potentially visible in multiple sources. |
| 7748 */ |
| 7749 SourceRange get visibleRange; |
| 7750 } |
| 7751 |
| 7752 /** |
| 7753 * A local variable. |
| 7754 */ |
| 7755 abstract class LocalVariableElement implements LocalElement, VariableElement { |
| 7756 /** |
| 7757 * An empty list of field elements. |
| 7758 */ |
| 7759 static const List<LocalVariableElement> EMPTY_LIST = |
| 7760 const <LocalVariableElement>[]; |
| 7761 |
| 7762 /** |
| 7763 * Return the resolved [VariableDeclaration] node that declares this |
| 7764 * [LocalVariableElement]. |
| 7765 * |
| 7766 * This method is expensive, because resolved AST might be evicted from cache, |
| 7767 * so parsing and resolving will be performed. |
| 7768 */ |
| 7769 @override |
| 7770 VariableDeclaration computeNode(); |
| 7771 } |
| 7772 |
| 7773 /** |
| 7774 * A concrete implementation of a [LocalVariableElement]. |
| 7775 */ |
| 7776 class LocalVariableElementImpl extends VariableElementImpl |
| 7777 with PotentiallyConstVariableElement |
| 7778 implements LocalVariableElement { |
| 7779 /** |
| 7780 * An empty list of field elements. |
| 7781 */ |
| 7782 @deprecated // Use LocalVariableElement.EMPTY_LIST |
| 7783 static const List<LocalVariableElement> EMPTY_ARRAY = |
| 7784 const <LocalVariableElement>[]; |
| 7785 |
| 7786 /** |
| 7787 * The offset to the beginning of the visible range for this element. |
| 7788 */ |
| 7789 int _visibleRangeOffset = 0; |
| 7790 |
| 7791 /** |
| 7792 * The length of the visible range for this element, or `-1` if this element |
| 7793 * does not have a visible range. |
| 7794 */ |
| 7795 int _visibleRangeLength = -1; |
| 7796 |
| 7797 /** |
| 7798 * Initialize a newly created method element to have the given [name] and |
| 7799 * [offset]. |
| 7800 */ |
| 7801 LocalVariableElementImpl(String name, int offset) : super(name, offset); |
| 7802 |
| 7803 /** |
| 7804 * Initialize a newly created local variable element to have the given [name]. |
| 7805 */ |
| 7806 LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 7807 |
| 7808 @override |
| 7809 String get identifier { |
| 7810 int enclosingOffset = |
| 7811 enclosingElement != null ? enclosingElement.nameOffset : 0; |
| 7812 int delta = nameOffset - enclosingOffset; |
| 7813 return '${super.identifier}@$delta'; |
| 7814 } |
| 7815 |
| 7816 @override |
| 7817 bool get isPotentiallyMutatedInClosure => |
| 7818 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); |
| 7819 |
| 7820 @override |
| 7821 bool get isPotentiallyMutatedInScope => |
| 7822 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); |
| 7823 |
| 7824 @override |
| 7825 ElementKind get kind => ElementKind.LOCAL_VARIABLE; |
| 7826 |
| 7827 @override |
| 7828 SourceRange get visibleRange { |
| 7829 if (_visibleRangeLength < 0) { |
| 7830 return null; |
| 7831 } |
| 7832 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 7833 } |
| 7834 |
| 7835 @override |
| 7836 accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this); |
| 7837 |
| 7838 @override |
| 7839 void appendTo(StringBuffer buffer) { |
| 7840 buffer.write(type); |
| 7841 buffer.write(" "); |
| 7842 buffer.write(displayName); |
| 7843 } |
| 7844 |
| 7845 @override |
| 7846 VariableDeclaration computeNode() => |
| 7847 getNodeMatching((node) => node is VariableDeclaration); |
| 7848 |
| 7849 /** |
| 7850 * Specifies that this variable is potentially mutated somewhere in closure. |
| 7851 */ |
| 7852 void markPotentiallyMutatedInClosure() { |
| 7853 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); |
| 7854 } |
| 7855 |
| 7856 /** |
| 7857 * Specifies that this variable is potentially mutated somewhere in its scope. |
| 7858 */ |
| 7859 void markPotentiallyMutatedInScope() { |
| 7860 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); |
| 7861 } |
| 7862 |
| 7863 /** |
| 7864 * Set the visible range for this element to the range starting at the given |
| 7865 * [offset] with the given [length]. |
| 7866 */ |
| 7867 void setVisibleRange(int offset, int length) { |
| 7868 _visibleRangeOffset = offset; |
| 7869 _visibleRangeLength = length; |
| 7870 } |
| 7871 } |
| 7872 |
| 7873 /** |
| 7874 * An element defined in a parameterized type where the values of the type |
| 7875 * parameters are known. |
| 7876 */ |
| 7877 abstract class Member implements Element { |
| 7878 /** |
| 7879 * The element on which the parameterized element was created. |
| 7880 */ |
| 7881 final Element _baseElement; |
| 7882 |
| 7883 /** |
| 7884 * The type in which the element is defined. |
| 7885 */ |
| 7886 final ParameterizedType _definingType; |
| 7887 |
| 7888 /** |
| 7889 * Initialize a newly created element to represent a constructor, based on the |
| 7890 * [baseElement], defined by the [definingType]. |
| 7891 */ |
| 7892 Member(this._baseElement, this._definingType); |
| 7893 |
| 7894 /** |
| 7895 * Return the element on which the parameterized element was created. |
| 7896 */ |
| 7897 Element get baseElement => _baseElement; |
| 7898 |
| 7899 @override |
| 7900 AnalysisContext get context => _baseElement.context; |
| 7901 |
| 7902 /** |
| 7903 * Return the type in which the element is defined. |
| 7904 */ |
| 7905 ParameterizedType get definingType => _definingType; |
| 7906 |
| 7907 @override |
| 7908 String get displayName => _baseElement.displayName; |
| 7909 |
| 7910 int get id => _baseElement.id; |
| 7911 |
| 7912 @override |
| 7913 bool get isDeprecated => _baseElement.isDeprecated; |
| 7914 |
| 7915 @override |
| 7916 bool get isOverride => _baseElement.isOverride; |
| 7917 |
| 7918 @override |
| 7919 bool get isPrivate => _baseElement.isPrivate; |
| 7920 |
| 7921 @override |
| 7922 bool get isPublic => _baseElement.isPublic; |
| 7923 |
| 7924 @override |
| 7925 bool get isSynthetic => _baseElement.isSynthetic; |
| 7926 |
| 7927 @override |
| 7928 ElementKind get kind => _baseElement.kind; |
| 7929 |
| 7930 @override |
| 7931 LibraryElement get library => _baseElement.library; |
| 7932 |
| 7933 @override |
| 7934 ElementLocation get location => _baseElement.location; |
| 7935 |
| 7936 @override |
| 7937 List<ElementAnnotation> get metadata => _baseElement.metadata; |
| 7938 |
| 7939 @override |
| 7940 String get name => _baseElement.name; |
| 7941 |
| 7942 @override |
| 7943 int get nameOffset => _baseElement.nameOffset; |
| 7944 |
| 7945 @deprecated |
| 7946 @override |
| 7947 AstNode get node => computeNode(); |
| 7948 |
| 7949 @override |
| 7950 Source get source => _baseElement.source; |
| 7951 |
| 7952 @override |
| 7953 CompilationUnit get unit => _baseElement.unit; |
| 7954 |
| 7955 @override |
| 7956 String computeDocumentationComment() => |
| 7957 _baseElement.computeDocumentationComment(); |
| 7958 |
| 7959 @override |
| 7960 AstNode computeNode() => _baseElement.computeNode(); |
| 7961 |
| 7962 @override |
| 7963 Element getAncestor(Predicate<Element> predicate) => |
| 7964 baseElement.getAncestor(predicate); |
| 7965 |
| 7966 @override |
| 7967 String getExtendedDisplayName(String shortName) => |
| 7968 _baseElement.getExtendedDisplayName(shortName); |
| 7969 |
| 7970 @override |
| 7971 bool isAccessibleIn(LibraryElement library) => |
| 7972 _baseElement.isAccessibleIn(library); |
| 7973 |
| 7974 /** |
| 7975 * If the given [child] is not `null`, use the given [visitor] to visit it. |
| 7976 */ |
| 7977 void safelyVisitChild(Element child, ElementVisitor visitor) { |
| 7978 // TODO(brianwilkerson) Make this private |
| 7979 if (child != null) { |
| 7980 child.accept(visitor); |
| 7981 } |
| 7982 } |
| 7983 |
| 7984 /** |
| 7985 * Use the given [visitor] to visit all of the [children]. |
| 7986 */ |
| 7987 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { |
| 7988 // TODO(brianwilkerson) Make this private |
| 7989 if (children != null) { |
| 7990 for (Element child in children) { |
| 7991 child.accept(visitor); |
| 7992 } |
| 7993 } |
| 7994 } |
| 7995 |
| 7996 /** |
| 7997 * Return the type that results from replacing the type parameters in the |
| 7998 * given [type] with the type arguments associated with this member. |
| 7999 */ |
| 8000 DartType substituteFor(DartType type) { |
| 8001 if (type == null) { |
| 8002 return null; |
| 8003 } |
| 8004 List<DartType> argumentTypes = _definingType.typeArguments; |
| 8005 List<DartType> parameterTypes = |
| 8006 TypeParameterTypeImpl.getTypes(_definingType.typeParameters); |
| 8007 return type.substitute2(argumentTypes, parameterTypes); |
| 8008 } |
| 8009 |
| 8010 /** |
| 8011 * Return the list of types that results from replacing the type parameters in |
| 8012 * the given [types] with the type arguments associated with this member. |
| 8013 */ |
| 8014 List<InterfaceType> substituteFor2(List<InterfaceType> types) { |
| 8015 int count = types.length; |
| 8016 List<InterfaceType> substitutedTypes = new List<InterfaceType>(count); |
| 8017 for (int i = 0; i < count; i++) { |
| 8018 substitutedTypes[i] = substituteFor(types[i]); |
| 8019 } |
| 8020 return substitutedTypes; |
| 8021 } |
| 8022 |
| 8023 @override |
| 8024 void visitChildren(ElementVisitor visitor) { |
| 8025 // There are no children to visit |
| 8026 } |
| 8027 } |
| 8028 |
| 8029 /** |
| 8030 * An element that represents a method defined within a type. |
| 8031 */ |
| 8032 abstract class MethodElement implements ClassMemberElement, ExecutableElement { |
| 8033 /** |
| 8034 * An empty list of method elements. |
| 8035 */ |
| 8036 static const List<MethodElement> EMPTY_LIST = const <MethodElement>[]; |
| 8037 |
| 8038 /** |
| 8039 * Return the resolved [MethodDeclaration] node that declares this |
| 8040 * [MethodElement]. |
| 8041 * |
| 8042 * This method is expensive, because resolved AST might be evicted from cache, |
| 8043 * so parsing and resolving will be performed. |
| 8044 */ |
| 8045 @override |
| 8046 MethodDeclaration computeNode(); |
| 8047 } |
| 8048 |
| 8049 /** |
| 8050 * A concrete implementation of a [MethodElement]. |
| 8051 */ |
| 8052 class MethodElementImpl extends ExecutableElementImpl implements MethodElement { |
| 8053 /** |
| 8054 * An empty list of method elements. |
| 8055 */ |
| 8056 @deprecated // Use MethodElement.EMPTY_LIST |
| 8057 static const List<MethodElement> EMPTY_ARRAY = const <MethodElement>[]; |
| 8058 |
| 8059 /** |
| 8060 * Initialize a newly created method element to have the given [name] at the |
| 8061 * given [offset]. |
| 8062 */ |
| 8063 MethodElementImpl(String name, int offset) : super(name, offset); |
| 8064 |
| 8065 /** |
| 8066 * Initialize a newly created method element to have the given [name]. |
| 8067 */ |
| 8068 MethodElementImpl.forNode(Identifier name) : super.forNode(name); |
| 8069 |
| 8070 /** |
| 8071 * Set whether this method is abstract. |
| 8072 */ |
| 8073 void set abstract(bool isAbstract) { |
| 8074 setModifier(Modifier.ABSTRACT, isAbstract); |
| 8075 } |
| 8076 |
| 8077 @override |
| 8078 String get displayName { |
| 8079 String displayName = super.displayName; |
| 8080 if ("unary-" == displayName) { |
| 8081 return "-"; |
| 8082 } |
| 8083 return displayName; |
| 8084 } |
| 8085 |
| 8086 @override |
| 8087 ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
| 8088 |
| 8089 @override |
| 8090 bool get isOperator { |
| 8091 String name = displayName; |
| 8092 if (name.isEmpty) { |
| 8093 return false; |
| 8094 } |
| 8095 int first = name.codeUnitAt(0); |
| 8096 return !((0x61 <= first && first <= 0x7A) || |
| 8097 (0x41 <= first && first <= 0x5A) || |
| 8098 first == 0x5F || |
| 8099 first == 0x24); |
| 8100 } |
| 8101 |
| 8102 @override |
| 8103 bool get isStatic => hasModifier(Modifier.STATIC); |
| 8104 |
| 8105 @override |
| 8106 ElementKind get kind => ElementKind.METHOD; |
| 8107 |
| 8108 @override |
| 8109 String get name { |
| 8110 String name = super.name; |
| 8111 if (isOperator && name == "-") { |
| 8112 if (parameters.length == 0) { |
| 8113 return "unary-"; |
| 8114 } |
| 8115 } |
| 8116 return super.name; |
| 8117 } |
| 8118 |
| 8119 /** |
| 8120 * Set whether this method is static. |
| 8121 */ |
| 8122 void set static(bool isStatic) { |
| 8123 setModifier(Modifier.STATIC, isStatic); |
| 8124 } |
| 8125 |
| 8126 @override |
| 8127 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); |
| 8128 |
| 8129 @override |
| 8130 void appendTo(StringBuffer buffer) { |
| 8131 buffer.write(displayName); |
| 8132 super.appendTo(buffer); |
| 8133 } |
| 8134 |
| 8135 @override |
| 8136 MethodDeclaration computeNode() => |
| 8137 getNodeMatching((node) => node is MethodDeclaration); |
| 8138 } |
| 8139 |
| 8140 /** |
| 8141 * A method element defined in a parameterized type where the values of the type |
| 8142 * parameters are known. |
| 8143 */ |
| 8144 class MethodMember extends ExecutableMember implements MethodElement { |
| 8145 /** |
| 8146 * Initialize a newly created element to represent a constructor, based on the |
| 8147 * [baseElement], defined by the [definingType]. |
| 8148 */ |
| 8149 MethodMember(MethodElement baseElement, InterfaceType definingType) |
| 8150 : super(baseElement, definingType); |
| 8151 |
| 8152 @override |
| 8153 MethodElement get baseElement => super.baseElement as MethodElement; |
| 8154 |
| 8155 @override |
| 8156 ClassElement get enclosingElement => baseElement.enclosingElement; |
| 8157 |
| 8158 @override |
| 8159 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); |
| 8160 |
| 8161 @override |
| 8162 MethodDeclaration computeNode() => baseElement.computeNode(); |
| 8163 |
| 8164 @override |
| 8165 String toString() { |
| 8166 MethodElement baseElement = this.baseElement; |
| 8167 List<ParameterElement> parameters = this.parameters; |
| 8168 FunctionType type = this.type; |
| 8169 StringBuffer buffer = new StringBuffer(); |
| 8170 buffer.write(baseElement.enclosingElement.displayName); |
| 8171 buffer.write("."); |
| 8172 buffer.write(baseElement.displayName); |
| 8173 buffer.write("("); |
| 8174 int parameterCount = parameters.length; |
| 8175 for (int i = 0; i < parameterCount; i++) { |
| 8176 if (i > 0) { |
| 8177 buffer.write(", "); |
| 8178 } |
| 8179 buffer.write(parameters[i]); |
| 8180 } |
| 8181 buffer.write(")"); |
| 8182 if (type != null) { |
| 8183 buffer.write(Element.RIGHT_ARROW); |
| 8184 buffer.write(type.returnType); |
| 8185 } |
| 8186 return buffer.toString(); |
| 8187 } |
| 8188 |
| 8189 /** |
| 8190 * If the given [method]'s type is different when any type parameters from the |
| 8191 * defining type's declaration are replaced with the actual type arguments |
| 8192 * from the [definingType], create a method member representing the given |
| 8193 * method. Return the member that was created, or the base method if no member |
| 8194 * was created. |
| 8195 */ |
| 8196 static MethodElement from(MethodElement method, InterfaceType definingType) { |
| 8197 if (method == null || definingType.typeArguments.length == 0) { |
| 8198 return method; |
| 8199 } |
| 8200 FunctionType baseType = method.type; |
| 8201 List<DartType> argumentTypes = definingType.typeArguments; |
| 8202 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 8203 FunctionType substitutedType = |
| 8204 baseType.substitute2(argumentTypes, parameterTypes); |
| 8205 if (baseType == substitutedType) { |
| 8206 return method; |
| 8207 } |
| 8208 // TODO(brianwilkerson) Consider caching the substituted type in the |
| 8209 // instance. It would use more memory but speed up some operations. |
| 8210 // We need to see how often the type is being re-computed. |
| 8211 return new MethodMember(method, definingType); |
| 8212 } |
| 8213 } |
| 8214 |
| 8215 /** |
| 8216 * The enumeration `Modifier` defines constants for all of the modifiers defined |
| 8217 * by the Dart language and for a few additional flags that are useful. |
| 8218 */ |
| 8219 class Modifier extends Enum<Modifier> { |
| 8220 /** |
| 8221 * Indicates that the modifier 'abstract' was applied to the element. |
| 8222 */ |
| 8223 static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0); |
| 8224 |
| 8225 /** |
| 8226 * Indicates that an executable element has a body marked as being |
| 8227 * asynchronous. |
| 8228 */ |
| 8229 static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1); |
| 8230 |
| 8231 /** |
| 8232 * Indicates that the modifier 'const' was applied to the element. |
| 8233 */ |
| 8234 static const Modifier CONST = const Modifier('CONST', 2); |
| 8235 |
| 8236 /** |
| 8237 * Indicates that the import element represents a deferred library. |
| 8238 */ |
| 8239 static const Modifier DEFERRED = const Modifier('DEFERRED', 3); |
| 8240 |
| 8241 /** |
| 8242 * Indicates that a class element was defined by an enum declaration. |
| 8243 */ |
| 8244 static const Modifier ENUM = const Modifier('ENUM', 4); |
| 8245 |
| 8246 /** |
| 8247 * Indicates that a class element was defined by an enum declaration. |
| 8248 */ |
| 8249 static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5); |
| 8250 |
| 8251 /** |
| 8252 * Indicates that the modifier 'factory' was applied to the element. |
| 8253 */ |
| 8254 static const Modifier FACTORY = const Modifier('FACTORY', 6); |
| 8255 |
| 8256 /** |
| 8257 * Indicates that the modifier 'final' was applied to the element. |
| 8258 */ |
| 8259 static const Modifier FINAL = const Modifier('FINAL', 7); |
| 8260 |
| 8261 /** |
| 8262 * Indicates that an executable element has a body marked as being a |
| 8263 * generator. |
| 8264 */ |
| 8265 static const Modifier GENERATOR = const Modifier('GENERATOR', 8); |
| 8266 |
| 8267 /** |
| 8268 * Indicates that the pseudo-modifier 'get' was applied to the element. |
| 8269 */ |
| 8270 static const Modifier GETTER = const Modifier('GETTER', 9); |
| 8271 |
| 8272 /** |
| 8273 * A flag used for libraries indicating that the defining compilation unit |
| 8274 * contains at least one import directive whose URI uses the "dart-ext" |
| 8275 * scheme. |
| 8276 */ |
| 8277 static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10); |
| 8278 |
| 8279 /** |
| 8280 * Indicates that the associated element did not have an explicit type |
| 8281 * associated with it. If the element is an [ExecutableElement], then the |
| 8282 * type being referred to is the return type. |
| 8283 */ |
| 8284 static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11); |
| 8285 |
| 8286 /** |
| 8287 * Indicates that a class can validly be used as a mixin. |
| 8288 */ |
| 8289 static const Modifier MIXIN = const Modifier('MIXIN', 12); |
| 8290 |
| 8291 /** |
| 8292 * Indicates that a class is a mixin application. |
| 8293 */ |
| 8294 static const Modifier MIXIN_APPLICATION = |
| 8295 const Modifier('MIXIN_APPLICATION', 13); |
| 8296 |
| 8297 /** |
| 8298 * Indicates that the value of a parameter or local variable might be mutated |
| 8299 * within the context. |
| 8300 */ |
| 8301 static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT = |
| 8302 const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 14); |
| 8303 |
| 8304 /** |
| 8305 * Indicates that the value of a parameter or local variable might be mutated |
| 8306 * within the scope. |
| 8307 */ |
| 8308 static const Modifier POTENTIALLY_MUTATED_IN_SCOPE = |
| 8309 const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 15); |
| 8310 |
| 8311 /** |
| 8312 * Indicates that a class contains an explicit reference to 'super'. |
| 8313 */ |
| 8314 static const Modifier REFERENCES_SUPER = |
| 8315 const Modifier('REFERENCES_SUPER', 16); |
| 8316 |
| 8317 /** |
| 8318 * Indicates that the pseudo-modifier 'set' was applied to the element. |
| 8319 */ |
| 8320 static const Modifier SETTER = const Modifier('SETTER', 17); |
| 8321 |
| 8322 /** |
| 8323 * Indicates that the modifier 'static' was applied to the element. |
| 8324 */ |
| 8325 static const Modifier STATIC = const Modifier('STATIC', 18); |
| 8326 |
| 8327 /** |
| 8328 * Indicates that the element does not appear in the source code but was |
| 8329 * implicitly created. For example, if a class does not define any |
| 8330 * constructors, an implicit zero-argument constructor will be created and it |
| 8331 * will be marked as being synthetic. |
| 8332 */ |
| 8333 static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 19); |
| 8334 |
| 8335 static const List<Modifier> values = const [ |
| 8336 ABSTRACT, |
| 8337 ASYNCHRONOUS, |
| 8338 CONST, |
| 8339 DEFERRED, |
| 8340 ENUM, |
| 8341 EXTERNAL, |
| 8342 FACTORY, |
| 8343 FINAL, |
| 8344 GENERATOR, |
| 8345 GETTER, |
| 8346 HAS_EXT_URI, |
| 8347 IMPLICIT_TYPE, |
| 8348 MIXIN, |
| 8349 MIXIN_APPLICATION, |
| 8350 POTENTIALLY_MUTATED_IN_CONTEXT, |
| 8351 POTENTIALLY_MUTATED_IN_SCOPE, |
| 8352 REFERENCES_SUPER, |
| 8353 SETTER, |
| 8354 STATIC, |
| 8355 SYNTHETIC |
| 8356 ]; |
| 8357 |
| 8358 const Modifier(String name, int ordinal) : super(name, ordinal); |
| 8359 } |
| 8360 |
| 8361 /** |
| 8362 * A pseudo-element that represents multiple elements defined within a single |
| 8363 * scope that have the same name. This situation is not allowed by the language, |
| 8364 * so objects implementing this interface always represent an error. As a |
| 8365 * result, most of the normal operations on elements do not make sense and will |
| 8366 * return useless results. |
| 8367 */ |
| 8368 abstract class MultiplyDefinedElement implements Element { |
| 8369 /** |
| 8370 * Return a list containing all of the elements that were defined within the |
| 8371 * scope to have the same name. |
| 8372 */ |
| 8373 List<Element> get conflictingElements; |
| 8374 |
| 8375 /** |
| 8376 * Return the type of this element as the dynamic type. |
| 8377 */ |
| 8378 DartType get type; |
| 8379 } |
| 8380 |
| 8381 /** |
| 8382 * A concrete implementation of a [MultiplyDefinedElement]. |
| 8383 */ |
| 8384 class MultiplyDefinedElementImpl implements MultiplyDefinedElement { |
| 8385 /** |
| 8386 * The unique integer identifier of this element. |
| 8387 */ |
| 8388 final int id = ElementImpl._NEXT_ID++; |
| 8389 |
| 8390 /** |
| 8391 * The analysis context in which the multiply defined elements are defined. |
| 8392 */ |
| 8393 final AnalysisContext context; |
| 8394 |
| 8395 /** |
| 8396 * The name of the conflicting elements. |
| 8397 */ |
| 8398 String _name; |
| 8399 |
| 8400 /** |
| 8401 * A list containing all of the elements that conflict. |
| 8402 */ |
| 8403 final List<Element> conflictingElements; |
| 8404 |
| 8405 /** |
| 8406 * Initialize a newly created element in the given [context] to represent a |
| 8407 * list of [conflictingElements]. |
| 8408 */ |
| 8409 MultiplyDefinedElementImpl(this.context, this.conflictingElements) { |
| 8410 _name = conflictingElements[0].name; |
| 8411 } |
| 8412 |
| 8413 @override |
| 8414 String get displayName => _name; |
| 8415 |
| 8416 @override |
| 8417 Element get enclosingElement => null; |
| 8418 |
| 8419 @override |
| 8420 bool get isDeprecated => false; |
| 8421 |
| 8422 @override |
| 8423 bool get isOverride => false; |
| 8424 |
| 8425 @override |
| 8426 bool get isPrivate { |
| 8427 String name = displayName; |
| 8428 if (name == null) { |
| 8429 return false; |
| 8430 } |
| 8431 return Identifier.isPrivateName(name); |
| 8432 } |
| 8433 |
| 8434 @override |
| 8435 bool get isPublic => !isPrivate; |
| 8436 |
| 8437 @override |
| 8438 bool get isSynthetic => true; |
| 8439 |
| 8440 @override |
| 8441 ElementKind get kind => ElementKind.ERROR; |
| 8442 |
| 8443 @override |
| 8444 LibraryElement get library => null; |
| 8445 |
| 8446 @override |
| 8447 ElementLocation get location => null; |
| 8448 |
| 8449 @override |
| 8450 List<ElementAnnotation> get metadata => ElementAnnotation.EMPTY_LIST; |
| 8451 |
| 8452 @override |
| 8453 String get name => _name; |
| 8454 |
| 8455 @override |
| 8456 int get nameOffset => -1; |
| 8457 |
| 8458 @deprecated |
| 8459 @override |
| 8460 AstNode get node => null; |
| 8461 |
| 8462 @override |
| 8463 Source get source => null; |
| 8464 |
| 8465 @override |
| 8466 DartType get type => DynamicTypeImpl.instance; |
| 8467 |
| 8468 @override |
| 8469 CompilationUnit get unit => null; |
| 8470 |
| 8471 @override |
| 8472 accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this); |
| 8473 |
| 8474 @override |
| 8475 String computeDocumentationComment() => null; |
| 8476 |
| 8477 @override |
| 8478 AstNode computeNode() => null; |
| 8479 |
| 8480 @override |
| 8481 Element getAncestor(Predicate<Element> predicate) => null; |
| 8482 |
| 8483 @override |
| 8484 String getExtendedDisplayName(String shortName) { |
| 8485 if (shortName != null) { |
| 8486 return shortName; |
| 8487 } |
| 8488 return displayName; |
| 8489 } |
| 8490 |
| 8491 @override |
| 8492 bool isAccessibleIn(LibraryElement library) { |
| 8493 for (Element element in conflictingElements) { |
| 8494 if (element.isAccessibleIn(library)) { |
| 8495 return true; |
| 8496 } |
| 8497 } |
| 8498 return false; |
| 8499 } |
| 8500 |
| 8501 @override |
| 8502 String toString() { |
| 8503 StringBuffer buffer = new StringBuffer(); |
| 8504 buffer.write("["); |
| 8505 int count = conflictingElements.length; |
| 8506 for (int i = 0; i < count; i++) { |
| 8507 if (i > 0) { |
| 8508 buffer.write(", "); |
| 8509 } |
| 8510 (conflictingElements[i] as ElementImpl).appendTo(buffer); |
| 8511 } |
| 8512 buffer.write("]"); |
| 8513 return buffer.toString(); |
| 8514 } |
| 8515 |
| 8516 @override |
| 8517 void visitChildren(ElementVisitor visitor) { |
| 8518 // There are no children to visit |
| 8519 } |
| 8520 |
| 8521 /** |
| 8522 * Return an element in the given [context] that represents the fact that the |
| 8523 * [firstElement] and [secondElement] conflict. (If the elements are the same, |
| 8524 * then one of the two will be returned directly.) |
| 8525 */ |
| 8526 static Element fromElements( |
| 8527 AnalysisContext context, Element firstElement, Element secondElement) { |
| 8528 List<Element> conflictingElements = |
| 8529 _computeConflictingElements(firstElement, secondElement); |
| 8530 int length = conflictingElements.length; |
| 8531 if (length == 0) { |
| 8532 return null; |
| 8533 } else if (length == 1) { |
| 8534 return conflictingElements[0]; |
| 8535 } |
| 8536 return new MultiplyDefinedElementImpl(context, conflictingElements); |
| 8537 } |
| 8538 |
| 8539 /** |
| 8540 * Add the given [element] to the list of [elements]. If the element is a |
| 8541 * multiply-defined element, add all of the conflicting elements that it |
| 8542 * represents. |
| 8543 */ |
| 8544 static void _add(HashSet<Element> elements, Element element) { |
| 8545 if (element is MultiplyDefinedElementImpl) { |
| 8546 for (Element conflictingElement in element.conflictingElements) { |
| 8547 elements.add(conflictingElement); |
| 8548 } |
| 8549 } else { |
| 8550 elements.add(element); |
| 8551 } |
| 8552 } |
| 8553 |
| 8554 /** |
| 8555 * Use the given elements to construct a list of conflicting elements. If |
| 8556 * either the [firstElement] or [secondElement] are multiply-defined elements |
| 8557 * then the conflicting elements they represent will be included in the array. |
| 8558 * Otherwise, the element itself will be included. |
| 8559 */ |
| 8560 static List<Element> _computeConflictingElements( |
| 8561 Element firstElement, Element secondElement) { |
| 8562 HashSet<Element> elements = new HashSet<Element>(); |
| 8563 _add(elements, firstElement); |
| 8564 _add(elements, secondElement); |
| 8565 return new List.from(elements); |
| 8566 } |
| 8567 } |
| 8568 |
| 8569 /** |
| 8570 * An [ExecutableElement], with the additional information of a list of |
| 8571 * [ExecutableElement]s from which this element was composed. |
| 8572 */ |
| 8573 abstract class MultiplyInheritedExecutableElement implements ExecutableElement { |
| 8574 /** |
| 8575 * Return a list containing all of the executable elements defined within this |
| 8576 * executable element. |
| 8577 */ |
| 8578 List<ExecutableElement> get inheritedElements; |
| 8579 } |
| 8580 |
| 8581 /** |
| 8582 * A [MethodElementImpl], with the additional information of a list of |
| 8583 * [ExecutableElement]s from which this element was composed. |
| 8584 */ |
| 8585 class MultiplyInheritedMethodElementImpl extends MethodElementImpl |
| 8586 implements MultiplyInheritedExecutableElement { |
| 8587 /** |
| 8588 * A list the array of executable elements that were used to compose this |
| 8589 * element. |
| 8590 */ |
| 8591 List<ExecutableElement> _elements = MethodElement.EMPTY_LIST; |
| 8592 |
| 8593 MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) { |
| 8594 synthetic = true; |
| 8595 } |
| 8596 |
| 8597 @override |
| 8598 List<ExecutableElement> get inheritedElements => _elements; |
| 8599 |
| 8600 void set inheritedElements(List<ExecutableElement> elements) { |
| 8601 this._elements = elements; |
| 8602 } |
| 8603 } |
| 8604 |
| 8605 /** |
| 8606 * A [PropertyAccessorElementImpl], with the additional information of a list of |
| 8607 * [ExecutableElement]s from which this element was composed. |
| 8608 */ |
| 8609 class MultiplyInheritedPropertyAccessorElementImpl |
| 8610 extends PropertyAccessorElementImpl |
| 8611 implements MultiplyInheritedExecutableElement { |
| 8612 /** |
| 8613 * A list the array of executable elements that were used to compose this |
| 8614 * element. |
| 8615 */ |
| 8616 List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST; |
| 8617 |
| 8618 MultiplyInheritedPropertyAccessorElementImpl(Identifier name) |
| 8619 : super.forNode(name) { |
| 8620 synthetic = true; |
| 8621 } |
| 8622 |
| 8623 @override |
| 8624 List<ExecutableElement> get inheritedElements => _elements; |
| 8625 |
| 8626 void set inheritedElements(List<ExecutableElement> elements) { |
| 8627 this._elements = elements; |
| 8628 } |
| 8629 } |
| 8630 |
| 8631 /** |
| 8632 * An object that controls how namespaces are combined. |
| 8633 */ |
| 8634 abstract class NamespaceCombinator { |
| 8635 /** |
| 8636 * An empty list of namespace combinators. |
| 8637 */ |
| 8638 @deprecated // Use NamespaceCombinator.EMPTY_LIST |
| 8639 static const List<NamespaceCombinator> EMPTY_ARRAY = |
| 8640 const <NamespaceCombinator>[]; |
| 8641 |
| 8642 /** |
| 8643 * An empty list of namespace combinators. |
| 8644 */ |
| 8645 static const List<NamespaceCombinator> EMPTY_LIST = |
| 8646 const <NamespaceCombinator>[]; |
| 8647 } |
| 8648 |
| 8649 /** |
| 8650 * A parameter defined within an executable element. |
| 8651 */ |
| 8652 abstract class ParameterElement |
| 8653 implements LocalElement, VariableElement, ConstantEvaluationTarget { |
| 8654 /** |
| 8655 * An empty list of parameter elements. |
| 8656 */ |
| 8657 static const List<ParameterElement> EMPTY_LIST = const <ParameterElement>[]; |
| 8658 |
| 8659 /** |
| 8660 * Return the Dart code of the default value, or `null` if no default value. |
| 8661 */ |
| 8662 String get defaultValueCode; |
| 8663 |
| 8664 /** |
| 8665 * Return `true` if this parameter is an initializing formal parameter. |
| 8666 */ |
| 8667 bool get isInitializingFormal; |
| 8668 |
| 8669 /** |
| 8670 * Return the kind of this parameter. |
| 8671 */ |
| 8672 ParameterKind get parameterKind; |
| 8673 |
| 8674 /** |
| 8675 * Return a list containing all of the parameters defined by this parameter. |
| 8676 * A parameter will only define other parameters if it is a function typed |
| 8677 * parameter. |
| 8678 */ |
| 8679 List<ParameterElement> get parameters; |
| 8680 |
| 8681 /** |
| 8682 * Return a list containing all of the type parameters defined by this |
| 8683 * parameter. A parameter will only define other parameters if it is a |
| 8684 * function typed parameter. |
| 8685 */ |
| 8686 List<TypeParameterElement> get typeParameters; |
| 8687 |
| 8688 /** |
| 8689 * Append the type, name and possibly the default value of this parameter to |
| 8690 * the given [buffer]. |
| 8691 */ |
| 8692 void appendToWithoutDelimiters(StringBuffer buffer); |
| 8693 |
| 8694 @override |
| 8695 FormalParameter computeNode(); |
| 8696 } |
| 8697 |
| 8698 /** |
| 8699 * A concrete implementation of a [ParameterElement]. |
| 8700 */ |
| 8701 class ParameterElementImpl extends VariableElementImpl |
| 8702 with ParameterElementMixin, PotentiallyConstVariableElement |
| 8703 implements ParameterElement { |
| 8704 /** |
| 8705 * An empty list of parameter elements. |
| 8706 */ |
| 8707 @deprecated // Use ParameterElement.EMPTY_LIST |
| 8708 static const List<ParameterElement> EMPTY_ARRAY = const <ParameterElement>[]; |
| 8709 |
| 8710 /** |
| 8711 * A list containing all of the parameters defined by this parameter element. |
| 8712 * There will only be parameters if this parameter is a function typed |
| 8713 * parameter. |
| 8714 */ |
| 8715 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; |
| 8716 |
| 8717 /** |
| 8718 * A list containing all of the type parameters defined for this parameter |
| 8719 * element. There will only be parameters if this parameter is a function |
| 8720 * typed parameter. |
| 8721 */ |
| 8722 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; |
| 8723 |
| 8724 /** |
| 8725 * The kind of this parameter. |
| 8726 */ |
| 8727 ParameterKind parameterKind; |
| 8728 |
| 8729 /** |
| 8730 * The Dart code of the default value. |
| 8731 */ |
| 8732 String _defaultValueCode; |
| 8733 |
| 8734 /** |
| 8735 * The offset to the beginning of the visible range for this element. |
| 8736 */ |
| 8737 int _visibleRangeOffset = 0; |
| 8738 |
| 8739 /** |
| 8740 * The length of the visible range for this element, or `-1` if this element |
| 8741 * does not have a visible range. |
| 8742 */ |
| 8743 int _visibleRangeLength = -1; |
| 8744 |
| 8745 /** |
| 8746 * Initialize a newly created parameter element to have the given [name] and |
| 8747 * [offset]. |
| 8748 */ |
| 8749 ParameterElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 8750 |
| 8751 /** |
| 8752 * Initialize a newly created parameter element to have the given [name]. |
| 8753 */ |
| 8754 ParameterElementImpl.forNode(Identifier name) : super.forNode(name); |
| 8755 |
| 8756 @override |
| 8757 String get defaultValueCode => _defaultValueCode; |
| 8758 |
| 8759 /** |
| 8760 * Set Dart code of the default value. |
| 8761 */ |
| 8762 void set defaultValueCode(String defaultValueCode) { |
| 8763 this._defaultValueCode = StringUtilities.intern(defaultValueCode); |
| 8764 } |
| 8765 |
| 8766 @override |
| 8767 bool get isInitializingFormal => false; |
| 8768 |
| 8769 @override |
| 8770 bool get isPotentiallyMutatedInClosure => |
| 8771 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); |
| 8772 |
| 8773 @override |
| 8774 bool get isPotentiallyMutatedInScope => |
| 8775 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); |
| 8776 |
| 8777 @override |
| 8778 ElementKind get kind => ElementKind.PARAMETER; |
| 8779 |
| 8780 @override |
| 8781 List<ParameterElement> get parameters => _parameters; |
| 8782 |
| 8783 /** |
| 8784 * Set the parameters defined by this executable element to the given |
| 8785 * [parameters]. |
| 8786 */ |
| 8787 void set parameters(List<ParameterElement> parameters) { |
| 8788 for (ParameterElement parameter in parameters) { |
| 8789 (parameter as ParameterElementImpl).enclosingElement = this; |
| 8790 } |
| 8791 this._parameters = parameters; |
| 8792 } |
| 8793 |
| 8794 @override |
| 8795 List<TypeParameterElement> get typeParameters => _typeParameters; |
| 8796 |
| 8797 /** |
| 8798 * Set the type parameters defined by this parameter element to the given |
| 8799 * [typeParameters]. |
| 8800 */ |
| 8801 void set typeParameters(List<TypeParameterElement> typeParameters) { |
| 8802 for (TypeParameterElement parameter in typeParameters) { |
| 8803 (parameter as TypeParameterElementImpl).enclosingElement = this; |
| 8804 } |
| 8805 this._typeParameters = typeParameters; |
| 8806 } |
| 8807 |
| 8808 @override |
| 8809 SourceRange get visibleRange { |
| 8810 if (_visibleRangeLength < 0) { |
| 8811 return null; |
| 8812 } |
| 8813 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); |
| 8814 } |
| 8815 |
| 8816 @override |
| 8817 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); |
| 8818 |
| 8819 @override |
| 8820 void appendTo(StringBuffer buffer) { |
| 8821 String left = ""; |
| 8822 String right = ""; |
| 8823 while (true) { |
| 8824 if (parameterKind == ParameterKind.NAMED) { |
| 8825 left = "{"; |
| 8826 right = "}"; |
| 8827 } else if (parameterKind == ParameterKind.POSITIONAL) { |
| 8828 left = "["; |
| 8829 right = "]"; |
| 8830 } else if (parameterKind == ParameterKind.REQUIRED) {} |
| 8831 break; |
| 8832 } |
| 8833 buffer.write(left); |
| 8834 appendToWithoutDelimiters(buffer); |
| 8835 buffer.write(right); |
| 8836 } |
| 8837 |
| 8838 @override |
| 8839 FormalParameter computeNode() => |
| 8840 getNodeMatching((node) => node is FormalParameter); |
| 8841 |
| 8842 @override |
| 8843 ElementImpl getChild(String identifier) { |
| 8844 for (ParameterElement parameter in _parameters) { |
| 8845 if ((parameter as ParameterElementImpl).identifier == identifier) { |
| 8846 return parameter as ParameterElementImpl; |
| 8847 } |
| 8848 } |
| 8849 return null; |
| 8850 } |
| 8851 |
| 8852 /** |
| 8853 * Specifies that this variable is potentially mutated somewhere in closure. |
| 8854 */ |
| 8855 void markPotentiallyMutatedInClosure() { |
| 8856 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); |
| 8857 } |
| 8858 |
| 8859 /** |
| 8860 * Specifies that this variable is potentially mutated somewhere in its scope. |
| 8861 */ |
| 8862 void markPotentiallyMutatedInScope() { |
| 8863 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); |
| 8864 } |
| 8865 |
| 8866 /** |
| 8867 * Set the visible range for this element to the range starting at the given |
| 8868 * [offset] with the given [length]. |
| 8869 */ |
| 8870 void setVisibleRange(int offset, int length) { |
| 8871 _visibleRangeOffset = offset; |
| 8872 _visibleRangeLength = length; |
| 8873 } |
| 8874 |
| 8875 @override |
| 8876 void visitChildren(ElementVisitor visitor) { |
| 8877 super.visitChildren(visitor); |
| 8878 safelyVisitChildren(_parameters, visitor); |
| 8879 } |
| 8880 } |
| 8881 |
| 8882 /** |
| 8883 * A mixin that provides a common implementation for methods defined in |
| 8884 * [ParameterElement]. |
| 8885 */ |
| 8886 abstract class ParameterElementMixin implements ParameterElement { |
| 8887 @override |
| 8888 void appendToWithoutDelimiters(StringBuffer buffer) { |
| 8889 buffer.write(type); |
| 8890 buffer.write(" "); |
| 8891 buffer.write(displayName); |
| 8892 if (defaultValueCode != null) { |
| 8893 if (parameterKind == ParameterKind.NAMED) { |
| 8894 buffer.write(": "); |
| 8895 } |
| 8896 if (parameterKind == ParameterKind.POSITIONAL) { |
| 8897 buffer.write(" = "); |
| 8898 } |
| 8899 buffer.write(defaultValueCode); |
| 8900 } |
| 8901 } |
| 8902 } |
| 8903 |
| 8904 /** |
| 8905 * A type with type parameters, such as a class or function type alias. |
| 8906 */ |
| 8907 abstract class ParameterizedType implements DartType { |
| 8908 /** |
| 8909 * Return a list containing the actual types of the type arguments. If this |
| 8910 * type's element does not have type parameters, then the array should be |
| 8911 * empty (although it is possible for type arguments to be erroneously |
| 8912 * declared). If the element has type parameters and the actual type does not |
| 8913 * explicitly include argument values, then the type "dynamic" will be |
| 8914 * automatically provided. |
| 8915 */ |
| 8916 List<DartType> get typeArguments; |
| 8917 |
| 8918 /** |
| 8919 * Return a list containing all of the type parameters declared for this type. |
| 8920 */ |
| 8921 List<TypeParameterElement> get typeParameters; |
| 8922 } |
| 8923 |
| 8924 /** |
| 8925 * A parameter element defined in a parameterized type where the values of the |
| 8926 * type parameters are known. |
| 8927 */ |
| 8928 class ParameterMember extends VariableMember |
| 8929 with ParameterElementMixin |
| 8930 implements ParameterElement { |
| 8931 /** |
| 8932 * Initialize a newly created element to represent a constructor, based on the |
| 8933 * [baseElement], defined by the [definingType]. |
| 8934 */ |
| 8935 ParameterMember(ParameterElement baseElement, ParameterizedType definingType) |
| 8936 : super(baseElement, definingType); |
| 8937 |
| 8938 @override |
| 8939 ParameterElement get baseElement => super.baseElement as ParameterElement; |
| 8940 |
| 8941 @override |
| 8942 String get defaultValueCode => baseElement.defaultValueCode; |
| 8943 |
| 8944 @override |
| 8945 Element get enclosingElement => baseElement.enclosingElement; |
| 8946 |
| 8947 @override |
| 8948 bool get isInitializingFormal => baseElement.isInitializingFormal; |
| 8949 |
| 8950 @override |
| 8951 ParameterKind get parameterKind => baseElement.parameterKind; |
| 8952 |
| 8953 @override |
| 8954 List<ParameterElement> get parameters { |
| 8955 List<ParameterElement> baseParameters = baseElement.parameters; |
| 8956 int parameterCount = baseParameters.length; |
| 8957 if (parameterCount == 0) { |
| 8958 return baseParameters; |
| 8959 } |
| 8960 List<ParameterElement> parameterizedParameters = |
| 8961 new List<ParameterElement>(parameterCount); |
| 8962 for (int i = 0; i < parameterCount; i++) { |
| 8963 parameterizedParameters[i] = |
| 8964 ParameterMember.from(baseParameters[i], definingType); |
| 8965 } |
| 8966 return parameterizedParameters; |
| 8967 } |
| 8968 |
| 8969 @override |
| 8970 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; |
| 8971 |
| 8972 @override |
| 8973 SourceRange get visibleRange => baseElement.visibleRange; |
| 8974 |
| 8975 @override |
| 8976 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); |
| 8977 |
| 8978 @override |
| 8979 FormalParameter computeNode() => baseElement.computeNode(); |
| 8980 |
| 8981 @override |
| 8982 Element getAncestor(Predicate<Element> predicate) { |
| 8983 Element element = baseElement.getAncestor(predicate); |
| 8984 ParameterizedType definingType = this.definingType; |
| 8985 if (definingType is InterfaceType) { |
| 8986 InterfaceType definingInterfaceType = definingType; |
| 8987 if (element is ConstructorElement) { |
| 8988 return ConstructorMember.from(element, definingInterfaceType); |
| 8989 } else if (element is MethodElement) { |
| 8990 return MethodMember.from(element, definingInterfaceType); |
| 8991 } else if (element is PropertyAccessorElement) { |
| 8992 return PropertyAccessorMember.from(element, definingInterfaceType); |
| 8993 } |
| 8994 } |
| 8995 return element; |
| 8996 } |
| 8997 |
| 8998 @override |
| 8999 String toString() { |
| 9000 ParameterElement baseElement = this.baseElement; |
| 9001 String left = ""; |
| 9002 String right = ""; |
| 9003 while (true) { |
| 9004 if (baseElement.parameterKind == ParameterKind.NAMED) { |
| 9005 left = "{"; |
| 9006 right = "}"; |
| 9007 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) { |
| 9008 left = "["; |
| 9009 right = "]"; |
| 9010 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {} |
| 9011 break; |
| 9012 } |
| 9013 return '$left$type ${baseElement.displayName}$right'; |
| 9014 } |
| 9015 |
| 9016 @override |
| 9017 void visitChildren(ElementVisitor visitor) { |
| 9018 super.visitChildren(visitor); |
| 9019 safelyVisitChildren(parameters, visitor); |
| 9020 } |
| 9021 |
| 9022 /** |
| 9023 * If the given [parameter]'s type is different when any type parameters from |
| 9024 * the defining type's declaration are replaced with the actual type |
| 9025 * arguments from the [definingType], create a parameter member representing |
| 9026 * the given parameter. Return the member that was created, or the base |
| 9027 * parameter if no member was created. |
| 9028 */ |
| 9029 static ParameterElement from( |
| 9030 ParameterElement parameter, ParameterizedType definingType) { |
| 9031 if (parameter == null || definingType.typeArguments.length == 0) { |
| 9032 return parameter; |
| 9033 } |
| 9034 // Check if parameter type depends on defining type type arguments. |
| 9035 // It is possible that we did not resolve field formal parameter yet, |
| 9036 // so skip this check for it. |
| 9037 bool isFieldFormal = parameter is FieldFormalParameterElement; |
| 9038 if (!isFieldFormal) { |
| 9039 DartType baseType = parameter.type; |
| 9040 List<DartType> argumentTypes = definingType.typeArguments; |
| 9041 List<DartType> parameterTypes = |
| 9042 TypeParameterTypeImpl.getTypes(definingType.typeParameters); |
| 9043 DartType substitutedType = |
| 9044 baseType.substitute2(argumentTypes, parameterTypes); |
| 9045 if (baseType == substitutedType) { |
| 9046 return parameter; |
| 9047 } |
| 9048 } |
| 9049 // TODO(brianwilkerson) Consider caching the substituted type in the |
| 9050 // instance. It would use more memory but speed up some operations. |
| 9051 // We need to see how often the type is being re-computed. |
| 9052 if (isFieldFormal) { |
| 9053 return new FieldFormalParameterMember( |
| 9054 parameter as FieldFormalParameterElement, definingType); |
| 9055 } |
| 9056 return new ParameterMember(parameter, definingType); |
| 9057 } |
| 9058 } |
| 9059 |
| 9060 /** |
| 9061 * Interface used by elements that might represent constant variables. |
| 9062 * |
| 9063 * This class may be used as a mixin in the case where [constInitializer] is |
| 9064 * known to return null. |
| 9065 * |
| 9066 * This class is not intended to be part of the public API for analyzer. |
| 9067 */ |
| 9068 abstract class PotentiallyConstVariableElement |
| 9069 implements VariableElementImpl, ConstantEvaluationTarget { |
| 9070 /** |
| 9071 * If this element represents a constant variable, and it has an initializer, |
| 9072 * a copy of the initializer for the constant. Otherwise `null`. |
| 9073 * |
| 9074 * Note that in correct Dart code, all constant variables must have |
| 9075 * initializers. However, analyzer also needs to handle incorrect Dart code, |
| 9076 * in which case there might be some constant variables that lack |
| 9077 * initializers. |
| 9078 */ |
| 9079 Expression get constantInitializer => null; |
| 9080 } |
| 9081 |
| 9082 /** |
| 9083 * A prefix used to import one or more libraries into another library. |
| 9084 */ |
| 9085 abstract class PrefixElement implements Element { |
| 9086 /** |
| 9087 * An empty list of prefix elements. |
| 9088 */ |
| 9089 static const List<PrefixElement> EMPTY_LIST = const <PrefixElement>[]; |
| 9090 |
| 9091 /** |
| 9092 * Return the library into which other libraries are imported using this |
| 9093 * prefix. |
| 9094 */ |
| 9095 @override |
| 9096 LibraryElement get enclosingElement; |
| 9097 |
| 9098 /** |
| 9099 * Return a list containing all of the libraries that are imported using this |
| 9100 * prefix. |
| 9101 */ |
| 9102 List<LibraryElement> get importedLibraries; |
| 9103 } |
| 9104 |
| 9105 /** |
| 9106 * A concrete implementation of a [PrefixElement]. |
| 9107 */ |
| 9108 class PrefixElementImpl extends ElementImpl implements PrefixElement { |
| 9109 /** |
| 9110 * An empty list of prefix elements. |
| 9111 */ |
| 9112 @deprecated // Use PrefixElement.EMPTY_LIST |
| 9113 static const List<PrefixElement> EMPTY_ARRAY = const <PrefixElement>[]; |
| 9114 |
| 9115 /** |
| 9116 * A list containing all of the libraries that are imported using this prefix. |
| 9117 */ |
| 9118 List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST; |
| 9119 |
| 9120 /** |
| 9121 * Initialize a newly created method element to have the given [name] and |
| 9122 * [offset]. |
| 9123 */ |
| 9124 PrefixElementImpl(String name, int nameOffset) : super(name, nameOffset); |
| 9125 |
| 9126 /** |
| 9127 * Initialize a newly created prefix element to have the given [name]. |
| 9128 */ |
| 9129 PrefixElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9130 |
| 9131 @override |
| 9132 LibraryElement get enclosingElement => |
| 9133 super.enclosingElement as LibraryElement; |
| 9134 |
| 9135 @override |
| 9136 String get identifier => "_${super.identifier}"; |
| 9137 |
| 9138 @override |
| 9139 List<LibraryElement> get importedLibraries => _importedLibraries; |
| 9140 |
| 9141 /** |
| 9142 * Set the libraries that are imported using this prefix to the given |
| 9143 * [libraries]. |
| 9144 */ |
| 9145 void set importedLibraries(List<LibraryElement> libraries) { |
| 9146 for (LibraryElement library in libraries) { |
| 9147 (library as LibraryElementImpl).enclosingElement = this; |
| 9148 } |
| 9149 _importedLibraries = libraries; |
| 9150 } |
| 9151 |
| 9152 @override |
| 9153 ElementKind get kind => ElementKind.PREFIX; |
| 9154 |
| 9155 @override |
| 9156 accept(ElementVisitor visitor) => visitor.visitPrefixElement(this); |
| 9157 |
| 9158 @override |
| 9159 void appendTo(StringBuffer buffer) { |
| 9160 buffer.write("as "); |
| 9161 super.appendTo(buffer); |
| 9162 } |
| 9163 } |
| 9164 |
| 9165 /** |
| 9166 * A getter or a setter. Note that explicitly defined property accessors |
| 9167 * implicitly define a synthetic field. Symmetrically, synthetic accessors are |
| 9168 * implicitly created for explicitly defined fields. The following rules apply: |
| 9169 * |
| 9170 * * Every explicit field is represented by a non-synthetic [FieldElement]. |
| 9171 * * Every explicit field induces a getter and possibly a setter, both of which |
| 9172 * are represented by synthetic [PropertyAccessorElement]s. |
| 9173 * * Every explicit getter or setter is represented by a non-synthetic |
| 9174 * [PropertyAccessorElement]. |
| 9175 * * Every explicit getter or setter (or pair thereof if they have the same |
| 9176 * name) induces a field that is represented by a synthetic [FieldElement]. |
| 9177 */ |
| 9178 abstract class PropertyAccessorElement implements ExecutableElement { |
| 9179 /** |
| 9180 * An empty list of property accessor elements. |
| 9181 */ |
| 9182 static const List<PropertyAccessorElement> EMPTY_LIST = |
| 9183 const <PropertyAccessorElement>[]; |
| 9184 |
| 9185 /** |
| 9186 * Return the accessor representing the getter that corresponds to (has the |
| 9187 * same name as) this setter, or `null` if this accessor is not a setter or if |
| 9188 * there is no corresponding getter. |
| 9189 */ |
| 9190 PropertyAccessorElement get correspondingGetter; |
| 9191 |
| 9192 /** |
| 9193 * Return the accessor representing the setter that corresponds to (has the |
| 9194 * same name as) this getter, or `null` if this accessor is not a getter or if |
| 9195 * there is no corresponding setter. |
| 9196 */ |
| 9197 PropertyAccessorElement get correspondingSetter; |
| 9198 |
| 9199 /** |
| 9200 * Return `true` if this accessor represents a getter. |
| 9201 */ |
| 9202 bool get isGetter; |
| 9203 |
| 9204 /** |
| 9205 * Return `true` if this accessor represents a setter. |
| 9206 */ |
| 9207 bool get isSetter; |
| 9208 |
| 9209 /** |
| 9210 * Return the field or top-level variable associated with this accessor. If |
| 9211 * this accessor was explicitly defined (is not synthetic) then the variable |
| 9212 * associated with it will be synthetic. |
| 9213 */ |
| 9214 PropertyInducingElement get variable; |
| 9215 } |
| 9216 |
| 9217 /** |
| 9218 * A concrete implementation of a [PropertyAccessorElement]. |
| 9219 */ |
| 9220 class PropertyAccessorElementImpl extends ExecutableElementImpl |
| 9221 implements PropertyAccessorElement { |
| 9222 /** |
| 9223 * An empty list of property accessor elements. |
| 9224 */ |
| 9225 @deprecated // Use PropertyAccessorElement.EMPTY_LIST |
| 9226 static const List<PropertyAccessorElement> EMPTY_ARRAY = |
| 9227 const <PropertyAccessorElement>[]; |
| 9228 |
| 9229 /** |
| 9230 * The variable associated with this accessor. |
| 9231 */ |
| 9232 PropertyInducingElement variable; |
| 9233 |
| 9234 /** |
| 9235 * Initialize a newly created property accessor element to have the given |
| 9236 * [name]. |
| 9237 */ |
| 9238 PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9239 |
| 9240 /** |
| 9241 * Initialize a newly created synthetic property accessor element to be |
| 9242 * associated with the given [variable]. |
| 9243 */ |
| 9244 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable) |
| 9245 : super(variable.name, variable.nameOffset) { |
| 9246 this.variable = variable; |
| 9247 static = variable.isStatic; |
| 9248 synthetic = true; |
| 9249 } |
| 9250 |
| 9251 /** |
| 9252 * Set whether this accessor is abstract. |
| 9253 */ |
| 9254 void set abstract(bool isAbstract) { |
| 9255 setModifier(Modifier.ABSTRACT, isAbstract); |
| 9256 } |
| 9257 |
| 9258 @override |
| 9259 PropertyAccessorElement get correspondingGetter { |
| 9260 if (isGetter || variable == null) { |
| 9261 return null; |
| 9262 } |
| 9263 return variable.getter; |
| 9264 } |
| 9265 |
| 9266 @override |
| 9267 PropertyAccessorElement get correspondingSetter { |
| 9268 if (isSetter || variable == null) { |
| 9269 return null; |
| 9270 } |
| 9271 return variable.setter; |
| 9272 } |
| 9273 |
| 9274 /** |
| 9275 * Set whether this accessor is a getter. |
| 9276 */ |
| 9277 void set getter(bool isGetter) { |
| 9278 setModifier(Modifier.GETTER, isGetter); |
| 9279 } |
| 9280 |
| 9281 @override |
| 9282 int get hashCode => JenkinsSmiHash.hash2(super.hashCode, isGetter ? 1 : 2); |
| 9283 |
| 9284 @override |
| 9285 String get identifier { |
| 9286 String name = displayName; |
| 9287 String suffix = isGetter ? "?" : "="; |
| 9288 return "$name$suffix"; |
| 9289 } |
| 9290 |
| 9291 @override |
| 9292 bool get isGetter => hasModifier(Modifier.GETTER); |
| 9293 |
| 9294 @override |
| 9295 bool get isSetter => hasModifier(Modifier.SETTER); |
| 9296 |
| 9297 @override |
| 9298 bool get isStatic => hasModifier(Modifier.STATIC); |
| 9299 |
| 9300 @override |
| 9301 ElementKind get kind { |
| 9302 if (isGetter) { |
| 9303 return ElementKind.GETTER; |
| 9304 } |
| 9305 return ElementKind.SETTER; |
| 9306 } |
| 9307 |
| 9308 @override |
| 9309 String get name { |
| 9310 if (isSetter) { |
| 9311 return "${super.name}="; |
| 9312 } |
| 9313 return super.name; |
| 9314 } |
| 9315 |
| 9316 /** |
| 9317 * Set whether this accessor is a setter. |
| 9318 */ |
| 9319 void set setter(bool isSetter) { |
| 9320 setModifier(Modifier.SETTER, isSetter); |
| 9321 } |
| 9322 |
| 9323 /** |
| 9324 * Set whether this accessor is static. |
| 9325 */ |
| 9326 void set static(bool isStatic) { |
| 9327 setModifier(Modifier.STATIC, isStatic); |
| 9328 } |
| 9329 |
| 9330 @override |
| 9331 bool operator ==(Object object) => super == object && |
| 9332 isGetter == (object as PropertyAccessorElement).isGetter; |
| 9333 |
| 9334 @override |
| 9335 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); |
| 9336 |
| 9337 @override |
| 9338 void appendTo(StringBuffer buffer) { |
| 9339 buffer.write(isGetter ? "get " : "set "); |
| 9340 buffer.write(variable.displayName); |
| 9341 super.appendTo(buffer); |
| 9342 } |
| 9343 |
| 9344 @override |
| 9345 AstNode computeNode() { |
| 9346 if (isSynthetic) { |
| 9347 return null; |
| 9348 } |
| 9349 if (enclosingElement is ClassElement) { |
| 9350 return getNodeMatching((node) => node is MethodDeclaration); |
| 9351 } |
| 9352 if (enclosingElement is CompilationUnitElement) { |
| 9353 return getNodeMatching((node) => node is FunctionDeclaration); |
| 9354 } |
| 9355 return null; |
| 9356 } |
| 9357 } |
| 9358 |
| 9359 /** |
| 9360 * A property accessor element defined in a parameterized type where the values |
| 9361 * of the type parameters are known. |
| 9362 */ |
| 9363 class PropertyAccessorMember extends ExecutableMember |
| 9364 implements PropertyAccessorElement { |
| 9365 /** |
| 9366 * Initialize a newly created element to represent a constructor, based on the |
| 9367 * [baseElement], defined by the [definingType]. |
| 9368 */ |
| 9369 PropertyAccessorMember( |
| 9370 PropertyAccessorElement baseElement, InterfaceType definingType) |
| 9371 : super(baseElement, definingType); |
| 9372 |
| 9373 @override |
| 9374 PropertyAccessorElement get baseElement => |
| 9375 super.baseElement as PropertyAccessorElement; |
| 9376 |
| 9377 @override |
| 9378 PropertyAccessorElement get correspondingGetter => |
| 9379 from(baseElement.correspondingGetter, definingType); |
| 9380 |
| 9381 @override |
| 9382 PropertyAccessorElement get correspondingSetter => |
| 9383 from(baseElement.correspondingSetter, definingType); |
| 9384 |
| 9385 @override |
| 9386 InterfaceType get definingType => super.definingType as InterfaceType; |
| 9387 |
| 9388 @override |
| 9389 Element get enclosingElement => baseElement.enclosingElement; |
| 9390 |
| 9391 @override |
| 9392 bool get isGetter => baseElement.isGetter; |
| 9393 |
| 9394 @override |
| 9395 bool get isSetter => baseElement.isSetter; |
| 9396 |
| 9397 @override |
| 9398 PropertyInducingElement get variable { |
| 9399 PropertyInducingElement variable = baseElement.variable; |
| 9400 if (variable is FieldElement) { |
| 9401 return FieldMember.from(variable, definingType); |
| 9402 } |
| 9403 return variable; |
| 9404 } |
| 9405 |
| 9406 @override |
| 9407 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); |
| 9408 |
| 9409 @override |
| 9410 String toString() { |
| 9411 PropertyAccessorElement baseElement = this.baseElement; |
| 9412 List<ParameterElement> parameters = this.parameters; |
| 9413 FunctionType type = this.type; |
| 9414 StringBuffer builder = new StringBuffer(); |
| 9415 if (isGetter) { |
| 9416 builder.write("get "); |
| 9417 } else { |
| 9418 builder.write("set "); |
| 9419 } |
| 9420 builder.write(baseElement.enclosingElement.displayName); |
| 9421 builder.write("."); |
| 9422 builder.write(baseElement.displayName); |
| 9423 builder.write("("); |
| 9424 int parameterCount = parameters.length; |
| 9425 for (int i = 0; i < parameterCount; i++) { |
| 9426 if (i > 0) { |
| 9427 builder.write(", "); |
| 9428 } |
| 9429 builder.write(parameters[i]); |
| 9430 } |
| 9431 builder.write(")"); |
| 9432 if (type != null) { |
| 9433 builder.write(Element.RIGHT_ARROW); |
| 9434 builder.write(type.returnType); |
| 9435 } |
| 9436 return builder.toString(); |
| 9437 } |
| 9438 |
| 9439 /** |
| 9440 * If the given [accessor]'s type is different when any type parameters from |
| 9441 * the defining type's declaration are replaced with the actual type |
| 9442 * arguments from the [definingType], create an accessor member representing |
| 9443 * the given accessor. Return the member that was created, or the base |
| 9444 * accessor if no member was created. |
| 9445 */ |
| 9446 static PropertyAccessorElement from( |
| 9447 PropertyAccessorElement accessor, InterfaceType definingType) { |
| 9448 if (!_isChangedByTypeSubstitution(accessor, definingType)) { |
| 9449 return accessor; |
| 9450 } |
| 9451 // TODO(brianwilkerson) Consider caching the substituted type in the |
| 9452 // instance. It would use more memory but speed up some operations. |
| 9453 // We need to see how often the type is being re-computed. |
| 9454 return new PropertyAccessorMember(accessor, definingType); |
| 9455 } |
| 9456 |
| 9457 /** |
| 9458 * Determine whether the given property [accessor]'s type is changed when type |
| 9459 * parameters from the defining type's declaration are replaced with the |
| 9460 * actual type arguments from the [definingType]. |
| 9461 */ |
| 9462 static bool _isChangedByTypeSubstitution( |
| 9463 PropertyAccessorElement accessor, InterfaceType definingType) { |
| 9464 List<DartType> argumentTypes = definingType.typeArguments; |
| 9465 if (accessor != null && argumentTypes.length != 0) { |
| 9466 FunctionType baseType = accessor.type; |
| 9467 if (baseType == null) { |
| 9468 AnalysisEngine.instance.logger.logInformation( |
| 9469 'Type of $accessor is null in PropertyAccessorMember._isChangedByTyp
eSubstitution'); |
| 9470 return false; |
| 9471 } |
| 9472 List<DartType> parameterTypes = definingType.element.type.typeArguments; |
| 9473 FunctionType substitutedType = |
| 9474 baseType.substitute2(argumentTypes, parameterTypes); |
| 9475 if (baseType != substitutedType) { |
| 9476 return true; |
| 9477 } |
| 9478 // If this property accessor is based on a field, that field might have a |
| 9479 // propagated type. In which case we need to check whether the propagated |
| 9480 // type of the field needs substitution. |
| 9481 PropertyInducingElement field = accessor.variable; |
| 9482 if (!field.isSynthetic) { |
| 9483 DartType baseFieldType = field.propagatedType; |
| 9484 if (baseFieldType != null) { |
| 9485 DartType substitutedFieldType = |
| 9486 baseFieldType.substitute2(argumentTypes, parameterTypes); |
| 9487 if (baseFieldType != substitutedFieldType) { |
| 9488 return true; |
| 9489 } |
| 9490 } |
| 9491 } |
| 9492 } |
| 9493 return false; |
| 9494 } |
| 9495 } |
| 9496 |
| 9497 /** |
| 9498 * A variable that has an associated getter and possibly a setter. Note that |
| 9499 * explicitly defined variables implicitly define a synthetic getter and that |
| 9500 * non-`final` explicitly defined variables implicitly define a synthetic |
| 9501 * setter. Symmetrically, synthetic fields are implicitly created for explicitly |
| 9502 * defined getters and setters. The following rules apply: |
| 9503 * |
| 9504 * * Every explicit variable is represented by a non-synthetic |
| 9505 * [PropertyInducingElement]. |
| 9506 * * Every explicit variable induces a getter and possibly a setter, both of |
| 9507 * which are represented by synthetic [PropertyAccessorElement]s. |
| 9508 * * Every explicit getter or setter is represented by a non-synthetic |
| 9509 * [PropertyAccessorElement]. |
| 9510 * * Every explicit getter or setter (or pair thereof if they have the same |
| 9511 * name) induces a variable that is represented by a synthetic |
| 9512 * [PropertyInducingElement]. |
| 9513 */ |
| 9514 abstract class PropertyInducingElement implements VariableElement { |
| 9515 /** |
| 9516 * An empty list of elements. |
| 9517 */ |
| 9518 static const List<PropertyInducingElement> EMPTY_LIST = |
| 9519 const <PropertyInducingElement>[]; |
| 9520 |
| 9521 /** |
| 9522 * Return the getter associated with this variable. If this variable was |
| 9523 * explicitly defined (is not synthetic) then the getter associated with it |
| 9524 * will be synthetic. |
| 9525 */ |
| 9526 PropertyAccessorElement get getter; |
| 9527 |
| 9528 /** |
| 9529 * Return the propagated type of this variable, or `null` if type propagation |
| 9530 * has not been performed, for example because the variable is not final. |
| 9531 */ |
| 9532 DartType get propagatedType; |
| 9533 |
| 9534 /** |
| 9535 * Return the setter associated with this variable, or `null` if the variable |
| 9536 * is effectively `final` and therefore does not have a setter associated with |
| 9537 * it. (This can happen either because the variable is explicitly defined as |
| 9538 * being `final` or because the variable is induced by an explicit getter that |
| 9539 * does not have a corresponding setter.) If this variable was explicitly |
| 9540 * defined (is not synthetic) then the setter associated with it will be |
| 9541 * synthetic. |
| 9542 */ |
| 9543 PropertyAccessorElement get setter; |
| 9544 } |
| 9545 |
| 9546 /** |
| 9547 * A concrete implementation of a [PropertyInducingElement]. |
| 9548 */ |
| 9549 abstract class PropertyInducingElementImpl extends VariableElementImpl |
| 9550 implements PropertyInducingElement { |
| 9551 /** |
| 9552 * An empty list of elements. |
| 9553 */ |
| 9554 @deprecated // Use PropertyInducingElement.EMPTY_LIST |
| 9555 static const List<PropertyInducingElement> EMPTY_ARRAY = |
| 9556 const <PropertyInducingElement>[]; |
| 9557 |
| 9558 /** |
| 9559 * The getter associated with this element. |
| 9560 */ |
| 9561 PropertyAccessorElement getter; |
| 9562 |
| 9563 /** |
| 9564 * The setter associated with this element, or `null` if the element is |
| 9565 * effectively `final` and therefore does not have a setter associated with |
| 9566 * it. |
| 9567 */ |
| 9568 PropertyAccessorElement setter; |
| 9569 |
| 9570 /** |
| 9571 * The propagated type of this variable, or `null` if type propagation has not |
| 9572 * been performed. |
| 9573 */ |
| 9574 DartType propagatedType; |
| 9575 |
| 9576 /** |
| 9577 * Initialize a newly created synthetic element to have the given [name] and |
| 9578 * [offset]. |
| 9579 */ |
| 9580 PropertyInducingElementImpl(String name, int offset) : super(name, offset); |
| 9581 |
| 9582 /** |
| 9583 * Initialize a newly created element to have the given [name]. |
| 9584 */ |
| 9585 PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9586 } |
| 9587 |
| 9588 /** |
| 9589 * A visitor that will recursively visit all of the element in an element model. |
| 9590 * For example, using an instance of this class to visit a |
| 9591 * [CompilationUnitElement] will also cause all of the types in the compilation |
| 9592 * unit to be visited. |
| 9593 * |
| 9594 * Subclasses that override a visit method must either invoke the overridden |
| 9595 * visit method or must explicitly ask the visited element to visit its |
| 9596 * children. Failure to do so will cause the children of the visited element to |
| 9597 * not be visited. |
| 9598 */ |
| 9599 class RecursiveElementVisitor<R> implements ElementVisitor<R> { |
| 9600 @override |
| 9601 R visitClassElement(ClassElement element) { |
| 9602 element.visitChildren(this); |
| 9603 return null; |
| 9604 } |
| 9605 |
| 9606 @override |
| 9607 R visitCompilationUnitElement(CompilationUnitElement element) { |
| 9608 element.visitChildren(this); |
| 9609 return null; |
| 9610 } |
| 9611 |
| 9612 @override |
| 9613 R visitConstructorElement(ConstructorElement element) { |
| 9614 element.visitChildren(this); |
| 9615 return null; |
| 9616 } |
| 9617 |
| 9618 @override |
| 9619 @deprecated |
| 9620 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) { |
| 9621 element.visitChildren(this); |
| 9622 return null; |
| 9623 } |
| 9624 |
| 9625 @override |
| 9626 R visitExportElement(ExportElement element) { |
| 9627 element.visitChildren(this); |
| 9628 return null; |
| 9629 } |
| 9630 |
| 9631 @override |
| 9632 @deprecated |
| 9633 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) { |
| 9634 element.visitChildren(this); |
| 9635 return null; |
| 9636 } |
| 9637 |
| 9638 @override |
| 9639 R visitFieldElement(FieldElement element) { |
| 9640 element.visitChildren(this); |
| 9641 return null; |
| 9642 } |
| 9643 |
| 9644 @override |
| 9645 R visitFieldFormalParameterElement(FieldFormalParameterElement element) { |
| 9646 element.visitChildren(this); |
| 9647 return null; |
| 9648 } |
| 9649 |
| 9650 @override |
| 9651 R visitFunctionElement(FunctionElement element) { |
| 9652 element.visitChildren(this); |
| 9653 return null; |
| 9654 } |
| 9655 |
| 9656 @override |
| 9657 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
| 9658 element.visitChildren(this); |
| 9659 return null; |
| 9660 } |
| 9661 |
| 9662 @override |
| 9663 @deprecated |
| 9664 R visitHtmlElement(HtmlElement element) { |
| 9665 element.visitChildren(this); |
| 9666 return null; |
| 9667 } |
| 9668 |
| 9669 @override |
| 9670 R visitImportElement(ImportElement element) { |
| 9671 element.visitChildren(this); |
| 9672 return null; |
| 9673 } |
| 9674 |
| 9675 @override |
| 9676 R visitLabelElement(LabelElement element) { |
| 9677 element.visitChildren(this); |
| 9678 return null; |
| 9679 } |
| 9680 |
| 9681 @override |
| 9682 R visitLibraryElement(LibraryElement element) { |
| 9683 element.visitChildren(this); |
| 9684 return null; |
| 9685 } |
| 9686 |
| 9687 @override |
| 9688 R visitLocalVariableElement(LocalVariableElement element) { |
| 9689 element.visitChildren(this); |
| 9690 return null; |
| 9691 } |
| 9692 |
| 9693 @override |
| 9694 R visitMethodElement(MethodElement element) { |
| 9695 element.visitChildren(this); |
| 9696 return null; |
| 9697 } |
| 9698 |
| 9699 @override |
| 9700 R visitMultiplyDefinedElement(MultiplyDefinedElement element) { |
| 9701 element.visitChildren(this); |
| 9702 return null; |
| 9703 } |
| 9704 |
| 9705 @override |
| 9706 R visitParameterElement(ParameterElement element) { |
| 9707 element.visitChildren(this); |
| 9708 return null; |
| 9709 } |
| 9710 |
| 9711 @override |
| 9712 R visitPrefixElement(PrefixElement element) { |
| 9713 element.visitChildren(this); |
| 9714 return null; |
| 9715 } |
| 9716 |
| 9717 @override |
| 9718 R visitPropertyAccessorElement(PropertyAccessorElement element) { |
| 9719 element.visitChildren(this); |
| 9720 return null; |
| 9721 } |
| 9722 |
| 9723 @override |
| 9724 R visitTopLevelVariableElement(TopLevelVariableElement element) { |
| 9725 element.visitChildren(this); |
| 9726 return null; |
| 9727 } |
| 9728 |
| 9729 @override |
| 9730 R visitTypeParameterElement(TypeParameterElement element) { |
| 9731 element.visitChildren(this); |
| 9732 return null; |
| 9733 } |
| 9734 } |
| 9735 |
| 9736 /** |
| 9737 * A combinator that cause some of the names in a namespace to be visible (and |
| 9738 * the rest hidden) when being imported. |
| 9739 */ |
| 9740 abstract class ShowElementCombinator implements NamespaceCombinator { |
| 9741 /** |
| 9742 * Return the offset of the character immediately following the last character |
| 9743 * of this node. |
| 9744 */ |
| 9745 int get end; |
| 9746 |
| 9747 /** |
| 9748 * Return the offset of the 'show' keyword of this element. |
| 9749 */ |
| 9750 int get offset; |
| 9751 |
| 9752 /** |
| 9753 * Return a list containing the names that are to be made visible in the |
| 9754 * importing library if they are defined in the imported library. |
| 9755 */ |
| 9756 List<String> get shownNames; |
| 9757 } |
| 9758 |
| 9759 /** |
| 9760 * A concrete implementation of a [ShowElementCombinator]. |
| 9761 */ |
| 9762 class ShowElementCombinatorImpl implements ShowElementCombinator { |
| 9763 /** |
| 9764 * The names that are to be made visible in the importing library if they are |
| 9765 * defined in the imported library. |
| 9766 */ |
| 9767 List<String> shownNames = StringUtilities.EMPTY_ARRAY; |
| 9768 |
| 9769 /** |
| 9770 * The offset of the character immediately following the last character of |
| 9771 * this node. |
| 9772 */ |
| 9773 int end = -1; |
| 9774 |
| 9775 /** |
| 9776 * The offset of the 'show' keyword of this element. |
| 9777 */ |
| 9778 int offset = 0; |
| 9779 |
| 9780 @override |
| 9781 String toString() { |
| 9782 StringBuffer buffer = new StringBuffer(); |
| 9783 buffer.write("show "); |
| 9784 int count = shownNames.length; |
| 9785 for (int i = 0; i < count; i++) { |
| 9786 if (i > 0) { |
| 9787 buffer.write(", "); |
| 9788 } |
| 9789 buffer.write(shownNames[i]); |
| 9790 } |
| 9791 return buffer.toString(); |
| 9792 } |
| 9793 } |
| 9794 |
| 9795 /** |
| 9796 * A visitor that will do nothing when visiting an element. It is intended to be |
| 9797 * a superclass for classes that use the visitor pattern primarily as a dispatch |
| 9798 * mechanism (and hence don't need to recursively visit a whole structure) and |
| 9799 * that only need to visit a small number of element types. |
| 9800 */ |
| 9801 class SimpleElementVisitor<R> implements ElementVisitor<R> { |
| 9802 @override |
| 9803 R visitClassElement(ClassElement element) => null; |
| 9804 |
| 9805 @override |
| 9806 R visitCompilationUnitElement(CompilationUnitElement element) => null; |
| 9807 |
| 9808 @override |
| 9809 R visitConstructorElement(ConstructorElement element) => null; |
| 9810 |
| 9811 @override |
| 9812 @deprecated |
| 9813 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null; |
| 9814 |
| 9815 @override |
| 9816 R visitExportElement(ExportElement element) => null; |
| 9817 |
| 9818 @override |
| 9819 @deprecated |
| 9820 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null; |
| 9821 |
| 9822 @override |
| 9823 R visitFieldElement(FieldElement element) => null; |
| 9824 |
| 9825 @override |
| 9826 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => |
| 9827 null; |
| 9828 |
| 9829 @override |
| 9830 R visitFunctionElement(FunctionElement element) => null; |
| 9831 |
| 9832 @override |
| 9833 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null; |
| 9834 |
| 9835 @override |
| 9836 @deprecated |
| 9837 R visitHtmlElement(HtmlElement element) => null; |
| 9838 |
| 9839 @override |
| 9840 R visitImportElement(ImportElement element) => null; |
| 9841 |
| 9842 @override |
| 9843 R visitLabelElement(LabelElement element) => null; |
| 9844 |
| 9845 @override |
| 9846 R visitLibraryElement(LibraryElement element) => null; |
| 9847 |
| 9848 @override |
| 9849 R visitLocalVariableElement(LocalVariableElement element) => null; |
| 9850 |
| 9851 @override |
| 9852 R visitMethodElement(MethodElement element) => null; |
| 9853 |
| 9854 @override |
| 9855 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null; |
| 9856 |
| 9857 @override |
| 9858 R visitParameterElement(ParameterElement element) => null; |
| 9859 |
| 9860 @override |
| 9861 R visitPrefixElement(PrefixElement element) => null; |
| 9862 |
| 9863 @override |
| 9864 R visitPropertyAccessorElement(PropertyAccessorElement element) => null; |
| 9865 |
| 9866 @override |
| 9867 R visitTopLevelVariableElement(TopLevelVariableElement element) => null; |
| 9868 |
| 9869 @override |
| 9870 R visitTypeParameterElement(TypeParameterElement element) => null; |
| 9871 } |
| 9872 |
| 9873 /** |
| 9874 * A top-level variable. |
| 9875 */ |
| 9876 abstract class TopLevelVariableElement implements PropertyInducingElement { |
| 9877 /** |
| 9878 * An empty list of top-level variable elements. |
| 9879 */ |
| 9880 static const List<TopLevelVariableElement> EMPTY_LIST = |
| 9881 const <TopLevelVariableElement>[]; |
| 9882 |
| 9883 @override |
| 9884 VariableDeclaration computeNode(); |
| 9885 } |
| 9886 |
| 9887 /** |
| 9888 * A concrete implementation of a [TopLevelVariableElement]. |
| 9889 */ |
| 9890 class TopLevelVariableElementImpl extends PropertyInducingElementImpl |
| 9891 with PotentiallyConstVariableElement |
| 9892 implements TopLevelVariableElement { |
| 9893 /** |
| 9894 * An empty list of top-level variable elements. |
| 9895 */ |
| 9896 @deprecated // Use TopLevelVariableElement.EMPTY_LIST |
| 9897 static const List<TopLevelVariableElement> EMPTY_ARRAY = |
| 9898 const <TopLevelVariableElement>[]; |
| 9899 |
| 9900 /** |
| 9901 * Initialize a newly created synthetic top-level variable element to have the |
| 9902 * given [name] and [offset]. |
| 9903 */ |
| 9904 TopLevelVariableElementImpl(String name, int offset) : super(name, offset); |
| 9905 |
| 9906 /** |
| 9907 * Initialize a newly created top-level variable element to have the given |
| 9908 * [name]. |
| 9909 */ |
| 9910 TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 9911 |
| 9912 @override |
| 9913 bool get isStatic => true; |
| 9914 |
| 9915 @override |
| 9916 ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE; |
| 9917 |
| 9918 @override |
| 9919 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this); |
| 9920 |
| 9921 @override |
| 9922 VariableDeclaration computeNode() => |
| 9923 getNodeMatching((node) => node is VariableDeclaration); |
| 9924 } |
| 9925 |
| 9926 /** |
| 9927 * An element that defines a type. |
| 9928 */ |
| 9929 abstract class TypeDefiningElement implements Element { |
| 9930 /** |
| 9931 * Return the type defined by this element. |
| 9932 */ |
| 9933 DartType get type; |
| 9934 } |
| 9935 |
| 9936 /** |
| 9937 * The abstract class `TypeImpl` implements the behavior common to objects |
| 9938 * representing the declared type of elements in the element model. |
| 9939 */ |
| 9940 abstract class TypeImpl implements DartType { |
| 9941 /** |
| 9942 * An empty list of types. |
| 9943 */ |
| 9944 @deprecated // Use DartType.EMPTY_LIST |
| 9945 static const List<DartType> EMPTY_ARRAY = const <DartType>[]; |
| 9946 |
| 9947 /** |
| 9948 * The element representing the declaration of this type, or `null` if the |
| 9949 * type has not, or cannot, be associated with an element. |
| 9950 */ |
| 9951 final Element _element; |
| 9952 |
| 9953 /** |
| 9954 * The name of this type, or `null` if the type does not have a name. |
| 9955 */ |
| 9956 final String name; |
| 9957 |
| 9958 /** |
| 9959 * Initialize a newly created type to be declared by the given [element] and |
| 9960 * to have the given [name]. |
| 9961 */ |
| 9962 TypeImpl(this._element, this.name); |
| 9963 |
| 9964 @override |
| 9965 String get displayName => name; |
| 9966 |
| 9967 @override |
| 9968 Element get element => _element; |
| 9969 |
| 9970 @override |
| 9971 bool get isBottom => false; |
| 9972 |
| 9973 @override |
| 9974 bool get isDartCoreFunction => false; |
| 9975 |
| 9976 @override |
| 9977 bool get isDynamic => false; |
| 9978 |
| 9979 @override |
| 9980 bool get isObject => false; |
| 9981 |
| 9982 @override |
| 9983 bool get isUndefined => false; |
| 9984 |
| 9985 @override |
| 9986 bool get isVoid => false; |
| 9987 |
| 9988 /** |
| 9989 * Append a textual representation of this type to the given [buffer]. The set |
| 9990 * of [visitedTypes] is used to prevent infinite recusion. |
| 9991 */ |
| 9992 void appendTo(StringBuffer buffer) { |
| 9993 if (name == null) { |
| 9994 buffer.write("<unnamed type>"); |
| 9995 } else { |
| 9996 buffer.write(name); |
| 9997 } |
| 9998 } |
| 9999 |
| 10000 @override |
| 10001 DartType getLeastUpperBound(DartType type) => null; |
| 10002 |
| 10003 /** |
| 10004 * Return `true` if this type is assignable to the given [type] (written in |
| 10005 * the spec as "T <=> S", where T=[this] and S=[type]). |
| 10006 * |
| 10007 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of |
| 10008 * function type aliases that have been expanded so far in the process of |
| 10009 * reaching [this] and [type], respectively. These are used to avoid |
| 10010 * infinite regress when analyzing invalid code; since the language spec |
| 10011 * forbids a typedef from referring to itself directly or indirectly, we can |
| 10012 * use these as sets of function type aliases that don't need to be expanded. |
| 10013 */ |
| 10014 @override |
| 10015 bool isAssignableTo(DartType type) { |
| 10016 // An interface type T may be assigned to a type S, written T <=> S, iff |
| 10017 // either T <: S or S <: T. |
| 10018 return isSubtypeOf(type) || (type as TypeImpl).isSubtypeOf(this); |
| 10019 } |
| 10020 |
| 10021 /** |
| 10022 * Return `true` if this type is more specific than the given [type] (written |
| 10023 * in the spec as "T << S", where T=[this] and S=[type]). |
| 10024 * |
| 10025 * If [withDynamic] is `true`, then "dynamic" should be considered as a |
| 10026 * subtype of any type (as though "dynamic" had been replaced with bottom). |
| 10027 * |
| 10028 * The set [visitedElements], if given, is the set of classes and type |
| 10029 * parameters that have been visited so far while examining the class |
| 10030 * hierarchy of [this]. This is used to avoid infinite regress when |
| 10031 * analyzing invalid code; since the language spec forbids loops in the class |
| 10032 * hierarchy, we can use this as a set of classes that don't need to be |
| 10033 * examined when walking the class hierarchy. |
| 10034 */ |
| 10035 @override |
| 10036 bool isMoreSpecificThan(DartType type, |
| 10037 [bool withDynamic = false, Set<Element> visitedElements]); |
| 10038 |
| 10039 /** |
| 10040 * Return `true` if this type is a subtype of the given [type] (written in |
| 10041 * the spec as "T <: S", where T=[this] and S=[type]). |
| 10042 * |
| 10043 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of |
| 10044 * function type aliases that have been expanded so far in the process of |
| 10045 * reaching [this] and [type], respectively. These are used to avoid |
| 10046 * infinite regress when analyzing invalid code; since the language spec |
| 10047 * forbids a typedef from referring to itself directly or indirectly, we can |
| 10048 * use these as sets of function type aliases that don't need to be expanded. |
| 10049 */ |
| 10050 @override |
| 10051 bool isSubtypeOf(DartType type) { |
| 10052 // For non-function types, T <: S iff [_|_/dynamic]T << S. |
| 10053 return isMoreSpecificThan(type, true); |
| 10054 } |
| 10055 |
| 10056 @override |
| 10057 bool isSupertypeOf(DartType type) => type.isSubtypeOf(this); |
| 10058 |
| 10059 /** |
| 10060 * Create a new [TypeImpl] that is identical to [this] except that when |
| 10061 * visiting type parameters, function parameter types, and function return |
| 10062 * types, function types listed in [prune] will not be expanded. This is |
| 10063 * used to avoid creating infinite types in the presence of circular |
| 10064 * typedefs. |
| 10065 * |
| 10066 * If [prune] is null, then [this] is returned unchanged. |
| 10067 * |
| 10068 * Only legal to call on a [TypeImpl] that is not already subject to pruning. |
| 10069 */ |
| 10070 TypeImpl pruned(List<FunctionTypeAliasElement> prune); |
| 10071 |
| 10072 /** |
| 10073 * Return the type resulting from substituting the given [argumentTypes] for |
| 10074 * the given [parameterTypes] in this type. |
| 10075 * |
| 10076 * In all classes derived from [TypeImpl], a new optional argument |
| 10077 * [prune] is added. If specified, it is a list of function typdefs |
| 10078 * which should not be expanded. This is used to avoid creating infinite |
| 10079 * types in response to self-referential typedefs. |
| 10080 */ |
| 10081 @override |
| 10082 DartType substitute2( |
| 10083 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 10084 [List<FunctionTypeAliasElement> prune]); |
| 10085 |
| 10086 @override |
| 10087 String toString() { |
| 10088 StringBuffer buffer = new StringBuffer(); |
| 10089 appendTo(buffer); |
| 10090 return buffer.toString(); |
| 10091 } |
| 10092 |
| 10093 /** |
| 10094 * Return `true` if corresponding elements of the [first] and [second] lists |
| 10095 * of type arguments are all equal. |
| 10096 */ |
| 10097 static bool equalArrays(List<DartType> first, List<DartType> second) { |
| 10098 if (first.length != second.length) { |
| 10099 return false; |
| 10100 } |
| 10101 for (int i = 0; i < first.length; i++) { |
| 10102 if (first[i] == null) { |
| 10103 AnalysisEngine.instance.logger |
| 10104 .logInformation('Found null type argument in TypeImpl.equalArrays'); |
| 10105 return second[i] == null; |
| 10106 } else if (second[i] == null) { |
| 10107 AnalysisEngine.instance.logger |
| 10108 .logInformation('Found null type argument in TypeImpl.equalArrays'); |
| 10109 return false; |
| 10110 } |
| 10111 if (first[i] != second[i]) { |
| 10112 return false; |
| 10113 } |
| 10114 } |
| 10115 return true; |
| 10116 } |
| 10117 |
| 10118 /** |
| 10119 * Return a list containing the results of using the given [argumentTypes] and |
| 10120 * [parameterTypes] to perform a substitution on all of the given [types]. |
| 10121 * |
| 10122 * If [prune] is specified, it is a list of function typdefs which should not |
| 10123 * be expanded. This is used to avoid creating infinite types in response to |
| 10124 * self-referential typedefs. |
| 10125 */ |
| 10126 static List<DartType> substitute(List<DartType> types, |
| 10127 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 10128 [List<FunctionTypeAliasElement> prune]) { |
| 10129 int length = types.length; |
| 10130 if (length == 0) { |
| 10131 return types; |
| 10132 } |
| 10133 List<DartType> newTypes = new List<DartType>(length); |
| 10134 for (int i = 0; i < length; i++) { |
| 10135 newTypes[i] = (types[i] as TypeImpl) |
| 10136 .substitute2(argumentTypes, parameterTypes, prune); |
| 10137 } |
| 10138 return newTypes; |
| 10139 } |
| 10140 } |
| 10141 |
| 10142 /** |
| 10143 * A type parameter. |
| 10144 */ |
| 10145 abstract class TypeParameterElement implements TypeDefiningElement { |
| 10146 /** |
| 10147 * An empty list of type parameter elements. |
| 10148 */ |
| 10149 static const List<TypeParameterElement> EMPTY_LIST = |
| 10150 const <TypeParameterElement>[]; |
| 10151 |
| 10152 /** |
| 10153 * Return the type representing the bound associated with this parameter, or |
| 10154 * `null` if this parameter does not have an explicit bound. |
| 10155 */ |
| 10156 DartType get bound; |
| 10157 |
| 10158 /** |
| 10159 * Return the type defined by this type parameter. |
| 10160 */ |
| 10161 TypeParameterType get type; |
| 10162 } |
| 10163 |
| 10164 /** |
| 10165 * A concrete implementation of a [TypeParameterElement]. |
| 10166 */ |
| 10167 class TypeParameterElementImpl extends ElementImpl |
| 10168 implements TypeParameterElement { |
| 10169 /** |
| 10170 * An empty list of type parameter elements. |
| 10171 */ |
| 10172 @deprecated // Use TypeParameterElement.EMPTY_LIST |
| 10173 static const List<TypeParameterElement> EMPTY_ARRAY = |
| 10174 const <TypeParameterElement>[]; |
| 10175 |
| 10176 /** |
| 10177 * The type defined by this type parameter. |
| 10178 */ |
| 10179 TypeParameterType type; |
| 10180 |
| 10181 /** |
| 10182 * The type representing the bound associated with this parameter, or `null` |
| 10183 * if this parameter does not have an explicit bound. |
| 10184 */ |
| 10185 DartType bound; |
| 10186 |
| 10187 /** |
| 10188 * Initialize a newly created method element to have the given [name] and |
| 10189 * [offset]. |
| 10190 */ |
| 10191 TypeParameterElementImpl(String name, int offset) : super(name, offset); |
| 10192 |
| 10193 /** |
| 10194 * Initialize a newly created type parameter element to have the given [name]. |
| 10195 */ |
| 10196 TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name); |
| 10197 |
| 10198 @override |
| 10199 ElementKind get kind => ElementKind.TYPE_PARAMETER; |
| 10200 |
| 10201 @override |
| 10202 accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this); |
| 10203 |
| 10204 @override |
| 10205 void appendTo(StringBuffer buffer) { |
| 10206 buffer.write(displayName); |
| 10207 if (bound != null) { |
| 10208 buffer.write(" extends "); |
| 10209 buffer.write(bound); |
| 10210 } |
| 10211 } |
| 10212 } |
| 10213 |
| 10214 /** |
| 10215 * The type introduced by a type parameter. |
| 10216 */ |
| 10217 abstract class TypeParameterType implements DartType { |
| 10218 /** |
| 10219 * An empty list of type parameter types. |
| 10220 */ |
| 10221 static const List<TypeParameterType> EMPTY_LIST = const <TypeParameterType>[]; |
| 10222 |
| 10223 @override |
| 10224 TypeParameterElement get element; |
| 10225 } |
| 10226 |
| 10227 /** |
| 10228 * A concrete implementation of a [TypeParameterType]. |
| 10229 */ |
| 10230 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { |
| 10231 /** |
| 10232 * An empty list of type parameter types. |
| 10233 */ |
| 10234 @deprecated // Use TypeParameterType.EMPTY_LIST |
| 10235 static const List<TypeParameterType> EMPTY_ARRAY = |
| 10236 const <TypeParameterType>[]; |
| 10237 |
| 10238 /** |
| 10239 * Initialize a newly created type parameter type to be declared by the given |
| 10240 * [element] and to have the given name. |
| 10241 */ |
| 10242 TypeParameterTypeImpl(TypeParameterElement element) |
| 10243 : super(element, element.name); |
| 10244 |
| 10245 @override |
| 10246 TypeParameterElement get element => super.element as TypeParameterElement; |
| 10247 |
| 10248 @override |
| 10249 int get hashCode => element.hashCode; |
| 10250 |
| 10251 @override |
| 10252 bool operator ==(Object object) => |
| 10253 object is TypeParameterTypeImpl && (element == object.element); |
| 10254 |
| 10255 @override |
| 10256 bool isMoreSpecificThan(DartType s, |
| 10257 [bool withDynamic = false, Set<Element> visitedElements]) { |
| 10258 // |
| 10259 // A type T is more specific than a type S, written T << S, |
| 10260 // if one of the following conditions is met: |
| 10261 // |
| 10262 // Reflexivity: T is S. |
| 10263 // |
| 10264 if (this == s) { |
| 10265 return true; |
| 10266 } |
| 10267 // S is dynamic. |
| 10268 // |
| 10269 if (s.isDynamic) { |
| 10270 return true; |
| 10271 } |
| 10272 // |
| 10273 // T is a type parameter and S is the upper bound of T. |
| 10274 // |
| 10275 TypeImpl bound = element.bound; |
| 10276 if (s == bound) { |
| 10277 return true; |
| 10278 } |
| 10279 // |
| 10280 // T is a type parameter and S is Object. |
| 10281 // |
| 10282 if (s.isObject) { |
| 10283 return true; |
| 10284 } |
| 10285 // We need upper bound to continue. |
| 10286 if (bound == null) { |
| 10287 return false; |
| 10288 } |
| 10289 // |
| 10290 // Transitivity: T << U and U << S. |
| 10291 // |
| 10292 // First check for infinite loops |
| 10293 if (element == null) { |
| 10294 return false; |
| 10295 } |
| 10296 if (visitedElements == null) { |
| 10297 visitedElements = new HashSet<Element>(); |
| 10298 } else if (visitedElements.contains(element)) { |
| 10299 return false; |
| 10300 } |
| 10301 visitedElements.add(element); |
| 10302 try { |
| 10303 return bound.isMoreSpecificThan(s, withDynamic, visitedElements); |
| 10304 } finally { |
| 10305 visitedElements.remove(element); |
| 10306 } |
| 10307 } |
| 10308 |
| 10309 @override |
| 10310 bool isSubtypeOf(DartType type) => isMoreSpecificThan(type, true); |
| 10311 |
| 10312 @override |
| 10313 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 10314 |
| 10315 @override |
| 10316 DartType substitute2( |
| 10317 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 10318 [List<FunctionTypeAliasElement> prune]) { |
| 10319 int length = parameterTypes.length; |
| 10320 for (int i = 0; i < length; i++) { |
| 10321 if (parameterTypes[i] == this) { |
| 10322 return argumentTypes[i]; |
| 10323 } |
| 10324 } |
| 10325 return this; |
| 10326 } |
| 10327 |
| 10328 /** |
| 10329 * Return a list containing the type parameter types defined by the given |
| 10330 * array of type parameter elements ([typeParameters]). |
| 10331 */ |
| 10332 static List<TypeParameterType> getTypes( |
| 10333 List<TypeParameterElement> typeParameters) { |
| 10334 int count = typeParameters.length; |
| 10335 if (count == 0) { |
| 10336 return TypeParameterType.EMPTY_LIST; |
| 10337 } |
| 10338 List<TypeParameterType> types = new List<TypeParameterType>(count); |
| 10339 for (int i = 0; i < count; i++) { |
| 10340 types[i] = typeParameters[i].type; |
| 10341 } |
| 10342 return types; |
| 10343 } |
| 10344 } |
| 10345 |
| 10346 /** |
| 10347 * A pseudo-elements that represents names that are undefined. This situation is |
| 10348 * not allowed by the language, so objects implementing this interface always |
| 10349 * represent an error. As a result, most of the normal operations on elements do |
| 10350 * not make sense and will return useless results. |
| 10351 */ |
| 10352 abstract class UndefinedElement implements Element {} |
| 10353 |
| 10354 /** |
| 10355 * The unique instance of the class `UndefinedTypeImpl` implements the type of |
| 10356 * typenames that couldn't be resolved. |
| 10357 * |
| 10358 * This class behaves like DynamicTypeImpl in almost every respect, to reduce |
| 10359 * cascading errors. |
| 10360 */ |
| 10361 class UndefinedTypeImpl extends TypeImpl { |
| 10362 /** |
| 10363 * The unique instance of this class. |
| 10364 */ |
| 10365 static UndefinedTypeImpl _INSTANCE = new UndefinedTypeImpl._(); |
| 10366 |
| 10367 /** |
| 10368 * Return the unique instance of this class. |
| 10369 */ |
| 10370 static UndefinedTypeImpl get instance => _INSTANCE; |
| 10371 |
| 10372 /** |
| 10373 * Prevent the creation of instances of this class. |
| 10374 */ |
| 10375 UndefinedTypeImpl._() |
| 10376 : super(DynamicElementImpl.instance, Keyword.DYNAMIC.syntax); |
| 10377 |
| 10378 @override |
| 10379 int get hashCode => 1; |
| 10380 |
| 10381 @override |
| 10382 bool get isDynamic => true; |
| 10383 |
| 10384 @override |
| 10385 bool get isUndefined => true; |
| 10386 |
| 10387 @override |
| 10388 bool operator ==(Object object) => identical(object, this); |
| 10389 |
| 10390 @override |
| 10391 bool isMoreSpecificThan(DartType type, |
| 10392 [bool withDynamic = false, Set<Element> visitedElements]) { |
| 10393 // T is S |
| 10394 if (identical(this, type)) { |
| 10395 return true; |
| 10396 } |
| 10397 // else |
| 10398 return withDynamic; |
| 10399 } |
| 10400 |
| 10401 @override |
| 10402 bool isSubtypeOf(DartType type) => true; |
| 10403 |
| 10404 @override |
| 10405 bool isSupertypeOf(DartType type) => true; |
| 10406 |
| 10407 @override |
| 10408 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 10409 |
| 10410 @override |
| 10411 DartType substitute2( |
| 10412 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 10413 [List<FunctionTypeAliasElement> prune]) { |
| 10414 int length = parameterTypes.length; |
| 10415 for (int i = 0; i < length; i++) { |
| 10416 if (parameterTypes[i] == this) { |
| 10417 return argumentTypes[i]; |
| 10418 } |
| 10419 } |
| 10420 return this; |
| 10421 } |
| 10422 } |
| 10423 |
| 10424 /** |
| 10425 * An element included into a library using some URI. |
| 10426 */ |
| 10427 abstract class UriReferencedElement implements Element { |
| 10428 /** |
| 10429 * Return the URI that is used to include this element into the enclosing |
| 10430 * library, or `null` if this is the defining compilation unit of a library. |
| 10431 */ |
| 10432 String get uri; |
| 10433 |
| 10434 /** |
| 10435 * Return the offset of the character immediately following the last character |
| 10436 * of this node's URI, or `-1` for synthetic import. |
| 10437 */ |
| 10438 int get uriEnd; |
| 10439 |
| 10440 /** |
| 10441 * Return the offset of the URI in the file, or `-1` if this element is |
| 10442 * synthetic. |
| 10443 */ |
| 10444 int get uriOffset; |
| 10445 } |
| 10446 |
| 10447 /** |
| 10448 * A concrete implementation of a [UriReferencedElement]. |
| 10449 */ |
| 10450 abstract class UriReferencedElementImpl extends ElementImpl |
| 10451 implements UriReferencedElement { |
| 10452 /** |
| 10453 * The offset of the URI in the file, may be `-1` if synthetic. |
| 10454 */ |
| 10455 int uriOffset = -1; |
| 10456 |
| 10457 /** |
| 10458 * The offset of the character immediately following the last character of |
| 10459 * this node's URI, may be `-1` if synthetic. |
| 10460 */ |
| 10461 int uriEnd = -1; |
| 10462 |
| 10463 /** |
| 10464 * The URI that is specified by this directive. |
| 10465 */ |
| 10466 String uri; |
| 10467 |
| 10468 /** |
| 10469 * Initialize a newly created import element to heve the given [name] and |
| 10470 * [offset]. The offset may be `-1` if the element is synthetic. |
| 10471 */ |
| 10472 UriReferencedElementImpl(String name, int offset) : super(name, offset); |
| 10473 } |
| 10474 |
| 10475 /** |
| 10476 * A variable. There are concrete subclasses for different kinds of variables. |
| 10477 */ |
| 10478 abstract class VariableElement implements Element, ConstantEvaluationTarget { |
| 10479 /** |
| 10480 * An empty list of variable elements. |
| 10481 */ |
| 10482 static const List<VariableElement> EMPTY_LIST = const <VariableElement>[]; |
| 10483 |
| 10484 /** |
| 10485 * Return `true` if this variable element did not have an explicit type |
| 10486 * specified for it. |
| 10487 */ |
| 10488 bool get hasImplicitType; |
| 10489 |
| 10490 /** |
| 10491 * Return a synthetic function representing this variable's initializer, or |
| 10492 * `null` if this variable does not have an initializer. The function will |
| 10493 * have no parameters. The return type of the function will be the |
| 10494 * compile-time type of the initialization expression. |
| 10495 */ |
| 10496 FunctionElement get initializer; |
| 10497 |
| 10498 /** |
| 10499 * Return `true` if this variable was declared with the 'const' modifier. |
| 10500 */ |
| 10501 bool get isConst; |
| 10502 |
| 10503 /** |
| 10504 * Return `true` if this variable was declared with the 'final' modifier. |
| 10505 * Variables that are declared with the 'const' modifier will return `false` |
| 10506 * even though they are implicitly final. |
| 10507 */ |
| 10508 bool get isFinal; |
| 10509 |
| 10510 /** |
| 10511 * Return `true` if this variable is potentially mutated somewhere in a |
| 10512 * closure. This information is only available for local variables (including |
| 10513 * parameters) and only after the compilation unit containing the variable has |
| 10514 * been resolved. |
| 10515 */ |
| 10516 bool get isPotentiallyMutatedInClosure; |
| 10517 |
| 10518 /** |
| 10519 * Return `true` if this variable is potentially mutated somewhere in its |
| 10520 * scope. This information is only available for local variables (including |
| 10521 * parameters) and only after the compilation unit containing the variable has |
| 10522 * been resolved. |
| 10523 */ |
| 10524 bool get isPotentiallyMutatedInScope; |
| 10525 |
| 10526 /** |
| 10527 * Return `true` if this element is a static variable, as per section 8 of the |
| 10528 * Dart Language Specification: |
| 10529 * |
| 10530 * > A static variable is a variable that is not associated with a particular |
| 10531 * > instance, but rather with an entire library or class. Static variables |
| 10532 * > include library variables and class variables. Class variables are |
| 10533 * > variables whose declaration is immediately nested inside a class |
| 10534 * > declaration and includes the modifier static. A library variable is |
| 10535 * > implicitly static. |
| 10536 */ |
| 10537 bool get isStatic; |
| 10538 |
| 10539 /** |
| 10540 * Return the declared type of this variable, or `null` if the variable did |
| 10541 * not have a declared type (such as if it was declared using the keyword |
| 10542 * 'var'). |
| 10543 */ |
| 10544 DartType get type; |
| 10545 } |
| 10546 |
| 10547 /** |
| 10548 * A concrete implementation of a [VariableElement]. |
| 10549 */ |
| 10550 abstract class VariableElementImpl extends ElementImpl |
| 10551 implements VariableElement { |
| 10552 /** |
| 10553 * An empty list of variable elements. |
| 10554 */ |
| 10555 @deprecated // Use VariableElement.EMPTY_LIST |
| 10556 static const List<VariableElement> EMPTY_ARRAY = const <VariableElement>[]; |
| 10557 |
| 10558 /** |
| 10559 * The declared type of this variable. |
| 10560 */ |
| 10561 DartType type; |
| 10562 |
| 10563 /** |
| 10564 * A synthetic function representing this variable's initializer, or `null` if |
| 10565 * this variable does not have an initializer. |
| 10566 */ |
| 10567 FunctionElement _initializer; |
| 10568 |
| 10569 /** |
| 10570 * Initialize a newly created variable element to have the given [name] and |
| 10571 * [offset]. |
| 10572 */ |
| 10573 VariableElementImpl(String name, int offset) : super(name, offset); |
| 10574 |
| 10575 /** |
| 10576 * Initialize a newly created variable element to have the given [name]. |
| 10577 */ |
| 10578 VariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| 10579 |
| 10580 /** |
| 10581 * Set whether this variable is const. |
| 10582 */ |
| 10583 void set const3(bool isConst) { |
| 10584 setModifier(Modifier.CONST, isConst); |
| 10585 } |
| 10586 |
| 10587 /** |
| 10588 * Return the result of evaluating this variable's initializer as a |
| 10589 * compile-time constant expression, or `null` if this variable is not a |
| 10590 * 'const' variable, if it does not have an initializer, or if the compilation |
| 10591 * unit containing the variable has not been resolved. |
| 10592 */ |
| 10593 EvaluationResultImpl get evaluationResult => null; |
| 10594 |
| 10595 /** |
| 10596 * Set the result of evaluating this variable's initializer as a compile-time |
| 10597 * constant expression to the given [result]. |
| 10598 */ |
| 10599 void set evaluationResult(EvaluationResultImpl result) { |
| 10600 throw new IllegalStateException( |
| 10601 "Invalid attempt to set a compile-time constant result"); |
| 10602 } |
| 10603 |
| 10604 /** |
| 10605 * Set whether this variable is final. |
| 10606 */ |
| 10607 void set final2(bool isFinal) { |
| 10608 setModifier(Modifier.FINAL, isFinal); |
| 10609 } |
| 10610 |
| 10611 @override |
| 10612 bool get hasImplicitType => hasModifier(Modifier.IMPLICIT_TYPE); |
| 10613 |
| 10614 /** |
| 10615 * Set whether this variable element has an implicit type. |
| 10616 */ |
| 10617 void set hasImplicitType(bool hasImplicitType) { |
| 10618 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType); |
| 10619 } |
| 10620 |
| 10621 @override |
| 10622 FunctionElement get initializer => _initializer; |
| 10623 |
| 10624 /** |
| 10625 * Set the function representing this variable's initializer to the given |
| 10626 * [function]. |
| 10627 */ |
| 10628 void set initializer(FunctionElement function) { |
| 10629 if (function != null) { |
| 10630 (function as FunctionElementImpl).enclosingElement = this; |
| 10631 } |
| 10632 this._initializer = function; |
| 10633 } |
| 10634 |
| 10635 @override |
| 10636 bool get isConst => hasModifier(Modifier.CONST); |
| 10637 |
| 10638 @override |
| 10639 bool get isFinal => hasModifier(Modifier.FINAL); |
| 10640 |
| 10641 @override |
| 10642 bool get isPotentiallyMutatedInClosure => false; |
| 10643 |
| 10644 @override |
| 10645 bool get isPotentiallyMutatedInScope => false; |
| 10646 |
| 10647 @override |
| 10648 bool get isStatic => hasModifier(Modifier.STATIC); |
| 10649 |
| 10650 @override |
| 10651 void appendTo(StringBuffer buffer) { |
| 10652 buffer.write(type); |
| 10653 buffer.write(" "); |
| 10654 buffer.write(displayName); |
| 10655 } |
| 10656 |
| 10657 @override |
| 10658 void visitChildren(ElementVisitor visitor) { |
| 10659 super.visitChildren(visitor); |
| 10660 safelyVisitChild(_initializer, visitor); |
| 10661 } |
| 10662 } |
| 10663 |
| 10664 /** |
| 10665 * A variable element defined in a parameterized type where the values of the |
| 10666 * type parameters are known. |
| 10667 */ |
| 10668 abstract class VariableMember extends Member implements VariableElement { |
| 10669 /** |
| 10670 * Initialize a newly created element to represent a constructor, based on the |
| 10671 * [baseElement], defined by the [definingType]. |
| 10672 */ |
| 10673 VariableMember(VariableElement baseElement, ParameterizedType definingType) |
| 10674 : super(baseElement, definingType); |
| 10675 |
| 10676 @override |
| 10677 VariableElement get baseElement => super.baseElement as VariableElement; |
| 10678 |
| 10679 @override |
| 10680 bool get hasImplicitType => baseElement.hasImplicitType; |
| 10681 |
| 10682 @override |
| 10683 FunctionElement get initializer { |
| 10684 // |
| 10685 // Elements within this element should have type parameters substituted, |
| 10686 // just like this element. |
| 10687 // |
| 10688 throw new UnsupportedOperationException(); |
| 10689 // return getBaseElement().getInitializer(); |
| 10690 } |
| 10691 |
| 10692 @override |
| 10693 bool get isConst => baseElement.isConst; |
| 10694 |
| 10695 @override |
| 10696 bool get isFinal => baseElement.isFinal; |
| 10697 |
| 10698 @override |
| 10699 bool get isPotentiallyMutatedInClosure => |
| 10700 baseElement.isPotentiallyMutatedInClosure; |
| 10701 |
| 10702 @override |
| 10703 bool get isPotentiallyMutatedInScope => |
| 10704 baseElement.isPotentiallyMutatedInScope; |
| 10705 |
| 10706 @override |
| 10707 bool get isStatic => baseElement.isStatic; |
| 10708 |
| 10709 @override |
| 10710 DartType get type => substituteFor(baseElement.type); |
| 10711 |
| 10712 @override |
| 10713 void visitChildren(ElementVisitor visitor) { |
| 10714 // TODO(brianwilkerson) We need to finish implementing the accessors used |
| 10715 // below so that we can safely invoke them. |
| 10716 super.visitChildren(visitor); |
| 10717 safelyVisitChild(baseElement.initializer, visitor); |
| 10718 } |
| 10719 } |
| 10720 |
| 10721 /** |
| 10722 * The type `void`. |
| 10723 */ |
| 10724 abstract class VoidType implements DartType { |
| 10725 @override |
| 10726 VoidType substitute2( |
| 10727 List<DartType> argumentTypes, List<DartType> parameterTypes); |
| 10728 } |
| 10729 |
| 10730 /** |
| 10731 * A concrete implementation of a [VoidType]. |
| 10732 */ |
| 10733 class VoidTypeImpl extends TypeImpl implements VoidType { |
| 10734 /** |
| 10735 * The unique instance of this class. |
| 10736 */ |
| 10737 static VoidTypeImpl _INSTANCE = new VoidTypeImpl(); |
| 10738 |
| 10739 /** |
| 10740 * Return the unique instance of this class. |
| 10741 */ |
| 10742 static VoidTypeImpl get instance => _INSTANCE; |
| 10743 |
| 10744 /** |
| 10745 * Prevent the creation of instances of this class. |
| 10746 */ |
| 10747 VoidTypeImpl() : super(null, Keyword.VOID.syntax); |
| 10748 |
| 10749 @override |
| 10750 int get hashCode => 2; |
| 10751 |
| 10752 @override |
| 10753 bool get isVoid => true; |
| 10754 |
| 10755 @override |
| 10756 bool operator ==(Object object) => identical(object, this); |
| 10757 |
| 10758 @override |
| 10759 bool isMoreSpecificThan(DartType type, |
| 10760 [bool withDynamic = false, Set<Element> visitedElements]) => |
| 10761 isSubtypeOf(type); |
| 10762 |
| 10763 @override |
| 10764 bool isSubtypeOf(DartType type) { |
| 10765 // The only subtype relations that pertain to void are therefore: |
| 10766 // void <: void (by reflexivity) |
| 10767 // bottom <: void (as bottom is a subtype of all types). |
| 10768 // void <: dynamic (as dynamic is a supertype of all types) |
| 10769 return identical(type, this) || type.isDynamic; |
| 10770 } |
| 10771 |
| 10772 @override |
| 10773 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; |
| 10774 |
| 10775 @override |
| 10776 VoidTypeImpl substitute2( |
| 10777 List<DartType> argumentTypes, List<DartType> parameterTypes, |
| 10778 [List<FunctionTypeAliasElement> prune]) => |
| 10779 this; |
| 10780 } |
| 10781 |
| 10782 /** |
| 10783 * A visitor that visit all the elements recursively and fill the given [map]. |
| 10784 */ |
| 10785 class _BuildOffsetToElementMap extends GeneralizingElementVisitor { |
| 10786 final Map<int, Element> map; |
| 10787 |
| 10788 _BuildOffsetToElementMap(this.map); |
| 10789 |
| 10790 @override |
| 10791 void visitElement(Element element) { |
| 10792 int offset = element.nameOffset; |
| 10793 if (offset != -1) { |
| 10794 map[offset] = element; |
| 10795 } |
| 10796 super.visitElement(element); |
| 10797 } |
| 10798 } |
OLD | NEW |