| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.element; | |
| 6 | |
| 7 import 'dart:collection'; | |
| 8 import 'dart:math' show min; | |
| 9 | |
| 10 import 'package:analyzer/src/generated/utilities_general.dart'; | |
| 11 import 'package:analyzer/src/task/dart.dart'; | |
| 12 import 'package:analyzer/task/model.dart' | |
| 13 show AnalysisTarget, ConstantEvaluationTarget; | |
| 14 | |
| 15 import 'ast.dart'; | |
| 16 import 'constant.dart' show DartObject, EvaluationResultImpl; | |
| 17 import 'engine.dart' show AnalysisContext, AnalysisEngine, AnalysisException; | |
| 18 import 'html.dart' show XmlAttributeNode, XmlTagNode; | |
| 19 import 'java_core.dart'; | |
| 20 import 'java_engine.dart'; | |
| 21 import 'resolver.dart'; | |
| 22 import 'scanner.dart' show Keyword; | |
| 23 import 'sdk.dart' show DartSdk; | |
| 24 import 'source.dart'; | |
| 25 import 'utilities_collection.dart'; | |
| 26 import 'utilities_dart.dart'; | |
| 27 | |
| 28 /** | 5 /** |
| 29 * For AST nodes that could be in both the getter and setter contexts | 6 * This library is deprecated. Please convert all references to this library to |
| 30 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved | 7 * reference one of the following public libraries: |
| 31 * elements are stored in the AST node, in an [AuxiliaryElements]. Because | 8 * * package:analyzer/dart/element/element.dart |
| 32 * resolved elements are either statically resolved or resolved using propagated | 9 * * package:analyzer/dart/element/type.dart |
| 33 * type information, this class is a wrapper for a pair of [ExecutableElement]s, | 10 * * package:analyzer/dart/element/visitor.dart |
| 34 * not just a single [ExecutableElement]. | |
| 35 */ | |
| 36 class AuxiliaryElements { | |
| 37 /** | |
| 38 * The element based on propagated type information, or `null` if the AST | |
| 39 * structure has not been resolved or if the node could not be resolved. | |
| 40 */ | |
| 41 final ExecutableElement propagatedElement; | |
| 42 | |
| 43 /** | |
| 44 * The element based on static type information, or `null` if the AST | |
| 45 * structure has not been resolved or if the node could not be resolved. | |
| 46 */ | |
| 47 final ExecutableElement staticElement; | |
| 48 | |
| 49 /** | |
| 50 * Initialize a newly created pair to have both the [staticElement] and the | |
| 51 * [propagatedElement]. | |
| 52 */ | |
| 53 AuxiliaryElements(this.staticElement, this.propagatedElement); | |
| 54 } | |
| 55 | |
| 56 /** | |
| 57 * A [Type] that represents the type 'bottom'. | |
| 58 */ | |
| 59 class BottomTypeImpl extends TypeImpl { | |
| 60 /** | |
| 61 * The unique instance of this class. | |
| 62 */ | |
| 63 static BottomTypeImpl _INSTANCE = new BottomTypeImpl._(); | |
| 64 | |
| 65 /** | |
| 66 * Return the unique instance of this class. | |
| 67 */ | |
| 68 static BottomTypeImpl get instance => _INSTANCE; | |
| 69 | |
| 70 /** | |
| 71 * Prevent the creation of instances of this class. | |
| 72 */ | |
| 73 BottomTypeImpl._() : super(null, "<bottom>"); | |
| 74 | |
| 75 @override | |
| 76 int get hashCode => 0; | |
| 77 | |
| 78 @override | |
| 79 bool get isBottom => true; | |
| 80 | |
| 81 @override | |
| 82 bool operator ==(Object object) => identical(object, this); | |
| 83 | |
| 84 @override | |
| 85 bool isMoreSpecificThan(DartType type, | |
| 86 [bool withDynamic = false, Set<Element> visitedElements]) => | |
| 87 true; | |
| 88 | |
| 89 @override | |
| 90 bool isSubtypeOf(DartType type) => true; | |
| 91 | |
| 92 @override | |
| 93 bool isSupertypeOf(DartType type) => false; | |
| 94 | |
| 95 @override | |
| 96 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 97 | |
| 98 @override | |
| 99 BottomTypeImpl substitute2( | |
| 100 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 101 [List<FunctionTypeAliasElement> prune]) => | |
| 102 this; | |
| 103 } | |
| 104 | |
| 105 /** | |
| 106 * Type created internally if a circular reference is ever detected. Behaves | |
| 107 * like `dynamic`, except that when converted to a string it is displayed as | |
| 108 * `...`. | |
| 109 */ | |
| 110 class CircularTypeImpl extends DynamicTypeImpl { | |
| 111 CircularTypeImpl() : super._circular(); | |
| 112 | |
| 113 @override | |
| 114 int get hashCode => 1; | |
| 115 | |
| 116 @override | |
| 117 bool operator ==(Object object) => object is CircularTypeImpl; | |
| 118 | |
| 119 @override | |
| 120 void appendTo(StringBuffer buffer) { | |
| 121 buffer.write('...'); | |
| 122 } | |
| 123 | |
| 124 @override | |
| 125 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 126 } | |
| 127 | |
| 128 /** | |
| 129 * An element that represents a class. | |
| 130 */ | |
| 131 abstract class ClassElement implements TypeDefiningElement { | |
| 132 /** | |
| 133 * An empty list of class elements. | |
| 134 */ | |
| 135 static const List<ClassElement> EMPTY_LIST = const <ClassElement>[]; | |
| 136 | |
| 137 /** | |
| 138 * Return a list containing all of the accessors (getters and setters) | |
| 139 * declared in this class. | |
| 140 */ | |
| 141 List<PropertyAccessorElement> get accessors; | |
| 142 | |
| 143 /** | |
| 144 * Return a list containing all the supertypes defined for this class and its | |
| 145 * supertypes. This includes superclasses, mixins and interfaces. | |
| 146 */ | |
| 147 List<InterfaceType> get allSupertypes; | |
| 148 | |
| 149 /** | |
| 150 * Return a list containing all of the constructors declared in this class. | |
| 151 */ | |
| 152 List<ConstructorElement> get constructors; | |
| 153 | |
| 154 /** | |
| 155 * Return a list containing all of the fields declared in this class. | |
| 156 */ | |
| 157 List<FieldElement> get fields; | |
| 158 | |
| 159 /** | |
| 160 * Return `true` if this class or its superclass declares a non-final instance | |
| 161 * field. | |
| 162 */ | |
| 163 bool get hasNonFinalField; | |
| 164 | |
| 165 /** | |
| 166 * Return `true` if this class has reference to super (so, for example, cannot | |
| 167 * be used as a mixin). | |
| 168 */ | |
| 169 bool get hasReferenceToSuper; | |
| 170 | |
| 171 /** | |
| 172 * Return `true` if this class declares a static member. | |
| 173 */ | |
| 174 bool get hasStaticMember; | |
| 175 | |
| 176 /** | |
| 177 * Return a list containing all of the interfaces that are implemented by this | |
| 178 * class. | |
| 179 * | |
| 180 * <b>Note:</b> Because the element model represents the state of the code, it | |
| 181 * is possible for it to be semantically invalid. In particular, it is not | |
| 182 * safe to assume that the inheritance structure of a class does not contain a | |
| 183 * cycle. Clients that traverse the inheritance structure must explicitly | |
| 184 * guard against infinite loops. | |
| 185 */ | |
| 186 List<InterfaceType> get interfaces; | |
| 187 | |
| 188 /** | |
| 189 * Return `true` if this class is abstract. A class is abstract if it has an | |
| 190 * explicit `abstract` modifier. Note, that this definition of <i>abstract</i> | |
| 191 * is different from <i>has unimplemented members</i>. | |
| 192 */ | |
| 193 bool get isAbstract; | |
| 194 | |
| 195 /** | |
| 196 * Return `true` if this class is defined by an enum declaration. | |
| 197 */ | |
| 198 bool get isEnum; | |
| 199 | |
| 200 /** | |
| 201 * Return `true` if this class is a mixin application. A class is a mixin | |
| 202 * application if it was declared using the syntax "class A = B with C;". | |
| 203 */ | |
| 204 bool get isMixinApplication; | |
| 205 | |
| 206 /** | |
| 207 * Return `true` if this class [isProxy], or if it inherits the proxy | |
| 208 * annotation from a supertype. | |
| 209 */ | |
| 210 bool get isOrInheritsProxy; | |
| 211 | |
| 212 /** | |
| 213 * Return `true` if this element has an annotation of the form '@proxy'. | |
| 214 */ | |
| 215 bool get isProxy; | |
| 216 | |
| 217 /** | |
| 218 * Return `true` if this class is a mixin application. Deprecated--please | |
| 219 * use [isMixinApplication] instead. | |
| 220 */ | |
| 221 @deprecated | |
| 222 bool get isTypedef; | |
| 223 | |
| 224 /** | |
| 225 * Return `true` if this class can validly be used as a mixin when defining | |
| 226 * another class. The behavior of this method is defined by the Dart Language | |
| 227 * Specification in section 9: | |
| 228 * <blockquote> | |
| 229 * It is a compile-time error if a declared or derived mixin refers to super. | |
| 230 * It is a compile-time error if a declared or derived mixin explicitly | |
| 231 * declares a constructor. It is a compile-time error if a mixin is derived | |
| 232 * from a class whose superclass is not Object. | |
| 233 * </blockquote> | |
| 234 */ | |
| 235 bool get isValidMixin; | |
| 236 | |
| 237 /** | |
| 238 * Return a list containing all of the methods declared in this class. | |
| 239 */ | |
| 240 List<MethodElement> get methods; | |
| 241 | |
| 242 /** | |
| 243 * Return a list containing all of the mixins that are applied to the class | |
| 244 * being extended in order to derive the superclass of this class. | |
| 245 * | |
| 246 * <b>Note:</b> Because the element model represents the state of the code, it | |
| 247 * is possible for it to be semantically invalid. In particular, it is not | |
| 248 * safe to assume that the inheritance structure of a class does not contain a | |
| 249 * cycle. Clients that traverse the inheritance structure must explicitly | |
| 250 * guard against infinite loops. | |
| 251 */ | |
| 252 List<InterfaceType> get mixins; | |
| 253 | |
| 254 /** | |
| 255 * Return the superclass of this class, or `null` if the class represents the | |
| 256 * class 'Object'. All other classes will have a non-`null` superclass. If the | |
| 257 * superclass was not explicitly declared then the implicit superclass | |
| 258 * 'Object' will be returned. | |
| 259 * | |
| 260 * <b>Note:</b> Because the element model represents the state of the code, it | |
| 261 * is possible for it to be semantically invalid. In particular, it is not | |
| 262 * safe to assume that the inheritance structure of a class does not contain a | |
| 263 * cycle. Clients that traverse the inheritance structure must explicitly | |
| 264 * guard against infinite loops. | |
| 265 */ | |
| 266 InterfaceType get supertype; | |
| 267 | |
| 268 @override | |
| 269 InterfaceType get type; | |
| 270 | |
| 271 /** | |
| 272 * Return a list containing all of the type parameters declared for this | |
| 273 * class. | |
| 274 */ | |
| 275 List<TypeParameterElement> get typeParameters; | |
| 276 | |
| 277 /** | |
| 278 * Return the unnamed constructor declared in this class, or `null` if this | |
| 279 * class does not declare an unnamed constructor but does declare named | |
| 280 * constructors. The returned constructor will be synthetic if this class does | |
| 281 * not declare any constructors, in which case it will represent the default | |
| 282 * constructor for the class. | |
| 283 */ | |
| 284 ConstructorElement get unnamedConstructor; | |
| 285 | |
| 286 /** | |
| 287 * Return the resolved [ClassDeclaration] or [EnumDeclaration] node that | |
| 288 * declares this [ClassElement]. | |
| 289 * | |
| 290 * This method is expensive, because resolved AST might be evicted from cache, | |
| 291 * so parsing and resolving will be performed. | |
| 292 */ | |
| 293 @override | |
| 294 NamedCompilationUnitMember computeNode(); | |
| 295 | |
| 296 /** | |
| 297 * Return the field (synthetic or explicit) defined in this class that has the | |
| 298 * given [name], or `null` if this class does not define a field with the | |
| 299 * given name. | |
| 300 */ | |
| 301 FieldElement getField(String name); | |
| 302 | |
| 303 /** | |
| 304 * Return the element representing the getter with the given [name] that is | |
| 305 * declared in this class, or `null` if this class does not declare a getter | |
| 306 * with the given name. | |
| 307 */ | |
| 308 PropertyAccessorElement getGetter(String name); | |
| 309 | |
| 310 /** | |
| 311 * Return the element representing the method with the given [name] that is | |
| 312 * declared in this class, or `null` if this class does not declare a method | |
| 313 * with the given name. | |
| 314 */ | |
| 315 MethodElement getMethod(String name); | |
| 316 | |
| 317 /** | |
| 318 * Return the named constructor declared in this class with the given [name], | |
| 319 * or `null` if this class does not declare a named constructor with the given | |
| 320 * name. | |
| 321 */ | |
| 322 ConstructorElement getNamedConstructor(String name); | |
| 323 | |
| 324 /** | |
| 325 * Return the element representing the setter with the given [name] that is | |
| 326 * declared in this class, or `null` if this class does not declare a setter | |
| 327 * with the given name. | |
| 328 */ | |
| 329 PropertyAccessorElement getSetter(String name); | |
| 330 | |
| 331 /** | |
| 332 * Determine whether the given [constructor], which exists in the superclass | |
| 333 * of this class, is accessible to constructors in this class. | |
| 334 */ | |
| 335 bool isSuperConstructorAccessible(ConstructorElement constructor); | |
| 336 | |
| 337 /** | |
| 338 * Return the element representing the method that results from looking up the | |
| 339 * given [methodName] in this class with respect to the given [library], | |
| 340 * ignoring abstract methods, or `null` if the look up fails. The behavior of | |
| 341 * this method is defined by the Dart Language Specification in section | |
| 342 * 16.15.1: | |
| 343 * <blockquote> | |
| 344 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 345 * library <i>L</i> is: If <i>C</i> declares an instance method named <i>m</i> | |
| 346 * that is accessible to <i>L</i>, then that method is the result of the | |
| 347 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result | |
| 348 * of the lookup is the result of looking up method <i>m</i> in <i>S</i> with | |
| 349 * respect to <i>L</i>. Otherwise, we say that the lookup has failed. | |
| 350 * </blockquote> | |
| 351 */ | |
| 352 MethodElement lookUpConcreteMethod(String methodName, LibraryElement library); | |
| 353 | |
| 354 /** | |
| 355 * Return the element representing the getter that results from looking up the | |
| 356 * given [getterName] in this class with respect to the given [library], or | |
| 357 * `null` if the look up fails. The behavior of this method is defined by the | |
| 358 * Dart Language Specification in section 16.15.2: | |
| 359 * <blockquote> | |
| 360 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 361 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an | |
| 362 * instance getter (respectively setter) named <i>m</i> that is accessible to | |
| 363 * <i>L</i>, then that getter (respectively setter) is the result of the | |
| 364 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result | |
| 365 * of the lookup is the result of looking up getter (respectively setter) | |
| 366 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the | |
| 367 * lookup has failed. | |
| 368 * </blockquote> | |
| 369 */ | |
| 370 PropertyAccessorElement lookUpGetter( | |
| 371 String getterName, LibraryElement library); | |
| 372 | |
| 373 /** | |
| 374 * Return the element representing the getter that results from looking up the | |
| 375 * given [getterName] in the superclass of this class with respect to the | |
| 376 * given [library], ignoring abstract getters, or `null` if the look up fails. | |
| 377 * The behavior of this method is defined by the Dart Language Specification | |
| 378 * in section 16.15.2: | |
| 379 * <blockquote> | |
| 380 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 381 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an | |
| 382 * instance getter (respectively setter) named <i>m</i> that is accessible to | |
| 383 * <i>L</i>, then that getter (respectively setter) is the result of the | |
| 384 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result | |
| 385 * of the lookup is the result of looking up getter (respectively setter) | |
| 386 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the | |
| 387 * lookup has failed. | |
| 388 * </blockquote> | |
| 389 */ | |
| 390 PropertyAccessorElement lookUpInheritedConcreteGetter( | |
| 391 String getterName, LibraryElement library); | |
| 392 | |
| 393 /** | |
| 394 * Return the element representing the method that results from looking up the | |
| 395 * given [methodName] in the superclass of this class with respect to the | |
| 396 * given [library], ignoring abstract methods, or `null` if the look up fails. | |
| 397 * The behavior of this method is defined by the Dart Language Specification | |
| 398 * in section 16.15.1: | |
| 399 * <blockquote> | |
| 400 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 401 * library <i>L</i> is: If <i>C</i> declares an instance method named | |
| 402 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of | |
| 403 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the | |
| 404 * result of the lookup is the result of looking up method <i>m</i> in | |
| 405 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has | |
| 406 * failed. | |
| 407 * </blockquote> | |
| 408 */ | |
| 409 MethodElement lookUpInheritedConcreteMethod( | |
| 410 String methodName, LibraryElement library); | |
| 411 | |
| 412 /** | |
| 413 * Return the element representing the setter that results from looking up the | |
| 414 * given [setterName] in the superclass of this class with respect to the | |
| 415 * given [library], ignoring abstract setters, or `null` if the look up fails. | |
| 416 * The behavior of this method is defined by the Dart Language Specification | |
| 417 * in section 16.15.2: | |
| 418 * <blockquote> | |
| 419 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 420 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an | |
| 421 * instance getter (respectively setter) named <i>m</i> that is accessible to | |
| 422 * <i>L</i>, then that getter (respectively setter) is the result of the | |
| 423 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result | |
| 424 * of the lookup is the result of looking up getter (respectively setter) | |
| 425 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the | |
| 426 * lookup has failed. | |
| 427 * </blockquote> | |
| 428 */ | |
| 429 PropertyAccessorElement lookUpInheritedConcreteSetter( | |
| 430 String setterName, LibraryElement library); | |
| 431 | |
| 432 /** | |
| 433 * Return the element representing the method that results from looking up the | |
| 434 * given [methodName] in the superclass of this class with respect to the | |
| 435 * given [library], or `null` if the look up fails. The behavior of this | |
| 436 * method is defined by the Dart Language Specification in section 16.15.1: | |
| 437 * <blockquote> | |
| 438 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 439 * library <i>L</i> is: If <i>C</i> declares an instance method named | |
| 440 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of | |
| 441 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the | |
| 442 * result of the lookup is the result of looking up method <i>m</i> in | |
| 443 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has | |
| 444 * failed. | |
| 445 * </blockquote> | |
| 446 */ | |
| 447 MethodElement lookUpInheritedMethod( | |
| 448 String methodName, LibraryElement library); | |
| 449 | |
| 450 /** | |
| 451 * Return the element representing the method that results from looking up the | |
| 452 * given [methodName] in this class with respect to the given [library], or | |
| 453 * `null` if the look up fails. The behavior of this method is defined by the | |
| 454 * Dart Language Specification in section 16.15.1: | |
| 455 * <blockquote> | |
| 456 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 457 * library <i>L</i> is: If <i>C</i> declares an instance method named | |
| 458 * <i>m</i> that is accessible to <i>L</i>, then that method is the result of | |
| 459 * the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the | |
| 460 * result of the lookup is the result of looking up method <i>m</i> in | |
| 461 * <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has | |
| 462 * failed. | |
| 463 * </blockquote> | |
| 464 */ | |
| 465 MethodElement lookUpMethod(String methodName, LibraryElement library); | |
| 466 | |
| 467 /** | |
| 468 * Return the element representing the setter that results from looking up the | |
| 469 * given [setterName] in this class with respect to the given [library], or | |
| 470 * `null` if the look up fails. The behavior of this method is defined by the | |
| 471 * Dart Language Specification in section 16.15.2: | |
| 472 * <blockquote> | |
| 473 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 474 * <i>C</i> with respect to library <i>L</i> is: If <i>C</i> declares an | |
| 475 * instance getter (respectively setter) named <i>m</i> that is accessible to | |
| 476 * <i>L</i>, then that getter (respectively setter) is the result of the | |
| 477 * lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result | |
| 478 * of the lookup is the result of looking up getter (respectively setter) | |
| 479 * <i>m</i> in <i>S</i> with respect to <i>L</i>. Otherwise, we say that the | |
| 480 * lookup has failed. | |
| 481 * </blockquote> | |
| 482 */ | |
| 483 PropertyAccessorElement lookUpSetter( | |
| 484 String setterName, LibraryElement library); | |
| 485 } | |
| 486 | |
| 487 /** | |
| 488 * A concrete implementation of a [ClassElement]. | |
| 489 */ | |
| 490 class ClassElementImpl extends ElementImpl implements ClassElement { | |
| 491 /** | |
| 492 * An empty list of class elements. | |
| 493 */ | |
| 494 @deprecated // Use ClassElement.EMPTY_LIST | |
| 495 static const List<ClassElement> EMPTY_ARRAY = const <ClassElement>[]; | |
| 496 | |
| 497 /** | |
| 498 * A list containing all of the accessors (getters and setters) contained in | |
| 499 * this class. | |
| 500 */ | |
| 501 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; | |
| 502 | |
| 503 /** | |
| 504 * For classes which are not mixin applications, a list containing all of the | |
| 505 * constructors contained in this class, or `null` if the list of | |
| 506 * constructors has not yet been built. | |
| 507 * | |
| 508 * For classes which are mixin applications, the list of constructors is | |
| 509 * computed on the fly by the [constructors] getter, and this field is | |
| 510 * `null`. | |
| 511 */ | |
| 512 List<ConstructorElement> _constructors; | |
| 513 | |
| 514 /** | |
| 515 * A list containing all of the fields contained in this class. | |
| 516 */ | |
| 517 List<FieldElement> _fields = FieldElement.EMPTY_LIST; | |
| 518 | |
| 519 /** | |
| 520 * A list containing all of the mixins that are applied to the class being | |
| 521 * extended in order to derive the superclass of this class. | |
| 522 */ | |
| 523 List<InterfaceType> mixins = InterfaceType.EMPTY_LIST; | |
| 524 | |
| 525 /** | |
| 526 * A list containing all of the interfaces that are implemented by this class. | |
| 527 */ | |
| 528 List<InterfaceType> interfaces = InterfaceType.EMPTY_LIST; | |
| 529 | |
| 530 /** | |
| 531 * A list containing all of the methods contained in this class. | |
| 532 */ | |
| 533 List<MethodElement> _methods = MethodElement.EMPTY_LIST; | |
| 534 | |
| 535 /** | |
| 536 * The superclass of the class, or `null` if the class does not have an | |
| 537 * explicit superclass. | |
| 538 */ | |
| 539 InterfaceType supertype; | |
| 540 | |
| 541 /** | |
| 542 * The type defined by the class. | |
| 543 */ | |
| 544 InterfaceType type; | |
| 545 | |
| 546 /** | |
| 547 * A list containing all of the type parameters defined for this class. | |
| 548 */ | |
| 549 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 550 | |
| 551 /** | |
| 552 * The [SourceRange] of the `with` clause, `null` if there is no one. | |
| 553 */ | |
| 554 SourceRange withClauseRange; | |
| 555 | |
| 556 /** | |
| 557 * A flag indicating whether the types associated with the instance members of | |
| 558 * this class have been inferred. | |
| 559 */ | |
| 560 bool hasBeenInferred = false; | |
| 561 | |
| 562 /** | |
| 563 * Initialize a newly created class element to have the given [name] at the | |
| 564 * given [offset] in the file that contains the declaration of this element. | |
| 565 */ | |
| 566 ClassElementImpl(String name, int offset) : super(name, offset); | |
| 567 | |
| 568 /** | |
| 569 * Initialize a newly created class element to have the given [name]. | |
| 570 */ | |
| 571 ClassElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 572 | |
| 573 /** | |
| 574 * Set whether this class is abstract. | |
| 575 */ | |
| 576 void set abstract(bool isAbstract) { | |
| 577 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 578 } | |
| 579 | |
| 580 @override | |
| 581 List<PropertyAccessorElement> get accessors => _accessors; | |
| 582 | |
| 583 /** | |
| 584 * Set the accessors contained in this class to the given [accessors]. | |
| 585 */ | |
| 586 void set accessors(List<PropertyAccessorElement> accessors) { | |
| 587 for (PropertyAccessorElement accessor in accessors) { | |
| 588 (accessor as PropertyAccessorElementImpl).enclosingElement = this; | |
| 589 } | |
| 590 this._accessors = accessors; | |
| 591 } | |
| 592 | |
| 593 @override | |
| 594 List<InterfaceType> get allSupertypes { | |
| 595 List<InterfaceType> list = new List<InterfaceType>(); | |
| 596 _collectAllSupertypes(list); | |
| 597 return list; | |
| 598 } | |
| 599 | |
| 600 @override | |
| 601 List<ConstructorElement> get constructors { | |
| 602 if (!isMixinApplication) { | |
| 603 assert(_constructors != null); | |
| 604 return _constructors == null | |
| 605 ? ConstructorElement.EMPTY_LIST | |
| 606 : _constructors; | |
| 607 } | |
| 608 | |
| 609 return _computeMixinAppConstructors(); | |
| 610 } | |
| 611 | |
| 612 /** | |
| 613 * Set the constructors contained in this class to the given [constructors]. | |
| 614 * | |
| 615 * Should only be used for class elements that are not mixin applications. | |
| 616 */ | |
| 617 void set constructors(List<ConstructorElement> constructors) { | |
| 618 assert(!isMixinApplication); | |
| 619 for (ConstructorElement constructor in constructors) { | |
| 620 (constructor as ConstructorElementImpl).enclosingElement = this; | |
| 621 } | |
| 622 this._constructors = constructors; | |
| 623 } | |
| 624 | |
| 625 /** | |
| 626 * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should | |
| 627 * be reported for this class. | |
| 628 */ | |
| 629 bool get doesMixinLackConstructors { | |
| 630 if (!isMixinApplication && mixins.isEmpty) { | |
| 631 // This class is not a mixin application and it doesn't have a "with" | |
| 632 // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is | |
| 633 // inapplicable. | |
| 634 return false; | |
| 635 } | |
| 636 if (supertype == null) { | |
| 637 // Should never happen, since Object is the only class that has no | |
| 638 // supertype, and it should have been caught by the test above. | |
| 639 assert(false); | |
| 640 return false; | |
| 641 } | |
| 642 // Find the nearest class in the supertype chain that is not a mixin | |
| 643 // application. | |
| 644 ClassElement nearestNonMixinClass = supertype.element; | |
| 645 if (nearestNonMixinClass.isMixinApplication) { | |
| 646 // Use a list to keep track of the classes we've seen, so that we won't | |
| 647 // go into an infinite loop in the event of a non-trivial loop in the | |
| 648 // class hierarchy. | |
| 649 List<ClassElementImpl> classesSeen = <ClassElementImpl>[this]; | |
| 650 while (nearestNonMixinClass.isMixinApplication) { | |
| 651 if (classesSeen.contains(nearestNonMixinClass)) { | |
| 652 // Loop in the class hierarchy (which is reported elsewhere). Don't | |
| 653 // confuse the user with further errors. | |
| 654 return false; | |
| 655 } | |
| 656 classesSeen.add(nearestNonMixinClass); | |
| 657 if (nearestNonMixinClass.supertype == null) { | |
| 658 // Should never happen, since Object is the only class that has no | |
| 659 // supertype, and it is not a mixin application. | |
| 660 assert(false); | |
| 661 return false; | |
| 662 } | |
| 663 nearestNonMixinClass = nearestNonMixinClass.supertype.element; | |
| 664 } | |
| 665 } | |
| 666 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); | |
| 667 } | |
| 668 | |
| 669 /** | |
| 670 * Set whether this class is defined by an enum declaration. | |
| 671 */ | |
| 672 void set enum2(bool isEnum) { | |
| 673 setModifier(Modifier.ENUM, isEnum); | |
| 674 } | |
| 675 | |
| 676 @override | |
| 677 List<FieldElement> get fields => _fields; | |
| 678 | |
| 679 /** | |
| 680 * Set the fields contained in this class to the given [fields]. | |
| 681 */ | |
| 682 void set fields(List<FieldElement> fields) { | |
| 683 for (FieldElement field in fields) { | |
| 684 (field as FieldElementImpl).enclosingElement = this; | |
| 685 } | |
| 686 this._fields = fields; | |
| 687 } | |
| 688 | |
| 689 @override | |
| 690 bool get hasNonFinalField { | |
| 691 List<ClassElement> classesToVisit = new List<ClassElement>(); | |
| 692 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 693 classesToVisit.add(this); | |
| 694 while (!classesToVisit.isEmpty) { | |
| 695 ClassElement currentElement = classesToVisit.removeAt(0); | |
| 696 if (visitedClasses.add(currentElement)) { | |
| 697 // check fields | |
| 698 for (FieldElement field in currentElement.fields) { | |
| 699 if (!field.isFinal && | |
| 700 !field.isConst && | |
| 701 !field.isStatic && | |
| 702 !field.isSynthetic) { | |
| 703 return true; | |
| 704 } | |
| 705 } | |
| 706 // check mixins | |
| 707 for (InterfaceType mixinType in currentElement.mixins) { | |
| 708 ClassElement mixinElement = mixinType.element; | |
| 709 classesToVisit.add(mixinElement); | |
| 710 } | |
| 711 // check super | |
| 712 InterfaceType supertype = currentElement.supertype; | |
| 713 if (supertype != null) { | |
| 714 ClassElement superElement = supertype.element; | |
| 715 if (superElement != null) { | |
| 716 classesToVisit.add(superElement); | |
| 717 } | |
| 718 } | |
| 719 } | |
| 720 } | |
| 721 // not found | |
| 722 return false; | |
| 723 } | |
| 724 | |
| 725 @override | |
| 726 bool get hasReferenceToSuper => hasModifier(Modifier.REFERENCES_SUPER); | |
| 727 | |
| 728 /** | |
| 729 * Set whether this class references 'super'. | |
| 730 */ | |
| 731 void set hasReferenceToSuper(bool isReferencedSuper) { | |
| 732 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); | |
| 733 } | |
| 734 | |
| 735 @override | |
| 736 bool get hasStaticMember { | |
| 737 for (MethodElement method in _methods) { | |
| 738 if (method.isStatic) { | |
| 739 return true; | |
| 740 } | |
| 741 } | |
| 742 for (PropertyAccessorElement accessor in _accessors) { | |
| 743 if (accessor.isStatic) { | |
| 744 return true; | |
| 745 } | |
| 746 } | |
| 747 return false; | |
| 748 } | |
| 749 | |
| 750 @override | |
| 751 bool get isAbstract => hasModifier(Modifier.ABSTRACT); | |
| 752 | |
| 753 @override | |
| 754 bool get isEnum => hasModifier(Modifier.ENUM); | |
| 755 | |
| 756 @override | |
| 757 bool get isMixinApplication => hasModifier(Modifier.MIXIN_APPLICATION); | |
| 758 | |
| 759 @override | |
| 760 bool get isOrInheritsProxy => | |
| 761 _safeIsOrInheritsProxy(this, new HashSet<ClassElement>()); | |
| 762 | |
| 763 @override | |
| 764 bool get isProxy { | |
| 765 for (ElementAnnotation annotation in metadata) { | |
| 766 if (annotation.isProxy) { | |
| 767 return true; | |
| 768 } | |
| 769 } | |
| 770 return false; | |
| 771 } | |
| 772 | |
| 773 @override | |
| 774 @deprecated | |
| 775 bool get isTypedef => isMixinApplication; | |
| 776 | |
| 777 @override | |
| 778 bool get isValidMixin => hasModifier(Modifier.MIXIN); | |
| 779 | |
| 780 @override | |
| 781 ElementKind get kind => ElementKind.CLASS; | |
| 782 | |
| 783 @override | |
| 784 List<MethodElement> get methods => _methods; | |
| 785 | |
| 786 /** | |
| 787 * Set the methods contained in this class to the given [methods]. | |
| 788 */ | |
| 789 void set methods(List<MethodElement> methods) { | |
| 790 for (MethodElement method in methods) { | |
| 791 (method as MethodElementImpl).enclosingElement = this; | |
| 792 } | |
| 793 this._methods = methods; | |
| 794 } | |
| 795 | |
| 796 /** | |
| 797 * Set whether this class is a mixin application. | |
| 798 */ | |
| 799 void set mixinApplication(bool isMixinApplication) { | |
| 800 setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); | |
| 801 } | |
| 802 | |
| 803 @override | |
| 804 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 805 | |
| 806 /** | |
| 807 * Set the type parameters defined for this class to the given | |
| 808 * [typeParameters]. | |
| 809 */ | |
| 810 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 811 for (TypeParameterElement typeParameter in typeParameters) { | |
| 812 (typeParameter as TypeParameterElementImpl).enclosingElement = this; | |
| 813 } | |
| 814 this._typeParameters = typeParameters; | |
| 815 } | |
| 816 | |
| 817 @override | |
| 818 ConstructorElement get unnamedConstructor { | |
| 819 for (ConstructorElement element in constructors) { | |
| 820 String name = element.displayName; | |
| 821 if (name == null || name.isEmpty) { | |
| 822 return element; | |
| 823 } | |
| 824 } | |
| 825 return null; | |
| 826 } | |
| 827 | |
| 828 /** | |
| 829 * Set whether this class is a valid mixin. | |
| 830 */ | |
| 831 void set validMixin(bool isValidMixin) { | |
| 832 setModifier(Modifier.MIXIN, isValidMixin); | |
| 833 } | |
| 834 | |
| 835 @override | |
| 836 accept(ElementVisitor visitor) => visitor.visitClassElement(this); | |
| 837 | |
| 838 @override | |
| 839 void appendTo(StringBuffer buffer) { | |
| 840 String name = displayName; | |
| 841 if (name == null) { | |
| 842 buffer.write("{unnamed class}"); | |
| 843 } else { | |
| 844 buffer.write(name); | |
| 845 } | |
| 846 int variableCount = _typeParameters.length; | |
| 847 if (variableCount > 0) { | |
| 848 buffer.write("<"); | |
| 849 for (int i = 0; i < variableCount; i++) { | |
| 850 if (i > 0) { | |
| 851 buffer.write(", "); | |
| 852 } | |
| 853 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 854 } | |
| 855 buffer.write(">"); | |
| 856 } | |
| 857 } | |
| 858 | |
| 859 @override | |
| 860 NamedCompilationUnitMember computeNode() { | |
| 861 if (isEnum) { | |
| 862 return getNodeMatching((node) => node is EnumDeclaration); | |
| 863 } else { | |
| 864 return getNodeMatching( | |
| 865 (node) => node is ClassDeclaration || node is ClassTypeAlias); | |
| 866 } | |
| 867 } | |
| 868 | |
| 869 @override | |
| 870 ElementImpl getChild(String identifier) { | |
| 871 // | |
| 872 // The casts in this method are safe because the set methods would have | |
| 873 // thrown a CCE if any of the elements in the arrays were not of the | |
| 874 // expected types. | |
| 875 // | |
| 876 for (PropertyAccessorElement accessor in _accessors) { | |
| 877 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { | |
| 878 return accessor as PropertyAccessorElementImpl; | |
| 879 } | |
| 880 } | |
| 881 for (ConstructorElement constructor in _constructors) { | |
| 882 if ((constructor as ConstructorElementImpl).identifier == identifier) { | |
| 883 return constructor as ConstructorElementImpl; | |
| 884 } | |
| 885 } | |
| 886 for (FieldElement field in _fields) { | |
| 887 if ((field as FieldElementImpl).identifier == identifier) { | |
| 888 return field as FieldElementImpl; | |
| 889 } | |
| 890 } | |
| 891 for (MethodElement method in _methods) { | |
| 892 if ((method as MethodElementImpl).identifier == identifier) { | |
| 893 return method as MethodElementImpl; | |
| 894 } | |
| 895 } | |
| 896 for (TypeParameterElement typeParameter in _typeParameters) { | |
| 897 if ((typeParameter as TypeParameterElementImpl).identifier == | |
| 898 identifier) { | |
| 899 return typeParameter as TypeParameterElementImpl; | |
| 900 } | |
| 901 } | |
| 902 return null; | |
| 903 } | |
| 904 | |
| 905 @override | |
| 906 FieldElement getField(String name) { | |
| 907 for (FieldElement fieldElement in _fields) { | |
| 908 if (name == fieldElement.name) { | |
| 909 return fieldElement; | |
| 910 } | |
| 911 } | |
| 912 return null; | |
| 913 } | |
| 914 | |
| 915 @override | |
| 916 PropertyAccessorElement getGetter(String getterName) { | |
| 917 for (PropertyAccessorElement accessor in _accessors) { | |
| 918 if (accessor.isGetter && accessor.name == getterName) { | |
| 919 return accessor; | |
| 920 } | |
| 921 } | |
| 922 return null; | |
| 923 } | |
| 924 | |
| 925 @override | |
| 926 MethodElement getMethod(String methodName) { | |
| 927 for (MethodElement method in _methods) { | |
| 928 if (method.name == methodName) { | |
| 929 return method; | |
| 930 } | |
| 931 } | |
| 932 return null; | |
| 933 } | |
| 934 | |
| 935 @override | |
| 936 ConstructorElement getNamedConstructor(String name) { | |
| 937 for (ConstructorElement element in constructors) { | |
| 938 String elementName = element.name; | |
| 939 if (elementName != null && elementName == name) { | |
| 940 return element; | |
| 941 } | |
| 942 } | |
| 943 return null; | |
| 944 } | |
| 945 | |
| 946 @override | |
| 947 PropertyAccessorElement getSetter(String setterName) { | |
| 948 // TODO (jwren) revisit- should we append '=' here or require clients to | |
| 949 // include it? | |
| 950 // Do we need the check for isSetter below? | |
| 951 if (!StringUtilities.endsWithChar(setterName, 0x3D)) { | |
| 952 setterName += '='; | |
| 953 } | |
| 954 for (PropertyAccessorElement accessor in _accessors) { | |
| 955 if (accessor.isSetter && accessor.name == setterName) { | |
| 956 return accessor; | |
| 957 } | |
| 958 } | |
| 959 return null; | |
| 960 } | |
| 961 | |
| 962 @override | |
| 963 bool isSuperConstructorAccessible(ConstructorElement constructor) { | |
| 964 // If this class has no mixins, then all superclass constructors are | |
| 965 // accessible. | |
| 966 if (mixins.isEmpty) { | |
| 967 return true; | |
| 968 } | |
| 969 // Otherwise only constructors that lack optional parameters are | |
| 970 // accessible (see dartbug.com/19576). | |
| 971 for (ParameterElement parameter in constructor.parameters) { | |
| 972 if (parameter.parameterKind != ParameterKind.REQUIRED) { | |
| 973 return false; | |
| 974 } | |
| 975 } | |
| 976 return true; | |
| 977 } | |
| 978 | |
| 979 @override | |
| 980 MethodElement lookUpConcreteMethod( | |
| 981 String methodName, LibraryElement library) => | |
| 982 _internalLookUpConcreteMethod(methodName, library, true); | |
| 983 | |
| 984 @override | |
| 985 PropertyAccessorElement lookUpGetter( | |
| 986 String getterName, LibraryElement library) => | |
| 987 _internalLookUpGetter(getterName, library, true); | |
| 988 | |
| 989 @override | |
| 990 PropertyAccessorElement lookUpInheritedConcreteGetter( | |
| 991 String getterName, LibraryElement library) => | |
| 992 _internalLookUpConcreteGetter(getterName, library, false); | |
| 993 | |
| 994 @override | |
| 995 MethodElement lookUpInheritedConcreteMethod( | |
| 996 String methodName, LibraryElement library) => | |
| 997 _internalLookUpConcreteMethod(methodName, library, false); | |
| 998 | |
| 999 @override | |
| 1000 PropertyAccessorElement lookUpInheritedConcreteSetter( | |
| 1001 String setterName, LibraryElement library) => | |
| 1002 _internalLookUpConcreteSetter(setterName, library, false); | |
| 1003 | |
| 1004 @override | |
| 1005 MethodElement lookUpInheritedMethod( | |
| 1006 String methodName, LibraryElement library) => | |
| 1007 _internalLookUpMethod(methodName, library, false); | |
| 1008 | |
| 1009 @override | |
| 1010 MethodElement lookUpMethod(String methodName, LibraryElement library) => | |
| 1011 _internalLookUpMethod(methodName, library, true); | |
| 1012 | |
| 1013 @override | |
| 1014 PropertyAccessorElement lookUpSetter( | |
| 1015 String setterName, LibraryElement library) => | |
| 1016 _internalLookUpSetter(setterName, library, true); | |
| 1017 | |
| 1018 @override | |
| 1019 void visitChildren(ElementVisitor visitor) { | |
| 1020 super.visitChildren(visitor); | |
| 1021 safelyVisitChildren(_accessors, visitor); | |
| 1022 safelyVisitChildren(_constructors, visitor); | |
| 1023 safelyVisitChildren(_fields, visitor); | |
| 1024 safelyVisitChildren(_methods, visitor); | |
| 1025 safelyVisitChildren(_typeParameters, visitor); | |
| 1026 } | |
| 1027 | |
| 1028 void _collectAllSupertypes(List<InterfaceType> supertypes) { | |
| 1029 List<InterfaceType> typesToVisit = new List<InterfaceType>(); | |
| 1030 List<ClassElement> visitedClasses = new List<ClassElement>(); | |
| 1031 typesToVisit.add(this.type); | |
| 1032 while (!typesToVisit.isEmpty) { | |
| 1033 InterfaceType currentType = typesToVisit.removeAt(0); | |
| 1034 ClassElement currentElement = currentType.element; | |
| 1035 if (!visitedClasses.contains(currentElement)) { | |
| 1036 visitedClasses.add(currentElement); | |
| 1037 if (!identical(currentType, this.type)) { | |
| 1038 supertypes.add(currentType); | |
| 1039 } | |
| 1040 InterfaceType supertype = currentType.superclass; | |
| 1041 if (supertype != null) { | |
| 1042 typesToVisit.add(supertype); | |
| 1043 } | |
| 1044 for (InterfaceType type in currentElement.interfaces) { | |
| 1045 typesToVisit.add(type); | |
| 1046 } | |
| 1047 for (InterfaceType type in currentElement.mixins) { | |
| 1048 ClassElement element = type.element; | |
| 1049 if (!visitedClasses.contains(element)) { | |
| 1050 supertypes.add(type); | |
| 1051 } | |
| 1052 } | |
| 1053 } | |
| 1054 } | |
| 1055 } | |
| 1056 | |
| 1057 /** | |
| 1058 * Compute a list of constructors for this class, which is a mixin | |
| 1059 * application. If specified, [visitedClasses] is a list of the other mixin | |
| 1060 * application classes which have been visited on the way to reaching this | |
| 1061 * one (this is used to detect circularities). | |
| 1062 */ | |
| 1063 List<ConstructorElement> _computeMixinAppConstructors( | |
| 1064 [List<ClassElementImpl> visitedClasses = null]) { | |
| 1065 // First get the list of constructors of the superclass which need to be | |
| 1066 // forwarded to this class. | |
| 1067 Iterable<ConstructorElement> constructorsToForward; | |
| 1068 if (supertype == null) { | |
| 1069 // Shouldn't ever happen, since the only class with no supertype is | |
| 1070 // Object, and it isn't a mixin application. But for safety's sake just | |
| 1071 // assume an empty list. | |
| 1072 assert(false); | |
| 1073 constructorsToForward = <ConstructorElement>[]; | |
| 1074 } else if (!supertype.element.isMixinApplication) { | |
| 1075 List<ConstructorElement> superclassConstructors = | |
| 1076 supertype.element.constructors; | |
| 1077 // Filter out any constructors with optional parameters (see | |
| 1078 // dartbug.com/15101). | |
| 1079 constructorsToForward = | |
| 1080 superclassConstructors.where(isSuperConstructorAccessible); | |
| 1081 } else { | |
| 1082 if (visitedClasses == null) { | |
| 1083 visitedClasses = <ClassElementImpl>[this]; | |
| 1084 } else { | |
| 1085 if (visitedClasses.contains(this)) { | |
| 1086 // Loop in the class hierarchy. Don't try to forward any | |
| 1087 // constructors. | |
| 1088 return <ConstructorElement>[]; | |
| 1089 } | |
| 1090 visitedClasses.add(this); | |
| 1091 } | |
| 1092 try { | |
| 1093 ClassElementImpl superclass = supertype.element; | |
| 1094 constructorsToForward = | |
| 1095 superclass._computeMixinAppConstructors(visitedClasses); | |
| 1096 } finally { | |
| 1097 visitedClasses.removeLast(); | |
| 1098 } | |
| 1099 } | |
| 1100 | |
| 1101 // Figure out the type parameter substitution we need to perform in order | |
| 1102 // to produce constructors for this class. We want to be robust in the | |
| 1103 // face of errors, so drop any extra type arguments and fill in any missing | |
| 1104 // ones with `dynamic`. | |
| 1105 List<DartType> parameterTypes = | |
| 1106 TypeParameterTypeImpl.getTypes(supertype.typeParameters); | |
| 1107 List<DartType> argumentTypes = new List<DartType>.filled( | |
| 1108 parameterTypes.length, DynamicTypeImpl.instance); | |
| 1109 for (int i = 0; i < supertype.typeArguments.length; i++) { | |
| 1110 if (i >= argumentTypes.length) { | |
| 1111 break; | |
| 1112 } | |
| 1113 argumentTypes[i] = supertype.typeArguments[i]; | |
| 1114 } | |
| 1115 | |
| 1116 // Now create an implicit constructor for every constructor found above, | |
| 1117 // substituting type parameters as appropriate. | |
| 1118 return constructorsToForward | |
| 1119 .map((ConstructorElement superclassConstructor) { | |
| 1120 ConstructorElementImpl implicitConstructor = | |
| 1121 new ConstructorElementImpl(superclassConstructor.name, -1); | |
| 1122 implicitConstructor.synthetic = true; | |
| 1123 implicitConstructor.redirectedConstructor = superclassConstructor; | |
| 1124 implicitConstructor.const2 = superclassConstructor.isConst; | |
| 1125 implicitConstructor.returnType = type; | |
| 1126 List<ParameterElement> superParameters = superclassConstructor.parameters; | |
| 1127 int count = superParameters.length; | |
| 1128 if (count > 0) { | |
| 1129 List<ParameterElement> implicitParameters = | |
| 1130 new List<ParameterElement>(count); | |
| 1131 for (int i = 0; i < count; i++) { | |
| 1132 ParameterElement superParameter = superParameters[i]; | |
| 1133 ParameterElementImpl implicitParameter = | |
| 1134 new ParameterElementImpl(superParameter.name, -1); | |
| 1135 implicitParameter.const3 = superParameter.isConst; | |
| 1136 implicitParameter.final2 = superParameter.isFinal; | |
| 1137 implicitParameter.parameterKind = superParameter.parameterKind; | |
| 1138 implicitParameter.synthetic = true; | |
| 1139 implicitParameter.type = | |
| 1140 superParameter.type.substitute2(argumentTypes, parameterTypes); | |
| 1141 implicitParameters[i] = implicitParameter; | |
| 1142 } | |
| 1143 implicitConstructor.parameters = implicitParameters; | |
| 1144 } | |
| 1145 FunctionTypeImpl constructorType = | |
| 1146 new FunctionTypeImpl(implicitConstructor); | |
| 1147 constructorType.typeArguments = type.typeArguments; | |
| 1148 implicitConstructor.type = constructorType; | |
| 1149 implicitConstructor.enclosingElement = this; | |
| 1150 return implicitConstructor; | |
| 1151 }).toList(); | |
| 1152 } | |
| 1153 | |
| 1154 PropertyAccessorElement _internalLookUpConcreteGetter( | |
| 1155 String getterName, LibraryElement library, bool includeThisClass) { | |
| 1156 PropertyAccessorElement getter = | |
| 1157 _internalLookUpGetter(getterName, library, includeThisClass); | |
| 1158 while (getter != null && getter.isAbstract) { | |
| 1159 Element definingClass = getter.enclosingElement; | |
| 1160 if (definingClass is! ClassElementImpl) { | |
| 1161 return null; | |
| 1162 } | |
| 1163 getter = (definingClass as ClassElementImpl) | |
| 1164 ._internalLookUpGetter(getterName, library, false); | |
| 1165 } | |
| 1166 return getter; | |
| 1167 } | |
| 1168 | |
| 1169 MethodElement _internalLookUpConcreteMethod( | |
| 1170 String methodName, LibraryElement library, bool includeThisClass) { | |
| 1171 MethodElement method = | |
| 1172 _internalLookUpMethod(methodName, library, includeThisClass); | |
| 1173 while (method != null && method.isAbstract) { | |
| 1174 ClassElement definingClass = method.enclosingElement; | |
| 1175 if (definingClass == null) { | |
| 1176 return null; | |
| 1177 } | |
| 1178 method = definingClass.lookUpInheritedMethod(methodName, library); | |
| 1179 } | |
| 1180 return method; | |
| 1181 } | |
| 1182 | |
| 1183 PropertyAccessorElement _internalLookUpConcreteSetter( | |
| 1184 String setterName, LibraryElement library, bool includeThisClass) { | |
| 1185 PropertyAccessorElement setter = | |
| 1186 _internalLookUpSetter(setterName, library, includeThisClass); | |
| 1187 while (setter != null && setter.isAbstract) { | |
| 1188 Element definingClass = setter.enclosingElement; | |
| 1189 if (definingClass is! ClassElementImpl) { | |
| 1190 return null; | |
| 1191 } | |
| 1192 setter = (definingClass as ClassElementImpl) | |
| 1193 ._internalLookUpSetter(setterName, library, false); | |
| 1194 } | |
| 1195 return setter; | |
| 1196 } | |
| 1197 | |
| 1198 PropertyAccessorElement _internalLookUpGetter( | |
| 1199 String getterName, LibraryElement library, bool includeThisClass) { | |
| 1200 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 1201 ClassElement currentElement = this; | |
| 1202 if (includeThisClass) { | |
| 1203 PropertyAccessorElement element = currentElement.getGetter(getterName); | |
| 1204 if (element != null && element.isAccessibleIn(library)) { | |
| 1205 return element; | |
| 1206 } | |
| 1207 } | |
| 1208 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 1209 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 1210 ClassElement mixinElement = mixin.element; | |
| 1211 if (mixinElement != null) { | |
| 1212 PropertyAccessorElement element = mixinElement.getGetter(getterName); | |
| 1213 if (element != null && element.isAccessibleIn(library)) { | |
| 1214 return element; | |
| 1215 } | |
| 1216 } | |
| 1217 } | |
| 1218 InterfaceType supertype = currentElement.supertype; | |
| 1219 if (supertype == null) { | |
| 1220 return null; | |
| 1221 } | |
| 1222 currentElement = supertype.element; | |
| 1223 PropertyAccessorElement element = currentElement.getGetter(getterName); | |
| 1224 if (element != null && element.isAccessibleIn(library)) { | |
| 1225 return element; | |
| 1226 } | |
| 1227 } | |
| 1228 return null; | |
| 1229 } | |
| 1230 | |
| 1231 MethodElement _internalLookUpMethod( | |
| 1232 String methodName, LibraryElement library, bool includeThisClass) { | |
| 1233 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 1234 ClassElement currentElement = this; | |
| 1235 if (includeThisClass) { | |
| 1236 MethodElement element = currentElement.getMethod(methodName); | |
| 1237 if (element != null && element.isAccessibleIn(library)) { | |
| 1238 return element; | |
| 1239 } | |
| 1240 } | |
| 1241 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 1242 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 1243 ClassElement mixinElement = mixin.element; | |
| 1244 if (mixinElement != null) { | |
| 1245 MethodElement element = mixinElement.getMethod(methodName); | |
| 1246 if (element != null && element.isAccessibleIn(library)) { | |
| 1247 return element; | |
| 1248 } | |
| 1249 } | |
| 1250 } | |
| 1251 InterfaceType supertype = currentElement.supertype; | |
| 1252 if (supertype == null) { | |
| 1253 return null; | |
| 1254 } | |
| 1255 currentElement = supertype.element; | |
| 1256 MethodElement element = currentElement.getMethod(methodName); | |
| 1257 if (element != null && element.isAccessibleIn(library)) { | |
| 1258 return element; | |
| 1259 } | |
| 1260 } | |
| 1261 return null; | |
| 1262 } | |
| 1263 | |
| 1264 PropertyAccessorElement _internalLookUpSetter( | |
| 1265 String setterName, LibraryElement library, bool includeThisClass) { | |
| 1266 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 1267 ClassElement currentElement = this; | |
| 1268 if (includeThisClass) { | |
| 1269 PropertyAccessorElement element = currentElement.getSetter(setterName); | |
| 1270 if (element != null && element.isAccessibleIn(library)) { | |
| 1271 return element; | |
| 1272 } | |
| 1273 } | |
| 1274 while (currentElement != null && visitedClasses.add(currentElement)) { | |
| 1275 for (InterfaceType mixin in currentElement.mixins.reversed) { | |
| 1276 ClassElement mixinElement = mixin.element; | |
| 1277 if (mixinElement != null) { | |
| 1278 PropertyAccessorElement element = mixinElement.getSetter(setterName); | |
| 1279 if (element != null && element.isAccessibleIn(library)) { | |
| 1280 return element; | |
| 1281 } | |
| 1282 } | |
| 1283 } | |
| 1284 InterfaceType supertype = currentElement.supertype; | |
| 1285 if (supertype == null) { | |
| 1286 return null; | |
| 1287 } | |
| 1288 currentElement = supertype.element; | |
| 1289 PropertyAccessorElement element = currentElement.getSetter(setterName); | |
| 1290 if (element != null && element.isAccessibleIn(library)) { | |
| 1291 return element; | |
| 1292 } | |
| 1293 } | |
| 1294 return null; | |
| 1295 } | |
| 1296 | |
| 1297 bool _safeIsOrInheritsProxy( | |
| 1298 ClassElement classElt, HashSet<ClassElement> visitedClassElts) { | |
| 1299 if (visitedClassElts.contains(classElt)) { | |
| 1300 return false; | |
| 1301 } | |
| 1302 visitedClassElts.add(classElt); | |
| 1303 if (classElt.isProxy) { | |
| 1304 return true; | |
| 1305 } else if (classElt.supertype != null && | |
| 1306 _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { | |
| 1307 return true; | |
| 1308 } | |
| 1309 List<InterfaceType> supertypes = classElt.interfaces; | |
| 1310 for (int i = 0; i < supertypes.length; i++) { | |
| 1311 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { | |
| 1312 return true; | |
| 1313 } | |
| 1314 } | |
| 1315 supertypes = classElt.mixins; | |
| 1316 for (int i = 0; i < supertypes.length; i++) { | |
| 1317 if (_safeIsOrInheritsProxy(supertypes[i].element, visitedClassElts)) { | |
| 1318 return true; | |
| 1319 } | |
| 1320 } | |
| 1321 return false; | |
| 1322 } | |
| 1323 } | |
| 1324 | |
| 1325 /** | |
| 1326 * An element that is contained within a [ClassElement]. | |
| 1327 */ | |
| 1328 abstract class ClassMemberElement implements Element { | |
| 1329 /** | |
| 1330 * Return the type in which this member is defined. | |
| 1331 */ | |
| 1332 @override | |
| 1333 ClassElement get enclosingElement; | |
| 1334 | |
| 1335 /** | |
| 1336 * Return `true` if this element is a static element. A static element is an | |
| 1337 * element that is not associated with a particular instance, but rather with | |
| 1338 * an entire library or class. | |
| 1339 */ | |
| 1340 bool get isStatic; | |
| 1341 } | |
| 1342 | |
| 1343 /** | |
| 1344 * An element representing a compilation unit. | |
| 1345 */ | |
| 1346 abstract class CompilationUnitElement implements Element, UriReferencedElement { | |
| 1347 /** | |
| 1348 * An empty list of compilation unit elements. | |
| 1349 */ | |
| 1350 static const List<CompilationUnitElement> EMPTY_LIST = | |
| 1351 const <CompilationUnitElement>[]; | |
| 1352 | |
| 1353 /** | |
| 1354 * Return a list containing all of the top-level accessors (getters and | |
| 1355 * setters) contained in this compilation unit. | |
| 1356 */ | |
| 1357 List<PropertyAccessorElement> get accessors; | |
| 1358 | |
| 1359 /** | |
| 1360 * Return the library in which this compilation unit is defined. | |
| 1361 */ | |
| 1362 @override | |
| 1363 LibraryElement get enclosingElement; | |
| 1364 | |
| 1365 /** | |
| 1366 * Return a list containing all of the enums contained in this compilation | |
| 1367 * unit. | |
| 1368 */ | |
| 1369 List<ClassElement> get enums; | |
| 1370 | |
| 1371 /** | |
| 1372 * Return a list containing all of the top-level functions contained in this | |
| 1373 * compilation unit. | |
| 1374 */ | |
| 1375 List<FunctionElement> get functions; | |
| 1376 | |
| 1377 /** | |
| 1378 * Return a list containing all of the function type aliases contained in this | |
| 1379 * compilation unit. | |
| 1380 */ | |
| 1381 List<FunctionTypeAliasElement> get functionTypeAliases; | |
| 1382 | |
| 1383 /** | |
| 1384 * Return `true` if this compilation unit defines a top-level function named | |
| 1385 * `loadLibrary`. | |
| 1386 */ | |
| 1387 bool get hasLoadLibraryFunction; | |
| 1388 | |
| 1389 /** | |
| 1390 * Return a list containing all of the top-level variables contained in this | |
| 1391 * compilation unit. | |
| 1392 */ | |
| 1393 List<TopLevelVariableElement> get topLevelVariables; | |
| 1394 | |
| 1395 /** | |
| 1396 * Return a list containing all of the classes contained in this compilation | |
| 1397 * unit. | |
| 1398 */ | |
| 1399 List<ClassElement> get types; | |
| 1400 | |
| 1401 /** | |
| 1402 * Return the resolved [CompilationUnit] node that declares this element. | |
| 1403 * | |
| 1404 * This method is expensive, because resolved AST might be evicted from cache, | |
| 1405 * so parsing and resolving will be performed. | |
| 1406 */ | |
| 1407 @override | |
| 1408 CompilationUnit computeNode(); | |
| 1409 | |
| 1410 /** | |
| 1411 * Return the element at the given [offset], maybe `null` if no such element. | |
| 1412 */ | |
| 1413 Element getElementAt(int offset); | |
| 1414 | |
| 1415 /** | |
| 1416 * Return the enum defined in this compilation unit that has the given [name], | |
| 1417 * or `null` if this compilation unit does not define an enum with the given | |
| 1418 * name. | |
| 1419 */ | |
| 1420 ClassElement getEnum(String name); | |
| 1421 | |
| 1422 /** | |
| 1423 * Return the class defined in this compilation unit that has the given | |
| 1424 * [name], or `null` if this compilation unit does not define a class with the | |
| 1425 * given name. | |
| 1426 */ | |
| 1427 ClassElement getType(String name); | |
| 1428 } | |
| 1429 | |
| 1430 /** | |
| 1431 * A concrete implementation of a [CompilationUnitElement]. | |
| 1432 */ | |
| 1433 class CompilationUnitElementImpl extends UriReferencedElementImpl | |
| 1434 implements CompilationUnitElement { | |
| 1435 /** | |
| 1436 * An empty list of compilation unit elements. | |
| 1437 */ | |
| 1438 @deprecated // Use CompilationUnitElement.EMPTY_LIST | |
| 1439 static const List<CompilationUnitElement> EMPTY_ARRAY = | |
| 1440 const <CompilationUnitElement>[]; | |
| 1441 | |
| 1442 /** | |
| 1443 * The source that corresponds to this compilation unit. | |
| 1444 */ | |
| 1445 Source source; | |
| 1446 | |
| 1447 /** | |
| 1448 * The source of the library containing this compilation unit. | |
| 1449 * | |
| 1450 * This is the same as the source of the containing [LibraryElement], | |
| 1451 * except that it does not require the containing [LibraryElement] to be | |
| 1452 * computed. | |
| 1453 */ | |
| 1454 Source librarySource; | |
| 1455 | |
| 1456 /** | |
| 1457 * A list containing all of the top-level accessors (getters and setters) | |
| 1458 * contained in this compilation unit. | |
| 1459 */ | |
| 1460 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; | |
| 1461 | |
| 1462 /** | |
| 1463 * A list containing all of the enums contained in this compilation unit. | |
| 1464 */ | |
| 1465 List<ClassElement> _enums = ClassElement.EMPTY_LIST; | |
| 1466 | |
| 1467 /** | |
| 1468 * A list containing all of the top-level functions contained in this | |
| 1469 * compilation unit. | |
| 1470 */ | |
| 1471 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; | |
| 1472 | |
| 1473 /** | |
| 1474 * A list containing all of the function type aliases contained in this | |
| 1475 * compilation unit. | |
| 1476 */ | |
| 1477 List<FunctionTypeAliasElement> _typeAliases = | |
| 1478 FunctionTypeAliasElement.EMPTY_LIST; | |
| 1479 | |
| 1480 /** | |
| 1481 * A list containing all of the types contained in this compilation unit. | |
| 1482 */ | |
| 1483 List<ClassElement> _types = ClassElement.EMPTY_LIST; | |
| 1484 | |
| 1485 /** | |
| 1486 * A list containing all of the variables contained in this compilation unit. | |
| 1487 */ | |
| 1488 List<TopLevelVariableElement> _variables = TopLevelVariableElement.EMPTY_LIST; | |
| 1489 | |
| 1490 /** | |
| 1491 * A map from offsets to elements of this unit at these offsets. | |
| 1492 */ | |
| 1493 final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>(); | |
| 1494 | |
| 1495 /** | |
| 1496 * Initialize a newly created compilation unit element to have the given | |
| 1497 * [name]. | |
| 1498 */ | |
| 1499 CompilationUnitElementImpl(String name) : super(name, -1); | |
| 1500 | |
| 1501 @override | |
| 1502 List<PropertyAccessorElement> get accessors => _accessors; | |
| 1503 | |
| 1504 /** | |
| 1505 * Set the top-level accessors (getters and setters) contained in this | |
| 1506 * compilation unit to the given [accessors]. | |
| 1507 */ | |
| 1508 void set accessors(List<PropertyAccessorElement> accessors) { | |
| 1509 for (PropertyAccessorElement accessor in accessors) { | |
| 1510 (accessor as PropertyAccessorElementImpl).enclosingElement = this; | |
| 1511 } | |
| 1512 this._accessors = accessors; | |
| 1513 } | |
| 1514 | |
| 1515 @override | |
| 1516 LibraryElement get enclosingElement => | |
| 1517 super.enclosingElement as LibraryElement; | |
| 1518 | |
| 1519 @override | |
| 1520 List<ClassElement> get enums => _enums; | |
| 1521 | |
| 1522 /** | |
| 1523 * Set the enums contained in this compilation unit to the given [enums]. | |
| 1524 */ | |
| 1525 void set enums(List<ClassElement> enums) { | |
| 1526 for (ClassElement enumDeclaration in enums) { | |
| 1527 (enumDeclaration as ClassElementImpl).enclosingElement = this; | |
| 1528 } | |
| 1529 this._enums = enums; | |
| 1530 } | |
| 1531 | |
| 1532 @override | |
| 1533 List<FunctionElement> get functions => _functions; | |
| 1534 | |
| 1535 /** | |
| 1536 * Set the top-level functions contained in this compilation unit to the given | |
| 1537 * [functions]. | |
| 1538 */ | |
| 1539 void set functions(List<FunctionElement> functions) { | |
| 1540 for (FunctionElement function in functions) { | |
| 1541 (function as FunctionElementImpl).enclosingElement = this; | |
| 1542 } | |
| 1543 this._functions = functions; | |
| 1544 } | |
| 1545 | |
| 1546 @override | |
| 1547 List<FunctionTypeAliasElement> get functionTypeAliases => _typeAliases; | |
| 1548 | |
| 1549 @override | |
| 1550 int get hashCode => source.hashCode; | |
| 1551 | |
| 1552 @override | |
| 1553 bool get hasLoadLibraryFunction { | |
| 1554 for (int i = 0; i < _functions.length; i++) { | |
| 1555 if (_functions[i].name == FunctionElement.LOAD_LIBRARY_NAME) { | |
| 1556 return true; | |
| 1557 } | |
| 1558 } | |
| 1559 return false; | |
| 1560 } | |
| 1561 | |
| 1562 @override | |
| 1563 String get identifier => source.encoding; | |
| 1564 | |
| 1565 @override | |
| 1566 ElementKind get kind => ElementKind.COMPILATION_UNIT; | |
| 1567 | |
| 1568 @override | |
| 1569 List<TopLevelVariableElement> get topLevelVariables => _variables; | |
| 1570 | |
| 1571 /** | |
| 1572 * Set the top-level variables contained in this compilation unit to the given | |
| 1573 * [variables]. | |
| 1574 */ | |
| 1575 void set topLevelVariables(List<TopLevelVariableElement> variables) { | |
| 1576 for (TopLevelVariableElement field in variables) { | |
| 1577 (field as TopLevelVariableElementImpl).enclosingElement = this; | |
| 1578 } | |
| 1579 this._variables = variables; | |
| 1580 } | |
| 1581 | |
| 1582 /** | |
| 1583 * Set the function type aliases contained in this compilation unit to the | |
| 1584 * given [typeAliases]. | |
| 1585 */ | |
| 1586 void set typeAliases(List<FunctionTypeAliasElement> typeAliases) { | |
| 1587 for (FunctionTypeAliasElement typeAlias in typeAliases) { | |
| 1588 (typeAlias as FunctionTypeAliasElementImpl).enclosingElement = this; | |
| 1589 } | |
| 1590 this._typeAliases = typeAliases; | |
| 1591 } | |
| 1592 | |
| 1593 @override | |
| 1594 List<ClassElement> get types => _types; | |
| 1595 | |
| 1596 /** | |
| 1597 * Set the types contained in this compilation unit to the given [types]. | |
| 1598 */ | |
| 1599 void set types(List<ClassElement> types) { | |
| 1600 for (ClassElement type in types) { | |
| 1601 (type as ClassElementImpl).enclosingElement = this; | |
| 1602 } | |
| 1603 this._types = types; | |
| 1604 } | |
| 1605 | |
| 1606 @override | |
| 1607 bool operator ==(Object object) => | |
| 1608 object is CompilationUnitElementImpl && source == object.source; | |
| 1609 | |
| 1610 @override | |
| 1611 accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this); | |
| 1612 | |
| 1613 /** | |
| 1614 * This method is invoked after this unit was incrementally resolved. | |
| 1615 */ | |
| 1616 void afterIncrementalResolution() { | |
| 1617 _offsetToElementMap.clear(); | |
| 1618 } | |
| 1619 | |
| 1620 @override | |
| 1621 void appendTo(StringBuffer buffer) { | |
| 1622 if (source == null) { | |
| 1623 buffer.write("{compilation unit}"); | |
| 1624 } else { | |
| 1625 buffer.write(source.fullName); | |
| 1626 } | |
| 1627 } | |
| 1628 | |
| 1629 @override | |
| 1630 CompilationUnit computeNode() => unit; | |
| 1631 | |
| 1632 @override | |
| 1633 ElementImpl getChild(String identifier) { | |
| 1634 // | |
| 1635 // The casts in this method are safe because the set methods would have | |
| 1636 // thrown a CCE if any of the elements in the arrays were not of the | |
| 1637 // expected types. | |
| 1638 // | |
| 1639 for (PropertyAccessorElement accessor in _accessors) { | |
| 1640 if ((accessor as PropertyAccessorElementImpl).identifier == identifier) { | |
| 1641 return accessor as PropertyAccessorElementImpl; | |
| 1642 } | |
| 1643 } | |
| 1644 for (VariableElement variable in _variables) { | |
| 1645 if ((variable as VariableElementImpl).identifier == identifier) { | |
| 1646 return variable as VariableElementImpl; | |
| 1647 } | |
| 1648 } | |
| 1649 for (ExecutableElement function in _functions) { | |
| 1650 if ((function as ExecutableElementImpl).identifier == identifier) { | |
| 1651 return function as ExecutableElementImpl; | |
| 1652 } | |
| 1653 } | |
| 1654 for (FunctionTypeAliasElement typeAlias in _typeAliases) { | |
| 1655 if ((typeAlias as FunctionTypeAliasElementImpl).identifier == | |
| 1656 identifier) { | |
| 1657 return typeAlias as FunctionTypeAliasElementImpl; | |
| 1658 } | |
| 1659 } | |
| 1660 for (ClassElement type in _types) { | |
| 1661 if ((type as ClassElementImpl).identifier == identifier) { | |
| 1662 return type as ClassElementImpl; | |
| 1663 } | |
| 1664 } | |
| 1665 for (ClassElement type in _enums) { | |
| 1666 if ((type as ClassElementImpl).identifier == identifier) { | |
| 1667 return type as ClassElementImpl; | |
| 1668 } | |
| 1669 } | |
| 1670 return null; | |
| 1671 } | |
| 1672 | |
| 1673 @override | |
| 1674 Element getElementAt(int offset) { | |
| 1675 if (_offsetToElementMap.isEmpty) { | |
| 1676 accept(new _BuildOffsetToElementMap(_offsetToElementMap)); | |
| 1677 } | |
| 1678 return _offsetToElementMap[offset]; | |
| 1679 } | |
| 1680 | |
| 1681 @override | |
| 1682 ClassElement getEnum(String enumName) { | |
| 1683 for (ClassElement enumDeclaration in _enums) { | |
| 1684 if (enumDeclaration.name == enumName) { | |
| 1685 return enumDeclaration; | |
| 1686 } | |
| 1687 } | |
| 1688 return null; | |
| 1689 } | |
| 1690 | |
| 1691 @override | |
| 1692 ClassElement getType(String className) { | |
| 1693 for (ClassElement type in _types) { | |
| 1694 if (type.name == className) { | |
| 1695 return type; | |
| 1696 } | |
| 1697 } | |
| 1698 return null; | |
| 1699 } | |
| 1700 | |
| 1701 /** | |
| 1702 * Replace the given [from] top-level variable with [to] in this compilation u
nit. | |
| 1703 */ | |
| 1704 void replaceTopLevelVariable( | |
| 1705 TopLevelVariableElement from, TopLevelVariableElement to) { | |
| 1706 int index = _variables.indexOf(from); | |
| 1707 _variables[index] = to; | |
| 1708 } | |
| 1709 | |
| 1710 @override | |
| 1711 void visitChildren(ElementVisitor visitor) { | |
| 1712 super.visitChildren(visitor); | |
| 1713 safelyVisitChildren(_accessors, visitor); | |
| 1714 safelyVisitChildren(_enums, visitor); | |
| 1715 safelyVisitChildren(_functions, visitor); | |
| 1716 safelyVisitChildren(_typeAliases, visitor); | |
| 1717 safelyVisitChildren(_types, visitor); | |
| 1718 safelyVisitChildren(_variables, visitor); | |
| 1719 } | |
| 1720 } | |
| 1721 | |
| 1722 /** | |
| 1723 * A [FieldElement] for a 'const' or 'final' field that has an initializer. | |
| 1724 * | 11 * |
| 1725 * TODO(paulberry): we should rename this class to reflect the fact that it's | 12 * If your code is using APIs not available in these public libraries, please |
| 1726 * used for both const and final fields. However, we shouldn't do so until | 13 * contact the analyzer team to either find an alternate API or have the API you |
| 1727 * we've created an API for reading the values of constants; until that API is | 14 * depend on added to the public API. |
| 1728 * available, clients are likely to read constant values by casting to | |
| 1729 * ConstFieldElementImpl, so it would be a breaking change to rename this | |
| 1730 * class. | |
| 1731 */ | |
| 1732 class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement { | |
| 1733 /** | |
| 1734 * The result of evaluating this variable's initializer. | |
| 1735 */ | |
| 1736 EvaluationResultImpl _result; | |
| 1737 | |
| 1738 /** | |
| 1739 * Initialize a newly created synthetic field element to have the given | |
| 1740 * [name] and [offset]. | |
| 1741 */ | |
| 1742 ConstFieldElementImpl(String name, int offset) : super(name, offset); | |
| 1743 | |
| 1744 /** | |
| 1745 * Initialize a newly created field element to have the given [name]. | |
| 1746 */ | |
| 1747 @deprecated // Use new ConstFieldElementImpl.forNode(name) | |
| 1748 ConstFieldElementImpl.con1(Identifier name) : super.forNode(name); | |
| 1749 | |
| 1750 /** | |
| 1751 * Initialize a newly created synthetic field element to have the given | |
| 1752 * [name] and [offset]. | |
| 1753 */ | |
| 1754 @deprecated // Use new ConstFieldElementImpl(name, offset) | |
| 1755 ConstFieldElementImpl.con2(String name, int offset) : super(name, offset); | |
| 1756 | |
| 1757 /** | |
| 1758 * Initialize a newly created field element to have the given [name]. | |
| 1759 */ | |
| 1760 ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1761 | |
| 1762 @override | |
| 1763 DartObject get constantValue => _result.value; | |
| 1764 | |
| 1765 @override | |
| 1766 EvaluationResultImpl get evaluationResult => _result; | |
| 1767 | |
| 1768 @override | |
| 1769 void set evaluationResult(EvaluationResultImpl result) { | |
| 1770 this._result = result; | |
| 1771 } | |
| 1772 } | |
| 1773 | |
| 1774 /** | |
| 1775 * A [LocalVariableElement] for a local 'const' variable that has an | |
| 1776 * initializer. | |
| 1777 */ | |
| 1778 class ConstLocalVariableElementImpl extends LocalVariableElementImpl | |
| 1779 with ConstVariableElement { | |
| 1780 /** | |
| 1781 * The result of evaluating this variable's initializer. | |
| 1782 */ | |
| 1783 EvaluationResultImpl _result; | |
| 1784 | |
| 1785 /** | |
| 1786 * Initialize a newly created local variable element to have the given [name] | |
| 1787 * and [offset]. | |
| 1788 */ | |
| 1789 ConstLocalVariableElementImpl(String name, int offset) : super(name, offset); | |
| 1790 | |
| 1791 /** | |
| 1792 * Initialize a newly created local variable element to have the given [name]. | |
| 1793 */ | |
| 1794 ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1795 | |
| 1796 @override | |
| 1797 DartObject get constantValue => _result.value; | |
| 1798 | |
| 1799 @override | |
| 1800 EvaluationResultImpl get evaluationResult => _result; | |
| 1801 | |
| 1802 @override | |
| 1803 void set evaluationResult(EvaluationResultImpl result) { | |
| 1804 this._result = result; | |
| 1805 } | |
| 1806 } | |
| 1807 | |
| 1808 /** | |
| 1809 * An element representing a constructor or a factory method defined within a | |
| 1810 * class. | |
| 1811 */ | |
| 1812 abstract class ConstructorElement | |
| 1813 implements ClassMemberElement, ExecutableElement, ConstantEvaluationTarget { | |
| 1814 /** | |
| 1815 * An empty list of constructor elements. | |
| 1816 */ | |
| 1817 static const List<ConstructorElement> EMPTY_LIST = | |
| 1818 const <ConstructorElement>[]; | |
| 1819 | |
| 1820 /** | |
| 1821 * Return `true` if this constructor is a const constructor. | |
| 1822 */ | |
| 1823 bool get isConst; | |
| 1824 | |
| 1825 /** | |
| 1826 * Return `true` if this constructor can be used as a default constructor - | |
| 1827 * unnamed and has no required parameters. | |
| 1828 */ | |
| 1829 bool get isDefaultConstructor; | |
| 1830 | |
| 1831 /** | |
| 1832 * Return `true` if this constructor represents a factory constructor. | |
| 1833 */ | |
| 1834 bool get isFactory; | |
| 1835 | |
| 1836 /** | |
| 1837 * Return the offset of the character immediately following the last character | |
| 1838 * of this constructor's name, or `null` if not named. | |
| 1839 */ | |
| 1840 int get nameEnd; | |
| 1841 | |
| 1842 /** | |
| 1843 * Return the offset of the `.` before this constructor name, or `null` if | |
| 1844 * not named. | |
| 1845 */ | |
| 1846 int get periodOffset; | |
| 1847 | |
| 1848 /** | |
| 1849 * Return the constructor to which this constructor is redirecting, or `null` | |
| 1850 * if this constructor does not redirect to another constructor or if the | |
| 1851 * library containing this constructor has not yet been resolved. | |
| 1852 */ | |
| 1853 ConstructorElement get redirectedConstructor; | |
| 1854 | |
| 1855 /** | |
| 1856 * Return the resolved [ConstructorDeclaration] node that declares this | |
| 1857 * [ConstructorElement] . | |
| 1858 * | |
| 1859 * This method is expensive, because resolved AST might be evicted from cache, | |
| 1860 * so parsing and resolving will be performed. | |
| 1861 */ | |
| 1862 @override | |
| 1863 ConstructorDeclaration computeNode(); | |
| 1864 } | |
| 1865 | |
| 1866 /** | |
| 1867 * A concrete implementation of a [ConstructorElement]. | |
| 1868 */ | |
| 1869 class ConstructorElementImpl extends ExecutableElementImpl | |
| 1870 implements ConstructorElement { | |
| 1871 /** | |
| 1872 * An empty list of constructor elements. | |
| 1873 */ | |
| 1874 @deprecated // Use ConstructorElement.EMPTY_LIST | |
| 1875 static const List<ConstructorElement> EMPTY_ARRAY = | |
| 1876 const <ConstructorElement>[]; | |
| 1877 | |
| 1878 /** | |
| 1879 * The constructor to which this constructor is redirecting. | |
| 1880 */ | |
| 1881 ConstructorElement redirectedConstructor; | |
| 1882 | |
| 1883 /** | |
| 1884 * The initializers for this constructor (used for evaluating constant | |
| 1885 * instance creation expressions). | |
| 1886 */ | |
| 1887 List<ConstructorInitializer> constantInitializers; | |
| 1888 | |
| 1889 /** | |
| 1890 * The offset of the `.` before this constructor name or `null` if not named. | |
| 1891 */ | |
| 1892 int periodOffset; | |
| 1893 | |
| 1894 /** | |
| 1895 * Return the offset of the character immediately following the last character | |
| 1896 * of this constructor's name, or `null` if not named. | |
| 1897 */ | |
| 1898 int nameEnd; | |
| 1899 | |
| 1900 /** | |
| 1901 * True if this constructor has been found by constant evaluation to be free | |
| 1902 * of redirect cycles, and is thus safe to evaluate. | |
| 1903 */ | |
| 1904 bool isCycleFree = false; | |
| 1905 | |
| 1906 /** | |
| 1907 * Initialize a newly created constructor element to have the given [name] and | |
| 1908 * [offset]. | |
| 1909 */ | |
| 1910 ConstructorElementImpl(String name, int offset) : super(name, offset); | |
| 1911 | |
| 1912 /** | |
| 1913 * Initialize a newly created constructor element to have the given [name]. | |
| 1914 */ | |
| 1915 ConstructorElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 1916 | |
| 1917 /** | |
| 1918 * Set whether this constructor represents a 'const' constructor. | |
| 1919 */ | |
| 1920 void set const2(bool isConst) { | |
| 1921 setModifier(Modifier.CONST, isConst); | |
| 1922 } | |
| 1923 | |
| 1924 @override | |
| 1925 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 1926 | |
| 1927 /** | |
| 1928 * Set whether this constructor represents a factory method. | |
| 1929 */ | |
| 1930 void set factory(bool isFactory) { | |
| 1931 setModifier(Modifier.FACTORY, isFactory); | |
| 1932 } | |
| 1933 | |
| 1934 @override | |
| 1935 bool get isConst => hasModifier(Modifier.CONST); | |
| 1936 | |
| 1937 @override | |
| 1938 bool get isDefaultConstructor { | |
| 1939 // unnamed | |
| 1940 String name = this.name; | |
| 1941 if (name != null && name.length != 0) { | |
| 1942 return false; | |
| 1943 } | |
| 1944 // no required parameters | |
| 1945 for (ParameterElement parameter in parameters) { | |
| 1946 if (parameter.parameterKind == ParameterKind.REQUIRED) { | |
| 1947 return false; | |
| 1948 } | |
| 1949 } | |
| 1950 // OK, can be used as default constructor | |
| 1951 return true; | |
| 1952 } | |
| 1953 | |
| 1954 @override | |
| 1955 bool get isFactory => hasModifier(Modifier.FACTORY); | |
| 1956 | |
| 1957 @override | |
| 1958 bool get isStatic => false; | |
| 1959 | |
| 1960 @override | |
| 1961 ElementKind get kind => ElementKind.CONSTRUCTOR; | |
| 1962 | |
| 1963 @override | |
| 1964 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); | |
| 1965 | |
| 1966 @override | |
| 1967 void appendTo(StringBuffer buffer) { | |
| 1968 if (enclosingElement == null) { | |
| 1969 String message; | |
| 1970 String name = displayName; | |
| 1971 if (name != null && !name.isEmpty) { | |
| 1972 message = | |
| 1973 'Found constructor element named $name with no enclosing element'; | |
| 1974 } else { | |
| 1975 message = 'Found unnamed constructor element with no enclosing element'; | |
| 1976 } | |
| 1977 AnalysisEngine.instance.logger.logError(message); | |
| 1978 buffer.write('<unknown class>'); | |
| 1979 } else { | |
| 1980 buffer.write(enclosingElement.displayName); | |
| 1981 } | |
| 1982 String name = displayName; | |
| 1983 if (name != null && !name.isEmpty) { | |
| 1984 buffer.write("."); | |
| 1985 buffer.write(name); | |
| 1986 } | |
| 1987 super.appendTo(buffer); | |
| 1988 } | |
| 1989 | |
| 1990 @override | |
| 1991 ConstructorDeclaration computeNode() => | |
| 1992 getNodeMatching((node) => node is ConstructorDeclaration); | |
| 1993 } | |
| 1994 | |
| 1995 /** | |
| 1996 * A constructor element defined in a parameterized type where the values of the | |
| 1997 * type parameters are known. | |
| 1998 */ | |
| 1999 class ConstructorMember extends ExecutableMember implements ConstructorElement { | |
| 2000 /** | |
| 2001 * Initialize a newly created element to represent a constructor, based on the | |
| 2002 * [baseElement], defined by the [definingType]. | |
| 2003 */ | |
| 2004 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType) | |
| 2005 : super(baseElement, definingType); | |
| 2006 | |
| 2007 @override | |
| 2008 ConstructorElement get baseElement => super.baseElement as ConstructorElement; | |
| 2009 | |
| 2010 @override | |
| 2011 InterfaceType get definingType => super.definingType as InterfaceType; | |
| 2012 | |
| 2013 @override | |
| 2014 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 2015 | |
| 2016 @override | |
| 2017 bool get isConst => baseElement.isConst; | |
| 2018 | |
| 2019 @override | |
| 2020 bool get isDefaultConstructor => baseElement.isDefaultConstructor; | |
| 2021 | |
| 2022 @override | |
| 2023 bool get isFactory => baseElement.isFactory; | |
| 2024 | |
| 2025 @override | |
| 2026 int get nameEnd => baseElement.nameEnd; | |
| 2027 | |
| 2028 @override | |
| 2029 int get periodOffset => baseElement.periodOffset; | |
| 2030 | |
| 2031 @override | |
| 2032 ConstructorElement get redirectedConstructor => | |
| 2033 from(baseElement.redirectedConstructor, definingType); | |
| 2034 | |
| 2035 @override | |
| 2036 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this); | |
| 2037 | |
| 2038 @override | |
| 2039 ConstructorDeclaration computeNode() => baseElement.computeNode(); | |
| 2040 | |
| 2041 @override | |
| 2042 String toString() { | |
| 2043 ConstructorElement baseElement = this.baseElement; | |
| 2044 List<ParameterElement> parameters = this.parameters; | |
| 2045 FunctionType type = this.type; | |
| 2046 StringBuffer buffer = new StringBuffer(); | |
| 2047 buffer.write(baseElement.enclosingElement.displayName); | |
| 2048 String name = displayName; | |
| 2049 if (name != null && !name.isEmpty) { | |
| 2050 buffer.write("."); | |
| 2051 buffer.write(name); | |
| 2052 } | |
| 2053 buffer.write("("); | |
| 2054 int parameterCount = parameters.length; | |
| 2055 for (int i = 0; i < parameterCount; i++) { | |
| 2056 if (i > 0) { | |
| 2057 buffer.write(", "); | |
| 2058 } | |
| 2059 buffer.write(parameters[i]); | |
| 2060 } | |
| 2061 buffer.write(")"); | |
| 2062 if (type != null) { | |
| 2063 buffer.write(Element.RIGHT_ARROW); | |
| 2064 buffer.write(type.returnType); | |
| 2065 } | |
| 2066 return buffer.toString(); | |
| 2067 } | |
| 2068 | |
| 2069 /** | |
| 2070 * If the given [constructor]'s type is different when any type parameters | |
| 2071 * from the defining type's declaration are replaced with the actual type | |
| 2072 * arguments from the [definingType], create a constructor member representing | |
| 2073 * the given constructor. Return the member that was created, or the original | |
| 2074 * constructor if no member was created. | |
| 2075 */ | |
| 2076 static ConstructorElement from( | |
| 2077 ConstructorElement constructor, InterfaceType definingType) { | |
| 2078 if (constructor == null || definingType.typeArguments.length == 0) { | |
| 2079 return constructor; | |
| 2080 } | |
| 2081 FunctionType baseType = constructor.type; | |
| 2082 if (baseType == null) { | |
| 2083 // TODO(brianwilkerson) We need to understand when this can happen. | |
| 2084 return constructor; | |
| 2085 } | |
| 2086 List<DartType> argumentTypes = definingType.typeArguments; | |
| 2087 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 2088 FunctionType substitutedType = | |
| 2089 baseType.substitute2(argumentTypes, parameterTypes); | |
| 2090 if (baseType == substitutedType) { | |
| 2091 return constructor; | |
| 2092 } | |
| 2093 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 2094 // instance. It would use more memory but speed up some operations. | |
| 2095 // We need to see how often the type is being re-computed. | |
| 2096 return new ConstructorMember(constructor, definingType); | |
| 2097 } | |
| 2098 } | |
| 2099 | |
| 2100 /** | |
| 2101 * A [TopLevelVariableElement] for a top-level 'const' variable that has an | |
| 2102 * initializer. | |
| 2103 */ | |
| 2104 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl | |
| 2105 with ConstVariableElement { | |
| 2106 /** | |
| 2107 * The result of evaluating this variable's initializer. | |
| 2108 */ | |
| 2109 EvaluationResultImpl _result; | |
| 2110 | |
| 2111 /** | |
| 2112 * Initialize a newly created top-level variable element to have the given | |
| 2113 * [name]. | |
| 2114 */ | |
| 2115 ConstTopLevelVariableElementImpl(Identifier name) : super.forNode(name); | |
| 2116 | |
| 2117 @override | |
| 2118 DartObject get constantValue => _result.value; | |
| 2119 | |
| 2120 @override | |
| 2121 EvaluationResultImpl get evaluationResult => _result; | |
| 2122 | |
| 2123 @override | |
| 2124 void set evaluationResult(EvaluationResultImpl result) { | |
| 2125 this._result = result; | |
| 2126 } | |
| 2127 } | |
| 2128 | |
| 2129 /** | |
| 2130 * Mixin used by elements that represent constant variables and have | |
| 2131 * initializers. | |
| 2132 * | |
| 2133 * Note that in correct Dart code, all constant variables must have | |
| 2134 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 2135 * in which case there might be some constant variables that lack initializers. | |
| 2136 * This interface is only used for constant variables that have initializers. | |
| 2137 * | |
| 2138 * This class is not intended to be part of the public API for analyzer. | |
| 2139 */ | |
| 2140 abstract class ConstVariableElement implements PotentiallyConstVariableElement { | |
| 2141 /** | |
| 2142 * If this element represents a constant variable, and it has an initializer, | |
| 2143 * a copy of the initializer for the constant. Otherwise `null`. | |
| 2144 * | |
| 2145 * Note that in correct Dart code, all constant variables must have | |
| 2146 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 2147 * in which case there might be some constant variables that lack | |
| 2148 * initializers. | |
| 2149 */ | |
| 2150 Expression constantInitializer; | |
| 2151 } | |
| 2152 | |
| 2153 /** | |
| 2154 * The type associated with elements in the element model. | |
| 2155 */ | |
| 2156 abstract class DartType { | |
| 2157 /** | |
| 2158 * An empty list of types. | |
| 2159 */ | |
| 2160 static const List<DartType> EMPTY_LIST = const <DartType>[]; | |
| 2161 | |
| 2162 /** | |
| 2163 * Return the name of this type as it should appear when presented to users in | |
| 2164 * contexts such as error messages. | |
| 2165 */ | |
| 2166 String get displayName; | |
| 2167 | |
| 2168 /** | |
| 2169 * Return the element representing the declaration of this type, or `null` if | |
| 2170 * the type has not, or cannot, be associated with an element. The former case | |
| 2171 * will occur if the element model is not yet complete; the latter case will | |
| 2172 * occur if this object represents an undefined type. | |
| 2173 */ | |
| 2174 Element get element; | |
| 2175 | |
| 2176 /** | |
| 2177 * Return `true` if this type represents the bottom type. | |
| 2178 */ | |
| 2179 bool get isBottom; | |
| 2180 | |
| 2181 /** | |
| 2182 * Return `true` if this type represents the type 'Function' defined in the | |
| 2183 * dart:core library. | |
| 2184 */ | |
| 2185 bool get isDartCoreFunction; | |
| 2186 | |
| 2187 /** | |
| 2188 * Return `true` if this type represents the type 'dynamic'. | |
| 2189 */ | |
| 2190 bool get isDynamic; | |
| 2191 | |
| 2192 /** | |
| 2193 * Return `true` if this type represents the type 'Object'. | |
| 2194 */ | |
| 2195 bool get isObject; | |
| 2196 | |
| 2197 /** | |
| 2198 * Return `true` if this type represents a typename that couldn't be resolved. | |
| 2199 */ | |
| 2200 bool get isUndefined; | |
| 2201 | |
| 2202 /** | |
| 2203 * Return `true` if this type represents the type 'void'. | |
| 2204 */ | |
| 2205 bool get isVoid; | |
| 2206 | |
| 2207 /** | |
| 2208 * Return the name of this type, or `null` if the type does not have a name, | |
| 2209 * such as when the type represents the type of an unnamed function. | |
| 2210 */ | |
| 2211 String get name; | |
| 2212 | |
| 2213 /** | |
| 2214 * Return the least upper bound of this type and the given [type], or `null` | |
| 2215 * if there is no least upper bound. | |
| 2216 * | |
| 2217 * Deprecated, since it is impossible to implement the correct algorithm | |
| 2218 * without access to a [TypeProvider]. Please use | |
| 2219 * [TypeSystem.getLeastUpperBound] instead. | |
| 2220 */ | |
| 2221 @deprecated | |
| 2222 DartType getLeastUpperBound(DartType type); | |
| 2223 | |
| 2224 /** | |
| 2225 * Return `true` if this type is assignable to the given [type]. A type | |
| 2226 * <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> ⇔ | |
| 2227 * <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i>. | |
| 2228 */ | |
| 2229 bool isAssignableTo(DartType type); | |
| 2230 | |
| 2231 /** | |
| 2232 * Return `true` if this type is more specific than the given [type]. | |
| 2233 */ | |
| 2234 bool isMoreSpecificThan(DartType type); | |
| 2235 | |
| 2236 /** | |
| 2237 * Return `true` if this type is a subtype of the given [type]. | |
| 2238 */ | |
| 2239 bool isSubtypeOf(DartType type); | |
| 2240 | |
| 2241 /** | |
| 2242 * Return `true` if this type is a supertype of the given [type]. A type | |
| 2243 * <i>S</i> is a supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff | |
| 2244 * <i>T</i> is a subtype of <i>S</i>. | |
| 2245 */ | |
| 2246 bool isSupertypeOf(DartType type); | |
| 2247 | |
| 2248 /** | |
| 2249 * Return the type resulting from substituting the given [argumentTypes] for | |
| 2250 * the given [parameterTypes] in this type. The specification defines this | |
| 2251 * operation in section 2: | |
| 2252 * <blockquote> | |
| 2253 * The notation <i>[x<sub>1</sub>, ..., x<sub>n</sub>/y<sub>1</sub>, ..., | |
| 2254 * y<sub>n</sub>]E</i> denotes a copy of <i>E</i> in which all occurrences of | |
| 2255 * <i>y<sub>i</sub>, 1 <= i <= n</i> have been replaced with | |
| 2256 * <i>x<sub>i</sub></i>. | |
| 2257 * </blockquote> | |
| 2258 * Note that, contrary to the specification, this method will not create a | |
| 2259 * copy of this type if no substitutions were required, but will return this | |
| 2260 * type directly. | |
| 2261 * | |
| 2262 * Note too that the current implementation of this method is only guaranteed | |
| 2263 * to work when the parameter types are type variables. | |
| 2264 */ | |
| 2265 DartType substitute2( | |
| 2266 List<DartType> argumentTypes, List<DartType> parameterTypes); | |
| 2267 } | |
| 2268 | |
| 2269 /** | |
| 2270 * A [FieldFormalParameterElementImpl] for parameters that have an initializer. | |
| 2271 */ | |
| 2272 class DefaultFieldFormalParameterElementImpl | |
| 2273 extends FieldFormalParameterElementImpl with ConstVariableElement { | |
| 2274 /** | |
| 2275 * The result of evaluating this variable's initializer. | |
| 2276 */ | |
| 2277 EvaluationResultImpl _result; | |
| 2278 | |
| 2279 /** | |
| 2280 * Initialize a newly created parameter element to have the given [name]. | |
| 2281 */ | |
| 2282 DefaultFieldFormalParameterElementImpl(Identifier name) : super(name); | |
| 2283 | |
| 2284 @override | |
| 2285 DartObject get constantValue => _result.value; | |
| 2286 | |
| 2287 @override | |
| 2288 EvaluationResultImpl get evaluationResult => _result; | |
| 2289 | |
| 2290 @override | |
| 2291 void set evaluationResult(EvaluationResultImpl result) { | |
| 2292 this._result = result; | |
| 2293 } | |
| 2294 } | |
| 2295 | |
| 2296 /** | |
| 2297 * A [ParameterElement] for parameters that have an initializer. | |
| 2298 */ | |
| 2299 class DefaultParameterElementImpl extends ParameterElementImpl | |
| 2300 with ConstVariableElement { | |
| 2301 /** | |
| 2302 * The result of evaluating this variable's initializer. | |
| 2303 */ | |
| 2304 EvaluationResultImpl _result; | |
| 2305 | |
| 2306 /** | |
| 2307 * Initialize a newly created parameter element to have the given [name]. | |
| 2308 */ | |
| 2309 DefaultParameterElementImpl(Identifier name) : super.forNode(name); | |
| 2310 | |
| 2311 @override | |
| 2312 DartObject get constantValue => _result.value; | |
| 2313 | |
| 2314 @override | |
| 2315 EvaluationResultImpl get evaluationResult => _result; | |
| 2316 | |
| 2317 @override | |
| 2318 void set evaluationResult(EvaluationResultImpl result) { | |
| 2319 this._result = result; | |
| 2320 } | |
| 2321 | |
| 2322 @override | |
| 2323 DefaultFormalParameter computeNode() => | |
| 2324 getNodeMatching((node) => node is DefaultFormalParameter); | |
| 2325 } | |
| 2326 | |
| 2327 /** | |
| 2328 * The synthetic element representing the declaration of the type `dynamic`. | |
| 2329 */ | |
| 2330 class DynamicElementImpl extends ElementImpl implements TypeDefiningElement { | |
| 2331 /** | |
| 2332 * Return the unique instance of this class. | |
| 2333 */ | |
| 2334 static DynamicElementImpl get instance => | |
| 2335 DynamicTypeImpl.instance.element as DynamicElementImpl; | |
| 2336 | |
| 2337 @override | |
| 2338 DynamicTypeImpl type; | |
| 2339 | |
| 2340 /** | |
| 2341 * Initialize a newly created instance of this class. Instances of this class | |
| 2342 * should <b>not</b> be created except as part of creating the type associated | |
| 2343 * with this element. The single instance of this class should be accessed | |
| 2344 * through the method [getInstance]. | |
| 2345 */ | |
| 2346 DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) { | |
| 2347 setModifier(Modifier.SYNTHETIC, true); | |
| 2348 } | |
| 2349 | |
| 2350 @override | |
| 2351 ElementKind get kind => ElementKind.DYNAMIC; | |
| 2352 | |
| 2353 @override | |
| 2354 accept(ElementVisitor visitor) => null; | |
| 2355 } | |
| 2356 | |
| 2357 /** | |
| 2358 * The [Type] representing the type `dynamic`. | |
| 2359 */ | |
| 2360 class DynamicTypeImpl extends TypeImpl { | |
| 2361 /** | |
| 2362 * The unique instance of this class. | |
| 2363 */ | |
| 2364 static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl._(); | |
| 2365 | |
| 2366 /** | |
| 2367 * Return the unique instance of this class. | |
| 2368 */ | |
| 2369 static DynamicTypeImpl get instance => _INSTANCE; | |
| 2370 | |
| 2371 /** | |
| 2372 * Prevent the creation of instances of this class. | |
| 2373 */ | |
| 2374 DynamicTypeImpl._() | |
| 2375 : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) { | |
| 2376 (element as DynamicElementImpl).type = this; | |
| 2377 } | |
| 2378 | |
| 2379 /** | |
| 2380 * Constructor used by [CircularTypeImpl]. | |
| 2381 */ | |
| 2382 DynamicTypeImpl._circular() | |
| 2383 : super(_INSTANCE.element, Keyword.DYNAMIC.syntax); | |
| 2384 | |
| 2385 @override | |
| 2386 int get hashCode => 1; | |
| 2387 | |
| 2388 @override | |
| 2389 bool get isDynamic => true; | |
| 2390 | |
| 2391 @override | |
| 2392 bool operator ==(Object object) => identical(object, this); | |
| 2393 | |
| 2394 @override | |
| 2395 bool isMoreSpecificThan(DartType type, | |
| 2396 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 2397 // T is S | |
| 2398 if (identical(this, type)) { | |
| 2399 return true; | |
| 2400 } | |
| 2401 // else | |
| 2402 return withDynamic; | |
| 2403 } | |
| 2404 | |
| 2405 @override | |
| 2406 bool isSubtypeOf(DartType type) => true; | |
| 2407 | |
| 2408 @override | |
| 2409 bool isSupertypeOf(DartType type) => true; | |
| 2410 | |
| 2411 @override | |
| 2412 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 2413 | |
| 2414 @override | |
| 2415 DartType substitute2( | |
| 2416 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 2417 [List<FunctionTypeAliasElement> prune]) { | |
| 2418 int length = parameterTypes.length; | |
| 2419 for (int i = 0; i < length; i++) { | |
| 2420 if (parameterTypes[i] == this) { | |
| 2421 return argumentTypes[i]; | |
| 2422 } | |
| 2423 } | |
| 2424 return this; | |
| 2425 } | |
| 2426 } | |
| 2427 | |
| 2428 /** | |
| 2429 * The base class for all of the elements in the element model. Generally | |
| 2430 * speaking, the element model is a semantic model of the program that | |
| 2431 * represents things that are declared with a name and hence can be referenced | |
| 2432 * elsewhere in the code. | |
| 2433 * | |
| 2434 * There are two exceptions to the general case. First, there are elements in | |
| 2435 * the element model that are created for the convenience of various kinds of | |
| 2436 * analysis but that do not have any corresponding declaration within the source | |
| 2437 * code. Such elements are marked as being <i>synthetic</i>. Examples of | |
| 2438 * synthetic elements include | |
| 2439 * * default constructors in classes that do not define any explicit | |
| 2440 * constructors, | |
| 2441 * * getters and setters that are induced by explicit field declarations, | |
| 2442 * * fields that are induced by explicit declarations of getters and setters, | |
| 2443 * and | |
| 2444 * * functions representing the initialization expression for a variable. | |
| 2445 * | |
| 2446 * Second, there are elements in the element model that do not have a name. | |
| 2447 * These correspond to unnamed functions and exist in order to more accurately | |
| 2448 * represent the semantic structure of the program. | |
| 2449 */ | |
| 2450 abstract class Element implements AnalysisTarget { | |
| 2451 /** | |
| 2452 * An Unicode right arrow. | |
| 2453 */ | |
| 2454 static final String RIGHT_ARROW = " \u2192 "; | |
| 2455 | |
| 2456 /** | |
| 2457 * A comparator that can be used to sort elements by their name offset. | |
| 2458 * Elements with a smaller offset will be sorted to be before elements with a | |
| 2459 * larger name offset. | |
| 2460 */ | |
| 2461 static final Comparator<Element> SORT_BY_OFFSET = (Element firstElement, | |
| 2462 Element secondElement) => | |
| 2463 firstElement.nameOffset - secondElement.nameOffset; | |
| 2464 | |
| 2465 /** | |
| 2466 * Return the analysis context in which this element is defined. | |
| 2467 */ | |
| 2468 AnalysisContext get context; | |
| 2469 | |
| 2470 /** | |
| 2471 * Return the display name of this element, or `null` if this element does not | |
| 2472 * have a name. | |
| 2473 * | |
| 2474 * In most cases the name and the display name are the same. Differences | |
| 2475 * though are cases such as setters where the name of some setter `set f(x)` | |
| 2476 * is `f=`, instead of `f`. | |
| 2477 */ | |
| 2478 String get displayName; | |
| 2479 | |
| 2480 /** | |
| 2481 * Return the source range of the documentation comment for this element, | |
| 2482 * or `null` if this element does not or cannot have a documentation. | |
| 2483 */ | |
| 2484 SourceRange get docRange; | |
| 2485 | |
| 2486 /** | |
| 2487 * Return the element that either physically or logically encloses this | |
| 2488 * element. This will be `null` if this element is a library because libraries | |
| 2489 * are the top-level elements in the model. | |
| 2490 */ | |
| 2491 Element get enclosingElement; | |
| 2492 | |
| 2493 /** | |
| 2494 * The unique integer identifier of this element. | |
| 2495 */ | |
| 2496 int get id; | |
| 2497 | |
| 2498 /** | |
| 2499 * Return `true` if this element has an annotation of the form '@deprecated' | |
| 2500 * or '@Deprecated('..')'. | |
| 2501 */ | |
| 2502 bool get isDeprecated; | |
| 2503 | |
| 2504 /** | |
| 2505 * Return `true` if this element has an annotation of the form '@override'. | |
| 2506 */ | |
| 2507 bool get isOverride; | |
| 2508 | |
| 2509 /** | |
| 2510 * Return `true` if this element is private. Private elements are visible only | |
| 2511 * within the library in which they are declared. | |
| 2512 */ | |
| 2513 bool get isPrivate; | |
| 2514 | |
| 2515 /** | |
| 2516 * Return `true` if this element is public. Public elements are visible within | |
| 2517 * any library that imports the library in which they are declared. | |
| 2518 */ | |
| 2519 bool get isPublic; | |
| 2520 | |
| 2521 /** | |
| 2522 * Return `true` if this element is synthetic. A synthetic element is an | |
| 2523 * element that is not represented in the source code explicitly, but is | |
| 2524 * implied by the source code, such as the default constructor for a class | |
| 2525 * that does not explicitly define any constructors. | |
| 2526 */ | |
| 2527 bool get isSynthetic; | |
| 2528 | |
| 2529 /** | |
| 2530 * Return the kind of element that this is. | |
| 2531 */ | |
| 2532 ElementKind get kind; | |
| 2533 | |
| 2534 /** | |
| 2535 * Return the library that contains this element. This will be the element | |
| 2536 * itself if it is a library element. This will be `null` if this element is | |
| 2537 * an HTML file because HTML files are not contained in libraries. | |
| 2538 */ | |
| 2539 LibraryElement get library; | |
| 2540 | |
| 2541 /** | |
| 2542 * Return an object representing the location of this element in the element | |
| 2543 * model. The object can be used to locate this element at a later time. | |
| 2544 */ | |
| 2545 ElementLocation get location; | |
| 2546 | |
| 2547 /** | |
| 2548 * Return a list containing all of the metadata associated with this element. | |
| 2549 * The array will be empty if the element does not have any metadata or if the | |
| 2550 * library containing this element has not yet been resolved. | |
| 2551 */ | |
| 2552 List<ElementAnnotation> get metadata; | |
| 2553 | |
| 2554 /** | |
| 2555 * Return the name of this element, or `null` if this element does not have a | |
| 2556 * name. | |
| 2557 */ | |
| 2558 String get name; | |
| 2559 | |
| 2560 /** | |
| 2561 * Return the length of the name of this element in the file that contains the | |
| 2562 * declaration of this element, or `0` if this element does not have a name. | |
| 2563 */ | |
| 2564 int get nameLength; | |
| 2565 | |
| 2566 /** | |
| 2567 * Return the offset of the name of this element in the file that contains the | |
| 2568 * declaration of this element, or `-1` if this element is synthetic, does not | |
| 2569 * have a name, or otherwise does not have an offset. | |
| 2570 */ | |
| 2571 int get nameOffset; | |
| 2572 | |
| 2573 /** | |
| 2574 * **DEPRECATED** Use `computeNode()` instead. | |
| 2575 * | |
| 2576 * Return the resolved [AstNode] node that declares this element, or `null` if | |
| 2577 * this element is synthetic or isn't contained in a compilation unit, such as | |
| 2578 * a [LibraryElement]. | |
| 2579 * | |
| 2580 * This method is expensive, because resolved AST might be evicted from cache, | |
| 2581 * so parsing and resolving will be performed. | |
| 2582 * | |
| 2583 * <b>Note:</b> This method cannot be used in an async environment. | |
| 2584 */ | |
| 2585 @deprecated | |
| 2586 AstNode get node; | |
| 2587 | |
| 2588 /** | |
| 2589 * Return the source that contains this element, or `null` if this element is | |
| 2590 * not contained in a source. | |
| 2591 */ | |
| 2592 Source get source; | |
| 2593 | |
| 2594 /** | |
| 2595 * Return the resolved [CompilationUnit] that declares this element, or `null` | |
| 2596 * if this element is synthetic. | |
| 2597 * | |
| 2598 * This method is expensive, because resolved AST might have been already | |
| 2599 * evicted from cache, so parsing and resolving will be performed. | |
| 2600 */ | |
| 2601 CompilationUnit get unit; | |
| 2602 | |
| 2603 /** | |
| 2604 * Use the given [visitor] to visit this element. Return the value returned by | |
| 2605 * the visitor as a result of visiting this element. | |
| 2606 */ | |
| 2607 accept(ElementVisitor visitor); | |
| 2608 | |
| 2609 /** | |
| 2610 * Return the documentation comment for this element as it appears in the | |
| 2611 * original source (complete with the beginning and ending delimiters), or | |
| 2612 * `null` if this element does not have a documentation comment associated | |
| 2613 * with it. This can be a long-running operation if the information needed to | |
| 2614 * access the comment is not cached. | |
| 2615 * | |
| 2616 * Throws [AnalysisException] if the documentation comment could not be | |
| 2617 * determined because the analysis could not be performed | |
| 2618 */ | |
| 2619 String computeDocumentationComment(); | |
| 2620 | |
| 2621 /** | |
| 2622 * Return the resolved [AstNode] node that declares this element, or `null` if | |
| 2623 * this element is synthetic or isn't contained in a compilation unit, such as | |
| 2624 * a [LibraryElement]. | |
| 2625 * | |
| 2626 * This method is expensive, because resolved AST might be evicted from cache, | |
| 2627 * so parsing and resolving will be performed. | |
| 2628 * | |
| 2629 * <b>Note:</b> This method cannot be used in an async environment. | |
| 2630 */ | |
| 2631 AstNode computeNode(); | |
| 2632 | |
| 2633 /** | |
| 2634 * Return the most immediate ancestor of this element for which the | |
| 2635 * [predicate] returns `true`, or `null` if there is no such ancestor. Note | |
| 2636 * that this element will never be returned. | |
| 2637 */ | |
| 2638 Element getAncestor(Predicate<Element> predicate); | |
| 2639 | |
| 2640 /** | |
| 2641 * Return a display name for the given element that includes the path to the | |
| 2642 * compilation unit in which the type is defined. If [shortName] is `null` | |
| 2643 * then [getDisplayName] will be used as the name of this element. Otherwise | |
| 2644 * the provided name will be used. | |
| 2645 */ | |
| 2646 // TODO(brianwilkerson) Make the parameter optional. | |
| 2647 String getExtendedDisplayName(String shortName); | |
| 2648 | |
| 2649 /** | |
| 2650 * Return `true` if this element, assuming that it is within scope, is | |
| 2651 * accessible to code in the given [library]. This is defined by the Dart | |
| 2652 * Language Specification in section 3.2: | |
| 2653 * <blockquote> | |
| 2654 * A declaration <i>m</i> is accessible to library <i>L</i> if <i>m</i> is | |
| 2655 * declared in <i>L</i> or if <i>m</i> is public. | |
| 2656 * </blockquote> | |
| 2657 */ | |
| 2658 bool isAccessibleIn(LibraryElement library); | |
| 2659 | |
| 2660 /** | |
| 2661 * Use the given [visitor] to visit all of the children of this element. There | |
| 2662 * is no guarantee of the order in which the children will be visited. | |
| 2663 */ | |
| 2664 void visitChildren(ElementVisitor visitor); | |
| 2665 } | |
| 2666 | |
| 2667 /** | |
| 2668 * A single annotation associated with an element. | |
| 2669 */ | |
| 2670 abstract class ElementAnnotation { | |
| 2671 /** | |
| 2672 * An empty list of annotations. | |
| 2673 */ | |
| 2674 static const List<ElementAnnotation> EMPTY_LIST = const <ElementAnnotation>[]; | |
| 2675 | |
| 2676 /** | |
| 2677 * Return a representation of the value of this annotation. | |
| 2678 * | |
| 2679 * Return `null` if the value of this annotation could not be computed because | |
| 2680 * of errors. | |
| 2681 */ | |
| 2682 DartObject get constantValue; | |
| 2683 | |
| 2684 /** | |
| 2685 * Return the element representing the field, variable, or const constructor | |
| 2686 * being used as an annotation. | |
| 2687 */ | |
| 2688 Element get element; | |
| 2689 | |
| 2690 /** | |
| 2691 * Return `true` if this annotation marks the associated element as being | |
| 2692 * deprecated. | |
| 2693 */ | |
| 2694 bool get isDeprecated; | |
| 2695 | |
| 2696 /** | |
| 2697 * Return `true` if this annotation marks the associated method as being | |
| 2698 * expected to override an inherited method. | |
| 2699 */ | |
| 2700 bool get isOverride; | |
| 2701 | |
| 2702 /** | |
| 2703 * Return `true` if this annotation marks the associated class as implementing | |
| 2704 * a proxy object. | |
| 2705 */ | |
| 2706 bool get isProxy; | |
| 2707 } | |
| 2708 | |
| 2709 /** | |
| 2710 * A concrete implementation of an [ElementAnnotation]. | |
| 2711 */ | |
| 2712 class ElementAnnotationImpl implements ElementAnnotation { | |
| 2713 /** | |
| 2714 * An empty list of annotations. | |
| 2715 */ | |
| 2716 @deprecated // Use ElementAnnotation.EMPTY_LIST | |
| 2717 static const List<ElementAnnotationImpl> EMPTY_ARRAY = | |
| 2718 const <ElementAnnotationImpl>[]; | |
| 2719 | |
| 2720 /** | |
| 2721 * The name of the class used to mark an element as being deprecated. | |
| 2722 */ | |
| 2723 static String _DEPRECATED_CLASS_NAME = "Deprecated"; | |
| 2724 | |
| 2725 /** | |
| 2726 * The name of the top-level variable used to mark an element as being | |
| 2727 * deprecated. | |
| 2728 */ | |
| 2729 static String _DEPRECATED_VARIABLE_NAME = "deprecated"; | |
| 2730 | |
| 2731 /** | |
| 2732 * The name of the top-level variable used to mark a method as being expected | |
| 2733 * to override an inherited method. | |
| 2734 */ | |
| 2735 static String _OVERRIDE_VARIABLE_NAME = "override"; | |
| 2736 | |
| 2737 /** | |
| 2738 * The name of the top-level variable used to mark a class as implementing a | |
| 2739 * proxy object. | |
| 2740 */ | |
| 2741 static String PROXY_VARIABLE_NAME = "proxy"; | |
| 2742 | |
| 2743 /** | |
| 2744 * The element representing the field, variable, or constructor being used as | |
| 2745 * an annotation. | |
| 2746 */ | |
| 2747 final Element element; | |
| 2748 | |
| 2749 /** | |
| 2750 * The result of evaluating this annotation as a compile-time constant | |
| 2751 * expression, or `null` if the compilation unit containing the variable has | |
| 2752 * not been resolved. | |
| 2753 */ | |
| 2754 EvaluationResultImpl evaluationResult; | |
| 2755 | |
| 2756 /** | |
| 2757 * Initialize a newly created annotation. The given [element] is the element | |
| 2758 * representing the field, variable, or constructor being used as an | |
| 2759 * annotation. | |
| 2760 */ | |
| 2761 ElementAnnotationImpl(this.element); | |
| 2762 | |
| 2763 @override | |
| 2764 DartObject get constantValue => evaluationResult.value; | |
| 2765 | |
| 2766 @override | |
| 2767 bool get isDeprecated { | |
| 2768 if (element != null) { | |
| 2769 LibraryElement library = element.library; | |
| 2770 if (library != null && library.isDartCore) { | |
| 2771 if (element is ConstructorElement) { | |
| 2772 ConstructorElement constructorElement = element as ConstructorElement; | |
| 2773 if (constructorElement.enclosingElement.name == | |
| 2774 _DEPRECATED_CLASS_NAME) { | |
| 2775 return true; | |
| 2776 } | |
| 2777 } else if (element is PropertyAccessorElement && | |
| 2778 element.name == _DEPRECATED_VARIABLE_NAME) { | |
| 2779 return true; | |
| 2780 } | |
| 2781 } | |
| 2782 } | |
| 2783 return false; | |
| 2784 } | |
| 2785 | |
| 2786 @override | |
| 2787 bool get isOverride { | |
| 2788 if (element != null) { | |
| 2789 LibraryElement library = element.library; | |
| 2790 if (library != null && library.isDartCore) { | |
| 2791 if (element is PropertyAccessorElement && | |
| 2792 element.name == _OVERRIDE_VARIABLE_NAME) { | |
| 2793 return true; | |
| 2794 } | |
| 2795 } | |
| 2796 } | |
| 2797 return false; | |
| 2798 } | |
| 2799 | |
| 2800 @override | |
| 2801 bool get isProxy { | |
| 2802 if (element != null) { | |
| 2803 LibraryElement library = element.library; | |
| 2804 if (library != null && library.isDartCore) { | |
| 2805 if (element is PropertyAccessorElement && | |
| 2806 element.name == PROXY_VARIABLE_NAME) { | |
| 2807 return true; | |
| 2808 } | |
| 2809 } | |
| 2810 } | |
| 2811 return false; | |
| 2812 } | |
| 2813 | |
| 2814 @override | |
| 2815 String toString() => '@$element'; | |
| 2816 } | |
| 2817 | |
| 2818 /** | |
| 2819 * A base class for concrete implementations of an [Element]. | |
| 2820 */ | |
| 2821 abstract class ElementImpl implements Element { | |
| 2822 static int _NEXT_ID = 0; | |
| 2823 | |
| 2824 final int id = _NEXT_ID++; | |
| 2825 | |
| 2826 /** | |
| 2827 * The enclosing element of this element, or `null` if this element is at the | |
| 2828 * root of the element structure. | |
| 2829 */ | |
| 2830 ElementImpl _enclosingElement; | |
| 2831 | |
| 2832 /** | |
| 2833 * The name of this element. | |
| 2834 */ | |
| 2835 String _name; | |
| 2836 | |
| 2837 /** | |
| 2838 * The offset of the name of this element in the file that contains the | |
| 2839 * declaration of this element. | |
| 2840 */ | |
| 2841 int _nameOffset = 0; | |
| 2842 | |
| 2843 /** | |
| 2844 * A bit-encoded form of the modifiers associated with this element. | |
| 2845 */ | |
| 2846 int _modifiers = 0; | |
| 2847 | |
| 2848 /** | |
| 2849 * A list containing all of the metadata associated with this element. | |
| 2850 */ | |
| 2851 List<ElementAnnotation> metadata = ElementAnnotation.EMPTY_LIST; | |
| 2852 | |
| 2853 /** | |
| 2854 * A cached copy of the calculated hashCode for this element. | |
| 2855 */ | |
| 2856 int _cachedHashCode; | |
| 2857 | |
| 2858 /** | |
| 2859 * A cached copy of the calculated location for this element. | |
| 2860 */ | |
| 2861 ElementLocation _cachedLocation; | |
| 2862 | |
| 2863 /** | |
| 2864 * The offset to the beginning of the documentation comment, | |
| 2865 * or `null` if this element does not have a documentation comment. | |
| 2866 */ | |
| 2867 int _docRangeOffset; | |
| 2868 | |
| 2869 /** | |
| 2870 * The length of the documentation comment range for this element. | |
| 2871 */ | |
| 2872 int _docRangeLength; | |
| 2873 | |
| 2874 /** | |
| 2875 * Initialize a newly created element to have the given [name] at the given | |
| 2876 * [_nameOffset]. | |
| 2877 */ | |
| 2878 ElementImpl(String name, this._nameOffset) { | |
| 2879 this._name = StringUtilities.intern(name); | |
| 2880 } | |
| 2881 | |
| 2882 /** | |
| 2883 * Initialize a newly created element to have the given [name]. | |
| 2884 */ | |
| 2885 ElementImpl.forNode(Identifier name) | |
| 2886 : this(name == null ? "" : name.name, name == null ? -1 : name.offset); | |
| 2887 | |
| 2888 @override | |
| 2889 AnalysisContext get context { | |
| 2890 if (_enclosingElement == null) { | |
| 2891 return null; | |
| 2892 } | |
| 2893 return _enclosingElement.context; | |
| 2894 } | |
| 2895 | |
| 2896 @override | |
| 2897 String get displayName => _name; | |
| 2898 | |
| 2899 @override | |
| 2900 SourceRange get docRange { | |
| 2901 if (_docRangeOffset != null && _docRangeLength != null) { | |
| 2902 return new SourceRange(_docRangeOffset, _docRangeLength); | |
| 2903 } | |
| 2904 return null; | |
| 2905 } | |
| 2906 | |
| 2907 @override | |
| 2908 Element get enclosingElement => _enclosingElement; | |
| 2909 | |
| 2910 /** | |
| 2911 * Set the enclosing element of this element to the given [element]. | |
| 2912 */ | |
| 2913 void set enclosingElement(Element element) { | |
| 2914 _enclosingElement = element as ElementImpl; | |
| 2915 _cachedLocation = null; | |
| 2916 _cachedHashCode = null; | |
| 2917 } | |
| 2918 | |
| 2919 @override | |
| 2920 int get hashCode { | |
| 2921 // TODO: We might want to re-visit this optimization in the future. | |
| 2922 // We cache the hash code value as this is a very frequently called method. | |
| 2923 if (_cachedHashCode == null) { | |
| 2924 int hashIdentifier = identifier.hashCode; | |
| 2925 Element enclosing = enclosingElement; | |
| 2926 if (enclosing != null) { | |
| 2927 _cachedHashCode = hashIdentifier + enclosing.hashCode; | |
| 2928 } else { | |
| 2929 _cachedHashCode = hashIdentifier; | |
| 2930 } | |
| 2931 } | |
| 2932 return _cachedHashCode; | |
| 2933 } | |
| 2934 | |
| 2935 /** | |
| 2936 * Return an identifier that uniquely identifies this element among the | |
| 2937 * children of this element's parent. | |
| 2938 */ | |
| 2939 String get identifier => name; | |
| 2940 | |
| 2941 @override | |
| 2942 bool get isDeprecated { | |
| 2943 for (ElementAnnotation annotation in metadata) { | |
| 2944 if (annotation.isDeprecated) { | |
| 2945 return true; | |
| 2946 } | |
| 2947 } | |
| 2948 return false; | |
| 2949 } | |
| 2950 | |
| 2951 @override | |
| 2952 bool get isOverride { | |
| 2953 for (ElementAnnotation annotation in metadata) { | |
| 2954 if (annotation.isOverride) { | |
| 2955 return true; | |
| 2956 } | |
| 2957 } | |
| 2958 return false; | |
| 2959 } | |
| 2960 | |
| 2961 @override | |
| 2962 bool get isPrivate { | |
| 2963 String name = displayName; | |
| 2964 if (name == null) { | |
| 2965 return true; | |
| 2966 } | |
| 2967 return Identifier.isPrivateName(name); | |
| 2968 } | |
| 2969 | |
| 2970 @override | |
| 2971 bool get isPublic => !isPrivate; | |
| 2972 | |
| 2973 @override | |
| 2974 bool get isSynthetic => hasModifier(Modifier.SYNTHETIC); | |
| 2975 | |
| 2976 @override | |
| 2977 LibraryElement get library => | |
| 2978 getAncestor((element) => element is LibraryElement); | |
| 2979 | |
| 2980 @override | |
| 2981 ElementLocation get location { | |
| 2982 if (_cachedLocation == null) { | |
| 2983 _cachedLocation = new ElementLocationImpl.con1(this); | |
| 2984 } | |
| 2985 return _cachedLocation; | |
| 2986 } | |
| 2987 | |
| 2988 @override | |
| 2989 String get name => _name; | |
| 2990 | |
| 2991 void set name(String name) { | |
| 2992 this._name = name; | |
| 2993 _cachedLocation = null; | |
| 2994 _cachedHashCode = null; | |
| 2995 } | |
| 2996 | |
| 2997 @override | |
| 2998 int get nameLength => displayName != null ? displayName.length : 0; | |
| 2999 | |
| 3000 @override | |
| 3001 int get nameOffset => _nameOffset; | |
| 3002 | |
| 3003 /** | |
| 3004 * Sets the offset of the name of this element in the file that contains the | |
| 3005 * declaration of this element. | |
| 3006 */ | |
| 3007 void set nameOffset(int offset) { | |
| 3008 _nameOffset = offset; | |
| 3009 _cachedHashCode = null; | |
| 3010 _cachedLocation = null; | |
| 3011 } | |
| 3012 | |
| 3013 @deprecated | |
| 3014 @override | |
| 3015 AstNode get node => computeNode(); | |
| 3016 | |
| 3017 @override | |
| 3018 Source get source { | |
| 3019 if (_enclosingElement == null) { | |
| 3020 return null; | |
| 3021 } | |
| 3022 return _enclosingElement.source; | |
| 3023 } | |
| 3024 | |
| 3025 /** | |
| 3026 * Set whether this element is synthetic. | |
| 3027 */ | |
| 3028 void set synthetic(bool isSynthetic) { | |
| 3029 setModifier(Modifier.SYNTHETIC, isSynthetic); | |
| 3030 } | |
| 3031 | |
| 3032 @override | |
| 3033 CompilationUnit get unit => context.resolveCompilationUnit(source, library); | |
| 3034 | |
| 3035 @override | |
| 3036 bool operator ==(Object object) { | |
| 3037 if (identical(this, object)) { | |
| 3038 return true; | |
| 3039 } | |
| 3040 if (object == null || hashCode != object.hashCode) { | |
| 3041 return false; | |
| 3042 } | |
| 3043 return object.runtimeType == runtimeType && | |
| 3044 (object as Element).location == location; | |
| 3045 } | |
| 3046 | |
| 3047 /** | |
| 3048 * Append a textual representation of this element to the given [buffer]. | |
| 3049 */ | |
| 3050 void appendTo(StringBuffer buffer) { | |
| 3051 if (_name == null) { | |
| 3052 buffer.write("<unnamed "); | |
| 3053 buffer.write(runtimeType.toString()); | |
| 3054 buffer.write(">"); | |
| 3055 } else { | |
| 3056 buffer.write(_name); | |
| 3057 } | |
| 3058 } | |
| 3059 | |
| 3060 @override | |
| 3061 String computeDocumentationComment() { | |
| 3062 AnalysisContext context = this.context; | |
| 3063 if (context == null) { | |
| 3064 return null; | |
| 3065 } | |
| 3066 return context.computeDocumentationComment(this); | |
| 3067 } | |
| 3068 | |
| 3069 @override | |
| 3070 AstNode computeNode() => getNodeMatching((node) => node is AstNode); | |
| 3071 | |
| 3072 /** | |
| 3073 * Set this element as the enclosing element for given [element]. | |
| 3074 */ | |
| 3075 void encloseElement(ElementImpl element) { | |
| 3076 element.enclosingElement = this; | |
| 3077 } | |
| 3078 | |
| 3079 @override | |
| 3080 Element getAncestor(Predicate<Element> predicate) { | |
| 3081 Element ancestor = _enclosingElement; | |
| 3082 while (ancestor != null && !predicate(ancestor)) { | |
| 3083 ancestor = ancestor.enclosingElement; | |
| 3084 } | |
| 3085 return ancestor; | |
| 3086 } | |
| 3087 | |
| 3088 /** | |
| 3089 * Return the child of this element that is uniquely identified by the given | |
| 3090 * [identifier], or `null` if there is no such child. | |
| 3091 */ | |
| 3092 ElementImpl getChild(String identifier) => null; | |
| 3093 | |
| 3094 @override | |
| 3095 String getExtendedDisplayName(String shortName) { | |
| 3096 if (shortName == null) { | |
| 3097 shortName = displayName; | |
| 3098 } | |
| 3099 Source source = this.source; | |
| 3100 if (source != null) { | |
| 3101 return "$shortName (${source.fullName})"; | |
| 3102 } | |
| 3103 return shortName; | |
| 3104 } | |
| 3105 | |
| 3106 /** | |
| 3107 * Return the resolved [AstNode] of the given type enclosing [getNameOffset]. | |
| 3108 */ | |
| 3109 AstNode getNodeMatching(Predicate<AstNode> predicate) { | |
| 3110 CompilationUnit unit = this.unit; | |
| 3111 if (unit == null) { | |
| 3112 return null; | |
| 3113 } | |
| 3114 int offset = nameOffset; | |
| 3115 AstNode node = new NodeLocator(offset).searchWithin(unit); | |
| 3116 if (node == null) { | |
| 3117 return null; | |
| 3118 } | |
| 3119 return node.getAncestor(predicate); | |
| 3120 } | |
| 3121 | |
| 3122 /** | |
| 3123 * Return `true` if this element has the given [modifier] associated with it. | |
| 3124 */ | |
| 3125 bool hasModifier(Modifier modifier) => | |
| 3126 BooleanArray.getEnum(_modifiers, modifier); | |
| 3127 | |
| 3128 @override | |
| 3129 bool isAccessibleIn(LibraryElement library) { | |
| 3130 if (Identifier.isPrivateName(_name)) { | |
| 3131 return library == this.library; | |
| 3132 } | |
| 3133 return true; | |
| 3134 } | |
| 3135 | |
| 3136 /** | |
| 3137 * If the given [child] is not `null`, use the given [visitor] to visit it. | |
| 3138 */ | |
| 3139 void safelyVisitChild(Element child, ElementVisitor visitor) { | |
| 3140 if (child != null) { | |
| 3141 child.accept(visitor); | |
| 3142 } | |
| 3143 } | |
| 3144 | |
| 3145 /** | |
| 3146 * Use the given [visitor] to visit all of the [children] in the given array. | |
| 3147 */ | |
| 3148 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { | |
| 3149 if (children != null) { | |
| 3150 for (Element child in children) { | |
| 3151 child.accept(visitor); | |
| 3152 } | |
| 3153 } | |
| 3154 } | |
| 3155 | |
| 3156 /** | |
| 3157 * Set the documentation comment source range for this element. | |
| 3158 */ | |
| 3159 void setDocRange(int offset, int length) { | |
| 3160 _docRangeOffset = offset; | |
| 3161 _docRangeLength = length; | |
| 3162 } | |
| 3163 | |
| 3164 /** | |
| 3165 * Set whether the given [modifier] is associated with this element to | |
| 3166 * correspond to the given [value]. | |
| 3167 */ | |
| 3168 void setModifier(Modifier modifier, bool value) { | |
| 3169 _modifiers = BooleanArray.setEnum(_modifiers, modifier, value); | |
| 3170 } | |
| 3171 | |
| 3172 @override | |
| 3173 String toString() { | |
| 3174 StringBuffer buffer = new StringBuffer(); | |
| 3175 appendTo(buffer); | |
| 3176 return buffer.toString(); | |
| 3177 } | |
| 3178 | |
| 3179 @override | |
| 3180 void visitChildren(ElementVisitor visitor) { | |
| 3181 // There are no children to visit | |
| 3182 } | |
| 3183 } | |
| 3184 | |
| 3185 /** | |
| 3186 * The enumeration `ElementKind` defines the various kinds of elements in the | |
| 3187 * element model. | |
| 3188 */ | |
| 3189 class ElementKind extends Enum<ElementKind> { | |
| 3190 static const ElementKind CLASS = const ElementKind('CLASS', 0, "class"); | |
| 3191 | |
| 3192 static const ElementKind COMPILATION_UNIT = | |
| 3193 const ElementKind('COMPILATION_UNIT', 1, "compilation unit"); | |
| 3194 | |
| 3195 static const ElementKind CONSTRUCTOR = | |
| 3196 const ElementKind('CONSTRUCTOR', 2, "constructor"); | |
| 3197 | |
| 3198 static const ElementKind DYNAMIC = | |
| 3199 const ElementKind('DYNAMIC', 3, "<dynamic>"); | |
| 3200 | |
| 3201 static const ElementKind EMBEDDED_HTML_SCRIPT = | |
| 3202 const ElementKind('EMBEDDED_HTML_SCRIPT', 4, "embedded html script"); | |
| 3203 | |
| 3204 static const ElementKind ERROR = const ElementKind('ERROR', 5, "<error>"); | |
| 3205 | |
| 3206 static const ElementKind EXPORT = | |
| 3207 const ElementKind('EXPORT', 6, "export directive"); | |
| 3208 | |
| 3209 static const ElementKind EXTERNAL_HTML_SCRIPT = | |
| 3210 const ElementKind('EXTERNAL_HTML_SCRIPT', 7, "external html script"); | |
| 3211 | |
| 3212 static const ElementKind FIELD = const ElementKind('FIELD', 8, "field"); | |
| 3213 | |
| 3214 static const ElementKind FUNCTION = | |
| 3215 const ElementKind('FUNCTION', 9, "function"); | |
| 3216 | |
| 3217 static const ElementKind GETTER = const ElementKind('GETTER', 10, "getter"); | |
| 3218 | |
| 3219 static const ElementKind HTML = const ElementKind('HTML', 11, "html"); | |
| 3220 | |
| 3221 static const ElementKind IMPORT = | |
| 3222 const ElementKind('IMPORT', 12, "import directive"); | |
| 3223 | |
| 3224 static const ElementKind LABEL = const ElementKind('LABEL', 13, "label"); | |
| 3225 | |
| 3226 static const ElementKind LIBRARY = | |
| 3227 const ElementKind('LIBRARY', 14, "library"); | |
| 3228 | |
| 3229 static const ElementKind LOCAL_VARIABLE = | |
| 3230 const ElementKind('LOCAL_VARIABLE', 15, "local variable"); | |
| 3231 | |
| 3232 static const ElementKind METHOD = const ElementKind('METHOD', 16, "method"); | |
| 3233 | |
| 3234 static const ElementKind NAME = const ElementKind('NAME', 17, "<name>"); | |
| 3235 | |
| 3236 static const ElementKind PARAMETER = | |
| 3237 const ElementKind('PARAMETER', 18, "parameter"); | |
| 3238 | |
| 3239 static const ElementKind PREFIX = | |
| 3240 const ElementKind('PREFIX', 19, "import prefix"); | |
| 3241 | |
| 3242 static const ElementKind SETTER = const ElementKind('SETTER', 20, "setter"); | |
| 3243 | |
| 3244 static const ElementKind TOP_LEVEL_VARIABLE = | |
| 3245 const ElementKind('TOP_LEVEL_VARIABLE', 21, "top level variable"); | |
| 3246 | |
| 3247 static const ElementKind FUNCTION_TYPE_ALIAS = | |
| 3248 const ElementKind('FUNCTION_TYPE_ALIAS', 22, "function type alias"); | |
| 3249 | |
| 3250 static const ElementKind TYPE_PARAMETER = | |
| 3251 const ElementKind('TYPE_PARAMETER', 23, "type parameter"); | |
| 3252 | |
| 3253 static const ElementKind UNIVERSE = | |
| 3254 const ElementKind('UNIVERSE', 24, "<universe>"); | |
| 3255 | |
| 3256 static const List<ElementKind> values = const [ | |
| 3257 CLASS, | |
| 3258 COMPILATION_UNIT, | |
| 3259 CONSTRUCTOR, | |
| 3260 DYNAMIC, | |
| 3261 EMBEDDED_HTML_SCRIPT, | |
| 3262 ERROR, | |
| 3263 EXPORT, | |
| 3264 EXTERNAL_HTML_SCRIPT, | |
| 3265 FIELD, | |
| 3266 FUNCTION, | |
| 3267 GETTER, | |
| 3268 HTML, | |
| 3269 IMPORT, | |
| 3270 LABEL, | |
| 3271 LIBRARY, | |
| 3272 LOCAL_VARIABLE, | |
| 3273 METHOD, | |
| 3274 NAME, | |
| 3275 PARAMETER, | |
| 3276 PREFIX, | |
| 3277 SETTER, | |
| 3278 TOP_LEVEL_VARIABLE, | |
| 3279 FUNCTION_TYPE_ALIAS, | |
| 3280 TYPE_PARAMETER, | |
| 3281 UNIVERSE | |
| 3282 ]; | |
| 3283 | |
| 3284 /** | |
| 3285 * The name displayed in the UI for this kind of element. | |
| 3286 */ | |
| 3287 final String displayName; | |
| 3288 | |
| 3289 /** | |
| 3290 * Initialize a newly created element kind to have the given [displayName]. | |
| 3291 */ | |
| 3292 const ElementKind(String name, int ordinal, this.displayName) | |
| 3293 : super(name, ordinal); | |
| 3294 | |
| 3295 /** | |
| 3296 * Return the kind of the given [element], or [ERROR] if the element is | |
| 3297 * `null`. This is a utility method that can reduce the need for null checks | |
| 3298 * in other places. | |
| 3299 */ | |
| 3300 static ElementKind of(Element element) { | |
| 3301 if (element == null) { | |
| 3302 return ERROR; | |
| 3303 } | |
| 3304 return element.kind; | |
| 3305 } | |
| 3306 } | |
| 3307 | |
| 3308 /** | |
| 3309 * The location of an element within the element model. | |
| 3310 */ | |
| 3311 abstract class ElementLocation { | |
| 3312 /** | |
| 3313 * Return the path to the element whose location is represented by this | |
| 3314 * object. Clients must not modify the returned array. | |
| 3315 */ | |
| 3316 List<String> get components; | |
| 3317 | |
| 3318 /** | |
| 3319 * Return an encoded representation of this location that can be used to | |
| 3320 * create a location that is equal to this location. | |
| 3321 */ | |
| 3322 String get encoding; | |
| 3323 } | |
| 3324 | |
| 3325 /** | |
| 3326 * A concrete implementation of an [ElementLocation]. | |
| 3327 */ | |
| 3328 class ElementLocationImpl implements ElementLocation { | |
| 3329 /** | |
| 3330 * The character used to separate components in the encoded form. | |
| 3331 */ | |
| 3332 static int _SEPARATOR_CHAR = 0x3B; | |
| 3333 | |
| 3334 /** | |
| 3335 * The path to the element whose location is represented by this object. | |
| 3336 */ | |
| 3337 List<String> _components; | |
| 3338 | |
| 3339 /** | |
| 3340 * The object managing [indexKeyId] and [indexLocationId]. | |
| 3341 */ | |
| 3342 Object indexOwner; | |
| 3343 | |
| 3344 /** | |
| 3345 * A cached id of this location in index. | |
| 3346 */ | |
| 3347 int indexKeyId; | |
| 3348 | |
| 3349 /** | |
| 3350 * A cached id of this location in index. | |
| 3351 */ | |
| 3352 int indexLocationId; | |
| 3353 | |
| 3354 /** | |
| 3355 * Initialize a newly created location to represent the given [element]. | |
| 3356 */ | |
| 3357 ElementLocationImpl.con1(Element element) { | |
| 3358 List<String> components = new List<String>(); | |
| 3359 Element ancestor = element; | |
| 3360 while (ancestor != null) { | |
| 3361 components.insert(0, (ancestor as ElementImpl).identifier); | |
| 3362 ancestor = ancestor.enclosingElement; | |
| 3363 } | |
| 3364 this._components = components; | |
| 3365 } | |
| 3366 | |
| 3367 /** | |
| 3368 * Initialize a newly created location from the given [encoding]. | |
| 3369 */ | |
| 3370 ElementLocationImpl.con2(String encoding) { | |
| 3371 this._components = _decode(encoding); | |
| 3372 } | |
| 3373 | |
| 3374 /** | |
| 3375 * Initialize a newly created location from the given [components]. | |
| 3376 */ | |
| 3377 ElementLocationImpl.con3(List<String> components) { | |
| 3378 this._components = components; | |
| 3379 } | |
| 3380 | |
| 3381 @override | |
| 3382 List<String> get components => _components; | |
| 3383 | |
| 3384 @override | |
| 3385 String get encoding { | |
| 3386 StringBuffer buffer = new StringBuffer(); | |
| 3387 int length = _components.length; | |
| 3388 for (int i = 0; i < length; i++) { | |
| 3389 if (i > 0) { | |
| 3390 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 3391 } | |
| 3392 _encode(buffer, _components[i]); | |
| 3393 } | |
| 3394 return buffer.toString(); | |
| 3395 } | |
| 3396 | |
| 3397 @override | |
| 3398 int get hashCode { | |
| 3399 int result = 1; | |
| 3400 for (int i = 0; i < _components.length; i++) { | |
| 3401 String component = _components[i]; | |
| 3402 result = 31 * result + component.hashCode; | |
| 3403 } | |
| 3404 return result; | |
| 3405 } | |
| 3406 | |
| 3407 @override | |
| 3408 bool operator ==(Object object) { | |
| 3409 if (identical(this, object)) { | |
| 3410 return true; | |
| 3411 } | |
| 3412 if (object is! ElementLocationImpl) { | |
| 3413 return false; | |
| 3414 } | |
| 3415 ElementLocationImpl location = object as ElementLocationImpl; | |
| 3416 List<String> otherComponents = location._components; | |
| 3417 int length = _components.length; | |
| 3418 if (otherComponents.length != length) { | |
| 3419 return false; | |
| 3420 } | |
| 3421 for (int i = 0; i < length; i++) { | |
| 3422 if (_components[i] != otherComponents[i]) { | |
| 3423 return false; | |
| 3424 } | |
| 3425 } | |
| 3426 return true; | |
| 3427 } | |
| 3428 | |
| 3429 @override | |
| 3430 String toString() => encoding; | |
| 3431 | |
| 3432 /** | |
| 3433 * Decode the [encoding] of a location into a list of components and return | |
| 3434 * the components. | |
| 3435 */ | |
| 3436 List<String> _decode(String encoding) { | |
| 3437 List<String> components = new List<String>(); | |
| 3438 StringBuffer buffer = new StringBuffer(); | |
| 3439 int index = 0; | |
| 3440 int length = encoding.length; | |
| 3441 while (index < length) { | |
| 3442 int currentChar = encoding.codeUnitAt(index); | |
| 3443 if (currentChar == _SEPARATOR_CHAR) { | |
| 3444 if (index + 1 < length && | |
| 3445 encoding.codeUnitAt(index + 1) == _SEPARATOR_CHAR) { | |
| 3446 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 3447 index += 2; | |
| 3448 } else { | |
| 3449 components.add(buffer.toString()); | |
| 3450 buffer = new StringBuffer(); | |
| 3451 index++; | |
| 3452 } | |
| 3453 } else { | |
| 3454 buffer.writeCharCode(currentChar); | |
| 3455 index++; | |
| 3456 } | |
| 3457 } | |
| 3458 components.add(buffer.toString()); | |
| 3459 return components; | |
| 3460 } | |
| 3461 | |
| 3462 /** | |
| 3463 * Append an encoded form of the given [component] to the given [buffer]. | |
| 3464 */ | |
| 3465 void _encode(StringBuffer buffer, String component) { | |
| 3466 int length = component.length; | |
| 3467 for (int i = 0; i < length; i++) { | |
| 3468 int currentChar = component.codeUnitAt(i); | |
| 3469 if (currentChar == _SEPARATOR_CHAR) { | |
| 3470 buffer.writeCharCode(_SEPARATOR_CHAR); | |
| 3471 } | |
| 3472 buffer.writeCharCode(currentChar); | |
| 3473 } | |
| 3474 } | |
| 3475 } | |
| 3476 | |
| 3477 /** | |
| 3478 * An object that can be used to visit an element structure. | |
| 3479 */ | |
| 3480 abstract class ElementVisitor<R> { | |
| 3481 R visitClassElement(ClassElement element); | |
| 3482 | |
| 3483 R visitCompilationUnitElement(CompilationUnitElement element); | |
| 3484 | |
| 3485 R visitConstructorElement(ConstructorElement element); | |
| 3486 | |
| 3487 @deprecated | |
| 3488 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element); | |
| 3489 | |
| 3490 R visitExportElement(ExportElement element); | |
| 3491 | |
| 3492 @deprecated | |
| 3493 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element); | |
| 3494 | |
| 3495 R visitFieldElement(FieldElement element); | |
| 3496 | |
| 3497 R visitFieldFormalParameterElement(FieldFormalParameterElement element); | |
| 3498 | |
| 3499 R visitFunctionElement(FunctionElement element); | |
| 3500 | |
| 3501 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element); | |
| 3502 | |
| 3503 @deprecated | |
| 3504 R visitHtmlElement(HtmlElement element); | |
| 3505 | |
| 3506 R visitImportElement(ImportElement element); | |
| 3507 | |
| 3508 R visitLabelElement(LabelElement element); | |
| 3509 | |
| 3510 R visitLibraryElement(LibraryElement element); | |
| 3511 | |
| 3512 R visitLocalVariableElement(LocalVariableElement element); | |
| 3513 | |
| 3514 R visitMethodElement(MethodElement element); | |
| 3515 | |
| 3516 R visitMultiplyDefinedElement(MultiplyDefinedElement element); | |
| 3517 | |
| 3518 R visitParameterElement(ParameterElement element); | |
| 3519 | |
| 3520 R visitPrefixElement(PrefixElement element); | |
| 3521 | |
| 3522 R visitPropertyAccessorElement(PropertyAccessorElement element); | |
| 3523 | |
| 3524 R visitTopLevelVariableElement(TopLevelVariableElement element); | |
| 3525 | |
| 3526 R visitTypeParameterElement(TypeParameterElement element); | |
| 3527 } | |
| 3528 | |
| 3529 /** | |
| 3530 * A script tag in an HTML file having content that defines a Dart library. | |
| 3531 */ | 15 */ |
| 3532 @deprecated | 16 @deprecated |
| 3533 abstract class EmbeddedHtmlScriptElement implements HtmlScriptElement { | 17 library analyzer.src.generated.element; |
| 3534 /** | |
| 3535 * Return the library element defined by the content of the script tag. | |
| 3536 */ | |
| 3537 LibraryElement get scriptLibrary; | |
| 3538 } | |
| 3539 | 18 |
| 3540 /** | 19 export 'package:analyzer/dart/element/element.dart'; |
| 3541 * A concrete implementation of an [EmbeddedHtmlScriptElement]. | 20 export 'package:analyzer/dart/element/type.dart'; |
| 3542 */ | 21 export 'package:analyzer/dart/element/visitor.dart'; |
| 3543 @deprecated | 22 export 'package:analyzer/src/dart/element/element.dart'; |
| 3544 class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl | 23 export 'package:analyzer/src/dart/element/member.dart'; |
| 3545 implements EmbeddedHtmlScriptElement { | 24 export 'package:analyzer/src/dart/element/type.dart'; |
| 3546 /** | |
| 3547 * The library defined by the script tag's content. | |
| 3548 */ | |
| 3549 LibraryElement _scriptLibrary; | |
| 3550 | |
| 3551 /** | |
| 3552 * Initialize a newly created script element to represent the given [node]. | |
| 3553 */ | |
| 3554 EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node); | |
| 3555 | |
| 3556 @override | |
| 3557 ElementKind get kind => ElementKind.EMBEDDED_HTML_SCRIPT; | |
| 3558 | |
| 3559 @override | |
| 3560 LibraryElement get scriptLibrary => _scriptLibrary; | |
| 3561 | |
| 3562 /** | |
| 3563 * Set the script library defined by the script tag's content to the given | |
| 3564 * [library]. | |
| 3565 */ | |
| 3566 void set scriptLibrary(LibraryElementImpl library) { | |
| 3567 library.enclosingElement = this; | |
| 3568 _scriptLibrary = library; | |
| 3569 } | |
| 3570 | |
| 3571 @override | |
| 3572 accept(ElementVisitor visitor) => | |
| 3573 visitor.visitEmbeddedHtmlScriptElement(this); | |
| 3574 | |
| 3575 @override | |
| 3576 void visitChildren(ElementVisitor visitor) { | |
| 3577 safelyVisitChild(_scriptLibrary, visitor); | |
| 3578 } | |
| 3579 } | |
| 3580 | |
| 3581 /** | |
| 3582 * An element representing an executable object, including functions, methods, | |
| 3583 * constructors, getters, and setters. | |
| 3584 */ | |
| 3585 abstract class ExecutableElement implements Element { | |
| 3586 /** | |
| 3587 * An empty list of executable elements. | |
| 3588 */ | |
| 3589 static const List<ExecutableElement> EMPTY_LIST = const <ExecutableElement>[]; | |
| 3590 | |
| 3591 /** | |
| 3592 * Return a list containing all of the functions defined within this | |
| 3593 * executable element. | |
| 3594 */ | |
| 3595 List<FunctionElement> get functions; | |
| 3596 | |
| 3597 /** | |
| 3598 * Return `true` if this executable element did not have an explicit return | |
| 3599 * type specified for it in the original source. Note that if there was no | |
| 3600 * explicit return type, and if the element model is fully populated, then | |
| 3601 * the [returnType] will not be `null`. | |
| 3602 */ | |
| 3603 bool get hasImplicitReturnType; | |
| 3604 | |
| 3605 /** | |
| 3606 * Return `true` if this executable element is abstract. Executable elements | |
| 3607 * are abstract if they are not external and have no body. | |
| 3608 */ | |
| 3609 bool get isAbstract; | |
| 3610 | |
| 3611 /** | |
| 3612 * Return `true` if this executable element has body marked as being | |
| 3613 * asynchronous. | |
| 3614 */ | |
| 3615 bool get isAsynchronous; | |
| 3616 | |
| 3617 /** | |
| 3618 * Return `true` if this executable element is external. Executable elements | |
| 3619 * are external if they are explicitly marked as such using the 'external' | |
| 3620 * keyword. | |
| 3621 */ | |
| 3622 bool get isExternal; | |
| 3623 | |
| 3624 /** | |
| 3625 * Return `true` if this executable element has a body marked as being a | |
| 3626 * generator. | |
| 3627 */ | |
| 3628 bool get isGenerator; | |
| 3629 | |
| 3630 /** | |
| 3631 * Return `true` if this executable element is an operator. The test may be | |
| 3632 * based on the name of the executable element, in which case the result will | |
| 3633 * be correct when the name is legal. | |
| 3634 */ | |
| 3635 bool get isOperator; | |
| 3636 | |
| 3637 /** | |
| 3638 * Return `true` if this element is a static element. A static element is an | |
| 3639 * element that is not associated with a particular instance, but rather with | |
| 3640 * an entire library or class. | |
| 3641 */ | |
| 3642 bool get isStatic; | |
| 3643 | |
| 3644 /** | |
| 3645 * Return `true` if this executable element has a body marked as being | |
| 3646 * synchronous. | |
| 3647 */ | |
| 3648 bool get isSynchronous; | |
| 3649 | |
| 3650 /** | |
| 3651 * Return a list containing all of the labels defined within this executable | |
| 3652 * element. | |
| 3653 */ | |
| 3654 List<LabelElement> get labels; | |
| 3655 | |
| 3656 /** | |
| 3657 * Return a list containing all of the local variables defined within this | |
| 3658 * executable element. | |
| 3659 */ | |
| 3660 List<LocalVariableElement> get localVariables; | |
| 3661 | |
| 3662 /** | |
| 3663 * Return a list containing all of the parameters defined by this executable | |
| 3664 * element. | |
| 3665 */ | |
| 3666 List<ParameterElement> get parameters; | |
| 3667 | |
| 3668 /** | |
| 3669 * Return the return type defined by this executable element. If the element | |
| 3670 * model is fully populated, then the [returnType] will not be `null`, even | |
| 3671 * if no return type was explicitly specified. | |
| 3672 */ | |
| 3673 DartType get returnType; | |
| 3674 | |
| 3675 /** | |
| 3676 * Return the type of function defined by this executable element. | |
| 3677 */ | |
| 3678 FunctionType get type; | |
| 3679 | |
| 3680 /** | |
| 3681 * Return a list containing all of the type parameters defined for this | |
| 3682 * executable element. | |
| 3683 */ | |
| 3684 List<TypeParameterElement> get typeParameters; | |
| 3685 } | |
| 3686 | |
| 3687 /** | |
| 3688 * A base class for concrete implementations of an [ExecutableElement]. | |
| 3689 */ | |
| 3690 abstract class ExecutableElementImpl extends ElementImpl | |
| 3691 implements ExecutableElement { | |
| 3692 /** | |
| 3693 * An empty list of executable elements. | |
| 3694 */ | |
| 3695 @deprecated // Use ExecutableElement.EMPTY_LIST | |
| 3696 static const List<ExecutableElement> EMPTY_ARRAY = | |
| 3697 const <ExecutableElement>[]; | |
| 3698 | |
| 3699 /** | |
| 3700 * A list containing all of the functions defined within this executable | |
| 3701 * element. | |
| 3702 */ | |
| 3703 List<FunctionElement> _functions = FunctionElement.EMPTY_LIST; | |
| 3704 | |
| 3705 /** | |
| 3706 * A list containing all of the labels defined within this executable element. | |
| 3707 */ | |
| 3708 List<LabelElement> _labels = LabelElement.EMPTY_LIST; | |
| 3709 | |
| 3710 /** | |
| 3711 * A list containing all of the local variables defined within this executable | |
| 3712 * element. | |
| 3713 */ | |
| 3714 List<LocalVariableElement> _localVariables = LocalVariableElement.EMPTY_LIST; | |
| 3715 | |
| 3716 /** | |
| 3717 * A list containing all of the parameters defined by this executable element. | |
| 3718 */ | |
| 3719 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 3720 | |
| 3721 /** | |
| 3722 * A list containing all of the type parameters defined for this executable | |
| 3723 * element. | |
| 3724 */ | |
| 3725 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 3726 | |
| 3727 /** | |
| 3728 * The return type defined by this executable element. | |
| 3729 */ | |
| 3730 DartType returnType; | |
| 3731 | |
| 3732 /** | |
| 3733 * The type of function defined by this executable element. | |
| 3734 */ | |
| 3735 FunctionType type; | |
| 3736 | |
| 3737 /** | |
| 3738 * Initialize a newly created executable element to have the given [name] and | |
| 3739 * [offset]. | |
| 3740 */ | |
| 3741 ExecutableElementImpl(String name, int offset) : super(name, offset); | |
| 3742 | |
| 3743 /** | |
| 3744 * Initialize a newly created executable element to have the given [name]. | |
| 3745 */ | |
| 3746 ExecutableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 3747 | |
| 3748 /** | |
| 3749 * Set whether this executable element's body is asynchronous. | |
| 3750 */ | |
| 3751 void set asynchronous(bool isAsynchronous) { | |
| 3752 setModifier(Modifier.ASYNCHRONOUS, isAsynchronous); | |
| 3753 } | |
| 3754 | |
| 3755 /** | |
| 3756 * Set whether this executable element is external. | |
| 3757 */ | |
| 3758 void set external(bool isExternal) { | |
| 3759 setModifier(Modifier.EXTERNAL, isExternal); | |
| 3760 } | |
| 3761 | |
| 3762 @override | |
| 3763 List<FunctionElement> get functions => _functions; | |
| 3764 | |
| 3765 /** | |
| 3766 * Set the functions defined within this executable element to the given | |
| 3767 * [functions]. | |
| 3768 */ | |
| 3769 void set functions(List<FunctionElement> functions) { | |
| 3770 for (FunctionElement function in functions) { | |
| 3771 (function as FunctionElementImpl).enclosingElement = this; | |
| 3772 } | |
| 3773 this._functions = functions; | |
| 3774 } | |
| 3775 | |
| 3776 /** | |
| 3777 * Set whether this method's body is a generator. | |
| 3778 */ | |
| 3779 void set generator(bool isGenerator) { | |
| 3780 setModifier(Modifier.GENERATOR, isGenerator); | |
| 3781 } | |
| 3782 | |
| 3783 @override | |
| 3784 bool get hasImplicitReturnType => hasModifier(Modifier.IMPLICIT_TYPE); | |
| 3785 | |
| 3786 /** | |
| 3787 * Set whether this executable element has an implicit return type. | |
| 3788 */ | |
| 3789 void set hasImplicitReturnType(bool hasImplicitReturnType) { | |
| 3790 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType); | |
| 3791 } | |
| 3792 | |
| 3793 @override | |
| 3794 bool get isAbstract => hasModifier(Modifier.ABSTRACT); | |
| 3795 | |
| 3796 @override | |
| 3797 bool get isAsynchronous => hasModifier(Modifier.ASYNCHRONOUS); | |
| 3798 | |
| 3799 @override | |
| 3800 bool get isExternal => hasModifier(Modifier.EXTERNAL); | |
| 3801 | |
| 3802 @override | |
| 3803 bool get isGenerator => hasModifier(Modifier.GENERATOR); | |
| 3804 | |
| 3805 @override | |
| 3806 bool get isOperator => false; | |
| 3807 | |
| 3808 @override | |
| 3809 bool get isSynchronous => !hasModifier(Modifier.ASYNCHRONOUS); | |
| 3810 | |
| 3811 @override | |
| 3812 List<LabelElement> get labels => _labels; | |
| 3813 | |
| 3814 /** | |
| 3815 * Set the labels defined within this executable element to the given | |
| 3816 * [labels]. | |
| 3817 */ | |
| 3818 void set labels(List<LabelElement> labels) { | |
| 3819 for (LabelElement label in labels) { | |
| 3820 (label as LabelElementImpl).enclosingElement = this; | |
| 3821 } | |
| 3822 this._labels = labels; | |
| 3823 } | |
| 3824 | |
| 3825 @override | |
| 3826 List<LocalVariableElement> get localVariables => _localVariables; | |
| 3827 | |
| 3828 /** | |
| 3829 * Set the local variables defined within this executable element to the given | |
| 3830 * [variables]. | |
| 3831 */ | |
| 3832 void set localVariables(List<LocalVariableElement> variables) { | |
| 3833 for (LocalVariableElement variable in variables) { | |
| 3834 (variable as LocalVariableElementImpl).enclosingElement = this; | |
| 3835 } | |
| 3836 this._localVariables = variables; | |
| 3837 } | |
| 3838 | |
| 3839 @override | |
| 3840 List<ParameterElement> get parameters => _parameters; | |
| 3841 | |
| 3842 /** | |
| 3843 * Set the parameters defined by this executable element to the given | |
| 3844 * [parameters]. | |
| 3845 */ | |
| 3846 void set parameters(List<ParameterElement> parameters) { | |
| 3847 for (ParameterElement parameter in parameters) { | |
| 3848 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 3849 } | |
| 3850 this._parameters = parameters; | |
| 3851 } | |
| 3852 | |
| 3853 @override | |
| 3854 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 3855 | |
| 3856 /** | |
| 3857 * Set the type parameters defined by this executable element to the given | |
| 3858 * [typeParameters]. | |
| 3859 */ | |
| 3860 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 3861 for (TypeParameterElement parameter in typeParameters) { | |
| 3862 (parameter as TypeParameterElementImpl).enclosingElement = this; | |
| 3863 } | |
| 3864 this._typeParameters = typeParameters; | |
| 3865 } | |
| 3866 | |
| 3867 @override | |
| 3868 void appendTo(StringBuffer buffer) { | |
| 3869 if (this.kind != ElementKind.GETTER) { | |
| 3870 int typeParameterCount = _typeParameters.length; | |
| 3871 if (typeParameterCount > 0) { | |
| 3872 buffer.write('<'); | |
| 3873 for (int i = 0; i < typeParameterCount; i++) { | |
| 3874 if (i > 0) { | |
| 3875 buffer.write(", "); | |
| 3876 } | |
| 3877 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 3878 } | |
| 3879 buffer.write('>'); | |
| 3880 } | |
| 3881 buffer.write("("); | |
| 3882 String closing = null; | |
| 3883 ParameterKind kind = ParameterKind.REQUIRED; | |
| 3884 int parameterCount = _parameters.length; | |
| 3885 for (int i = 0; i < parameterCount; i++) { | |
| 3886 if (i > 0) { | |
| 3887 buffer.write(", "); | |
| 3888 } | |
| 3889 ParameterElementImpl parameter = _parameters[i] as ParameterElementImpl; | |
| 3890 ParameterKind parameterKind = parameter.parameterKind; | |
| 3891 if (parameterKind != kind) { | |
| 3892 if (closing != null) { | |
| 3893 buffer.write(closing); | |
| 3894 } | |
| 3895 if (parameterKind == ParameterKind.POSITIONAL) { | |
| 3896 buffer.write("["); | |
| 3897 closing = "]"; | |
| 3898 } else if (parameterKind == ParameterKind.NAMED) { | |
| 3899 buffer.write("{"); | |
| 3900 closing = "}"; | |
| 3901 } else { | |
| 3902 closing = null; | |
| 3903 } | |
| 3904 } | |
| 3905 kind = parameterKind; | |
| 3906 parameter.appendToWithoutDelimiters(buffer); | |
| 3907 } | |
| 3908 if (closing != null) { | |
| 3909 buffer.write(closing); | |
| 3910 } | |
| 3911 buffer.write(")"); | |
| 3912 } | |
| 3913 if (type != null) { | |
| 3914 buffer.write(Element.RIGHT_ARROW); | |
| 3915 buffer.write(type.returnType); | |
| 3916 } | |
| 3917 } | |
| 3918 | |
| 3919 @override | |
| 3920 ElementImpl getChild(String identifier) { | |
| 3921 for (ExecutableElement function in _functions) { | |
| 3922 if ((function as ExecutableElementImpl).identifier == identifier) { | |
| 3923 return function as ExecutableElementImpl; | |
| 3924 } | |
| 3925 } | |
| 3926 for (LabelElement label in _labels) { | |
| 3927 if ((label as LabelElementImpl).identifier == identifier) { | |
| 3928 return label as LabelElementImpl; | |
| 3929 } | |
| 3930 } | |
| 3931 for (VariableElement variable in _localVariables) { | |
| 3932 if ((variable as VariableElementImpl).identifier == identifier) { | |
| 3933 return variable as VariableElementImpl; | |
| 3934 } | |
| 3935 } | |
| 3936 for (ParameterElement parameter in _parameters) { | |
| 3937 if ((parameter as ParameterElementImpl).identifier == identifier) { | |
| 3938 return parameter as ParameterElementImpl; | |
| 3939 } | |
| 3940 } | |
| 3941 return null; | |
| 3942 } | |
| 3943 | |
| 3944 @override | |
| 3945 void visitChildren(ElementVisitor visitor) { | |
| 3946 super.visitChildren(visitor); | |
| 3947 safelyVisitChildren(_functions, visitor); | |
| 3948 safelyVisitChildren(_labels, visitor); | |
| 3949 safelyVisitChildren(_localVariables, visitor); | |
| 3950 safelyVisitChildren(_parameters, visitor); | |
| 3951 } | |
| 3952 } | |
| 3953 | |
| 3954 /** | |
| 3955 * An executable element defined in a parameterized type where the values of the | |
| 3956 * type parameters are known. | |
| 3957 */ | |
| 3958 abstract class ExecutableMember extends Member implements ExecutableElement { | |
| 3959 /** | |
| 3960 * Initialize a newly created element to represent a constructor, based on the | |
| 3961 * [baseElement], defined by the [definingType]. | |
| 3962 */ | |
| 3963 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType) | |
| 3964 : super(baseElement, definingType); | |
| 3965 | |
| 3966 @override | |
| 3967 ExecutableElement get baseElement => super.baseElement as ExecutableElement; | |
| 3968 | |
| 3969 @override | |
| 3970 List<FunctionElement> get functions { | |
| 3971 // | |
| 3972 // Elements within this element should have type parameters substituted, | |
| 3973 // just like this element. | |
| 3974 // | |
| 3975 throw new UnsupportedOperationException(); | |
| 3976 // return getBaseElement().getFunctions(); | |
| 3977 } | |
| 3978 | |
| 3979 @override | |
| 3980 bool get hasImplicitReturnType => baseElement.hasImplicitReturnType; | |
| 3981 | |
| 3982 @override | |
| 3983 bool get isAbstract => baseElement.isAbstract; | |
| 3984 | |
| 3985 @override | |
| 3986 bool get isAsynchronous => baseElement.isAsynchronous; | |
| 3987 | |
| 3988 @override | |
| 3989 bool get isExternal => baseElement.isExternal; | |
| 3990 | |
| 3991 @override | |
| 3992 bool get isGenerator => baseElement.isGenerator; | |
| 3993 | |
| 3994 @override | |
| 3995 bool get isOperator => baseElement.isOperator; | |
| 3996 | |
| 3997 @override | |
| 3998 bool get isStatic => baseElement.isStatic; | |
| 3999 | |
| 4000 @override | |
| 4001 bool get isSynchronous => baseElement.isSynchronous; | |
| 4002 | |
| 4003 @override | |
| 4004 List<LabelElement> get labels => baseElement.labels; | |
| 4005 | |
| 4006 @override | |
| 4007 List<LocalVariableElement> get localVariables { | |
| 4008 // | |
| 4009 // Elements within this element should have type parameters substituted, | |
| 4010 // just like this element. | |
| 4011 // | |
| 4012 throw new UnsupportedOperationException(); | |
| 4013 // return getBaseElement().getLocalVariables(); | |
| 4014 } | |
| 4015 | |
| 4016 @override | |
| 4017 List<ParameterElement> get parameters { | |
| 4018 List<ParameterElement> baseParameters = baseElement.parameters; | |
| 4019 int parameterCount = baseParameters.length; | |
| 4020 if (parameterCount == 0) { | |
| 4021 return baseParameters; | |
| 4022 } | |
| 4023 List<ParameterElement> parameterizedParameters = | |
| 4024 new List<ParameterElement>(parameterCount); | |
| 4025 for (int i = 0; i < parameterCount; i++) { | |
| 4026 parameterizedParameters[i] = | |
| 4027 ParameterMember.from(baseParameters[i], definingType); | |
| 4028 } | |
| 4029 return parameterizedParameters; | |
| 4030 } | |
| 4031 | |
| 4032 @override | |
| 4033 DartType get returnType => substituteFor(baseElement.returnType); | |
| 4034 | |
| 4035 @override | |
| 4036 FunctionType get type => substituteFor(baseElement.type); | |
| 4037 | |
| 4038 @override | |
| 4039 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; | |
| 4040 | |
| 4041 @override | |
| 4042 void visitChildren(ElementVisitor visitor) { | |
| 4043 // TODO(brianwilkerson) We need to finish implementing the accessors used | |
| 4044 // below so that we can safely invoke them. | |
| 4045 super.visitChildren(visitor); | |
| 4046 safelyVisitChildren(baseElement.functions, visitor); | |
| 4047 safelyVisitChildren(labels, visitor); | |
| 4048 safelyVisitChildren(baseElement.localVariables, visitor); | |
| 4049 safelyVisitChildren(parameters, visitor); | |
| 4050 } | |
| 4051 } | |
| 4052 | |
| 4053 /** | |
| 4054 * An export directive within a library. | |
| 4055 */ | |
| 4056 abstract class ExportElement implements Element, UriReferencedElement { | |
| 4057 /** | |
| 4058 * An empty list of export elements. | |
| 4059 */ | |
| 4060 @deprecated // Use ExportElement.EMPTY_LIST | |
| 4061 static const List<ExportElement> EMPTY_ARRAY = const <ExportElement>[]; | |
| 4062 | |
| 4063 /** | |
| 4064 * An empty list of export elements. | |
| 4065 */ | |
| 4066 static const List<ExportElement> EMPTY_LIST = const <ExportElement>[]; | |
| 4067 | |
| 4068 /** | |
| 4069 * Return a list containing the combinators that were specified as part of the | |
| 4070 * export directive in the order in which they were specified. | |
| 4071 */ | |
| 4072 List<NamespaceCombinator> get combinators; | |
| 4073 | |
| 4074 /** | |
| 4075 * Return the library that is exported from this library by this export | |
| 4076 * directive. | |
| 4077 */ | |
| 4078 LibraryElement get exportedLibrary; | |
| 4079 } | |
| 4080 | |
| 4081 /** | |
| 4082 * A concrete implementation of an [ExportElement]. | |
| 4083 */ | |
| 4084 class ExportElementImpl extends UriReferencedElementImpl | |
| 4085 implements ExportElement { | |
| 4086 /** | |
| 4087 * The library that is exported from this library by this export directive. | |
| 4088 */ | |
| 4089 LibraryElement exportedLibrary; | |
| 4090 | |
| 4091 /** | |
| 4092 * The combinators that were specified as part of the export directive in the | |
| 4093 * order in which they were specified. | |
| 4094 */ | |
| 4095 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; | |
| 4096 | |
| 4097 /** | |
| 4098 * Initialize a newly created export element at the given [offset]. | |
| 4099 */ | |
| 4100 ExportElementImpl(int offset) : super(null, offset); | |
| 4101 | |
| 4102 @override | |
| 4103 String get identifier => exportedLibrary.name; | |
| 4104 | |
| 4105 @override | |
| 4106 ElementKind get kind => ElementKind.EXPORT; | |
| 4107 | |
| 4108 @override | |
| 4109 accept(ElementVisitor visitor) => visitor.visitExportElement(this); | |
| 4110 | |
| 4111 @override | |
| 4112 void appendTo(StringBuffer buffer) { | |
| 4113 buffer.write("export "); | |
| 4114 (exportedLibrary as LibraryElementImpl).appendTo(buffer); | |
| 4115 } | |
| 4116 } | |
| 4117 | |
| 4118 /** | |
| 4119 * A script tag in an HTML file having a `source` attribute that references a | |
| 4120 * Dart library source file. | |
| 4121 */ | |
| 4122 @deprecated | |
| 4123 abstract class ExternalHtmlScriptElement implements HtmlScriptElement { | |
| 4124 /** | |
| 4125 * Return the source referenced by this element, or `null` if this element | |
| 4126 * does not reference a Dart library source file. | |
| 4127 */ | |
| 4128 Source get scriptSource; | |
| 4129 } | |
| 4130 | |
| 4131 /** | |
| 4132 * A concrete implementation of an [ExternalHtmlScriptElement]. | |
| 4133 */ | |
| 4134 @deprecated | |
| 4135 class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl | |
| 4136 implements ExternalHtmlScriptElement { | |
| 4137 /** | |
| 4138 * The source specified in the `source` attribute or `null` if unspecified. | |
| 4139 */ | |
| 4140 Source scriptSource; | |
| 4141 | |
| 4142 /** | |
| 4143 * Initialize a newly created script element to correspond to the given | |
| 4144 * [node]. | |
| 4145 */ | |
| 4146 ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node); | |
| 4147 | |
| 4148 @override | |
| 4149 ElementKind get kind => ElementKind.EXTERNAL_HTML_SCRIPT; | |
| 4150 | |
| 4151 @override | |
| 4152 accept(ElementVisitor visitor) => | |
| 4153 visitor.visitExternalHtmlScriptElement(this); | |
| 4154 } | |
| 4155 | |
| 4156 /** | |
| 4157 * A field defined within a type. | |
| 4158 */ | |
| 4159 abstract class FieldElement | |
| 4160 implements ClassMemberElement, PropertyInducingElement { | |
| 4161 /** | |
| 4162 * An empty list of field elements. | |
| 4163 */ | |
| 4164 static const List<FieldElement> EMPTY_LIST = const <FieldElement>[]; | |
| 4165 | |
| 4166 /** | |
| 4167 * Return {@code true} if this element is an enum constant. | |
| 4168 */ | |
| 4169 bool get isEnumConstant; | |
| 4170 | |
| 4171 /** | |
| 4172 * Return the resolved [VariableDeclaration] or [EnumConstantDeclaration] | |
| 4173 * node that declares this [FieldElement]. | |
| 4174 * | |
| 4175 * This method is expensive, because resolved AST might be evicted from cache, | |
| 4176 * so parsing and resolving will be performed. | |
| 4177 */ | |
| 4178 @override | |
| 4179 AstNode computeNode(); | |
| 4180 } | |
| 4181 | |
| 4182 /** | |
| 4183 * A concrete implementation of a [FieldElement]. | |
| 4184 */ | |
| 4185 class FieldElementImpl extends PropertyInducingElementImpl | |
| 4186 with PotentiallyConstVariableElement | |
| 4187 implements FieldElement { | |
| 4188 /** | |
| 4189 * An empty list of field elements. | |
| 4190 */ | |
| 4191 @deprecated // Use FieldElement.EMPTY_LIST | |
| 4192 static const List<FieldElement> EMPTY_ARRAY = const <FieldElement>[]; | |
| 4193 | |
| 4194 /** | |
| 4195 * Initialize a newly created synthetic field element to have the given [name] | |
| 4196 * at the given [offset]. | |
| 4197 */ | |
| 4198 FieldElementImpl(String name, int offset) : super(name, offset); | |
| 4199 | |
| 4200 /** | |
| 4201 * Initialize a newly created field element to have the given [name]. | |
| 4202 */ | |
| 4203 FieldElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 4204 | |
| 4205 @override | |
| 4206 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 4207 | |
| 4208 @override | |
| 4209 bool get isEnumConstant => | |
| 4210 enclosingElement != null ? enclosingElement.isEnum : false; | |
| 4211 | |
| 4212 @override | |
| 4213 ElementKind get kind => ElementKind.FIELD; | |
| 4214 | |
| 4215 /** | |
| 4216 * Set whether this field is static. | |
| 4217 */ | |
| 4218 void set static(bool isStatic) { | |
| 4219 setModifier(Modifier.STATIC, isStatic); | |
| 4220 } | |
| 4221 | |
| 4222 @override | |
| 4223 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); | |
| 4224 | |
| 4225 @override | |
| 4226 AstNode computeNode() { | |
| 4227 if (isEnumConstant) { | |
| 4228 return getNodeMatching((node) => node is EnumConstantDeclaration); | |
| 4229 } else { | |
| 4230 return getNodeMatching((node) => node is VariableDeclaration); | |
| 4231 } | |
| 4232 } | |
| 4233 } | |
| 4234 | |
| 4235 /** | |
| 4236 * A field formal parameter defined within a constructor element. | |
| 4237 */ | |
| 4238 abstract class FieldFormalParameterElement implements ParameterElement { | |
| 4239 /** | |
| 4240 * Return the field element associated with this field formal parameter, or | |
| 4241 * `null` if the parameter references a field that doesn't exist. | |
| 4242 */ | |
| 4243 FieldElement get field; | |
| 4244 } | |
| 4245 | |
| 4246 /** | |
| 4247 * A [ParameterElementImpl] that has the additional information of the | |
| 4248 * [FieldElement] associated with the parameter. | |
| 4249 */ | |
| 4250 class FieldFormalParameterElementImpl extends ParameterElementImpl | |
| 4251 implements FieldFormalParameterElement { | |
| 4252 /** | |
| 4253 * The field associated with this field formal parameter. | |
| 4254 */ | |
| 4255 FieldElement field; | |
| 4256 | |
| 4257 /** | |
| 4258 * Initialize a newly created parameter element to have the given [name]. | |
| 4259 */ | |
| 4260 FieldFormalParameterElementImpl(Identifier name) : super.forNode(name); | |
| 4261 | |
| 4262 @override | |
| 4263 bool get isInitializingFormal => true; | |
| 4264 | |
| 4265 @override | |
| 4266 accept(ElementVisitor visitor) => | |
| 4267 visitor.visitFieldFormalParameterElement(this); | |
| 4268 } | |
| 4269 | |
| 4270 /** | |
| 4271 * A parameter element defined in a parameterized type where the values of the | |
| 4272 * type parameters are known. | |
| 4273 */ | |
| 4274 class FieldFormalParameterMember extends ParameterMember | |
| 4275 implements FieldFormalParameterElement { | |
| 4276 /** | |
| 4277 * Initialize a newly created element to represent a constructor, based on the | |
| 4278 * [baseElement], defined by the [definingType]. | |
| 4279 */ | |
| 4280 FieldFormalParameterMember( | |
| 4281 FieldFormalParameterElement baseElement, ParameterizedType definingType) | |
| 4282 : super(baseElement, definingType); | |
| 4283 | |
| 4284 @override | |
| 4285 FieldElement get field { | |
| 4286 FieldElement field = (baseElement as FieldFormalParameterElement).field; | |
| 4287 if (field is FieldElement) { | |
| 4288 return FieldMember.from(field, definingType); | |
| 4289 } | |
| 4290 return field; | |
| 4291 } | |
| 4292 | |
| 4293 @override | |
| 4294 accept(ElementVisitor visitor) => | |
| 4295 visitor.visitFieldFormalParameterElement(this); | |
| 4296 } | |
| 4297 | |
| 4298 /** | |
| 4299 * A field element defined in a parameterized type where the values of the type | |
| 4300 * parameters are known. | |
| 4301 */ | |
| 4302 class FieldMember extends VariableMember implements FieldElement { | |
| 4303 /** | |
| 4304 * Initialize a newly created element to represent a constructor, based on the | |
| 4305 * [baseElement], defined by the [definingType]. | |
| 4306 */ | |
| 4307 FieldMember(FieldElement baseElement, InterfaceType definingType) | |
| 4308 : super(baseElement, definingType); | |
| 4309 | |
| 4310 @override | |
| 4311 FieldElement get baseElement => super.baseElement as FieldElement; | |
| 4312 | |
| 4313 @override | |
| 4314 InterfaceType get definingType => super.definingType as InterfaceType; | |
| 4315 | |
| 4316 @override | |
| 4317 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 4318 | |
| 4319 @override | |
| 4320 PropertyAccessorElement get getter => | |
| 4321 PropertyAccessorMember.from(baseElement.getter, definingType); | |
| 4322 | |
| 4323 @override | |
| 4324 bool get isEnumConstant => baseElement.isEnumConstant; | |
| 4325 | |
| 4326 @override | |
| 4327 DartType get propagatedType => substituteFor(baseElement.propagatedType); | |
| 4328 | |
| 4329 @override | |
| 4330 PropertyAccessorElement get setter => | |
| 4331 PropertyAccessorMember.from(baseElement.setter, definingType); | |
| 4332 | |
| 4333 @override | |
| 4334 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); | |
| 4335 | |
| 4336 @override | |
| 4337 VariableDeclaration computeNode() => baseElement.computeNode(); | |
| 4338 | |
| 4339 @override | |
| 4340 String toString() => '$type $displayName'; | |
| 4341 | |
| 4342 /** | |
| 4343 * If the given [field]'s type is different when any type parameters from the | |
| 4344 * defining type's declaration are replaced with the actual type arguments | |
| 4345 * from the [definingType], create a field member representing the given | |
| 4346 * field. Return the member that was created, or the base field if no member | |
| 4347 * was created. | |
| 4348 */ | |
| 4349 static FieldElement from(FieldElement field, InterfaceType definingType) { | |
| 4350 if (!_isChangedByTypeSubstitution(field, definingType)) { | |
| 4351 return field; | |
| 4352 } | |
| 4353 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 4354 // instance. It would use more memory but speed up some operations. | |
| 4355 // We need to see how often the type is being re-computed. | |
| 4356 return new FieldMember(field, definingType); | |
| 4357 } | |
| 4358 | |
| 4359 /** | |
| 4360 * Determine whether the given [field]'s type is changed when type parameters | |
| 4361 * from the [definingType]'s declaration are replaced with the actual type | |
| 4362 * arguments from the defining type. | |
| 4363 */ | |
| 4364 static bool _isChangedByTypeSubstitution( | |
| 4365 FieldElement field, InterfaceType definingType) { | |
| 4366 List<DartType> argumentTypes = definingType.typeArguments; | |
| 4367 if (field != null && argumentTypes.length != 0) { | |
| 4368 DartType baseType = field.type; | |
| 4369 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 4370 if (baseType != null) { | |
| 4371 DartType substitutedType = | |
| 4372 baseType.substitute2(argumentTypes, parameterTypes); | |
| 4373 if (baseType != substitutedType) { | |
| 4374 return true; | |
| 4375 } | |
| 4376 } | |
| 4377 // If the field has a propagated type, then we need to check whether the | |
| 4378 // propagated type needs substitution. | |
| 4379 DartType basePropagatedType = field.propagatedType; | |
| 4380 if (basePropagatedType != null) { | |
| 4381 DartType substitutedPropagatedType = | |
| 4382 basePropagatedType.substitute2(argumentTypes, parameterTypes); | |
| 4383 if (basePropagatedType != substitutedPropagatedType) { | |
| 4384 return true; | |
| 4385 } | |
| 4386 } | |
| 4387 } | |
| 4388 return false; | |
| 4389 } | |
| 4390 } | |
| 4391 | |
| 4392 /** | |
| 4393 * A (non-method) function. This can be either a top-level function, a local | |
| 4394 * function, a closure, or the initialization expression for a field or | |
| 4395 * variable. | |
| 4396 */ | |
| 4397 abstract class FunctionElement implements ExecutableElement, LocalElement { | |
| 4398 /** | |
| 4399 * An empty list of function elements. | |
| 4400 */ | |
| 4401 static const List<FunctionElement> EMPTY_LIST = const <FunctionElement>[]; | |
| 4402 | |
| 4403 /** | |
| 4404 * The name of the method that can be implemented by a class to allow its | |
| 4405 * instances to be invoked as if they were a function. | |
| 4406 */ | |
| 4407 static final String CALL_METHOD_NAME = "call"; | |
| 4408 | |
| 4409 /** | |
| 4410 * The name of the synthetic function defined for libraries that are deferred. | |
| 4411 */ | |
| 4412 static final String LOAD_LIBRARY_NAME = "loadLibrary"; | |
| 4413 | |
| 4414 /** | |
| 4415 * The name of the function used as an entry point. | |
| 4416 */ | |
| 4417 static const String MAIN_FUNCTION_NAME = "main"; | |
| 4418 | |
| 4419 /** | |
| 4420 * The name of the method that will be invoked if an attempt is made to invoke | |
| 4421 * an undefined method on an object. | |
| 4422 */ | |
| 4423 static final String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod"; | |
| 4424 | |
| 4425 /** | |
| 4426 * Return `true` if the function is an entry point, i.e. a top-level function | |
| 4427 * and has the name `main`. | |
| 4428 */ | |
| 4429 bool get isEntryPoint; | |
| 4430 | |
| 4431 /** | |
| 4432 * Return the resolved function declaration node that declares this element. | |
| 4433 * | |
| 4434 * This method is expensive, because resolved AST might be evicted from cache, | |
| 4435 * so parsing and resolving will be performed. | |
| 4436 */ | |
| 4437 @override | |
| 4438 FunctionDeclaration computeNode(); | |
| 4439 } | |
| 4440 | |
| 4441 /** | |
| 4442 * A concrete implementation of a [FunctionElement]. | |
| 4443 */ | |
| 4444 class FunctionElementImpl extends ExecutableElementImpl | |
| 4445 implements FunctionElement { | |
| 4446 /** | |
| 4447 * An empty list of function elements. | |
| 4448 */ | |
| 4449 @deprecated // Use FunctionElement.EMPTY_LIST | |
| 4450 static const List<FunctionElement> EMPTY_ARRAY = const <FunctionElement>[]; | |
| 4451 | |
| 4452 /** | |
| 4453 * The offset to the beginning of the visible range for this element. | |
| 4454 */ | |
| 4455 int _visibleRangeOffset = 0; | |
| 4456 | |
| 4457 /** | |
| 4458 * The length of the visible range for this element, or `-1` if this element | |
| 4459 * does not have a visible range. | |
| 4460 */ | |
| 4461 int _visibleRangeLength = -1; | |
| 4462 | |
| 4463 /** | |
| 4464 * Initialize a newly created function element to have the given [name] and | |
| 4465 * [offset]. | |
| 4466 */ | |
| 4467 FunctionElementImpl(String name, int offset) : super(name, offset); | |
| 4468 | |
| 4469 /** | |
| 4470 * Initialize a newly created function element to have the given [name]. | |
| 4471 */ | |
| 4472 FunctionElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 4473 | |
| 4474 /** | |
| 4475 * Initialize a newly created function element to have no name and the given | |
| 4476 * [offset]. This is used for function expressions, that have no name. | |
| 4477 */ | |
| 4478 FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset); | |
| 4479 | |
| 4480 @override | |
| 4481 String get identifier { | |
| 4482 String identifier = super.identifier; | |
| 4483 if (!isStatic) { | |
| 4484 identifier += "@$nameOffset"; | |
| 4485 } | |
| 4486 return identifier; | |
| 4487 } | |
| 4488 | |
| 4489 @override | |
| 4490 bool get isEntryPoint { | |
| 4491 return isStatic && displayName == FunctionElement.MAIN_FUNCTION_NAME; | |
| 4492 } | |
| 4493 | |
| 4494 @override | |
| 4495 bool get isStatic => enclosingElement is CompilationUnitElement; | |
| 4496 | |
| 4497 @override | |
| 4498 ElementKind get kind => ElementKind.FUNCTION; | |
| 4499 | |
| 4500 @override | |
| 4501 SourceRange get visibleRange { | |
| 4502 if (_visibleRangeLength < 0) { | |
| 4503 return null; | |
| 4504 } | |
| 4505 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 4506 } | |
| 4507 | |
| 4508 @override | |
| 4509 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this); | |
| 4510 | |
| 4511 @override | |
| 4512 void appendTo(StringBuffer buffer) { | |
| 4513 String name = displayName; | |
| 4514 if (name != null) { | |
| 4515 buffer.write(name); | |
| 4516 } | |
| 4517 super.appendTo(buffer); | |
| 4518 } | |
| 4519 | |
| 4520 @override | |
| 4521 FunctionDeclaration computeNode() => | |
| 4522 getNodeMatching((node) => node is FunctionDeclaration); | |
| 4523 | |
| 4524 /** | |
| 4525 * Set the visible range for this element to the range starting at the given | |
| 4526 * [offset] with the given [length]. | |
| 4527 */ | |
| 4528 void setVisibleRange(int offset, int length) { | |
| 4529 _visibleRangeOffset = offset; | |
| 4530 _visibleRangeLength = length; | |
| 4531 } | |
| 4532 } | |
| 4533 | |
| 4534 /** | |
| 4535 * The type of a function, method, constructor, getter, or setter. Function | |
| 4536 * types come in three variations: | |
| 4537 * | |
| 4538 * * The types of functions that only have required parameters. These have the | |
| 4539 * general form <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i>. | |
| 4540 * * The types of functions with optional positional parameters. These have the | |
| 4541 * general form <i>(T<sub>1</sub>, …, T<sub>n</sub>, [T<sub>n+1</sub> | |
| 4542 * …, T<sub>n+k</sub>]) → T</i>. | |
| 4543 * * The types of functions with named parameters. These have the general form | |
| 4544 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>x1</sub> x1, …, | |
| 4545 * T<sub>xk</sub> xk}) → T</i>. | |
| 4546 */ | |
| 4547 abstract class FunctionType implements ParameterizedType { | |
| 4548 /** | |
| 4549 * Return a map from the names of named parameters to the types of the named | |
| 4550 * parameters of this type of function. The entries in the map will be | |
| 4551 * iterated in the same order as the order in which the named parameters were | |
| 4552 * defined. If there were no named parameters declared then the map will be | |
| 4553 * empty. | |
| 4554 */ | |
| 4555 Map<String, DartType> get namedParameterTypes; | |
| 4556 | |
| 4557 /** | |
| 4558 * Return a list containing the types of the normal parameters of this type of | |
| 4559 * function. The parameter types are in the same order as they appear in the | |
| 4560 * declaration of the function. | |
| 4561 */ | |
| 4562 List<DartType> get normalParameterTypes; | |
| 4563 | |
| 4564 /** | |
| 4565 * Return a map from the names of optional (positional) parameters to the | |
| 4566 * types of the optional parameters of this type of function. The entries in | |
| 4567 * the map will be iterated in the same order as the order in which the | |
| 4568 * optional parameters were defined. If there were no optional parameters | |
| 4569 * declared then the map will be empty. | |
| 4570 */ | |
| 4571 List<DartType> get optionalParameterTypes; | |
| 4572 | |
| 4573 /** | |
| 4574 * Return a list containing the parameters elements of this type of function. | |
| 4575 * The parameter types are in the same order as they appear in the declaration | |
| 4576 * of the function. | |
| 4577 */ | |
| 4578 List<ParameterElement> get parameters; | |
| 4579 | |
| 4580 /** | |
| 4581 * Return the type of object returned by this type of function. | |
| 4582 */ | |
| 4583 DartType get returnType; | |
| 4584 | |
| 4585 /** | |
| 4586 * Return `true` if this type is a subtype of the given [type]. | |
| 4587 * | |
| 4588 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i> is | |
| 4589 * a subtype of the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>) | |
| 4590 * → S</i>, if all of the following conditions are met: | |
| 4591 * | |
| 4592 * * Either | |
| 4593 * * <i>S</i> is void, or | |
| 4594 * * <i>T ⇔ S</i>. | |
| 4595 * | |
| 4596 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ | |
| 4597 * S<sub>i</sub></i>. | |
| 4598 * | |
| 4599 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, | |
| 4600 * [T<sub>n+1</sub>, …, T<sub>n+k</sub>]) → T</i> is a subtype of | |
| 4601 * the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>, | |
| 4602 * [S<sub>n+1</sub>, …, S<sub>n+m</sub>]) → S</i>, if all of the | |
| 4603 * following conditions are met: | |
| 4604 * | |
| 4605 * * Either | |
| 4606 * * <i>S</i> is void, or | |
| 4607 * * <i>T ⇔ S</i>. | |
| 4608 * | |
| 4609 * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, | |
| 4610 * <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>. | |
| 4611 * | |
| 4612 * A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, | |
| 4613 * {T<sub>x1</sub> x1, …, T<sub>xk</sub> xk}) → T</i> is a subtype | |
| 4614 * of the function type <i>(S<sub>1</sub>, …, S<sub>n</sub>, | |
| 4615 * {S<sub>y1</sub> y1, …, S<sub>ym</sub> ym}) → S</i>, if all of | |
| 4616 * the following conditions are met: | |
| 4617 * * Either | |
| 4618 * * <i>S</i> is void, | |
| 4619 * * or <i>T ⇔ S</i>. | |
| 4620 * | |
| 4621 * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ | |
| 4622 * S<sub>i</sub></i>. | |
| 4623 * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, | |
| 4624 * …, x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>. | |
| 4625 * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, …, | |
| 4626 * y<sub>m</sub>}</i>, <i>y<sub>i</sub> = x<sub>j</sub> => Tj ⇔ Si</i>. | |
| 4627 * | |
| 4628 * In addition, the following subtype rules apply: | |
| 4629 * | |
| 4630 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, []) → T <: (T<sub>1</sub>, | |
| 4631 * …, T<sub>n</sub>) → T.</i><br> | |
| 4632 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, | |
| 4633 * …, T<sub>n</sub>, {}) → T.</i><br> | |
| 4634 * <i>(T<sub>1</sub>, …, T<sub>n</sub>, {}) → T <: (T<sub>1</sub>, | |
| 4635 * …, T<sub>n</sub>) → T.</i><br> | |
| 4636 * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, | |
| 4637 * …, T<sub>n</sub>, []) → T.</i> | |
| 4638 * | |
| 4639 * All functions implement the class `Function`. However not all function | |
| 4640 * types are a subtype of `Function`. If an interface type <i>I</i> includes a | |
| 4641 * method named `call()`, and the type of `call()` is the function type | |
| 4642 * <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>. | |
| 4643 */ | |
| 4644 @override | |
| 4645 bool isSubtypeOf(DartType type); | |
| 4646 | |
| 4647 @override | |
| 4648 FunctionType substitute2( | |
| 4649 List<DartType> argumentTypes, List<DartType> parameterTypes); | |
| 4650 | |
| 4651 /** | |
| 4652 * Return the type resulting from substituting the given [argumentTypes] for | |
| 4653 * this type's parameters. This is fully equivalent to | |
| 4654 * `substitute(argumentTypes, getTypeArguments())`. | |
| 4655 */ | |
| 4656 FunctionType substitute3(List<DartType> argumentTypes); | |
| 4657 } | |
| 4658 | |
| 4659 /** | |
| 4660 * A function type alias (`typedef`). | |
| 4661 */ | |
| 4662 abstract class FunctionTypeAliasElement implements TypeDefiningElement { | |
| 4663 /** | |
| 4664 * An empty array of type alias elements. | |
| 4665 */ | |
| 4666 static List<FunctionTypeAliasElement> EMPTY_LIST = | |
| 4667 new List<FunctionTypeAliasElement>(0); | |
| 4668 | |
| 4669 /** | |
| 4670 * Return the compilation unit in which this type alias is defined. | |
| 4671 */ | |
| 4672 @override | |
| 4673 CompilationUnitElement get enclosingElement; | |
| 4674 | |
| 4675 /** | |
| 4676 * Return a list containing all of the parameters defined by this type alias. | |
| 4677 */ | |
| 4678 List<ParameterElement> get parameters; | |
| 4679 | |
| 4680 /** | |
| 4681 * Return the return type defined by this type alias. | |
| 4682 */ | |
| 4683 DartType get returnType; | |
| 4684 | |
| 4685 @override | |
| 4686 FunctionType get type; | |
| 4687 | |
| 4688 /** | |
| 4689 * Return a list containing all of the type parameters defined for this type. | |
| 4690 */ | |
| 4691 List<TypeParameterElement> get typeParameters; | |
| 4692 | |
| 4693 /** | |
| 4694 * Return the resolved function type alias node that declares this element. | |
| 4695 * | |
| 4696 * This method is expensive, because resolved AST might be evicted from cache, | |
| 4697 * so parsing and resolving will be performed. | |
| 4698 */ | |
| 4699 @override | |
| 4700 FunctionTypeAlias computeNode(); | |
| 4701 } | |
| 4702 | |
| 4703 /** | |
| 4704 * A concrete implementation of a [FunctionTypeAliasElement]. | |
| 4705 */ | |
| 4706 class FunctionTypeAliasElementImpl extends ElementImpl | |
| 4707 implements FunctionTypeAliasElement { | |
| 4708 /** | |
| 4709 * An empty array of type alias elements. | |
| 4710 */ | |
| 4711 @deprecated // Use FunctionTypeAliasElement.EMPTY_LIST | |
| 4712 static List<FunctionTypeAliasElement> EMPTY_ARRAY = | |
| 4713 new List<FunctionTypeAliasElement>(0); | |
| 4714 | |
| 4715 /** | |
| 4716 * A list containing all of the parameters defined by this type alias. | |
| 4717 */ | |
| 4718 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 4719 | |
| 4720 /** | |
| 4721 * The return type defined by this type alias. | |
| 4722 */ | |
| 4723 DartType returnType; | |
| 4724 | |
| 4725 /** | |
| 4726 * The type of function defined by this type alias. | |
| 4727 */ | |
| 4728 FunctionType type; | |
| 4729 | |
| 4730 /** | |
| 4731 * A list containing all of the type parameters defined for this type. | |
| 4732 */ | |
| 4733 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 4734 | |
| 4735 /** | |
| 4736 * Initialize a newly created type alias element to have the given name. | |
| 4737 * | |
| 4738 * [name] the name of this element | |
| 4739 * [nameOffset] the offset of the name of this element in the file that | |
| 4740 * contains the declaration of this element | |
| 4741 */ | |
| 4742 FunctionTypeAliasElementImpl(String name, int nameOffset) | |
| 4743 : super(name, nameOffset); | |
| 4744 | |
| 4745 /** | |
| 4746 * Initialize a newly created type alias element to have the given [name]. | |
| 4747 */ | |
| 4748 FunctionTypeAliasElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 4749 | |
| 4750 @override | |
| 4751 CompilationUnitElement get enclosingElement => | |
| 4752 super.enclosingElement as CompilationUnitElement; | |
| 4753 | |
| 4754 @override | |
| 4755 ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS; | |
| 4756 | |
| 4757 @override | |
| 4758 List<ParameterElement> get parameters => _parameters; | |
| 4759 | |
| 4760 /** | |
| 4761 * Set the parameters defined by this type alias to the given [parameters]. | |
| 4762 */ | |
| 4763 void set parameters(List<ParameterElement> parameters) { | |
| 4764 if (parameters != null) { | |
| 4765 for (ParameterElement parameter in parameters) { | |
| 4766 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 4767 } | |
| 4768 } | |
| 4769 this._parameters = parameters; | |
| 4770 } | |
| 4771 | |
| 4772 @override | |
| 4773 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 4774 | |
| 4775 /** | |
| 4776 * Set the type parameters defined for this type to the given | |
| 4777 * [typeParameters]. | |
| 4778 */ | |
| 4779 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 4780 for (TypeParameterElement typeParameter in typeParameters) { | |
| 4781 (typeParameter as TypeParameterElementImpl).enclosingElement = this; | |
| 4782 } | |
| 4783 this._typeParameters = typeParameters; | |
| 4784 } | |
| 4785 | |
| 4786 @override | |
| 4787 accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this); | |
| 4788 | |
| 4789 @override | |
| 4790 void appendTo(StringBuffer buffer) { | |
| 4791 buffer.write("typedef "); | |
| 4792 buffer.write(displayName); | |
| 4793 int typeParameterCount = _typeParameters.length; | |
| 4794 if (typeParameterCount > 0) { | |
| 4795 buffer.write("<"); | |
| 4796 for (int i = 0; i < typeParameterCount; i++) { | |
| 4797 if (i > 0) { | |
| 4798 buffer.write(", "); | |
| 4799 } | |
| 4800 (_typeParameters[i] as TypeParameterElementImpl).appendTo(buffer); | |
| 4801 } | |
| 4802 buffer.write(">"); | |
| 4803 } | |
| 4804 buffer.write("("); | |
| 4805 int parameterCount = _parameters.length; | |
| 4806 for (int i = 0; i < parameterCount; i++) { | |
| 4807 if (i > 0) { | |
| 4808 buffer.write(", "); | |
| 4809 } | |
| 4810 (_parameters[i] as ParameterElementImpl).appendTo(buffer); | |
| 4811 } | |
| 4812 buffer.write(")"); | |
| 4813 if (type != null) { | |
| 4814 buffer.write(Element.RIGHT_ARROW); | |
| 4815 buffer.write(type.returnType); | |
| 4816 } else if (returnType != null) { | |
| 4817 buffer.write(Element.RIGHT_ARROW); | |
| 4818 buffer.write(returnType); | |
| 4819 } | |
| 4820 } | |
| 4821 | |
| 4822 @override | |
| 4823 FunctionTypeAlias computeNode() => | |
| 4824 getNodeMatching((node) => node is FunctionTypeAlias); | |
| 4825 | |
| 4826 @override | |
| 4827 ElementImpl getChild(String identifier) { | |
| 4828 for (VariableElement parameter in _parameters) { | |
| 4829 if ((parameter as VariableElementImpl).identifier == identifier) { | |
| 4830 return parameter as VariableElementImpl; | |
| 4831 } | |
| 4832 } | |
| 4833 for (TypeParameterElement typeParameter in _typeParameters) { | |
| 4834 if ((typeParameter as TypeParameterElementImpl).identifier == | |
| 4835 identifier) { | |
| 4836 return typeParameter as TypeParameterElementImpl; | |
| 4837 } | |
| 4838 } | |
| 4839 return null; | |
| 4840 } | |
| 4841 | |
| 4842 /** | |
| 4843 * Set the parameters defined by this type alias to the given [parameters] | |
| 4844 * without becoming the parent of the parameters. This should only be used by | |
| 4845 * the [TypeResolverVisitor] when creating a synthetic type alias. | |
| 4846 */ | |
| 4847 void shareParameters(List<ParameterElement> parameters) { | |
| 4848 this._parameters = parameters; | |
| 4849 } | |
| 4850 | |
| 4851 /** | |
| 4852 * Set the type parameters defined for this type to the given [typeParameters] | |
| 4853 * without becoming the parent of the parameters. This should only be used by | |
| 4854 * the [TypeResolverVisitor] when creating a synthetic type alias. | |
| 4855 */ | |
| 4856 void shareTypeParameters(List<TypeParameterElement> typeParameters) { | |
| 4857 this._typeParameters = typeParameters; | |
| 4858 } | |
| 4859 | |
| 4860 @override | |
| 4861 void visitChildren(ElementVisitor visitor) { | |
| 4862 super.visitChildren(visitor); | |
| 4863 safelyVisitChildren(_parameters, visitor); | |
| 4864 safelyVisitChildren(_typeParameters, visitor); | |
| 4865 } | |
| 4866 } | |
| 4867 | |
| 4868 /** | |
| 4869 * The type of a function, method, constructor, getter, or setter. | |
| 4870 */ | |
| 4871 class FunctionTypeImpl extends TypeImpl implements FunctionType { | |
| 4872 /** | |
| 4873 * A list containing the actual types of the type arguments. | |
| 4874 */ | |
| 4875 List<DartType> typeArguments = DartType.EMPTY_LIST; | |
| 4876 | |
| 4877 /** | |
| 4878 * The set of typedefs which should not be expanded when exploring this type, | |
| 4879 * to avoid creating infinite types in response to self-referential typedefs. | |
| 4880 */ | |
| 4881 final List<FunctionTypeAliasElement> prunedTypedefs; | |
| 4882 | |
| 4883 /** | |
| 4884 * Initialize a newly created function type to be declared by the given | |
| 4885 * [element]. | |
| 4886 */ | |
| 4887 FunctionTypeImpl(ExecutableElement element, [this.prunedTypedefs]) | |
| 4888 : super(element, null); | |
| 4889 | |
| 4890 /** | |
| 4891 * Initialize a newly created function type to be declared by the given | |
| 4892 * [element]. | |
| 4893 */ | |
| 4894 @deprecated // Use new FunctionTypeImpl(element) | |
| 4895 FunctionTypeImpl.con1(ExecutableElement element) | |
| 4896 : prunedTypedefs = null, | |
| 4897 super(element, null); | |
| 4898 | |
| 4899 /** | |
| 4900 * Initialize a newly created function type to be declared by the given | |
| 4901 * [element]. | |
| 4902 */ | |
| 4903 @deprecated // Use new FunctionTypeImpl.forTypedef(element) | |
| 4904 FunctionTypeImpl.con2(FunctionTypeAliasElement element) | |
| 4905 : prunedTypedefs = null, | |
| 4906 super(element, element == null ? null : element.name); | |
| 4907 | |
| 4908 /** | |
| 4909 * Initialize a newly created function type to be declared by the given | |
| 4910 * [element]. | |
| 4911 */ | |
| 4912 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element, | |
| 4913 [this.prunedTypedefs]) | |
| 4914 : super(element, element == null ? null : element.name); | |
| 4915 | |
| 4916 /** | |
| 4917 * Private constructor. | |
| 4918 */ | |
| 4919 FunctionTypeImpl._(Element element, String name, this.prunedTypedefs) | |
| 4920 : super(element, name); | |
| 4921 | |
| 4922 /** | |
| 4923 * Return the base parameter elements of this function element. | |
| 4924 */ | |
| 4925 List<ParameterElement> get baseParameters { | |
| 4926 Element element = this.element; | |
| 4927 if (element is ExecutableElement) { | |
| 4928 return element.parameters; | |
| 4929 } else { | |
| 4930 return (element as FunctionTypeAliasElement).parameters; | |
| 4931 } | |
| 4932 } | |
| 4933 | |
| 4934 /** | |
| 4935 * Return the return type defined by this function's element. | |
| 4936 */ | |
| 4937 DartType get baseReturnType { | |
| 4938 Element element = this.element; | |
| 4939 if (element is ExecutableElement) { | |
| 4940 return element.returnType; | |
| 4941 } else { | |
| 4942 return (element as FunctionTypeAliasElement).returnType; | |
| 4943 } | |
| 4944 } | |
| 4945 | |
| 4946 @override | |
| 4947 String get displayName { | |
| 4948 String name = this.name; | |
| 4949 if (name == null || name.length == 0) { | |
| 4950 // Function types have an empty name when they are defined implicitly by | |
| 4951 // either a closure or as part of a parameter declaration. | |
| 4952 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 4953 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 4954 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; | |
| 4955 DartType returnType = this.returnType; | |
| 4956 StringBuffer buffer = new StringBuffer(); | |
| 4957 buffer.write("("); | |
| 4958 bool needsComma = false; | |
| 4959 if (normalParameterTypes.length > 0) { | |
| 4960 for (DartType type in normalParameterTypes) { | |
| 4961 if (needsComma) { | |
| 4962 buffer.write(", "); | |
| 4963 } else { | |
| 4964 needsComma = true; | |
| 4965 } | |
| 4966 buffer.write(type.displayName); | |
| 4967 } | |
| 4968 } | |
| 4969 if (optionalParameterTypes.length > 0) { | |
| 4970 if (needsComma) { | |
| 4971 buffer.write(", "); | |
| 4972 needsComma = false; | |
| 4973 } | |
| 4974 buffer.write("["); | |
| 4975 for (DartType type in optionalParameterTypes) { | |
| 4976 if (needsComma) { | |
| 4977 buffer.write(", "); | |
| 4978 } else { | |
| 4979 needsComma = true; | |
| 4980 } | |
| 4981 buffer.write(type.displayName); | |
| 4982 } | |
| 4983 buffer.write("]"); | |
| 4984 needsComma = true; | |
| 4985 } | |
| 4986 if (namedParameterTypes.length > 0) { | |
| 4987 if (needsComma) { | |
| 4988 buffer.write(", "); | |
| 4989 needsComma = false; | |
| 4990 } | |
| 4991 buffer.write("{"); | |
| 4992 namedParameterTypes.forEach((String name, DartType type) { | |
| 4993 if (needsComma) { | |
| 4994 buffer.write(", "); | |
| 4995 } else { | |
| 4996 needsComma = true; | |
| 4997 } | |
| 4998 buffer.write(name); | |
| 4999 buffer.write(": "); | |
| 5000 buffer.write(type.displayName); | |
| 5001 }); | |
| 5002 buffer.write("}"); | |
| 5003 needsComma = true; | |
| 5004 } | |
| 5005 buffer.write(")"); | |
| 5006 buffer.write(Element.RIGHT_ARROW); | |
| 5007 if (returnType == null) { | |
| 5008 buffer.write("null"); | |
| 5009 } else { | |
| 5010 buffer.write(returnType.displayName); | |
| 5011 } | |
| 5012 name = buffer.toString(); | |
| 5013 } | |
| 5014 return name; | |
| 5015 } | |
| 5016 | |
| 5017 @override | |
| 5018 int get hashCode { | |
| 5019 if (element == null) { | |
| 5020 return 0; | |
| 5021 } | |
| 5022 // Reference the arrays of parameters | |
| 5023 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 5024 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 5025 Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values; | |
| 5026 // Generate the hashCode | |
| 5027 int code = (returnType as TypeImpl).hashCode; | |
| 5028 for (int i = 0; i < normalParameterTypes.length; i++) { | |
| 5029 code = (code << 1) + (normalParameterTypes[i] as TypeImpl).hashCode; | |
| 5030 } | |
| 5031 for (int i = 0; i < optionalParameterTypes.length; i++) { | |
| 5032 code = (code << 1) + (optionalParameterTypes[i] as TypeImpl).hashCode; | |
| 5033 } | |
| 5034 for (DartType type in namedParameterTypes) { | |
| 5035 code = (code << 1) + (type as TypeImpl).hashCode; | |
| 5036 } | |
| 5037 return code; | |
| 5038 } | |
| 5039 | |
| 5040 @override | |
| 5041 Map<String, DartType> get namedParameterTypes { | |
| 5042 LinkedHashMap<String, DartType> namedParameterTypes = | |
| 5043 new LinkedHashMap<String, DartType>(); | |
| 5044 List<ParameterElement> parameters = baseParameters; | |
| 5045 if (parameters.length == 0) { | |
| 5046 return namedParameterTypes; | |
| 5047 } | |
| 5048 List<DartType> typeParameters = | |
| 5049 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 5050 for (ParameterElement parameter in parameters) { | |
| 5051 if (parameter.parameterKind == ParameterKind.NAMED) { | |
| 5052 DartType type = parameter.type; | |
| 5053 if (typeArguments.length != 0 && | |
| 5054 typeArguments.length == typeParameters.length) { | |
| 5055 type = (type as TypeImpl) | |
| 5056 .substitute2(typeArguments, typeParameters, newPrune); | |
| 5057 } else { | |
| 5058 type = (type as TypeImpl).pruned(newPrune); | |
| 5059 } | |
| 5060 namedParameterTypes[parameter.name] = type; | |
| 5061 } | |
| 5062 } | |
| 5063 return namedParameterTypes; | |
| 5064 } | |
| 5065 | |
| 5066 /** | |
| 5067 * Determine the new set of typedefs which should be pruned when expanding | |
| 5068 * this function type. | |
| 5069 */ | |
| 5070 List<FunctionTypeAliasElement> get newPrune { | |
| 5071 Element element = this.element; | |
| 5072 if (element is FunctionTypeAliasElement && !element.isSynthetic) { | |
| 5073 // This typedef should be pruned, along with anything that was previously | |
| 5074 // pruned. | |
| 5075 if (prunedTypedefs == null) { | |
| 5076 return <FunctionTypeAliasElement>[element]; | |
| 5077 } else { | |
| 5078 return new List<FunctionTypeAliasElement>.from(prunedTypedefs) | |
| 5079 ..add(element); | |
| 5080 } | |
| 5081 } else { | |
| 5082 // This is not a typedef, so nothing additional needs to be pruned. | |
| 5083 return prunedTypedefs; | |
| 5084 } | |
| 5085 } | |
| 5086 | |
| 5087 @override | |
| 5088 List<DartType> get normalParameterTypes { | |
| 5089 List<ParameterElement> parameters = baseParameters; | |
| 5090 if (parameters.length == 0) { | |
| 5091 return DartType.EMPTY_LIST; | |
| 5092 } | |
| 5093 List<DartType> typeParameters = | |
| 5094 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 5095 List<DartType> types = new List<DartType>(); | |
| 5096 for (ParameterElement parameter in parameters) { | |
| 5097 if (parameter.parameterKind == ParameterKind.REQUIRED) { | |
| 5098 DartType type = parameter.type; | |
| 5099 if (typeArguments.length != 0 && | |
| 5100 typeArguments.length == typeParameters.length) { | |
| 5101 type = (type as TypeImpl) | |
| 5102 .substitute2(typeArguments, typeParameters, newPrune); | |
| 5103 } else { | |
| 5104 type = (type as TypeImpl).pruned(newPrune); | |
| 5105 } | |
| 5106 types.add(type); | |
| 5107 } | |
| 5108 } | |
| 5109 return types; | |
| 5110 } | |
| 5111 | |
| 5112 @override | |
| 5113 List<DartType> get optionalParameterTypes { | |
| 5114 List<ParameterElement> parameters = baseParameters; | |
| 5115 if (parameters.length == 0) { | |
| 5116 return DartType.EMPTY_LIST; | |
| 5117 } | |
| 5118 List<DartType> typeParameters = | |
| 5119 TypeParameterTypeImpl.getTypes(this.typeParameters); | |
| 5120 List<DartType> types = new List<DartType>(); | |
| 5121 for (ParameterElement parameter in parameters) { | |
| 5122 if (parameter.parameterKind == ParameterKind.POSITIONAL) { | |
| 5123 DartType type = parameter.type; | |
| 5124 if (typeArguments.length != 0 && | |
| 5125 typeArguments.length == typeParameters.length) { | |
| 5126 type = (type as TypeImpl) | |
| 5127 .substitute2(typeArguments, typeParameters, newPrune); | |
| 5128 } else { | |
| 5129 type = (type as TypeImpl).pruned(newPrune); | |
| 5130 } | |
| 5131 types.add(type); | |
| 5132 } | |
| 5133 } | |
| 5134 return types; | |
| 5135 } | |
| 5136 | |
| 5137 @override | |
| 5138 List<ParameterElement> get parameters { | |
| 5139 List<ParameterElement> baseParameters = this.baseParameters; | |
| 5140 // no parameters, quick return | |
| 5141 int parameterCount = baseParameters.length; | |
| 5142 if (parameterCount == 0) { | |
| 5143 return baseParameters; | |
| 5144 } | |
| 5145 // create specialized parameters | |
| 5146 List<ParameterElement> specializedParameters = | |
| 5147 new List<ParameterElement>(parameterCount); | |
| 5148 for (int i = 0; i < parameterCount; i++) { | |
| 5149 specializedParameters[i] = ParameterMember.from(baseParameters[i], this); | |
| 5150 } | |
| 5151 return specializedParameters; | |
| 5152 } | |
| 5153 | |
| 5154 @override | |
| 5155 DartType get returnType { | |
| 5156 DartType baseReturnType = this.baseReturnType; | |
| 5157 if (baseReturnType == null) { | |
| 5158 // TODO(brianwilkerson) This is a patch. The return type should never be | |
| 5159 // null and we need to understand why it is and fix it. | |
| 5160 return DynamicTypeImpl.instance; | |
| 5161 } | |
| 5162 // If there are no arguments to substitute, or if the arguments size doesn't | |
| 5163 // match the parameter size, return the base return type. | |
| 5164 if (typeArguments.length == 0 || | |
| 5165 typeArguments.length != typeParameters.length) { | |
| 5166 return (baseReturnType as TypeImpl).pruned(newPrune); | |
| 5167 } | |
| 5168 return (baseReturnType as TypeImpl).substitute2(typeArguments, | |
| 5169 TypeParameterTypeImpl.getTypes(typeParameters), newPrune); | |
| 5170 } | |
| 5171 | |
| 5172 @override | |
| 5173 List<TypeParameterElement> get typeParameters { | |
| 5174 Element element = this.element; | |
| 5175 if (element is FunctionTypeAliasElement) { | |
| 5176 return element.typeParameters; | |
| 5177 } | |
| 5178 ClassElement definingClass = | |
| 5179 element.getAncestor((element) => element is ClassElement); | |
| 5180 if (definingClass != null) { | |
| 5181 return definingClass.typeParameters; | |
| 5182 } | |
| 5183 return TypeParameterElement.EMPTY_LIST; | |
| 5184 } | |
| 5185 | |
| 5186 @override | |
| 5187 bool operator ==(Object object) { | |
| 5188 if (object is! FunctionTypeImpl) { | |
| 5189 return false; | |
| 5190 } | |
| 5191 FunctionTypeImpl otherType = object as FunctionTypeImpl; | |
| 5192 return returnType == otherType.returnType && | |
| 5193 TypeImpl.equalArrays( | |
| 5194 normalParameterTypes, otherType.normalParameterTypes) && | |
| 5195 TypeImpl.equalArrays( | |
| 5196 optionalParameterTypes, otherType.optionalParameterTypes) && | |
| 5197 _equals(namedParameterTypes, otherType.namedParameterTypes); | |
| 5198 } | |
| 5199 | |
| 5200 @override | |
| 5201 void appendTo(StringBuffer buffer) { | |
| 5202 List<DartType> normalParameterTypes = this.normalParameterTypes; | |
| 5203 List<DartType> optionalParameterTypes = this.optionalParameterTypes; | |
| 5204 Map<String, DartType> namedParameterTypes = this.namedParameterTypes; | |
| 5205 DartType returnType = this.returnType; | |
| 5206 buffer.write("("); | |
| 5207 bool needsComma = false; | |
| 5208 if (normalParameterTypes.length > 0) { | |
| 5209 for (DartType type in normalParameterTypes) { | |
| 5210 if (needsComma) { | |
| 5211 buffer.write(", "); | |
| 5212 } else { | |
| 5213 needsComma = true; | |
| 5214 } | |
| 5215 (type as TypeImpl).appendTo(buffer); | |
| 5216 } | |
| 5217 } | |
| 5218 if (optionalParameterTypes.length > 0) { | |
| 5219 if (needsComma) { | |
| 5220 buffer.write(", "); | |
| 5221 needsComma = false; | |
| 5222 } | |
| 5223 buffer.write("["); | |
| 5224 for (DartType type in optionalParameterTypes) { | |
| 5225 if (needsComma) { | |
| 5226 buffer.write(", "); | |
| 5227 } else { | |
| 5228 needsComma = true; | |
| 5229 } | |
| 5230 (type as TypeImpl).appendTo(buffer); | |
| 5231 } | |
| 5232 buffer.write("]"); | |
| 5233 needsComma = true; | |
| 5234 } | |
| 5235 if (namedParameterTypes.length > 0) { | |
| 5236 if (needsComma) { | |
| 5237 buffer.write(", "); | |
| 5238 needsComma = false; | |
| 5239 } | |
| 5240 buffer.write("{"); | |
| 5241 namedParameterTypes.forEach((String name, DartType type) { | |
| 5242 if (needsComma) { | |
| 5243 buffer.write(", "); | |
| 5244 } else { | |
| 5245 needsComma = true; | |
| 5246 } | |
| 5247 buffer.write(name); | |
| 5248 buffer.write(": "); | |
| 5249 (type as TypeImpl).appendTo(buffer); | |
| 5250 }); | |
| 5251 buffer.write("}"); | |
| 5252 needsComma = true; | |
| 5253 } | |
| 5254 buffer.write(")"); | |
| 5255 buffer.write(Element.RIGHT_ARROW); | |
| 5256 if (returnType == null) { | |
| 5257 buffer.write("null"); | |
| 5258 } else { | |
| 5259 (returnType as TypeImpl).appendTo(buffer); | |
| 5260 } | |
| 5261 } | |
| 5262 | |
| 5263 @override | |
| 5264 bool isAssignableTo(DartType type) { | |
| 5265 // A function type T may be assigned to a function type S, written T <=> S, | |
| 5266 // iff T <: S. | |
| 5267 return isSubtypeOf(type); | |
| 5268 } | |
| 5269 | |
| 5270 @override | |
| 5271 bool isMoreSpecificThan(DartType type, | |
| 5272 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 5273 // Note: visitedElements is only used for breaking recursion in the type | |
| 5274 // hierarchy; we don't use it when recursing into the function type. | |
| 5275 | |
| 5276 // trivial base cases | |
| 5277 if (type == null) { | |
| 5278 return false; | |
| 5279 } else if (identical(this, type) || | |
| 5280 type.isDynamic || | |
| 5281 type.isDartCoreFunction || | |
| 5282 type.isObject) { | |
| 5283 return true; | |
| 5284 } else if (type is! FunctionType) { | |
| 5285 return false; | |
| 5286 } else if (this == type) { | |
| 5287 return true; | |
| 5288 } | |
| 5289 FunctionType t = this; | |
| 5290 FunctionType s = type as FunctionType; | |
| 5291 List<DartType> tTypes = t.normalParameterTypes; | |
| 5292 List<DartType> tOpTypes = t.optionalParameterTypes; | |
| 5293 List<DartType> sTypes = s.normalParameterTypes; | |
| 5294 List<DartType> sOpTypes = s.optionalParameterTypes; | |
| 5295 // If one function has positional and the other has named parameters, | |
| 5296 // return false. | |
| 5297 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || | |
| 5298 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { | |
| 5299 return false; | |
| 5300 } | |
| 5301 // named parameters case | |
| 5302 if (t.namedParameterTypes.length > 0) { | |
| 5303 // check that the number of required parameters are equal, and check that | |
| 5304 // every t_i is more specific than every s_i | |
| 5305 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { | |
| 5306 return false; | |
| 5307 } else if (t.normalParameterTypes.length > 0) { | |
| 5308 for (int i = 0; i < tTypes.length; i++) { | |
| 5309 if (!(tTypes[i] as TypeImpl) | |
| 5310 .isMoreSpecificThan(sTypes[i], withDynamic)) { | |
| 5311 return false; | |
| 5312 } | |
| 5313 } | |
| 5314 } | |
| 5315 Map<String, DartType> namedTypesT = t.namedParameterTypes; | |
| 5316 Map<String, DartType> namedTypesS = s.namedParameterTypes; | |
| 5317 // if k >= m is false, return false: the passed function type has more | |
| 5318 // named parameter types than this | |
| 5319 if (namedTypesT.length < namedTypesS.length) { | |
| 5320 return false; | |
| 5321 } | |
| 5322 // Loop through each element in S verifying that T has a matching | |
| 5323 // parameter name and that the corresponding type is more specific then | |
| 5324 // the type in S. | |
| 5325 for (String keyS in namedTypesS.keys) { | |
| 5326 DartType typeT = namedTypesT[keyS]; | |
| 5327 if (typeT == null) { | |
| 5328 return false; | |
| 5329 } | |
| 5330 if (!(typeT as TypeImpl) | |
| 5331 .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) { | |
| 5332 return false; | |
| 5333 } | |
| 5334 } | |
| 5335 } else if (s.namedParameterTypes.length > 0) { | |
| 5336 return false; | |
| 5337 } else { | |
| 5338 // positional parameter case | |
| 5339 int tArgLength = tTypes.length + tOpTypes.length; | |
| 5340 int sArgLength = sTypes.length + sOpTypes.length; | |
| 5341 // Check that the total number of parameters in t is greater than or equal | |
| 5342 // to the number of parameters in s and that the number of required | |
| 5343 // parameters in s is greater than or equal to the number of required | |
| 5344 // parameters in t. | |
| 5345 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { | |
| 5346 return false; | |
| 5347 } | |
| 5348 if (tOpTypes.length == 0 && sOpTypes.length == 0) { | |
| 5349 // No positional arguments, don't copy contents to new array | |
| 5350 for (int i = 0; i < sTypes.length; i++) { | |
| 5351 if (!(tTypes[i] as TypeImpl) | |
| 5352 .isMoreSpecificThan(sTypes[i], withDynamic)) { | |
| 5353 return false; | |
| 5354 } | |
| 5355 } | |
| 5356 } else { | |
| 5357 // Else, we do have positional parameters, copy required and positional | |
| 5358 // parameter types into arrays to do the compare (for loop below). | |
| 5359 List<DartType> tAllTypes = new List<DartType>(sArgLength); | |
| 5360 for (int i = 0; i < tTypes.length; i++) { | |
| 5361 tAllTypes[i] = tTypes[i]; | |
| 5362 } | |
| 5363 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 5364 tAllTypes[i] = tOpTypes[j]; | |
| 5365 } | |
| 5366 List<DartType> sAllTypes = new List<DartType>(sArgLength); | |
| 5367 for (int i = 0; i < sTypes.length; i++) { | |
| 5368 sAllTypes[i] = sTypes[i]; | |
| 5369 } | |
| 5370 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 5371 sAllTypes[i] = sOpTypes[j]; | |
| 5372 } | |
| 5373 for (int i = 0; i < sAllTypes.length; i++) { | |
| 5374 if (!(tAllTypes[i] as TypeImpl) | |
| 5375 .isMoreSpecificThan(sAllTypes[i], withDynamic)) { | |
| 5376 return false; | |
| 5377 } | |
| 5378 } | |
| 5379 } | |
| 5380 } | |
| 5381 DartType tRetType = t.returnType; | |
| 5382 DartType sRetType = s.returnType; | |
| 5383 return sRetType.isVoid || | |
| 5384 (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic); | |
| 5385 } | |
| 5386 | |
| 5387 @override | |
| 5388 bool isSubtypeOf(DartType type) { | |
| 5389 // trivial base cases | |
| 5390 if (type == null) { | |
| 5391 return false; | |
| 5392 } else if (identical(this, type) || | |
| 5393 type.isDynamic || | |
| 5394 type.isDartCoreFunction || | |
| 5395 type.isObject) { | |
| 5396 return true; | |
| 5397 } else if (type is! FunctionType) { | |
| 5398 return false; | |
| 5399 } else if (this == type) { | |
| 5400 return true; | |
| 5401 } | |
| 5402 FunctionType t = this; | |
| 5403 FunctionType s = type as FunctionType; | |
| 5404 List<DartType> tTypes = t.normalParameterTypes; | |
| 5405 List<DartType> tOpTypes = t.optionalParameterTypes; | |
| 5406 List<DartType> sTypes = s.normalParameterTypes; | |
| 5407 List<DartType> sOpTypes = s.optionalParameterTypes; | |
| 5408 // If one function has positional and the other has named parameters, | |
| 5409 // return false. | |
| 5410 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || | |
| 5411 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) { | |
| 5412 return false; | |
| 5413 } | |
| 5414 // named parameters case | |
| 5415 if (t.namedParameterTypes.length > 0) { | |
| 5416 // check that the number of required parameters are equal, | |
| 5417 // and check that every t_i is assignable to every s_i | |
| 5418 if (t.normalParameterTypes.length != s.normalParameterTypes.length) { | |
| 5419 return false; | |
| 5420 } else if (t.normalParameterTypes.length > 0) { | |
| 5421 for (int i = 0; i < tTypes.length; i++) { | |
| 5422 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { | |
| 5423 return false; | |
| 5424 } | |
| 5425 } | |
| 5426 } | |
| 5427 Map<String, DartType> namedTypesT = t.namedParameterTypes; | |
| 5428 Map<String, DartType> namedTypesS = s.namedParameterTypes; | |
| 5429 // if k >= m is false, return false: the passed function type has more | |
| 5430 // named parameter types than this | |
| 5431 if (namedTypesT.length < namedTypesS.length) { | |
| 5432 return false; | |
| 5433 } | |
| 5434 // Loop through each element in S verifying that T has a matching | |
| 5435 // parameter name and that the corresponding type is assignable to the | |
| 5436 // type in S. | |
| 5437 for (String keyS in namedTypesS.keys) { | |
| 5438 DartType typeT = namedTypesT[keyS]; | |
| 5439 if (typeT == null) { | |
| 5440 return false; | |
| 5441 } | |
| 5442 if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) { | |
| 5443 return false; | |
| 5444 } | |
| 5445 } | |
| 5446 } else if (s.namedParameterTypes.length > 0) { | |
| 5447 return false; | |
| 5448 } else { | |
| 5449 // positional parameter case | |
| 5450 int tArgLength = tTypes.length + tOpTypes.length; | |
| 5451 int sArgLength = sTypes.length + sOpTypes.length; | |
| 5452 // Check that the total number of parameters in t is greater than or | |
| 5453 // equal to the number of parameters in s and that the number of | |
| 5454 // required parameters in s is greater than or equal to the number of | |
| 5455 // required parameters in t. | |
| 5456 if (tArgLength < sArgLength || sTypes.length < tTypes.length) { | |
| 5457 return false; | |
| 5458 } | |
| 5459 if (tOpTypes.length == 0 && sOpTypes.length == 0) { | |
| 5460 // No positional arguments, don't copy contents to new array | |
| 5461 for (int i = 0; i < sTypes.length; i++) { | |
| 5462 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) { | |
| 5463 return false; | |
| 5464 } | |
| 5465 } | |
| 5466 } else { | |
| 5467 // Else, we do have positional parameters, copy required and | |
| 5468 // positional parameter types into arrays to do the compare (for loop | |
| 5469 // below). | |
| 5470 List<DartType> tAllTypes = new List<DartType>(sArgLength); | |
| 5471 for (int i = 0; i < tTypes.length; i++) { | |
| 5472 tAllTypes[i] = tTypes[i]; | |
| 5473 } | |
| 5474 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 5475 tAllTypes[i] = tOpTypes[j]; | |
| 5476 } | |
| 5477 List<DartType> sAllTypes = new List<DartType>(sArgLength); | |
| 5478 for (int i = 0; i < sTypes.length; i++) { | |
| 5479 sAllTypes[i] = sTypes[i]; | |
| 5480 } | |
| 5481 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { | |
| 5482 sAllTypes[i] = sOpTypes[j]; | |
| 5483 } | |
| 5484 for (int i = 0; i < sAllTypes.length; i++) { | |
| 5485 if (!(tAllTypes[i] as TypeImpl).isAssignableTo(sAllTypes[i])) { | |
| 5486 return false; | |
| 5487 } | |
| 5488 } | |
| 5489 } | |
| 5490 } | |
| 5491 DartType tRetType = t.returnType; | |
| 5492 DartType sRetType = s.returnType; | |
| 5493 return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType); | |
| 5494 } | |
| 5495 | |
| 5496 @override | |
| 5497 TypeImpl pruned(List<FunctionTypeAliasElement> prune) { | |
| 5498 if (prune == null) { | |
| 5499 return this; | |
| 5500 } else if (prune.contains(element)) { | |
| 5501 // Circularity found. Prune the type declaration. | |
| 5502 return new CircularTypeImpl(); | |
| 5503 } else { | |
| 5504 // There should never be a reason to prune a type that has already been | |
| 5505 // pruned, since pruning is only done when expanding a function type | |
| 5506 // alias, and function type aliases are always expanded by starting with | |
| 5507 // base types. | |
| 5508 assert(this.prunedTypedefs == null); | |
| 5509 FunctionTypeImpl result = new FunctionTypeImpl._(element, name, prune); | |
| 5510 result.typeArguments = | |
| 5511 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList(); | |
| 5512 return result; | |
| 5513 } | |
| 5514 } | |
| 5515 | |
| 5516 @override | |
| 5517 DartType substitute2( | |
| 5518 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 5519 [List<FunctionTypeAliasElement> prune]) { | |
| 5520 // Pruned types should only ever result from peforming type variable | |
| 5521 // substitution, and it doesn't make sense to substitute again after | |
| 5522 // substituting once. | |
| 5523 assert(this.prunedTypedefs == null); | |
| 5524 if (argumentTypes.length != parameterTypes.length) { | |
| 5525 throw new IllegalArgumentException( | |
| 5526 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); | |
| 5527 } | |
| 5528 Element element = this.element; | |
| 5529 if (prune != null && prune.contains(element)) { | |
| 5530 // Circularity found. Prune the type declaration. | |
| 5531 return new CircularTypeImpl(); | |
| 5532 } | |
| 5533 if (argumentTypes.length == 0) { | |
| 5534 return this.pruned(prune); | |
| 5535 } | |
| 5536 FunctionTypeImpl newType = (element is ExecutableElement) | |
| 5537 ? new FunctionTypeImpl(element, prune) | |
| 5538 : new FunctionTypeImpl.forTypedef( | |
| 5539 element as FunctionTypeAliasElement, prune); | |
| 5540 newType.typeArguments = | |
| 5541 TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes); | |
| 5542 return newType; | |
| 5543 } | |
| 5544 | |
| 5545 @override | |
| 5546 FunctionTypeImpl substitute3(List<DartType> argumentTypes) => | |
| 5547 substitute2(argumentTypes, typeArguments); | |
| 5548 | |
| 5549 /** | |
| 5550 * Compute the least upper bound of types [f] and [g], both of which are | |
| 5551 * known to be function types. | |
| 5552 * | |
| 5553 * In the event that f and g have different numbers of required parameters, | |
| 5554 * `null` is returned, in which case the least upper bound is the interface | |
| 5555 * type `Function`. | |
| 5556 */ | |
| 5557 static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) { | |
| 5558 // TODO(paulberry): implement this. | |
| 5559 return null; | |
| 5560 } | |
| 5561 | |
| 5562 /** | |
| 5563 * Return `true` if all of the name/type pairs in the first map ([firstTypes]) | |
| 5564 * are equal to the corresponding name/type pairs in the second map | |
| 5565 * ([secondTypes]). The maps are expected to iterate over their entries in the | |
| 5566 * same order in which those entries were added to the map. | |
| 5567 */ | |
| 5568 static bool _equals( | |
| 5569 Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) { | |
| 5570 if (secondTypes.length != firstTypes.length) { | |
| 5571 return false; | |
| 5572 } | |
| 5573 Iterator<String> firstKeys = firstTypes.keys.iterator; | |
| 5574 Iterator<String> secondKeys = secondTypes.keys.iterator; | |
| 5575 while (firstKeys.moveNext() && secondKeys.moveNext()) { | |
| 5576 String firstKey = firstKeys.current; | |
| 5577 String secondKey = secondKeys.current; | |
| 5578 TypeImpl firstType = firstTypes[firstKey]; | |
| 5579 TypeImpl secondType = secondTypes[secondKey]; | |
| 5580 if (firstKey != secondKey || firstType != secondType) { | |
| 5581 return false; | |
| 5582 } | |
| 5583 } | |
| 5584 return true; | |
| 5585 } | |
| 5586 } | |
| 5587 | |
| 5588 /** | |
| 5589 * An element visitor that will recursively visit all of the elements in an | |
| 5590 * element model (like instances of the class [RecursiveElementVisitor]). In | |
| 5591 * addition, when an element of a specific type is visited not only will the | |
| 5592 * visit method for that specific type of element be invoked, but additional | |
| 5593 * methods for the supertypes of that element will also be invoked. For example, | |
| 5594 * using an instance of this class to visit a [MethodElement] will cause the | |
| 5595 * method [visitMethodElement] to be invoked but will also cause the methods | |
| 5596 * [visitExecutableElement] and [visitElement] to be subsequently invoked. This | |
| 5597 * allows visitors to be written that visit all executable elements without | |
| 5598 * needing to override the visit method for each of the specific subclasses of | |
| 5599 * [ExecutableElement]. | |
| 5600 * | |
| 5601 * Note, however, that unlike many visitors, element visitors visit objects | |
| 5602 * based on the interfaces implemented by those elements. Because interfaces | |
| 5603 * form a graph structure rather than a tree structure the way classes do, and | |
| 5604 * because it is generally undesirable for an object to be visited more than | |
| 5605 * once, this class flattens the interface graph into a pseudo-tree. In | |
| 5606 * particular, this class treats elements as if the element types were | |
| 5607 * structured in the following way: | |
| 5608 * | |
| 5609 * <pre> | |
| 5610 * Element | |
| 5611 * ClassElement | |
| 5612 * CompilationUnitElement | |
| 5613 * ExecutableElement | |
| 5614 * ConstructorElement | |
| 5615 * LocalElement | |
| 5616 * FunctionElement | |
| 5617 * MethodElement | |
| 5618 * PropertyAccessorElement | |
| 5619 * ExportElement | |
| 5620 * HtmlElement | |
| 5621 * ImportElement | |
| 5622 * LabelElement | |
| 5623 * LibraryElement | |
| 5624 * MultiplyDefinedElement | |
| 5625 * PrefixElement | |
| 5626 * TypeAliasElement | |
| 5627 * TypeParameterElement | |
| 5628 * UndefinedElement | |
| 5629 * VariableElement | |
| 5630 * PropertyInducingElement | |
| 5631 * FieldElement | |
| 5632 * TopLevelVariableElement | |
| 5633 * LocalElement | |
| 5634 * LocalVariableElement | |
| 5635 * ParameterElement | |
| 5636 * FieldFormalParameterElement | |
| 5637 * </pre> | |
| 5638 * | |
| 5639 * Subclasses that override a visit method must either invoke the overridden | |
| 5640 * visit method or explicitly invoke the more general visit method. Failure to | |
| 5641 * do so will cause the visit methods for superclasses of the element to not be | |
| 5642 * invoked and will cause the children of the visited node to not be visited. | |
| 5643 */ | |
| 5644 class GeneralizingElementVisitor<R> implements ElementVisitor<R> { | |
| 5645 @override | |
| 5646 R visitClassElement(ClassElement element) => visitElement(element); | |
| 5647 | |
| 5648 @override | |
| 5649 R visitCompilationUnitElement(CompilationUnitElement element) => | |
| 5650 visitElement(element); | |
| 5651 | |
| 5652 @override | |
| 5653 R visitConstructorElement(ConstructorElement element) => | |
| 5654 visitExecutableElement(element); | |
| 5655 | |
| 5656 R visitElement(Element element) { | |
| 5657 element.visitChildren(this); | |
| 5658 return null; | |
| 5659 } | |
| 5660 | |
| 5661 @override | |
| 5662 @deprecated | |
| 5663 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => | |
| 5664 visitHtmlScriptElement(element); | |
| 5665 | |
| 5666 R visitExecutableElement(ExecutableElement element) => visitElement(element); | |
| 5667 | |
| 5668 @override | |
| 5669 R visitExportElement(ExportElement element) => visitElement(element); | |
| 5670 | |
| 5671 @override | |
| 5672 @deprecated | |
| 5673 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => | |
| 5674 visitHtmlScriptElement(element); | |
| 5675 | |
| 5676 @override | |
| 5677 R visitFieldElement(FieldElement element) => | |
| 5678 visitPropertyInducingElement(element); | |
| 5679 | |
| 5680 @override | |
| 5681 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => | |
| 5682 visitParameterElement(element); | |
| 5683 | |
| 5684 @override | |
| 5685 R visitFunctionElement(FunctionElement element) => visitLocalElement(element); | |
| 5686 | |
| 5687 @override | |
| 5688 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => | |
| 5689 visitElement(element); | |
| 5690 | |
| 5691 @override | |
| 5692 @deprecated | |
| 5693 R visitHtmlElement(HtmlElement element) => visitElement(element); | |
| 5694 | |
| 5695 @deprecated | |
| 5696 R visitHtmlScriptElement(HtmlScriptElement element) => visitElement(element); | |
| 5697 | |
| 5698 @override | |
| 5699 R visitImportElement(ImportElement element) => visitElement(element); | |
| 5700 | |
| 5701 @override | |
| 5702 R visitLabelElement(LabelElement element) => visitElement(element); | |
| 5703 | |
| 5704 @override | |
| 5705 R visitLibraryElement(LibraryElement element) => visitElement(element); | |
| 5706 | |
| 5707 R visitLocalElement(LocalElement element) { | |
| 5708 if (element is LocalVariableElement) { | |
| 5709 return visitVariableElement(element); | |
| 5710 } else if (element is ParameterElement) { | |
| 5711 return visitVariableElement(element); | |
| 5712 } else if (element is FunctionElement) { | |
| 5713 return visitExecutableElement(element); | |
| 5714 } | |
| 5715 return null; | |
| 5716 } | |
| 5717 | |
| 5718 @override | |
| 5719 R visitLocalVariableElement(LocalVariableElement element) => | |
| 5720 visitLocalElement(element); | |
| 5721 | |
| 5722 @override | |
| 5723 R visitMethodElement(MethodElement element) => | |
| 5724 visitExecutableElement(element); | |
| 5725 | |
| 5726 @override | |
| 5727 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => | |
| 5728 visitElement(element); | |
| 5729 | |
| 5730 @override | |
| 5731 R visitParameterElement(ParameterElement element) => | |
| 5732 visitLocalElement(element); | |
| 5733 | |
| 5734 @override | |
| 5735 R visitPrefixElement(PrefixElement element) => visitElement(element); | |
| 5736 | |
| 5737 @override | |
| 5738 R visitPropertyAccessorElement(PropertyAccessorElement element) => | |
| 5739 visitExecutableElement(element); | |
| 5740 | |
| 5741 R visitPropertyInducingElement(PropertyInducingElement element) => | |
| 5742 visitVariableElement(element); | |
| 5743 | |
| 5744 @override | |
| 5745 R visitTopLevelVariableElement(TopLevelVariableElement element) => | |
| 5746 visitPropertyInducingElement(element); | |
| 5747 | |
| 5748 @override | |
| 5749 R visitTypeParameterElement(TypeParameterElement element) => | |
| 5750 visitElement(element); | |
| 5751 | |
| 5752 R visitVariableElement(VariableElement element) => visitElement(element); | |
| 5753 } | |
| 5754 | |
| 5755 /** | |
| 5756 * A combinator that causes some of the names in a namespace to be hidden when | |
| 5757 * being imported. | |
| 5758 */ | |
| 5759 abstract class HideElementCombinator implements NamespaceCombinator { | |
| 5760 /** | |
| 5761 * Return a list containing the names that are not to be made visible in the | |
| 5762 * importing library even if they are defined in the imported library. | |
| 5763 */ | |
| 5764 List<String> get hiddenNames; | |
| 5765 } | |
| 5766 | |
| 5767 /** | |
| 5768 * A concrete implementation of a [HideElementCombinator]. | |
| 5769 */ | |
| 5770 class HideElementCombinatorImpl implements HideElementCombinator { | |
| 5771 /** | |
| 5772 * The names that are not to be made visible in the importing library even if | |
| 5773 * they are defined in the imported library. | |
| 5774 */ | |
| 5775 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY; | |
| 5776 | |
| 5777 @override | |
| 5778 String toString() { | |
| 5779 StringBuffer buffer = new StringBuffer(); | |
| 5780 buffer.write("show "); | |
| 5781 int count = hiddenNames.length; | |
| 5782 for (int i = 0; i < count; i++) { | |
| 5783 if (i > 0) { | |
| 5784 buffer.write(", "); | |
| 5785 } | |
| 5786 buffer.write(hiddenNames[i]); | |
| 5787 } | |
| 5788 return buffer.toString(); | |
| 5789 } | |
| 5790 } | |
| 5791 | |
| 5792 /** | |
| 5793 * An HTML file. | |
| 5794 */ | |
| 5795 @deprecated | |
| 5796 abstract class HtmlElement implements Element { | |
| 5797 /** | |
| 5798 * An empty list of HTML file elements. | |
| 5799 */ | |
| 5800 static const List<HtmlElement> EMPTY_LIST = const <HtmlElement>[]; | |
| 5801 | |
| 5802 /** | |
| 5803 * Return a list containing all of the script elements contained in the HTML | |
| 5804 * file. This includes scripts with libraries that are defined by the content | |
| 5805 * of a script tag as well as libraries that are referenced in the `source` | |
| 5806 * attribute of a script tag. | |
| 5807 */ | |
| 5808 List<HtmlScriptElement> get scripts; | |
| 5809 } | |
| 5810 | |
| 5811 /** | |
| 5812 * A concrete implementation of an [HtmlElement]. | |
| 5813 */ | |
| 5814 @deprecated | |
| 5815 class HtmlElementImpl extends ElementImpl implements HtmlElement { | |
| 5816 /** | |
| 5817 * An empty list of HTML file elements. | |
| 5818 */ | |
| 5819 @deprecated // Use HtmlElement.EMPTY_LIST | |
| 5820 static const List<HtmlElement> EMPTY_ARRAY = const <HtmlElement>[]; | |
| 5821 | |
| 5822 /** | |
| 5823 * The analysis context in which this library is defined. | |
| 5824 */ | |
| 5825 final AnalysisContext context; | |
| 5826 | |
| 5827 /** | |
| 5828 * The scripts contained in or referenced from script tags in the HTML file. | |
| 5829 */ | |
| 5830 List<HtmlScriptElement> _scripts = HtmlScriptElement.EMPTY_LIST; | |
| 5831 | |
| 5832 /** | |
| 5833 * The source that corresponds to this HTML file. | |
| 5834 */ | |
| 5835 Source source; | |
| 5836 | |
| 5837 /** | |
| 5838 * Initialize a newly created HTML element in the given [context] to have the | |
| 5839 * given [name]. | |
| 5840 */ | |
| 5841 HtmlElementImpl(this.context, String name) : super(name, -1); | |
| 5842 | |
| 5843 @override | |
| 5844 int get hashCode => source.hashCode; | |
| 5845 | |
| 5846 @override | |
| 5847 String get identifier => source.encoding; | |
| 5848 | |
| 5849 @override | |
| 5850 ElementKind get kind => ElementKind.HTML; | |
| 5851 | |
| 5852 @override | |
| 5853 List<HtmlScriptElement> get scripts => _scripts; | |
| 5854 | |
| 5855 /** | |
| 5856 * Set the scripts contained in the HTML file to the given [scripts]. | |
| 5857 */ | |
| 5858 void set scripts(List<HtmlScriptElement> scripts) { | |
| 5859 if (scripts.length == 0) { | |
| 5860 this._scripts = HtmlScriptElement.EMPTY_LIST; | |
| 5861 return; | |
| 5862 } | |
| 5863 for (HtmlScriptElement script in scripts) { | |
| 5864 (script as HtmlScriptElementImpl).enclosingElement = this; | |
| 5865 } | |
| 5866 this._scripts = scripts; | |
| 5867 } | |
| 5868 | |
| 5869 @override | |
| 5870 bool operator ==(Object object) { | |
| 5871 if (identical(object, this)) { | |
| 5872 return true; | |
| 5873 } | |
| 5874 return object is HtmlElementImpl && source == object.source; | |
| 5875 } | |
| 5876 | |
| 5877 @override | |
| 5878 accept(ElementVisitor visitor) => visitor.visitHtmlElement(this); | |
| 5879 | |
| 5880 @override | |
| 5881 void appendTo(StringBuffer buffer) { | |
| 5882 if (source == null) { | |
| 5883 buffer.write("{HTML file}"); | |
| 5884 } else { | |
| 5885 buffer.write(source.fullName); | |
| 5886 } | |
| 5887 } | |
| 5888 | |
| 5889 @override | |
| 5890 void visitChildren(ElementVisitor visitor) { | |
| 5891 super.visitChildren(visitor); | |
| 5892 safelyVisitChildren(_scripts, visitor); | |
| 5893 } | |
| 5894 } | |
| 5895 | |
| 5896 /** | |
| 5897 * A script tag in an HTML file. | |
| 5898 * | |
| 5899 * See [EmbeddedHtmlScriptElement], and [ExternalHtmlScriptElement]. | |
| 5900 */ | |
| 5901 @deprecated | |
| 5902 abstract class HtmlScriptElement implements Element { | |
| 5903 /** | |
| 5904 * An empty list of HTML script elements. | |
| 5905 */ | |
| 5906 static const List<HtmlScriptElement> EMPTY_LIST = const <HtmlScriptElement>[]; | |
| 5907 } | |
| 5908 | |
| 5909 /** | |
| 5910 * A concrete implementation of an [HtmlScriptElement]. | |
| 5911 */ | |
| 5912 @deprecated | |
| 5913 abstract class HtmlScriptElementImpl extends ElementImpl | |
| 5914 implements HtmlScriptElement { | |
| 5915 /** | |
| 5916 * An empty list of HTML script elements. | |
| 5917 */ | |
| 5918 @deprecated // Use HtmlScriptElement.EMPTY_LIST | |
| 5919 static const List<HtmlScriptElement> EMPTY_ARRAY = | |
| 5920 const <HtmlScriptElement>[]; | |
| 5921 | |
| 5922 /** | |
| 5923 * Initialize a newly created script element corresponding to the given | |
| 5924 * [node]. | |
| 5925 */ | |
| 5926 HtmlScriptElementImpl(XmlTagNode node) | |
| 5927 : super(node.tag, node.tagToken.offset); | |
| 5928 } | |
| 5929 | |
| 5930 /** | |
| 5931 * A single import directive within a library. | |
| 5932 */ | |
| 5933 abstract class ImportElement implements Element, UriReferencedElement { | |
| 5934 /** | |
| 5935 * An empty list of import elements. | |
| 5936 */ | |
| 5937 @deprecated // Use ImportElement.EMPTY_LIST | |
| 5938 static const List<ImportElement> EMPTY_ARRAY = const <ImportElement>[]; | |
| 5939 | |
| 5940 /** | |
| 5941 * An empty list of import elements. | |
| 5942 */ | |
| 5943 static const List<ImportElement> EMPTY_LIST = const <ImportElement>[]; | |
| 5944 | |
| 5945 /** | |
| 5946 * Return a list containing the combinators that were specified as part of the | |
| 5947 * import directive in the order in which they were specified. | |
| 5948 */ | |
| 5949 List<NamespaceCombinator> get combinators; | |
| 5950 | |
| 5951 /** | |
| 5952 * Return the library that is imported into this library by this import | |
| 5953 * directive. | |
| 5954 */ | |
| 5955 LibraryElement get importedLibrary; | |
| 5956 | |
| 5957 /** | |
| 5958 * Return `true` if this import is for a deferred library. | |
| 5959 */ | |
| 5960 bool get isDeferred; | |
| 5961 | |
| 5962 /** | |
| 5963 * Return the prefix that was specified as part of the import directive, or | |
| 5964 * `null` if there was no prefix specified. | |
| 5965 */ | |
| 5966 PrefixElement get prefix; | |
| 5967 | |
| 5968 /** | |
| 5969 * Return the offset of the prefix of this import in the file that contains | |
| 5970 * this import directive, or `-1` if this import is synthetic, does not have a | |
| 5971 * prefix, or otherwise does not have an offset. | |
| 5972 */ | |
| 5973 int get prefixOffset; | |
| 5974 } | |
| 5975 | |
| 5976 /** | |
| 5977 * A concrete implementation of an [ImportElement]. | |
| 5978 */ | |
| 5979 class ImportElementImpl extends UriReferencedElementImpl | |
| 5980 implements ImportElement { | |
| 5981 /** | |
| 5982 * The offset of the prefix of this import in the file that contains the this | |
| 5983 * import directive, or `-1` if this import is synthetic. | |
| 5984 */ | |
| 5985 int prefixOffset = 0; | |
| 5986 | |
| 5987 /** | |
| 5988 * The library that is imported into this library by this import directive. | |
| 5989 */ | |
| 5990 LibraryElement importedLibrary; | |
| 5991 | |
| 5992 /** | |
| 5993 * The combinators that were specified as part of the import directive in the | |
| 5994 * order in which they were specified. | |
| 5995 */ | |
| 5996 List<NamespaceCombinator> combinators = NamespaceCombinator.EMPTY_LIST; | |
| 5997 | |
| 5998 /** | |
| 5999 * The prefix that was specified as part of the import directive, or `null` if | |
| 6000 * there was no prefix specified. | |
| 6001 */ | |
| 6002 PrefixElement prefix; | |
| 6003 | |
| 6004 /** | |
| 6005 * Initialize a newly created import element at the given [offset]. | |
| 6006 * The offset may be `-1` if the import is synthetic. | |
| 6007 */ | |
| 6008 ImportElementImpl(int offset) : super(null, offset); | |
| 6009 | |
| 6010 /** | |
| 6011 * Set whether this import is for a deferred library. | |
| 6012 */ | |
| 6013 void set deferred(bool isDeferred) { | |
| 6014 setModifier(Modifier.DEFERRED, isDeferred); | |
| 6015 } | |
| 6016 | |
| 6017 @override | |
| 6018 String get identifier => | |
| 6019 "${(importedLibrary as LibraryElementImpl).identifier}@$nameOffset"; | |
| 6020 | |
| 6021 @override | |
| 6022 bool get isDeferred => hasModifier(Modifier.DEFERRED); | |
| 6023 | |
| 6024 @override | |
| 6025 ElementKind get kind => ElementKind.IMPORT; | |
| 6026 | |
| 6027 @override | |
| 6028 accept(ElementVisitor visitor) => visitor.visitImportElement(this); | |
| 6029 | |
| 6030 @override | |
| 6031 void appendTo(StringBuffer buffer) { | |
| 6032 buffer.write("import "); | |
| 6033 (importedLibrary as LibraryElementImpl).appendTo(buffer); | |
| 6034 } | |
| 6035 | |
| 6036 @override | |
| 6037 void visitChildren(ElementVisitor visitor) { | |
| 6038 super.visitChildren(visitor); | |
| 6039 safelyVisitChild(prefix, visitor); | |
| 6040 } | |
| 6041 } | |
| 6042 | |
| 6043 /** | |
| 6044 * The type introduced by either a class or an interface, or a reference to such | |
| 6045 * a type. | |
| 6046 */ | |
| 6047 abstract class InterfaceType implements ParameterizedType { | |
| 6048 /** | |
| 6049 * An empty list of types. | |
| 6050 */ | |
| 6051 @deprecated // Use InterfaceType.EMPTY_LIST | |
| 6052 static const List<InterfaceType> EMPTY_ARRAY = const <InterfaceType>[]; | |
| 6053 | |
| 6054 /** | |
| 6055 * An empty list of types. | |
| 6056 */ | |
| 6057 static const List<InterfaceType> EMPTY_LIST = const <InterfaceType>[]; | |
| 6058 | |
| 6059 /** | |
| 6060 * Return a list containing all of the accessors (getters and setters) | |
| 6061 * declared in this type. | |
| 6062 */ | |
| 6063 List<PropertyAccessorElement> get accessors; | |
| 6064 | |
| 6065 /** | |
| 6066 * Return a list containing all of the constructors declared in this type. | |
| 6067 */ | |
| 6068 List<ConstructorElement> get constructors; | |
| 6069 | |
| 6070 @override | |
| 6071 ClassElement get element; | |
| 6072 | |
| 6073 /** | |
| 6074 * Return a list containing all of the interfaces that are implemented by this | |
| 6075 * interface. Note that this is <b>not</b>, in general, equivalent to getting | |
| 6076 * the interfaces from this type's element because the types returned by this | |
| 6077 * method will have had their type parameters replaced. | |
| 6078 */ | |
| 6079 List<InterfaceType> get interfaces; | |
| 6080 | |
| 6081 /** | |
| 6082 * Return a list containing all of the methods declared in this type. | |
| 6083 */ | |
| 6084 List<MethodElement> get methods; | |
| 6085 | |
| 6086 /** | |
| 6087 * Return a list containing all of the mixins that are applied to the class | |
| 6088 * being extended in order to derive the superclass of this class. Note that | |
| 6089 * this is <b>not</b>, in general, equivalent to getting the mixins from this | |
| 6090 * type's element because the types returned by this method will have had | |
| 6091 * their type parameters replaced. | |
| 6092 */ | |
| 6093 List<InterfaceType> get mixins; | |
| 6094 | |
| 6095 /** | |
| 6096 * Return the type representing the superclass of this type, or null if this | |
| 6097 * type represents the class 'Object'. Note that this is <b>not</b>, in | |
| 6098 * general, equivalent to getting the superclass from this type's element | |
| 6099 * because the type returned by this method will have had it's type parameters | |
| 6100 * replaced. | |
| 6101 */ | |
| 6102 InterfaceType get superclass; | |
| 6103 | |
| 6104 /** | |
| 6105 * Return the element representing the getter with the given [name] that is | |
| 6106 * declared in this class, or `null` if this class does not declare a getter | |
| 6107 * with the given name. | |
| 6108 */ | |
| 6109 PropertyAccessorElement getGetter(String name); | |
| 6110 | |
| 6111 /** | |
| 6112 * Return the least upper bound of this type and the given [type], or `null` | |
| 6113 * if there is no least upper bound. | |
| 6114 * | |
| 6115 * Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the | |
| 6116 * set of superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of | |
| 6117 * superinterfaces of <i>J</i> and let <i>S = (I ∪ S<sub>I</sub>) ∩ | |
| 6118 * (J ∪ S<sub>J</sub>)</i>. Furthermore, we define <i>S<sub>n</sub> = | |
| 6119 * {T | T ∈ S ∧ depth(T) = n}</i> for any finite <i>n</i>, where | |
| 6120 * <i>depth(T)</i> is the number of steps in the longest inheritance path from | |
| 6121 * <i>T</i> to <i>Object</i>. Let <i>q</i> be the largest number such that | |
| 6122 * <i>S<sub>q</sub></i> has cardinality one. The least upper bound of <i>I</i> | |
| 6123 * and <i>J</i> is the sole element of <i>S<sub>q</sub></i>. | |
| 6124 */ | |
| 6125 @override | |
| 6126 @deprecated | |
| 6127 DartType getLeastUpperBound(DartType type); | |
| 6128 | |
| 6129 /** | |
| 6130 * Return the element representing the method with the given [name] that is | |
| 6131 * declared in this class, or `null` if this class does not declare a method | |
| 6132 * with the given name. | |
| 6133 */ | |
| 6134 MethodElement getMethod(String name); | |
| 6135 | |
| 6136 /** | |
| 6137 * Return the element representing the setter with the given [name] that is | |
| 6138 * declared in this class, or `null` if this class does not declare a setter | |
| 6139 * with the given name. | |
| 6140 */ | |
| 6141 PropertyAccessorElement getSetter(String name); | |
| 6142 | |
| 6143 /** | |
| 6144 * Return `true` if this type is a direct supertype of the given [type]. The | |
| 6145 * implicit interface of class <i>I</i> is a direct supertype of the implicit | |
| 6146 * interface of class <i>J</i> iff: | |
| 6147 * | |
| 6148 * * <i>I</i> is Object, and <i>J</i> has no extends clause. | |
| 6149 * * <i>I</i> is listed in the extends clause of <i>J</i>. | |
| 6150 * * <i>I</i> is listed in the implements clause of <i>J</i>. | |
| 6151 * * <i>I</i> is listed in the with clause of <i>J</i>. | |
| 6152 * * <i>J</i> is a mixin application of the mixin of <i>I</i>. | |
| 6153 */ | |
| 6154 bool isDirectSupertypeOf(InterfaceType type); | |
| 6155 | |
| 6156 /** | |
| 6157 * Return `true` if this type is more specific than the given [type]. An | |
| 6158 * interface type <i>T</i> is more specific than an interface type <i>S</i>, | |
| 6159 * written <i>T « S</i>, if one of the following conditions is met: | |
| 6160 * | |
| 6161 * * Reflexivity: <i>T</i> is <i>S</i>. | |
| 6162 * * <i>T</i> is bottom. | |
| 6163 * * <i>S</i> is dynamic. | |
| 6164 * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>. | |
| 6165 * * <i>T</i> is a type parameter and <i>S</i> is the upper bound of <i>T</i>. | |
| 6166 * * Covariance: <i>T</i> is of the form <i>I<T<sub>1</sub>, …, | |
| 6167 * T<sub>n</sub>></i> and S</i> is of the form <i>I<S<sub>1</sub>, | |
| 6168 * …, S<sub>n</sub>></i> and <i>T<sub>i</sub> « | |
| 6169 * S<sub>i</sub></i>, <i>1 <= i <= n</i>. | |
| 6170 * * Transitivity: <i>T « U</i> and <i>U « S</i>. | |
| 6171 */ | |
| 6172 @override | |
| 6173 bool isMoreSpecificThan(DartType type); | |
| 6174 | |
| 6175 /** | |
| 6176 * Return `true` if this type is a subtype of the given [type]. An interface | |
| 6177 * type <i>T</i> is a subtype of an interface type <i>S</i>, written <i>T</i> | |
| 6178 * <: <i>S</i>, iff <i>[bottom/dynamic]T</i> « <i>S</i> (<i>T</i> is | |
| 6179 * more specific than <i>S</i>). If an interface type <i>I</i> includes a | |
| 6180 * method named <i>call()</i>, and the type of <i>call()</i> is the function | |
| 6181 * type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>. | |
| 6182 */ | |
| 6183 @override | |
| 6184 bool isSubtypeOf(DartType type); | |
| 6185 | |
| 6186 /** | |
| 6187 * Return the element representing the constructor that results from looking | |
| 6188 * up the constructor with the given [name] in this class with respect to the | |
| 6189 * given [library], or `null` if the look up fails. The behavior of this | |
| 6190 * method is defined by the Dart Language Specification in section 12.11.1: | |
| 6191 * <blockquote> | |
| 6192 * If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be the | |
| 6193 * constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<i>. | |
| 6194 * Otherwise, if <i>q</i> is not defined or not accessible, a | |
| 6195 * NoSuchMethodException is thrown. | |
| 6196 * </blockquote> | |
| 6197 */ | |
| 6198 ConstructorElement lookUpConstructor(String name, LibraryElement library); | |
| 6199 | |
| 6200 /** | |
| 6201 * Return the element representing the getter that results from looking up the | |
| 6202 * getter with the given [name] in this class with respect to the given | |
| 6203 * [library], or `null` if the look up fails. The behavior of this method is | |
| 6204 * defined by the Dart Language Specification in section 12.15.1: | |
| 6205 * <blockquote> | |
| 6206 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 6207 * <i>C</i> with respect to library <i>L</i> is: | |
| 6208 * * If <i>C</i> declares an instance getter (respectively setter) named | |
| 6209 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively | |
| 6210 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a | |
| 6211 * superclass <i>S</i>, then the result of the lookup is the result of | |
| 6212 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect | |
| 6213 * to <i>L</i>. Otherwise, we say that the lookup has failed. | |
| 6214 * </blockquote> | |
| 6215 */ | |
| 6216 PropertyAccessorElement lookUpGetter(String name, LibraryElement library); | |
| 6217 | |
| 6218 /** | |
| 6219 * Return the element representing the getter that results from looking up the | |
| 6220 * getter with the given [name] in the superclass of this class with respect | |
| 6221 * to the given [library], or `null` if the look up fails. The behavior of | |
| 6222 * this method is defined by the Dart Language Specification in section | |
| 6223 * 12.15.1: | |
| 6224 * <blockquote> | |
| 6225 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 6226 * <i>C</i> with respect to library <i>L</i> is: | |
| 6227 * * If <i>C</i> declares an instance getter (respectively setter) named | |
| 6228 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively | |
| 6229 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a | |
| 6230 * superclass <i>S</i>, then the result of the lookup is the result of | |
| 6231 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect | |
| 6232 * to <i>L</i>. Otherwise, we say that the lookup has failed. | |
| 6233 * </blockquote> | |
| 6234 */ | |
| 6235 PropertyAccessorElement lookUpGetterInSuperclass( | |
| 6236 String name, LibraryElement library); | |
| 6237 | |
| 6238 /** | |
| 6239 * Return the element representing the method that results from looking up the | |
| 6240 * method with the given [name] in this class with respect to the given | |
| 6241 * [library], or `null` if the look up fails. The behavior of this method is | |
| 6242 * defined by the Dart Language Specification in section 12.15.1: | |
| 6243 * <blockquote> | |
| 6244 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 6245 * library <i>L</i> is: | |
| 6246 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible | |
| 6247 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if | |
| 6248 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the | |
| 6249 * result of looking up method <i>m</i> in <i>S</i> with respect to <i>L</i> | |
| 6250 * Otherwise, we say that the lookup has failed. | |
| 6251 * </blockquote> | |
| 6252 */ | |
| 6253 MethodElement lookUpMethod(String name, LibraryElement library); | |
| 6254 | |
| 6255 /** | |
| 6256 * Return the element representing the method that results from looking up the | |
| 6257 * method with the given [name] in the superclass of this class with respect | |
| 6258 * to the given [library], or `null` if the look up fails. The behavior of | |
| 6259 * this method is defined by the Dart Language Specification in section | |
| 6260 * 12.15.1: | |
| 6261 * <blockquote> | |
| 6262 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | |
| 6263 * library <i>L</i> is: | |
| 6264 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible | |
| 6265 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if | |
| 6266 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the | |
| 6267 * result of looking up method <i>m</i> in <i>S</i> with respect to <i>L</i>. | |
| 6268 * Otherwise, we say that the lookup has failed. | |
| 6269 * </blockquote> | |
| 6270 */ | |
| 6271 MethodElement lookUpMethodInSuperclass(String name, LibraryElement library); | |
| 6272 | |
| 6273 /** | |
| 6274 * Return the element representing the setter that results from looking up the | |
| 6275 * setter with the given [name] in this class with respect to the given | |
| 6276 * [library], or `null` if the look up fails. The behavior of this method is | |
| 6277 * defined by the Dart Language Specification in section 12.16: | |
| 6278 * <blockquote> | |
| 6279 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 6280 * <i>C</i> with respect to library <i>L</i> is: | |
| 6281 * * If <i>C</i> declares an instance getter (respectively setter) named | |
| 6282 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively | |
| 6283 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a | |
| 6284 * superclass <i>S</i>, then the result of the lookup is the result of | |
| 6285 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect | |
| 6286 * to <i>L</i>. Otherwise, we say that the lookup has failed. | |
| 6287 * </blockquote> | |
| 6288 */ | |
| 6289 PropertyAccessorElement lookUpSetter(String name, LibraryElement library); | |
| 6290 | |
| 6291 /** | |
| 6292 * Return the element representing the setter that results from looking up the | |
| 6293 * setter with the given [name] in the superclass of this class with respect | |
| 6294 * to the given [library], or `null` if the look up fails. The behavior of | |
| 6295 * this method is defined by the Dart Language Specification in section 12.16: | |
| 6296 * <blockquote> | |
| 6297 * The result of looking up getter (respectively setter) <i>m</i> in class | |
| 6298 * <i>C</i> with respect to library <i>L</i> is: | |
| 6299 * * If <i>C</i> declares an instance getter (respectively setter) named | |
| 6300 * <i>m</i> that is accessible to <i>L</i>, then that getter (respectively | |
| 6301 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a | |
| 6302 * superclass <i>S</i>, then the result of the lookup is the result of | |
| 6303 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect | |
| 6304 * to <i>L</i>. Otherwise, we say that the lookup has failed. | |
| 6305 * </blockquote> | |
| 6306 */ | |
| 6307 PropertyAccessorElement lookUpSetterInSuperclass( | |
| 6308 String name, LibraryElement library); | |
| 6309 | |
| 6310 @override | |
| 6311 InterfaceType substitute2( | |
| 6312 List<DartType> argumentTypes, List<DartType> parameterTypes); | |
| 6313 | |
| 6314 /** | |
| 6315 * Return the type resulting from substituting the given arguments for this | |
| 6316 * type's parameters. This is fully equivalent to `substitute2(argumentTypes, | |
| 6317 * getTypeArguments())`. | |
| 6318 */ | |
| 6319 InterfaceType substitute4(List<DartType> argumentTypes); | |
| 6320 | |
| 6321 /** | |
| 6322 * Returns a "smart" version of the "least upper bound" of the given types. | |
| 6323 * | |
| 6324 * If these types have the same element and differ only in terms of the type | |
| 6325 * arguments, attempts to find a compatible set of type arguments. | |
| 6326 * | |
| 6327 * Otherwise, calls [DartType.getLeastUpperBound]. | |
| 6328 */ | |
| 6329 static InterfaceType getSmartLeastUpperBound( | |
| 6330 InterfaceType first, InterfaceType second) { | |
| 6331 // TODO(paulberry): this needs to be deprecated and replaced with a method | |
| 6332 // in [TypeSystem], since it relies on the deprecated functionality of | |
| 6333 // [DartType.getLeastUpperBound]. | |
| 6334 if (first.element == second.element) { | |
| 6335 return _leastUpperBound(first, second); | |
| 6336 } | |
| 6337 return first.getLeastUpperBound(second); | |
| 6338 } | |
| 6339 | |
| 6340 /** | |
| 6341 * Return the "least upper bound" of the given types under the assumption that | |
| 6342 * the types have the same element and differ only in terms of the type | |
| 6343 * arguments. | |
| 6344 * | |
| 6345 * The resulting type is composed by comparing the corresponding type | |
| 6346 * arguments, keeping those that are the same, and using 'dynamic' for those | |
| 6347 * that are different. | |
| 6348 */ | |
| 6349 static InterfaceType _leastUpperBound( | |
| 6350 InterfaceType firstType, InterfaceType secondType) { | |
| 6351 ClassElement firstElement = firstType.element; | |
| 6352 ClassElement secondElement = secondType.element; | |
| 6353 if (firstElement != secondElement) { | |
| 6354 throw new IllegalArgumentException('The same elements expected, but ' | |
| 6355 '$firstElement and $secondElement are given.'); | |
| 6356 } | |
| 6357 if (firstType == secondType) { | |
| 6358 return firstType; | |
| 6359 } | |
| 6360 List<DartType> firstArguments = firstType.typeArguments; | |
| 6361 List<DartType> secondArguments = secondType.typeArguments; | |
| 6362 int argumentCount = firstArguments.length; | |
| 6363 if (argumentCount == 0) { | |
| 6364 return firstType; | |
| 6365 } | |
| 6366 List<DartType> lubArguments = new List<DartType>(argumentCount); | |
| 6367 for (int i = 0; i < argumentCount; i++) { | |
| 6368 // | |
| 6369 // Ideally we would take the least upper bound of the two argument types, | |
| 6370 // but this can cause an infinite recursion (such as when finding the | |
| 6371 // least upper bound of String and num). | |
| 6372 // | |
| 6373 if (firstArguments[i] == secondArguments[i]) { | |
| 6374 lubArguments[i] = firstArguments[i]; | |
| 6375 } | |
| 6376 if (lubArguments[i] == null) { | |
| 6377 lubArguments[i] = DynamicTypeImpl.instance; | |
| 6378 } | |
| 6379 } | |
| 6380 InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement); | |
| 6381 lub.typeArguments = lubArguments; | |
| 6382 return lub; | |
| 6383 } | |
| 6384 } | |
| 6385 | |
| 6386 /** | |
| 6387 * A concrete implementation of an [InterfaceType]. | |
| 6388 */ | |
| 6389 class InterfaceTypeImpl extends TypeImpl implements InterfaceType { | |
| 6390 /** | |
| 6391 * A list containing the actual types of the type arguments. | |
| 6392 */ | |
| 6393 List<DartType> typeArguments = DartType.EMPTY_LIST; | |
| 6394 | |
| 6395 /** | |
| 6396 * The set of typedefs which should not be expanded when exploring this type, | |
| 6397 * to avoid creating infinite types in response to self-referential typedefs. | |
| 6398 */ | |
| 6399 final List<FunctionTypeAliasElement> prunedTypedefs; | |
| 6400 | |
| 6401 /** | |
| 6402 * Initialize a newly created type to be declared by the given [element]. | |
| 6403 */ | |
| 6404 InterfaceTypeImpl(ClassElement element, [this.prunedTypedefs]) | |
| 6405 : super(element, element.displayName); | |
| 6406 | |
| 6407 /** | |
| 6408 * Initialize a newly created type to be declared by the given [element]. | |
| 6409 */ | |
| 6410 @deprecated // Use new InterfaceTypeImpl(element) | |
| 6411 InterfaceTypeImpl.con1(ClassElement element) | |
| 6412 : prunedTypedefs = null, | |
| 6413 super(element, element.displayName); | |
| 6414 | |
| 6415 /** | |
| 6416 * Initialize a newly created type to have the given [name]. This constructor | |
| 6417 * should only be used in cases where there is no declaration of the type. | |
| 6418 */ | |
| 6419 @deprecated // Use new InterfaceTypeImpl.named(name) | |
| 6420 InterfaceTypeImpl.con2(String name) | |
| 6421 : prunedTypedefs = null, | |
| 6422 super(null, name); | |
| 6423 | |
| 6424 /** | |
| 6425 * Initialize a newly created type to have the given [name]. This constructor | |
| 6426 * should only be used in cases where there is no declaration of the type. | |
| 6427 */ | |
| 6428 InterfaceTypeImpl.named(String name) | |
| 6429 : prunedTypedefs = null, | |
| 6430 super(null, name); | |
| 6431 | |
| 6432 /** | |
| 6433 * Private constructor. | |
| 6434 */ | |
| 6435 InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs) | |
| 6436 : super(element, name); | |
| 6437 | |
| 6438 @override | |
| 6439 List<PropertyAccessorElement> get accessors { | |
| 6440 List<PropertyAccessorElement> accessors = element.accessors; | |
| 6441 List<PropertyAccessorElement> members = | |
| 6442 new List<PropertyAccessorElement>(accessors.length); | |
| 6443 for (int i = 0; i < accessors.length; i++) { | |
| 6444 members[i] = PropertyAccessorMember.from(accessors[i], this); | |
| 6445 } | |
| 6446 return members; | |
| 6447 } | |
| 6448 | |
| 6449 @override | |
| 6450 List<ConstructorElement> get constructors { | |
| 6451 List<ConstructorElement> constructors = element.constructors; | |
| 6452 List<ConstructorElement> members = | |
| 6453 new List<ConstructorElement>(constructors.length); | |
| 6454 for (int i = 0; i < constructors.length; i++) { | |
| 6455 members[i] = ConstructorMember.from(constructors[i], this); | |
| 6456 } | |
| 6457 return members; | |
| 6458 } | |
| 6459 | |
| 6460 @override | |
| 6461 String get displayName { | |
| 6462 String name = this.name; | |
| 6463 List<DartType> typeArguments = this.typeArguments; | |
| 6464 bool allDynamic = true; | |
| 6465 for (DartType type in typeArguments) { | |
| 6466 if (type != null && !type.isDynamic) { | |
| 6467 allDynamic = false; | |
| 6468 break; | |
| 6469 } | |
| 6470 } | |
| 6471 // If there is at least one non-dynamic type, then list them out | |
| 6472 if (!allDynamic) { | |
| 6473 StringBuffer buffer = new StringBuffer(); | |
| 6474 buffer.write(name); | |
| 6475 buffer.write("<"); | |
| 6476 for (int i = 0; i < typeArguments.length; i++) { | |
| 6477 if (i != 0) { | |
| 6478 buffer.write(", "); | |
| 6479 } | |
| 6480 DartType typeArg = typeArguments[i]; | |
| 6481 buffer.write(typeArg.displayName); | |
| 6482 } | |
| 6483 buffer.write(">"); | |
| 6484 name = buffer.toString(); | |
| 6485 } | |
| 6486 return name; | |
| 6487 } | |
| 6488 | |
| 6489 @override | |
| 6490 ClassElement get element => super.element as ClassElement; | |
| 6491 | |
| 6492 @override | |
| 6493 int get hashCode { | |
| 6494 ClassElement element = this.element; | |
| 6495 if (element == null) { | |
| 6496 return 0; | |
| 6497 } | |
| 6498 return element.hashCode; | |
| 6499 } | |
| 6500 | |
| 6501 @override | |
| 6502 List<InterfaceType> get interfaces { | |
| 6503 ClassElement classElement = element; | |
| 6504 List<InterfaceType> interfaces = classElement.interfaces; | |
| 6505 List<TypeParameterElement> typeParameters = classElement.typeParameters; | |
| 6506 List<DartType> parameterTypes = classElement.type.typeArguments; | |
| 6507 if (typeParameters.length == 0) { | |
| 6508 return interfaces; | |
| 6509 } | |
| 6510 int count = interfaces.length; | |
| 6511 List<InterfaceType> typedInterfaces = new List<InterfaceType>(count); | |
| 6512 for (int i = 0; i < count; i++) { | |
| 6513 typedInterfaces[i] = | |
| 6514 interfaces[i].substitute2(typeArguments, parameterTypes); | |
| 6515 } | |
| 6516 return typedInterfaces; | |
| 6517 } | |
| 6518 | |
| 6519 @override | |
| 6520 bool get isDartCoreFunction { | |
| 6521 ClassElement element = this.element; | |
| 6522 if (element == null) { | |
| 6523 return false; | |
| 6524 } | |
| 6525 return element.name == "Function" && element.library.isDartCore; | |
| 6526 } | |
| 6527 | |
| 6528 @override | |
| 6529 bool get isObject => element.supertype == null; | |
| 6530 | |
| 6531 @override | |
| 6532 List<MethodElement> get methods { | |
| 6533 List<MethodElement> methods = element.methods; | |
| 6534 List<MethodElement> members = new List<MethodElement>(methods.length); | |
| 6535 for (int i = 0; i < methods.length; i++) { | |
| 6536 members[i] = MethodMember.from(methods[i], this); | |
| 6537 } | |
| 6538 return members; | |
| 6539 } | |
| 6540 | |
| 6541 @override | |
| 6542 List<InterfaceType> get mixins { | |
| 6543 ClassElement classElement = element; | |
| 6544 List<InterfaceType> mixins = classElement.mixins; | |
| 6545 List<TypeParameterElement> typeParameters = classElement.typeParameters; | |
| 6546 List<DartType> parameterTypes = classElement.type.typeArguments; | |
| 6547 if (typeParameters.length == 0) { | |
| 6548 return mixins; | |
| 6549 } | |
| 6550 int count = mixins.length; | |
| 6551 List<InterfaceType> typedMixins = new List<InterfaceType>(count); | |
| 6552 for (int i = 0; i < count; i++) { | |
| 6553 typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes); | |
| 6554 } | |
| 6555 return typedMixins; | |
| 6556 } | |
| 6557 | |
| 6558 @override | |
| 6559 InterfaceType get superclass { | |
| 6560 ClassElement classElement = element; | |
| 6561 InterfaceType supertype = classElement.supertype; | |
| 6562 if (supertype == null) { | |
| 6563 return null; | |
| 6564 } | |
| 6565 List<DartType> typeParameters = classElement.type.typeArguments; | |
| 6566 if (typeArguments.length == 0 || | |
| 6567 typeArguments.length != typeParameters.length) { | |
| 6568 return supertype; | |
| 6569 } | |
| 6570 return supertype.substitute2(typeArguments, typeParameters); | |
| 6571 } | |
| 6572 | |
| 6573 @override | |
| 6574 List<TypeParameterElement> get typeParameters => element.typeParameters; | |
| 6575 | |
| 6576 @override | |
| 6577 bool operator ==(Object object) { | |
| 6578 if (identical(object, this)) { | |
| 6579 return true; | |
| 6580 } | |
| 6581 if (object is! InterfaceTypeImpl) { | |
| 6582 return false; | |
| 6583 } | |
| 6584 InterfaceTypeImpl otherType = object as InterfaceTypeImpl; | |
| 6585 return (element == otherType.element) && | |
| 6586 TypeImpl.equalArrays(typeArguments, otherType.typeArguments); | |
| 6587 } | |
| 6588 | |
| 6589 @override | |
| 6590 void appendTo(StringBuffer buffer) { | |
| 6591 buffer.write(name); | |
| 6592 int argumentCount = typeArguments.length; | |
| 6593 if (argumentCount > 0) { | |
| 6594 buffer.write("<"); | |
| 6595 for (int i = 0; i < argumentCount; i++) { | |
| 6596 if (i > 0) { | |
| 6597 buffer.write(", "); | |
| 6598 } | |
| 6599 (typeArguments[i] as TypeImpl).appendTo(buffer); | |
| 6600 } | |
| 6601 buffer.write(">"); | |
| 6602 } | |
| 6603 } | |
| 6604 | |
| 6605 @override | |
| 6606 PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember | |
| 6607 .from((element as ClassElementImpl).getGetter(getterName), this); | |
| 6608 | |
| 6609 @override | |
| 6610 @deprecated | |
| 6611 DartType getLeastUpperBound(DartType type) { | |
| 6612 // quick check for self | |
| 6613 if (identical(type, this)) { | |
| 6614 return this; | |
| 6615 } | |
| 6616 // dynamic | |
| 6617 DartType dynamicType = DynamicTypeImpl.instance; | |
| 6618 if (identical(this, dynamicType) || identical(type, dynamicType)) { | |
| 6619 return dynamicType; | |
| 6620 } | |
| 6621 // TODO (jwren) opportunity here for a better, faster algorithm if this | |
| 6622 // turns out to be a bottle-neck | |
| 6623 if (type is! InterfaceType) { | |
| 6624 return null; | |
| 6625 } | |
| 6626 return computeLeastUpperBound(this, type); | |
| 6627 } | |
| 6628 | |
| 6629 @override | |
| 6630 MethodElement getMethod(String methodName) => MethodMember.from( | |
| 6631 (element as ClassElementImpl).getMethod(methodName), this); | |
| 6632 | |
| 6633 @override | |
| 6634 PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember | |
| 6635 .from((element as ClassElementImpl).getSetter(setterName), this); | |
| 6636 | |
| 6637 @override | |
| 6638 bool isDirectSupertypeOf(InterfaceType type) { | |
| 6639 InterfaceType i = this; | |
| 6640 InterfaceType j = type; | |
| 6641 ClassElement jElement = j.element; | |
| 6642 InterfaceType supertype = jElement.supertype; | |
| 6643 // | |
| 6644 // If J has no direct supertype then it is Object, and Object has no direct | |
| 6645 // supertypes. | |
| 6646 // | |
| 6647 if (supertype == null) { | |
| 6648 return false; | |
| 6649 } | |
| 6650 // | |
| 6651 // I is listed in the extends clause of J. | |
| 6652 // | |
| 6653 List<DartType> jArgs = j.typeArguments; | |
| 6654 List<DartType> jVars = jElement.type.typeArguments; | |
| 6655 supertype = supertype.substitute2(jArgs, jVars); | |
| 6656 if (supertype == i) { | |
| 6657 return true; | |
| 6658 } | |
| 6659 // | |
| 6660 // I is listed in the implements clause of J. | |
| 6661 // | |
| 6662 for (InterfaceType interfaceType in jElement.interfaces) { | |
| 6663 interfaceType = interfaceType.substitute2(jArgs, jVars); | |
| 6664 if (interfaceType == i) { | |
| 6665 return true; | |
| 6666 } | |
| 6667 } | |
| 6668 // | |
| 6669 // I is listed in the with clause of J. | |
| 6670 // | |
| 6671 for (InterfaceType mixinType in jElement.mixins) { | |
| 6672 mixinType = mixinType.substitute2(jArgs, jVars); | |
| 6673 if (mixinType == i) { | |
| 6674 return true; | |
| 6675 } | |
| 6676 } | |
| 6677 // | |
| 6678 // J is a mixin application of the mixin of I. | |
| 6679 // | |
| 6680 // TODO(brianwilkerson) Determine whether this needs to be implemented or | |
| 6681 // whether it is covered by the case above. | |
| 6682 return false; | |
| 6683 } | |
| 6684 | |
| 6685 @override | |
| 6686 bool isMoreSpecificThan(DartType type, | |
| 6687 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 6688 // | |
| 6689 // S is dynamic. | |
| 6690 // The test to determine whether S is dynamic is done here because dynamic | |
| 6691 // is not an instance of InterfaceType. | |
| 6692 // | |
| 6693 if (type.isDynamic) { | |
| 6694 return true; | |
| 6695 } | |
| 6696 // | |
| 6697 // A type T is more specific than a type S, written T << S, | |
| 6698 // if one of the following conditions is met: | |
| 6699 // | |
| 6700 // Reflexivity: T is S. | |
| 6701 // | |
| 6702 if (this == type) { | |
| 6703 return true; | |
| 6704 } | |
| 6705 if (type is InterfaceType) { | |
| 6706 // | |
| 6707 // T is bottom. (This case is handled by the class BottomTypeImpl.) | |
| 6708 // | |
| 6709 // Direct supertype: S is a direct supertype of T. | |
| 6710 // | |
| 6711 if (type.isDirectSupertypeOf(this)) { | |
| 6712 return true; | |
| 6713 } | |
| 6714 // | |
| 6715 // Covariance: T is of the form I<T1, ..., Tn> and S is of the form | |
| 6716 // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n. | |
| 6717 // | |
| 6718 ClassElement tElement = this.element; | |
| 6719 ClassElement sElement = type.element; | |
| 6720 if (tElement == sElement) { | |
| 6721 List<DartType> tArguments = typeArguments; | |
| 6722 List<DartType> sArguments = type.typeArguments; | |
| 6723 if (tArguments.length != sArguments.length) { | |
| 6724 return false; | |
| 6725 } | |
| 6726 for (int i = 0; i < tArguments.length; i++) { | |
| 6727 if (!(tArguments[i] as TypeImpl) | |
| 6728 .isMoreSpecificThan(sArguments[i], withDynamic)) { | |
| 6729 return false; | |
| 6730 } | |
| 6731 } | |
| 6732 return true; | |
| 6733 } | |
| 6734 } | |
| 6735 // | |
| 6736 // Transitivity: T << U and U << S. | |
| 6737 // | |
| 6738 // First check for infinite loops | |
| 6739 if (element == null) { | |
| 6740 return false; | |
| 6741 } | |
| 6742 if (visitedElements == null) { | |
| 6743 visitedElements = new HashSet<ClassElement>(); | |
| 6744 } else if (visitedElements.contains(element)) { | |
| 6745 return false; | |
| 6746 } | |
| 6747 visitedElements.add(element); | |
| 6748 try { | |
| 6749 // Iterate over all of the types U that are more specific than T because | |
| 6750 // they are direct supertypes of T and return true if any of them are more | |
| 6751 // specific than S. | |
| 6752 InterfaceTypeImpl supertype = superclass; | |
| 6753 if (supertype != null && | |
| 6754 supertype.isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 6755 return true; | |
| 6756 } | |
| 6757 for (InterfaceType interfaceType in interfaces) { | |
| 6758 if ((interfaceType as InterfaceTypeImpl) | |
| 6759 .isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 6760 return true; | |
| 6761 } | |
| 6762 } | |
| 6763 for (InterfaceType mixinType in mixins) { | |
| 6764 if ((mixinType as InterfaceTypeImpl) | |
| 6765 .isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 6766 return true; | |
| 6767 } | |
| 6768 } | |
| 6769 // If a type I includes an instance method named `call`, and the type of | |
| 6770 // `call` is the function type F, then I is considered to be more specific | |
| 6771 // than F. | |
| 6772 MethodElement callMethod = getMethod('call'); | |
| 6773 if (callMethod != null && !callMethod.isStatic) { | |
| 6774 FunctionTypeImpl callType = callMethod.type; | |
| 6775 if (callType.isMoreSpecificThan(type, withDynamic, visitedElements)) { | |
| 6776 return true; | |
| 6777 } | |
| 6778 } | |
| 6779 return false; | |
| 6780 } finally { | |
| 6781 visitedElements.remove(element); | |
| 6782 } | |
| 6783 } | |
| 6784 | |
| 6785 @override | |
| 6786 ConstructorElement lookUpConstructor( | |
| 6787 String constructorName, LibraryElement library) { | |
| 6788 // prepare base ConstructorElement | |
| 6789 ConstructorElement constructorElement; | |
| 6790 if (constructorName == null) { | |
| 6791 constructorElement = element.unnamedConstructor; | |
| 6792 } else { | |
| 6793 constructorElement = element.getNamedConstructor(constructorName); | |
| 6794 } | |
| 6795 // not found or not accessible | |
| 6796 if (constructorElement == null || | |
| 6797 !constructorElement.isAccessibleIn(library)) { | |
| 6798 return null; | |
| 6799 } | |
| 6800 // return member | |
| 6801 return ConstructorMember.from(constructorElement, this); | |
| 6802 } | |
| 6803 | |
| 6804 @override | |
| 6805 PropertyAccessorElement lookUpGetter( | |
| 6806 String getterName, LibraryElement library) { | |
| 6807 PropertyAccessorElement element = getGetter(getterName); | |
| 6808 if (element != null && element.isAccessibleIn(library)) { | |
| 6809 return element; | |
| 6810 } | |
| 6811 return lookUpGetterInSuperclass(getterName, library); | |
| 6812 } | |
| 6813 | |
| 6814 @override | |
| 6815 PropertyAccessorElement lookUpGetterInSuperclass( | |
| 6816 String getterName, LibraryElement library) { | |
| 6817 for (InterfaceType mixin in mixins.reversed) { | |
| 6818 PropertyAccessorElement element = mixin.getGetter(getterName); | |
| 6819 if (element != null && element.isAccessibleIn(library)) { | |
| 6820 return element; | |
| 6821 } | |
| 6822 } | |
| 6823 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 6824 InterfaceType supertype = superclass; | |
| 6825 ClassElement supertypeElement = | |
| 6826 supertype == null ? null : supertype.element; | |
| 6827 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 6828 visitedClasses.add(supertypeElement); | |
| 6829 PropertyAccessorElement element = supertype.getGetter(getterName); | |
| 6830 if (element != null && element.isAccessibleIn(library)) { | |
| 6831 return element; | |
| 6832 } | |
| 6833 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 6834 element = mixin.getGetter(getterName); | |
| 6835 if (element != null && element.isAccessibleIn(library)) { | |
| 6836 return element; | |
| 6837 } | |
| 6838 } | |
| 6839 supertype = supertype.superclass; | |
| 6840 supertypeElement = supertype == null ? null : supertype.element; | |
| 6841 } | |
| 6842 return null; | |
| 6843 } | |
| 6844 | |
| 6845 @override | |
| 6846 MethodElement lookUpMethod(String methodName, LibraryElement library) { | |
| 6847 MethodElement element = getMethod(methodName); | |
| 6848 if (element != null && element.isAccessibleIn(library)) { | |
| 6849 return element; | |
| 6850 } | |
| 6851 return lookUpMethodInSuperclass(methodName, library); | |
| 6852 } | |
| 6853 | |
| 6854 @override | |
| 6855 MethodElement lookUpMethodInSuperclass( | |
| 6856 String methodName, LibraryElement library) { | |
| 6857 for (InterfaceType mixin in mixins.reversed) { | |
| 6858 MethodElement element = mixin.getMethod(methodName); | |
| 6859 if (element != null && element.isAccessibleIn(library)) { | |
| 6860 return element; | |
| 6861 } | |
| 6862 } | |
| 6863 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 6864 InterfaceType supertype = superclass; | |
| 6865 ClassElement supertypeElement = | |
| 6866 supertype == null ? null : supertype.element; | |
| 6867 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 6868 visitedClasses.add(supertypeElement); | |
| 6869 MethodElement element = supertype.getMethod(methodName); | |
| 6870 if (element != null && element.isAccessibleIn(library)) { | |
| 6871 return element; | |
| 6872 } | |
| 6873 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 6874 element = mixin.getMethod(methodName); | |
| 6875 if (element != null && element.isAccessibleIn(library)) { | |
| 6876 return element; | |
| 6877 } | |
| 6878 } | |
| 6879 supertype = supertype.superclass; | |
| 6880 supertypeElement = supertype == null ? null : supertype.element; | |
| 6881 } | |
| 6882 return null; | |
| 6883 } | |
| 6884 | |
| 6885 @override | |
| 6886 PropertyAccessorElement lookUpSetter( | |
| 6887 String setterName, LibraryElement library) { | |
| 6888 PropertyAccessorElement element = getSetter(setterName); | |
| 6889 if (element != null && element.isAccessibleIn(library)) { | |
| 6890 return element; | |
| 6891 } | |
| 6892 return lookUpSetterInSuperclass(setterName, library); | |
| 6893 } | |
| 6894 | |
| 6895 @override | |
| 6896 PropertyAccessorElement lookUpSetterInSuperclass( | |
| 6897 String setterName, LibraryElement library) { | |
| 6898 for (InterfaceType mixin in mixins.reversed) { | |
| 6899 PropertyAccessorElement element = mixin.getSetter(setterName); | |
| 6900 if (element != null && element.isAccessibleIn(library)) { | |
| 6901 return element; | |
| 6902 } | |
| 6903 } | |
| 6904 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); | |
| 6905 InterfaceType supertype = superclass; | |
| 6906 ClassElement supertypeElement = | |
| 6907 supertype == null ? null : supertype.element; | |
| 6908 while (supertype != null && !visitedClasses.contains(supertypeElement)) { | |
| 6909 visitedClasses.add(supertypeElement); | |
| 6910 PropertyAccessorElement element = supertype.getSetter(setterName); | |
| 6911 if (element != null && element.isAccessibleIn(library)) { | |
| 6912 return element; | |
| 6913 } | |
| 6914 for (InterfaceType mixin in supertype.mixins.reversed) { | |
| 6915 element = mixin.getSetter(setterName); | |
| 6916 if (element != null && element.isAccessibleIn(library)) { | |
| 6917 return element; | |
| 6918 } | |
| 6919 } | |
| 6920 supertype = supertype.superclass; | |
| 6921 supertypeElement = supertype == null ? null : supertype.element; | |
| 6922 } | |
| 6923 return null; | |
| 6924 } | |
| 6925 | |
| 6926 @override | |
| 6927 InterfaceTypeImpl pruned(List<FunctionTypeAliasElement> prune) { | |
| 6928 if (prune == null) { | |
| 6929 return this; | |
| 6930 } else { | |
| 6931 // There should never be a reason to prune a type that has already been | |
| 6932 // pruned, since pruning is only done when expanding a function type | |
| 6933 // alias, and function type aliases are always expanded by starting with | |
| 6934 // base types. | |
| 6935 assert(this.prunedTypedefs == null); | |
| 6936 InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune); | |
| 6937 result.typeArguments = | |
| 6938 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList(); | |
| 6939 return result; | |
| 6940 } | |
| 6941 } | |
| 6942 | |
| 6943 @override | |
| 6944 InterfaceTypeImpl substitute2( | |
| 6945 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 6946 [List<FunctionTypeAliasElement> prune]) { | |
| 6947 // Pruned types should only ever result from performing type variable | |
| 6948 // substitution, and it doesn't make sense to substitute again after | |
| 6949 // substituting once. | |
| 6950 assert(this.prunedTypedefs == null); | |
| 6951 if (argumentTypes.length != parameterTypes.length) { | |
| 6952 throw new IllegalArgumentException( | |
| 6953 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng
th (${parameterTypes.length})"); | |
| 6954 } | |
| 6955 if (argumentTypes.length == 0 || typeArguments.length == 0) { | |
| 6956 return this.pruned(prune); | |
| 6957 } | |
| 6958 List<DartType> newTypeArguments = TypeImpl.substitute( | |
| 6959 typeArguments, argumentTypes, parameterTypes, prune); | |
| 6960 if (JavaArrays.equals(newTypeArguments, typeArguments)) { | |
| 6961 return this; | |
| 6962 } | |
| 6963 InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune); | |
| 6964 newType.typeArguments = newTypeArguments; | |
| 6965 return newType; | |
| 6966 } | |
| 6967 | |
| 6968 @override | |
| 6969 InterfaceTypeImpl substitute4(List<DartType> argumentTypes) => | |
| 6970 substitute2(argumentTypes, typeArguments); | |
| 6971 | |
| 6972 /** | |
| 6973 * Compute the least upper bound of types [i] and [j], both of which are | |
| 6974 * known to be interface types. | |
| 6975 * | |
| 6976 * In the event that the algorithm fails (which might occur due to a bug in | |
| 6977 * the analyzer), `null` is returned. | |
| 6978 */ | |
| 6979 static InterfaceType computeLeastUpperBound( | |
| 6980 InterfaceType i, InterfaceType j) { | |
| 6981 // compute set of supertypes | |
| 6982 Set<InterfaceType> si = computeSuperinterfaceSet(i); | |
| 6983 Set<InterfaceType> sj = computeSuperinterfaceSet(j); | |
| 6984 // union si with i and sj with j | |
| 6985 si.add(i); | |
| 6986 sj.add(j); | |
| 6987 // compute intersection, reference as set 's' | |
| 6988 List<InterfaceType> s = _intersection(si, sj); | |
| 6989 // for each element in Set s, compute the largest inheritance path to Object | |
| 6990 List<int> depths = new List<int>.filled(s.length, 0); | |
| 6991 int maxDepth = 0; | |
| 6992 for (int n = 0; n < s.length; n++) { | |
| 6993 depths[n] = computeLongestInheritancePathToObject(s[n]); | |
| 6994 if (depths[n] > maxDepth) { | |
| 6995 maxDepth = depths[n]; | |
| 6996 } | |
| 6997 } | |
| 6998 // ensure that the currently computed maxDepth is unique, | |
| 6999 // otherwise, decrement and test for uniqueness again | |
| 7000 for (; maxDepth >= 0; maxDepth--) { | |
| 7001 int indexOfLeastUpperBound = -1; | |
| 7002 int numberOfTypesAtMaxDepth = 0; | |
| 7003 for (int m = 0; m < depths.length; m++) { | |
| 7004 if (depths[m] == maxDepth) { | |
| 7005 numberOfTypesAtMaxDepth++; | |
| 7006 indexOfLeastUpperBound = m; | |
| 7007 } | |
| 7008 } | |
| 7009 if (numberOfTypesAtMaxDepth == 1) { | |
| 7010 return s[indexOfLeastUpperBound]; | |
| 7011 } | |
| 7012 } | |
| 7013 // Should be impossible--there should always be exactly one type with the | |
| 7014 // maximum depth. | |
| 7015 assert(false); | |
| 7016 return null; | |
| 7017 } | |
| 7018 | |
| 7019 /** | |
| 7020 * Return the length of the longest inheritance path from the given [type] to | |
| 7021 * Object. | |
| 7022 * | |
| 7023 * See [computeLeastUpperBound]. | |
| 7024 */ | |
| 7025 static int computeLongestInheritancePathToObject(InterfaceType type) => | |
| 7026 _computeLongestInheritancePathToObject( | |
| 7027 type, 0, new HashSet<ClassElement>()); | |
| 7028 | |
| 7029 /** | |
| 7030 * Returns the set of all superinterfaces of the given [type]. | |
| 7031 * | |
| 7032 * See [computeLeastUpperBound]. | |
| 7033 */ | |
| 7034 static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => | |
| 7035 _computeSuperinterfaceSet(type, new HashSet<InterfaceType>()); | |
| 7036 | |
| 7037 /** | |
| 7038 * Return the length of the longest inheritance path from a subtype of the | |
| 7039 * given [type] to Object, where the given [depth] is the length of the | |
| 7040 * longest path from the subtype to this type. The set of [visitedTypes] is | |
| 7041 * used to prevent infinite recursion in the case of a cyclic type structure. | |
| 7042 * | |
| 7043 * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound]. | |
| 7044 */ | |
| 7045 static int _computeLongestInheritancePathToObject( | |
| 7046 InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) { | |
| 7047 ClassElement classElement = type.element; | |
| 7048 // Object case | |
| 7049 if (classElement.supertype == null || visitedTypes.contains(classElement)) { | |
| 7050 return depth; | |
| 7051 } | |
| 7052 int longestPath = 1; | |
| 7053 try { | |
| 7054 visitedTypes.add(classElement); | |
| 7055 List<InterfaceType> superinterfaces = classElement.interfaces; | |
| 7056 int pathLength; | |
| 7057 if (superinterfaces.length > 0) { | |
| 7058 // loop through each of the superinterfaces recursively calling this | |
| 7059 // method and keeping track of the longest path to return | |
| 7060 for (InterfaceType superinterface in superinterfaces) { | |
| 7061 pathLength = _computeLongestInheritancePathToObject( | |
| 7062 superinterface, depth + 1, visitedTypes); | |
| 7063 if (pathLength > longestPath) { | |
| 7064 longestPath = pathLength; | |
| 7065 } | |
| 7066 } | |
| 7067 } | |
| 7068 // finally, perform this same check on the super type | |
| 7069 // TODO(brianwilkerson) Does this also need to add in the number of mixin | |
| 7070 // classes? | |
| 7071 InterfaceType supertype = classElement.supertype; | |
| 7072 pathLength = _computeLongestInheritancePathToObject( | |
| 7073 supertype, depth + 1, visitedTypes); | |
| 7074 if (pathLength > longestPath) { | |
| 7075 longestPath = pathLength; | |
| 7076 } | |
| 7077 } finally { | |
| 7078 visitedTypes.remove(classElement); | |
| 7079 } | |
| 7080 return longestPath; | |
| 7081 } | |
| 7082 | |
| 7083 /** | |
| 7084 * Add all of the superinterfaces of the given [type] to the given [set]. | |
| 7085 * Return the [set] as a convenience. | |
| 7086 * | |
| 7087 * See [computeSuperinterfaceSet], and [computeLeastUpperBound]. | |
| 7088 */ | |
| 7089 static Set<InterfaceType> _computeSuperinterfaceSet( | |
| 7090 InterfaceType type, HashSet<InterfaceType> set) { | |
| 7091 Element element = type.element; | |
| 7092 if (element != null) { | |
| 7093 List<InterfaceType> superinterfaces = type.interfaces; | |
| 7094 for (InterfaceType superinterface in superinterfaces) { | |
| 7095 if (set.add(superinterface)) { | |
| 7096 _computeSuperinterfaceSet(superinterface, set); | |
| 7097 } | |
| 7098 } | |
| 7099 InterfaceType supertype = type.superclass; | |
| 7100 if (supertype != null) { | |
| 7101 if (set.add(supertype)) { | |
| 7102 _computeSuperinterfaceSet(supertype, set); | |
| 7103 } | |
| 7104 } | |
| 7105 } | |
| 7106 return set; | |
| 7107 } | |
| 7108 | |
| 7109 /** | |
| 7110 * Return the intersection of the [first] and [second] sets of types, where | |
| 7111 * intersection is based on the equality of the types themselves. | |
| 7112 */ | |
| 7113 static List<InterfaceType> _intersection( | |
| 7114 Set<InterfaceType> first, Set<InterfaceType> second) { | |
| 7115 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); | |
| 7116 result.retainAll(second); | |
| 7117 return new List.from(result); | |
| 7118 } | |
| 7119 } | |
| 7120 | |
| 7121 /** | |
| 7122 * A label associated with a statement. | |
| 7123 */ | |
| 7124 abstract class LabelElement implements Element { | |
| 7125 /** | |
| 7126 * An empty list of label elements. | |
| 7127 */ | |
| 7128 static const List<LabelElement> EMPTY_LIST = const <LabelElement>[]; | |
| 7129 | |
| 7130 /** | |
| 7131 * Return the executable element in which this label is defined. | |
| 7132 */ | |
| 7133 @override | |
| 7134 ExecutableElement get enclosingElement; | |
| 7135 } | |
| 7136 | |
| 7137 /** | |
| 7138 * A concrete implementation of a [LabelElement]. | |
| 7139 */ | |
| 7140 class LabelElementImpl extends ElementImpl implements LabelElement { | |
| 7141 /** | |
| 7142 * An empty list of label elements. | |
| 7143 */ | |
| 7144 @deprecated // Use LabelElement.EMPTY_LIST | |
| 7145 static const List<LabelElement> EMPTY_ARRAY = const <LabelElement>[]; | |
| 7146 | |
| 7147 /** | |
| 7148 * A flag indicating whether this label is associated with a `switch` | |
| 7149 * statement. | |
| 7150 */ | |
| 7151 // TODO(brianwilkerson) Make this a modifier. | |
| 7152 final bool _onSwitchStatement; | |
| 7153 | |
| 7154 /** | |
| 7155 * A flag indicating whether this label is associated with a `switch` member | |
| 7156 * (`case` or `default`). | |
| 7157 */ | |
| 7158 // TODO(brianwilkerson) Make this a modifier. | |
| 7159 final bool _onSwitchMember; | |
| 7160 | |
| 7161 /** | |
| 7162 * Initialize a newly created label element to have the given [name]. | |
| 7163 * [onSwitchStatement] should be `true` if this label is associated with a | |
| 7164 * `switch` statement and [onSwitchMember] should be `true` if this label is | |
| 7165 * associated with a `switch` member. | |
| 7166 */ | |
| 7167 LabelElementImpl( | |
| 7168 Identifier name, this._onSwitchStatement, this._onSwitchMember) | |
| 7169 : super.forNode(name); | |
| 7170 | |
| 7171 @override | |
| 7172 ExecutableElement get enclosingElement => | |
| 7173 super.enclosingElement as ExecutableElement; | |
| 7174 | |
| 7175 /** | |
| 7176 * Return `true` if this label is associated with a `switch` member (`case` or | |
| 7177 * `default`). | |
| 7178 */ | |
| 7179 bool get isOnSwitchMember => _onSwitchMember; | |
| 7180 | |
| 7181 /** | |
| 7182 * Return `true` if this label is associated with a `switch` statement. | |
| 7183 */ | |
| 7184 bool get isOnSwitchStatement => _onSwitchStatement; | |
| 7185 | |
| 7186 @override | |
| 7187 ElementKind get kind => ElementKind.LABEL; | |
| 7188 | |
| 7189 @override | |
| 7190 accept(ElementVisitor visitor) => visitor.visitLabelElement(this); | |
| 7191 } | |
| 7192 | |
| 7193 /** | |
| 7194 * A library. | |
| 7195 */ | |
| 7196 abstract class LibraryElement implements Element { | |
| 7197 /** | |
| 7198 * An empty list of library elements. | |
| 7199 */ | |
| 7200 static const List<LibraryElement> EMPTY_LIST = const <LibraryElement>[]; | |
| 7201 | |
| 7202 /** | |
| 7203 * Return the compilation unit that defines this library. | |
| 7204 */ | |
| 7205 CompilationUnitElement get definingCompilationUnit; | |
| 7206 | |
| 7207 /** | |
| 7208 * Return the entry point for this library, or `null` if this library does not | |
| 7209 * have an entry point. The entry point is defined to be a zero argument | |
| 7210 * top-level function whose name is `main`. | |
| 7211 */ | |
| 7212 FunctionElement get entryPoint; | |
| 7213 | |
| 7214 /** | |
| 7215 * Return a list containing all of the libraries that are exported from this | |
| 7216 * library. | |
| 7217 */ | |
| 7218 List<LibraryElement> get exportedLibraries; | |
| 7219 | |
| 7220 /** | |
| 7221 * The export [Namespace] of this library, `null` if it has not been | |
| 7222 * computed yet. | |
| 7223 */ | |
| 7224 Namespace get exportNamespace; | |
| 7225 | |
| 7226 /** | |
| 7227 * Return a list containing all of the exports defined in this library. | |
| 7228 */ | |
| 7229 List<ExportElement> get exports; | |
| 7230 | |
| 7231 /** | |
| 7232 * Return `true` if the defining compilation unit of this library contains at | |
| 7233 * least one import directive whose URI uses the "dart-ext" scheme. | |
| 7234 */ | |
| 7235 bool get hasExtUri; | |
| 7236 | |
| 7237 /** | |
| 7238 * Return `true` if this library defines a top-level function named | |
| 7239 * `loadLibrary`. | |
| 7240 */ | |
| 7241 bool get hasLoadLibraryFunction; | |
| 7242 | |
| 7243 /** | |
| 7244 * Return a list containing all of the libraries that are imported into this | |
| 7245 * library. This includes all of the libraries that are imported using a | |
| 7246 * prefix (also available through the prefixes returned by [getPrefixes]) and | |
| 7247 * those that are imported without a prefix. | |
| 7248 */ | |
| 7249 List<LibraryElement> get importedLibraries; | |
| 7250 | |
| 7251 /** | |
| 7252 * Return a list containing all of the imports defined in this library. | |
| 7253 */ | |
| 7254 List<ImportElement> get imports; | |
| 7255 | |
| 7256 /** | |
| 7257 * Return `true` if this library is an application that can be run in the | |
| 7258 * browser. | |
| 7259 */ | |
| 7260 bool get isBrowserApplication; | |
| 7261 | |
| 7262 /** | |
| 7263 * Return `true` if this library is the dart:core library. | |
| 7264 */ | |
| 7265 bool get isDartCore; | |
| 7266 | |
| 7267 /** | |
| 7268 * Return `true` if this library is part of the SDK. | |
| 7269 */ | |
| 7270 bool get isInSdk; | |
| 7271 | |
| 7272 /** | |
| 7273 * Return the element representing the synthetic function `loadLibrary` that | |
| 7274 * is implicitly defined for this library if the library is imported using a | |
| 7275 * deferred import. | |
| 7276 */ | |
| 7277 FunctionElement get loadLibraryFunction; | |
| 7278 | |
| 7279 /** | |
| 7280 * Return a list containing all of the compilation units that are included in | |
| 7281 * this library using a `part` directive. This does not include the defining | |
| 7282 * compilation unit that contains the `part` directives. | |
| 7283 */ | |
| 7284 List<CompilationUnitElement> get parts; | |
| 7285 | |
| 7286 /** | |
| 7287 * Return a list containing elements for each of the prefixes used to `import` | |
| 7288 * libraries into this library. Each prefix can be used in more than one | |
| 7289 * `import` directive. | |
| 7290 */ | |
| 7291 List<PrefixElement> get prefixes; | |
| 7292 | |
| 7293 /** | |
| 7294 * The public [Namespace] of this library, `null` if it has not been | |
| 7295 * computed yet. | |
| 7296 */ | |
| 7297 Namespace get publicNamespace; | |
| 7298 | |
| 7299 /** | |
| 7300 * Return a list containing all of the compilation units this library consists | |
| 7301 * of. This includes the defining compilation unit and units included using | |
| 7302 * the `part` directive. | |
| 7303 */ | |
| 7304 List<CompilationUnitElement> get units; | |
| 7305 | |
| 7306 /** | |
| 7307 * Return a list containing all directly and indirectly imported libraries. | |
| 7308 */ | |
| 7309 List<LibraryElement> get visibleLibraries; | |
| 7310 | |
| 7311 /** | |
| 7312 * Return a list containing all of the imports that share the given [prefix], | |
| 7313 * or an empty array if there are no such imports. | |
| 7314 */ | |
| 7315 List<ImportElement> getImportsWithPrefix(PrefixElement prefix); | |
| 7316 | |
| 7317 /** | |
| 7318 * Return the class defined in this library that has the given [name], or | |
| 7319 * `null` if this library does not define a class with the given name. | |
| 7320 */ | |
| 7321 ClassElement getType(String className); | |
| 7322 | |
| 7323 /** | |
| 7324 * Return `true` if this library is up to date with respect to the given | |
| 7325 * [timeStamp]. If any transitively referenced Source is newer than the time | |
| 7326 * stamp, this method returns false. | |
| 7327 */ | |
| 7328 bool isUpToDate(int timeStamp); | |
| 7329 } | |
| 7330 | |
| 7331 /** | |
| 7332 * A concrete implementation of a [LibraryElement]. | |
| 7333 */ | |
| 7334 class LibraryElementImpl extends ElementImpl implements LibraryElement { | |
| 7335 /** | |
| 7336 * An empty list of library elements. | |
| 7337 */ | |
| 7338 @deprecated // Use LibraryElement.EMPTY_LIST | |
| 7339 static const List<LibraryElement> EMPTY_ARRAY = const <LibraryElement>[]; | |
| 7340 | |
| 7341 /** | |
| 7342 * The analysis context in which this library is defined. | |
| 7343 */ | |
| 7344 final AnalysisContext context; | |
| 7345 | |
| 7346 /** | |
| 7347 * The compilation unit that defines this library. | |
| 7348 */ | |
| 7349 CompilationUnitElement _definingCompilationUnit; | |
| 7350 | |
| 7351 /** | |
| 7352 * The entry point for this library, or `null` if this library does not have | |
| 7353 * an entry point. | |
| 7354 */ | |
| 7355 FunctionElement entryPoint; | |
| 7356 | |
| 7357 /** | |
| 7358 * A list containing specifications of all of the imports defined in this | |
| 7359 * library. | |
| 7360 */ | |
| 7361 List<ImportElement> _imports = ImportElement.EMPTY_LIST; | |
| 7362 | |
| 7363 /** | |
| 7364 * A list containing specifications of all of the exports defined in this | |
| 7365 * library. | |
| 7366 */ | |
| 7367 List<ExportElement> _exports = ExportElement.EMPTY_LIST; | |
| 7368 | |
| 7369 /** | |
| 7370 * A list containing the strongly connected component in the import/export | |
| 7371 * graph in which the current library resides. Computed on demand, null | |
| 7372 * if not present. If _libraryCycle is set, then the _libraryCycle field | |
| 7373 * for all libraries reachable from this library in the import/export graph | |
| 7374 * is also set. | |
| 7375 */ | |
| 7376 List<LibraryElement> _libraryCycle = null; | |
| 7377 | |
| 7378 /** | |
| 7379 * A list containing all of the compilation units that are included in this | |
| 7380 * library using a `part` directive. | |
| 7381 */ | |
| 7382 List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST; | |
| 7383 | |
| 7384 /** | |
| 7385 * The element representing the synthetic function `loadLibrary` that is | |
| 7386 * defined for this library, or `null` if the element has not yet been created
. | |
| 7387 */ | |
| 7388 FunctionElement _loadLibraryFunction; | |
| 7389 | |
| 7390 @override | |
| 7391 final int nameLength; | |
| 7392 | |
| 7393 /** | |
| 7394 * The export [Namespace] of this library, `null` if it has not been | |
| 7395 * computed yet. | |
| 7396 */ | |
| 7397 @override | |
| 7398 Namespace exportNamespace; | |
| 7399 | |
| 7400 /** | |
| 7401 * The public [Namespace] of this library, `null` if it has not been | |
| 7402 * computed yet. | |
| 7403 */ | |
| 7404 @override | |
| 7405 Namespace publicNamespace; | |
| 7406 | |
| 7407 /** | |
| 7408 * Initialize a newly created library element in the given [context] to have | |
| 7409 * the given [name] and [offset]. | |
| 7410 */ | |
| 7411 LibraryElementImpl(this.context, String name, int offset, this.nameLength) | |
| 7412 : super(name, offset); | |
| 7413 | |
| 7414 /** | |
| 7415 * Initialize a newly created library element in the given [context] to have | |
| 7416 * the given [name]. | |
| 7417 */ | |
| 7418 LibraryElementImpl.forNode(this.context, LibraryIdentifier name) | |
| 7419 : super.forNode(name), | |
| 7420 nameLength = name != null ? name.length : 0; | |
| 7421 | |
| 7422 @override | |
| 7423 CompilationUnitElement get definingCompilationUnit => | |
| 7424 _definingCompilationUnit; | |
| 7425 | |
| 7426 /** | |
| 7427 * Set the compilation unit that defines this library to the given compilation | |
| 7428 * [unit]. | |
| 7429 */ | |
| 7430 void set definingCompilationUnit(CompilationUnitElement unit) { | |
| 7431 assert((unit as CompilationUnitElementImpl).librarySource == unit.source); | |
| 7432 (unit as CompilationUnitElementImpl).enclosingElement = this; | |
| 7433 this._definingCompilationUnit = unit; | |
| 7434 } | |
| 7435 | |
| 7436 @override | |
| 7437 List<LibraryElement> get exportedLibraries { | |
| 7438 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); | |
| 7439 for (ExportElement element in _exports) { | |
| 7440 LibraryElement library = element.exportedLibrary; | |
| 7441 if (library != null) { | |
| 7442 libraries.add(library); | |
| 7443 } | |
| 7444 } | |
| 7445 return new List.from(libraries); | |
| 7446 } | |
| 7447 | |
| 7448 @override | |
| 7449 List<ExportElement> get exports => _exports; | |
| 7450 | |
| 7451 /** | |
| 7452 * Set the specifications of all of the exports defined in this library to the | |
| 7453 * given list of [exports]. | |
| 7454 */ | |
| 7455 void set exports(List<ExportElement> exports) { | |
| 7456 for (ExportElement exportElement in exports) { | |
| 7457 (exportElement as ExportElementImpl).enclosingElement = this; | |
| 7458 } | |
| 7459 this._exports = exports; | |
| 7460 } | |
| 7461 | |
| 7462 @override | |
| 7463 bool get hasExtUri => hasModifier(Modifier.HAS_EXT_URI); | |
| 7464 | |
| 7465 /** | |
| 7466 * Set whether this library has an import of a "dart-ext" URI. | |
| 7467 */ | |
| 7468 void set hasExtUri(bool hasExtUri) { | |
| 7469 setModifier(Modifier.HAS_EXT_URI, hasExtUri); | |
| 7470 } | |
| 7471 | |
| 7472 @override | |
| 7473 int get hashCode => _definingCompilationUnit.hashCode; | |
| 7474 | |
| 7475 @override | |
| 7476 bool get hasLoadLibraryFunction { | |
| 7477 if (_definingCompilationUnit.hasLoadLibraryFunction) { | |
| 7478 return true; | |
| 7479 } | |
| 7480 for (int i = 0; i < _parts.length; i++) { | |
| 7481 if (_parts[i].hasLoadLibraryFunction) { | |
| 7482 return true; | |
| 7483 } | |
| 7484 } | |
| 7485 return false; | |
| 7486 } | |
| 7487 | |
| 7488 @override | |
| 7489 String get identifier => _definingCompilationUnit.source.encoding; | |
| 7490 | |
| 7491 @override | |
| 7492 List<LibraryElement> get importedLibraries { | |
| 7493 HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); | |
| 7494 for (ImportElement element in _imports) { | |
| 7495 LibraryElement library = element.importedLibrary; | |
| 7496 if (library != null) { | |
| 7497 libraries.add(library); | |
| 7498 } | |
| 7499 } | |
| 7500 return new List.from(libraries); | |
| 7501 } | |
| 7502 | |
| 7503 @override | |
| 7504 List<ImportElement> get imports => _imports; | |
| 7505 | |
| 7506 /** | |
| 7507 * Set the specifications of all of the imports defined in this library to the | |
| 7508 * given list of [imports]. | |
| 7509 */ | |
| 7510 void set imports(List<ImportElement> imports) { | |
| 7511 for (ImportElement importElement in imports) { | |
| 7512 (importElement as ImportElementImpl).enclosingElement = this; | |
| 7513 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; | |
| 7514 if (prefix != null) { | |
| 7515 prefix.enclosingElement = this; | |
| 7516 } | |
| 7517 } | |
| 7518 this._imports = imports; | |
| 7519 } | |
| 7520 | |
| 7521 @override | |
| 7522 bool get isBrowserApplication => | |
| 7523 entryPoint != null && isOrImportsBrowserLibrary; | |
| 7524 | |
| 7525 @override | |
| 7526 bool get isDartCore => name == "dart.core"; | |
| 7527 | |
| 7528 @override | |
| 7529 bool get isInSdk => | |
| 7530 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); | |
| 7531 | |
| 7532 /** | |
| 7533 * Return `true` if the receiver directly or indirectly imports the | |
| 7534 * 'dart:html' libraries. | |
| 7535 */ | |
| 7536 bool get isOrImportsBrowserLibrary { | |
| 7537 List<LibraryElement> visited = new List<LibraryElement>(); | |
| 7538 Source htmlLibSource = context.sourceFactory.forUri(DartSdk.DART_HTML); | |
| 7539 visited.add(this); | |
| 7540 for (int index = 0; index < visited.length; index++) { | |
| 7541 LibraryElement library = visited[index]; | |
| 7542 Source source = library.definingCompilationUnit.source; | |
| 7543 if (source == htmlLibSource) { | |
| 7544 return true; | |
| 7545 } | |
| 7546 for (LibraryElement importedLibrary in library.importedLibraries) { | |
| 7547 if (!visited.contains(importedLibrary)) { | |
| 7548 visited.add(importedLibrary); | |
| 7549 } | |
| 7550 } | |
| 7551 for (LibraryElement exportedLibrary in library.exportedLibraries) { | |
| 7552 if (!visited.contains(exportedLibrary)) { | |
| 7553 visited.add(exportedLibrary); | |
| 7554 } | |
| 7555 } | |
| 7556 } | |
| 7557 return false; | |
| 7558 } | |
| 7559 | |
| 7560 @override | |
| 7561 ElementKind get kind => ElementKind.LIBRARY; | |
| 7562 | |
| 7563 @override | |
| 7564 LibraryElement get library => this; | |
| 7565 | |
| 7566 List<LibraryElement> get libraryCycle { | |
| 7567 if (_libraryCycle != null) { | |
| 7568 return _libraryCycle; | |
| 7569 } | |
| 7570 | |
| 7571 // Global counter for this run of the algorithm | |
| 7572 int counter = 0; | |
| 7573 // The discovery times of each library | |
| 7574 Map<LibraryElementImpl, int> indices = {}; | |
| 7575 // The set of scc candidates | |
| 7576 Set<LibraryElementImpl> active = new Set(); | |
| 7577 // The stack of discovered elements | |
| 7578 List<LibraryElementImpl> stack = []; | |
| 7579 // For a given library that has not yet been processed by this run of the | |
| 7580 // algorithm, compute the strongly connected components. | |
| 7581 int scc(LibraryElementImpl library) { | |
| 7582 int index = counter++; | |
| 7583 int root = index; | |
| 7584 indices[library] = index; | |
| 7585 active.add(library); | |
| 7586 stack.add(library); | |
| 7587 void recurse(LibraryElementImpl child) { | |
| 7588 if (!indices.containsKey(child)) { | |
| 7589 // We haven't visited this child yet, so recurse on the child, | |
| 7590 // returning the lowest numbered node reachable from the child. If | |
| 7591 // the child can reach a root which is lower numbered than anything | |
| 7592 // we've reached so far, update the root. | |
| 7593 root = min(root, scc(child)); | |
| 7594 } else if (active.contains(child)) { | |
| 7595 // The child has been visited, but has not yet been placed into a | |
| 7596 // component. If the child is higher than anything we've seen so far | |
| 7597 // update the root appropriately. | |
| 7598 root = min(root, indices[child]); | |
| 7599 } | |
| 7600 } | |
| 7601 // Recurse on all of the children in the import/export graph, filtering | |
| 7602 // out those for which library cycles have already been computed. | |
| 7603 library.exportedLibraries | |
| 7604 .where((l) => l._libraryCycle == null) | |
| 7605 .forEach(recurse); | |
| 7606 library.importedLibraries | |
| 7607 .where((l) => l._libraryCycle == null) | |
| 7608 .forEach(recurse); | |
| 7609 | |
| 7610 if (root == index) { | |
| 7611 // This is the root of a strongly connected component. | |
| 7612 // Pop the elements, and share the component across all | |
| 7613 // of the elements. | |
| 7614 List<LibraryElement> component = <LibraryElement>[]; | |
| 7615 LibraryElementImpl cur = null; | |
| 7616 do { | |
| 7617 cur = stack.removeLast(); | |
| 7618 active.remove(cur); | |
| 7619 component.add(cur); | |
| 7620 cur._libraryCycle = component; | |
| 7621 } while (cur != library); | |
| 7622 } | |
| 7623 return root; | |
| 7624 } | |
| 7625 scc(library); | |
| 7626 return _libraryCycle; | |
| 7627 } | |
| 7628 | |
| 7629 @override | |
| 7630 FunctionElement get loadLibraryFunction { | |
| 7631 if (_loadLibraryFunction == null) { | |
| 7632 FunctionElementImpl function = | |
| 7633 new FunctionElementImpl(FunctionElement.LOAD_LIBRARY_NAME, -1); | |
| 7634 function.synthetic = true; | |
| 7635 function.enclosingElement = this; | |
| 7636 function.returnType = loadLibraryReturnType; | |
| 7637 function.type = new FunctionTypeImpl(function); | |
| 7638 _loadLibraryFunction = function; | |
| 7639 } | |
| 7640 return _loadLibraryFunction; | |
| 7641 } | |
| 7642 | |
| 7643 /** | |
| 7644 * Return the object representing the type 'Future' from the 'dart:async' | |
| 7645 * library, or the type 'void' if the type 'Future' cannot be accessed. | |
| 7646 */ | |
| 7647 DartType get loadLibraryReturnType { | |
| 7648 try { | |
| 7649 Source asyncSource = context.sourceFactory.forUri(DartSdk.DART_ASYNC); | |
| 7650 if (asyncSource == null) { | |
| 7651 AnalysisEngine.instance.logger | |
| 7652 .logError("Could not create a source for dart:async"); | |
| 7653 return VoidTypeImpl.instance; | |
| 7654 } | |
| 7655 LibraryElement asyncElement = context.computeLibraryElement(asyncSource); | |
| 7656 if (asyncElement == null) { | |
| 7657 AnalysisEngine.instance.logger | |
| 7658 .logError("Could not build the element model for dart:async"); | |
| 7659 return VoidTypeImpl.instance; | |
| 7660 } | |
| 7661 ClassElement futureElement = asyncElement.getType("Future"); | |
| 7662 if (futureElement == null) { | |
| 7663 AnalysisEngine.instance.logger | |
| 7664 .logError("Could not find type Future in dart:async"); | |
| 7665 return VoidTypeImpl.instance; | |
| 7666 } | |
| 7667 InterfaceType futureType = futureElement.type; | |
| 7668 return futureType.substitute4(<DartType>[DynamicTypeImpl.instance]); | |
| 7669 } on AnalysisException catch (exception, stackTrace) { | |
| 7670 AnalysisEngine.instance.logger.logError( | |
| 7671 "Could not build the element model for dart:async", | |
| 7672 new CaughtException(exception, stackTrace)); | |
| 7673 return VoidTypeImpl.instance; | |
| 7674 } | |
| 7675 } | |
| 7676 | |
| 7677 @override | |
| 7678 List<CompilationUnitElement> get parts => _parts; | |
| 7679 | |
| 7680 /** | |
| 7681 * Set the compilation units that are included in this library using a `part` | |
| 7682 * directive to the given list of [parts]. | |
| 7683 */ | |
| 7684 void set parts(List<CompilationUnitElement> parts) { | |
| 7685 for (CompilationUnitElement compilationUnit in parts) { | |
| 7686 assert((compilationUnit as CompilationUnitElementImpl).librarySource == | |
| 7687 source); | |
| 7688 (compilationUnit as CompilationUnitElementImpl).enclosingElement = this; | |
| 7689 } | |
| 7690 this._parts = parts; | |
| 7691 } | |
| 7692 | |
| 7693 @override | |
| 7694 List<PrefixElement> get prefixes { | |
| 7695 HashSet<PrefixElement> prefixes = new HashSet<PrefixElement>(); | |
| 7696 for (ImportElement element in _imports) { | |
| 7697 PrefixElement prefix = element.prefix; | |
| 7698 if (prefix != null) { | |
| 7699 prefixes.add(prefix); | |
| 7700 } | |
| 7701 } | |
| 7702 return new List.from(prefixes); | |
| 7703 } | |
| 7704 | |
| 7705 @override | |
| 7706 Source get source { | |
| 7707 if (_definingCompilationUnit == null) { | |
| 7708 return null; | |
| 7709 } | |
| 7710 return _definingCompilationUnit.source; | |
| 7711 } | |
| 7712 | |
| 7713 @override | |
| 7714 List<CompilationUnitElement> get units { | |
| 7715 List<CompilationUnitElement> units = new List<CompilationUnitElement>(); | |
| 7716 units.add(_definingCompilationUnit); | |
| 7717 units.addAll(_parts); | |
| 7718 return units; | |
| 7719 } | |
| 7720 | |
| 7721 @override | |
| 7722 List<LibraryElement> get visibleLibraries { | |
| 7723 Set<LibraryElement> visibleLibraries = new Set(); | |
| 7724 _addVisibleLibraries(visibleLibraries, false); | |
| 7725 return new List.from(visibleLibraries); | |
| 7726 } | |
| 7727 | |
| 7728 @override | |
| 7729 bool operator ==(Object object) => object is LibraryElementImpl && | |
| 7730 _definingCompilationUnit == object.definingCompilationUnit; | |
| 7731 | |
| 7732 @override | |
| 7733 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); | |
| 7734 | |
| 7735 @override | |
| 7736 ElementImpl getChild(String identifier) { | |
| 7737 if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier == | |
| 7738 identifier) { | |
| 7739 return _definingCompilationUnit as CompilationUnitElementImpl; | |
| 7740 } | |
| 7741 for (CompilationUnitElement part in _parts) { | |
| 7742 if ((part as CompilationUnitElementImpl).identifier == identifier) { | |
| 7743 return part as CompilationUnitElementImpl; | |
| 7744 } | |
| 7745 } | |
| 7746 for (ImportElement importElement in _imports) { | |
| 7747 if ((importElement as ImportElementImpl).identifier == identifier) { | |
| 7748 return importElement as ImportElementImpl; | |
| 7749 } | |
| 7750 } | |
| 7751 for (ExportElement exportElement in _exports) { | |
| 7752 if ((exportElement as ExportElementImpl).identifier == identifier) { | |
| 7753 return exportElement as ExportElementImpl; | |
| 7754 } | |
| 7755 } | |
| 7756 return null; | |
| 7757 } | |
| 7758 | |
| 7759 @override | |
| 7760 List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) { | |
| 7761 int count = _imports.length; | |
| 7762 List<ImportElement> importList = new List<ImportElement>(); | |
| 7763 for (int i = 0; i < count; i++) { | |
| 7764 if (identical(_imports[i].prefix, prefixElement)) { | |
| 7765 importList.add(_imports[i]); | |
| 7766 } | |
| 7767 } | |
| 7768 return importList; | |
| 7769 } | |
| 7770 | |
| 7771 @override | |
| 7772 ClassElement getType(String className) { | |
| 7773 ClassElement type = _definingCompilationUnit.getType(className); | |
| 7774 if (type != null) { | |
| 7775 return type; | |
| 7776 } | |
| 7777 for (CompilationUnitElement part in _parts) { | |
| 7778 type = part.getType(className); | |
| 7779 if (type != null) { | |
| 7780 return type; | |
| 7781 } | |
| 7782 } | |
| 7783 return null; | |
| 7784 } | |
| 7785 | |
| 7786 @override | |
| 7787 bool isUpToDate(int timeStamp) { | |
| 7788 Set<LibraryElement> visitedLibraries = new Set(); | |
| 7789 return _safeIsUpToDate(this, timeStamp, visitedLibraries); | |
| 7790 } | |
| 7791 | |
| 7792 @override | |
| 7793 void visitChildren(ElementVisitor visitor) { | |
| 7794 super.visitChildren(visitor); | |
| 7795 safelyVisitChild(_definingCompilationUnit, visitor); | |
| 7796 safelyVisitChildren(_exports, visitor); | |
| 7797 safelyVisitChildren(_imports, visitor); | |
| 7798 safelyVisitChildren(_parts, visitor); | |
| 7799 } | |
| 7800 | |
| 7801 /** | |
| 7802 * Recursively fills set of visible libraries for | |
| 7803 * [getVisibleElementsLibraries]. | |
| 7804 */ | |
| 7805 void _addVisibleLibraries( | |
| 7806 Set<LibraryElement> visibleLibraries, bool includeExports) { | |
| 7807 // maybe already processed | |
| 7808 if (!visibleLibraries.add(this)) { | |
| 7809 return; | |
| 7810 } | |
| 7811 // add imported libraries | |
| 7812 for (ImportElement importElement in _imports) { | |
| 7813 LibraryElement importedLibrary = importElement.importedLibrary; | |
| 7814 if (importedLibrary != null) { | |
| 7815 (importedLibrary as LibraryElementImpl) | |
| 7816 ._addVisibleLibraries(visibleLibraries, true); | |
| 7817 } | |
| 7818 } | |
| 7819 // add exported libraries | |
| 7820 if (includeExports) { | |
| 7821 for (ExportElement exportElement in _exports) { | |
| 7822 LibraryElement exportedLibrary = exportElement.exportedLibrary; | |
| 7823 if (exportedLibrary != null) { | |
| 7824 (exportedLibrary as LibraryElementImpl) | |
| 7825 ._addVisibleLibraries(visibleLibraries, true); | |
| 7826 } | |
| 7827 } | |
| 7828 } | |
| 7829 } | |
| 7830 | |
| 7831 /** | |
| 7832 * Return `true` if the given [library] is up to date with respect to the | |
| 7833 * given [timeStamp]. The set of [visitedLibraries] is used to prevent | |
| 7834 * infinite recusion in the case of mutually dependent libraries. | |
| 7835 */ | |
| 7836 static bool _safeIsUpToDate(LibraryElement library, int timeStamp, | |
| 7837 Set<LibraryElement> visitedLibraries) { | |
| 7838 if (!visitedLibraries.contains(library)) { | |
| 7839 visitedLibraries.add(library); | |
| 7840 AnalysisContext context = library.context; | |
| 7841 // Check the defining compilation unit. | |
| 7842 if (timeStamp < | |
| 7843 context | |
| 7844 .getModificationStamp(library.definingCompilationUnit.source)) { | |
| 7845 return false; | |
| 7846 } | |
| 7847 // Check the parted compilation units. | |
| 7848 for (CompilationUnitElement element in library.parts) { | |
| 7849 if (timeStamp < context.getModificationStamp(element.source)) { | |
| 7850 return false; | |
| 7851 } | |
| 7852 } | |
| 7853 // Check the imported libraries. | |
| 7854 for (LibraryElement importedLibrary in library.importedLibraries) { | |
| 7855 if (!_safeIsUpToDate(importedLibrary, timeStamp, visitedLibraries)) { | |
| 7856 return false; | |
| 7857 } | |
| 7858 } | |
| 7859 // Check the exported libraries. | |
| 7860 for (LibraryElement exportedLibrary in library.exportedLibraries) { | |
| 7861 if (!_safeIsUpToDate(exportedLibrary, timeStamp, visitedLibraries)) { | |
| 7862 return false; | |
| 7863 } | |
| 7864 } | |
| 7865 } | |
| 7866 return true; | |
| 7867 } | |
| 7868 } | |
| 7869 | |
| 7870 /** | |
| 7871 * An element that can be (but are not required to be) defined within a method | |
| 7872 * or function (an [ExecutableElement]). | |
| 7873 */ | |
| 7874 abstract class LocalElement implements Element { | |
| 7875 /** | |
| 7876 * Return a source range that covers the approximate portion of the source in | |
| 7877 * which the name of this element is visible, or `null` if there is no single | |
| 7878 * range of characters within which the element name is visible. | |
| 7879 * | |
| 7880 * * For a local variable, this includes everything from the end of the | |
| 7881 * variable's initializer to the end of the block that encloses the variable | |
| 7882 * declaration. | |
| 7883 * * For a parameter, this includes the body of the method or function that | |
| 7884 * declares the parameter. | |
| 7885 * * For a local function, this includes everything from the beginning of the | |
| 7886 * function's body to the end of the block that encloses the function | |
| 7887 * declaration. | |
| 7888 * * For top-level functions, `null` will be returned because they are | |
| 7889 * potentially visible in multiple sources. | |
| 7890 */ | |
| 7891 SourceRange get visibleRange; | |
| 7892 } | |
| 7893 | |
| 7894 /** | |
| 7895 * A local variable. | |
| 7896 */ | |
| 7897 abstract class LocalVariableElement implements LocalElement, VariableElement { | |
| 7898 /** | |
| 7899 * An empty list of field elements. | |
| 7900 */ | |
| 7901 static const List<LocalVariableElement> EMPTY_LIST = | |
| 7902 const <LocalVariableElement>[]; | |
| 7903 | |
| 7904 /** | |
| 7905 * Return the resolved [VariableDeclaration] node that declares this | |
| 7906 * [LocalVariableElement]. | |
| 7907 * | |
| 7908 * This method is expensive, because resolved AST might be evicted from cache, | |
| 7909 * so parsing and resolving will be performed. | |
| 7910 */ | |
| 7911 @override | |
| 7912 VariableDeclaration computeNode(); | |
| 7913 } | |
| 7914 | |
| 7915 /** | |
| 7916 * A concrete implementation of a [LocalVariableElement]. | |
| 7917 */ | |
| 7918 class LocalVariableElementImpl extends VariableElementImpl | |
| 7919 with PotentiallyConstVariableElement | |
| 7920 implements LocalVariableElement { | |
| 7921 /** | |
| 7922 * An empty list of field elements. | |
| 7923 */ | |
| 7924 @deprecated // Use LocalVariableElement.EMPTY_LIST | |
| 7925 static const List<LocalVariableElement> EMPTY_ARRAY = | |
| 7926 const <LocalVariableElement>[]; | |
| 7927 | |
| 7928 /** | |
| 7929 * The offset to the beginning of the visible range for this element. | |
| 7930 */ | |
| 7931 int _visibleRangeOffset = 0; | |
| 7932 | |
| 7933 /** | |
| 7934 * The length of the visible range for this element, or `-1` if this element | |
| 7935 * does not have a visible range. | |
| 7936 */ | |
| 7937 int _visibleRangeLength = -1; | |
| 7938 | |
| 7939 /** | |
| 7940 * Initialize a newly created method element to have the given [name] and | |
| 7941 * [offset]. | |
| 7942 */ | |
| 7943 LocalVariableElementImpl(String name, int offset) : super(name, offset); | |
| 7944 | |
| 7945 /** | |
| 7946 * Initialize a newly created local variable element to have the given [name]. | |
| 7947 */ | |
| 7948 LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 7949 | |
| 7950 @override | |
| 7951 String get identifier { | |
| 7952 int enclosingOffset = | |
| 7953 enclosingElement != null ? enclosingElement.nameOffset : 0; | |
| 7954 int delta = nameOffset - enclosingOffset; | |
| 7955 return '${super.identifier}@$delta'; | |
| 7956 } | |
| 7957 | |
| 7958 @override | |
| 7959 bool get isPotentiallyMutatedInClosure => | |
| 7960 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); | |
| 7961 | |
| 7962 @override | |
| 7963 bool get isPotentiallyMutatedInScope => | |
| 7964 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); | |
| 7965 | |
| 7966 @override | |
| 7967 ElementKind get kind => ElementKind.LOCAL_VARIABLE; | |
| 7968 | |
| 7969 @override | |
| 7970 SourceRange get visibleRange { | |
| 7971 if (_visibleRangeLength < 0) { | |
| 7972 return null; | |
| 7973 } | |
| 7974 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 7975 } | |
| 7976 | |
| 7977 @override | |
| 7978 accept(ElementVisitor visitor) => visitor.visitLocalVariableElement(this); | |
| 7979 | |
| 7980 @override | |
| 7981 void appendTo(StringBuffer buffer) { | |
| 7982 buffer.write(type); | |
| 7983 buffer.write(" "); | |
| 7984 buffer.write(displayName); | |
| 7985 } | |
| 7986 | |
| 7987 @override | |
| 7988 VariableDeclaration computeNode() => | |
| 7989 getNodeMatching((node) => node is VariableDeclaration); | |
| 7990 | |
| 7991 /** | |
| 7992 * Specifies that this variable is potentially mutated somewhere in closure. | |
| 7993 */ | |
| 7994 void markPotentiallyMutatedInClosure() { | |
| 7995 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); | |
| 7996 } | |
| 7997 | |
| 7998 /** | |
| 7999 * Specifies that this variable is potentially mutated somewhere in its scope. | |
| 8000 */ | |
| 8001 void markPotentiallyMutatedInScope() { | |
| 8002 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); | |
| 8003 } | |
| 8004 | |
| 8005 /** | |
| 8006 * Set the visible range for this element to the range starting at the given | |
| 8007 * [offset] with the given [length]. | |
| 8008 */ | |
| 8009 void setVisibleRange(int offset, int length) { | |
| 8010 _visibleRangeOffset = offset; | |
| 8011 _visibleRangeLength = length; | |
| 8012 } | |
| 8013 } | |
| 8014 | |
| 8015 /** | |
| 8016 * An element defined in a parameterized type where the values of the type | |
| 8017 * parameters are known. | |
| 8018 */ | |
| 8019 abstract class Member implements Element { | |
| 8020 /** | |
| 8021 * The element on which the parameterized element was created. | |
| 8022 */ | |
| 8023 final Element _baseElement; | |
| 8024 | |
| 8025 /** | |
| 8026 * The type in which the element is defined. | |
| 8027 */ | |
| 8028 final ParameterizedType _definingType; | |
| 8029 | |
| 8030 /** | |
| 8031 * Initialize a newly created element to represent a constructor, based on the | |
| 8032 * [baseElement], defined by the [definingType]. | |
| 8033 */ | |
| 8034 Member(this._baseElement, this._definingType); | |
| 8035 | |
| 8036 /** | |
| 8037 * Return the element on which the parameterized element was created. | |
| 8038 */ | |
| 8039 Element get baseElement => _baseElement; | |
| 8040 | |
| 8041 @override | |
| 8042 AnalysisContext get context => _baseElement.context; | |
| 8043 | |
| 8044 /** | |
| 8045 * Return the type in which the element is defined. | |
| 8046 */ | |
| 8047 ParameterizedType get definingType => _definingType; | |
| 8048 | |
| 8049 @override | |
| 8050 String get displayName => _baseElement.displayName; | |
| 8051 | |
| 8052 @override | |
| 8053 SourceRange get docRange => _baseElement.docRange; | |
| 8054 | |
| 8055 int get id => _baseElement.id; | |
| 8056 | |
| 8057 @override | |
| 8058 bool get isDeprecated => _baseElement.isDeprecated; | |
| 8059 | |
| 8060 @override | |
| 8061 bool get isOverride => _baseElement.isOverride; | |
| 8062 | |
| 8063 @override | |
| 8064 bool get isPrivate => _baseElement.isPrivate; | |
| 8065 | |
| 8066 @override | |
| 8067 bool get isPublic => _baseElement.isPublic; | |
| 8068 | |
| 8069 @override | |
| 8070 bool get isSynthetic => _baseElement.isSynthetic; | |
| 8071 | |
| 8072 @override | |
| 8073 ElementKind get kind => _baseElement.kind; | |
| 8074 | |
| 8075 @override | |
| 8076 LibraryElement get library => _baseElement.library; | |
| 8077 | |
| 8078 @override | |
| 8079 ElementLocation get location => _baseElement.location; | |
| 8080 | |
| 8081 @override | |
| 8082 List<ElementAnnotation> get metadata => _baseElement.metadata; | |
| 8083 | |
| 8084 @override | |
| 8085 String get name => _baseElement.name; | |
| 8086 | |
| 8087 @override | |
| 8088 int get nameLength => _baseElement.nameLength; | |
| 8089 | |
| 8090 @override | |
| 8091 int get nameOffset => _baseElement.nameOffset; | |
| 8092 | |
| 8093 @deprecated | |
| 8094 @override | |
| 8095 AstNode get node => computeNode(); | |
| 8096 | |
| 8097 @override | |
| 8098 Source get source => _baseElement.source; | |
| 8099 | |
| 8100 @override | |
| 8101 CompilationUnit get unit => _baseElement.unit; | |
| 8102 | |
| 8103 @override | |
| 8104 String computeDocumentationComment() => | |
| 8105 _baseElement.computeDocumentationComment(); | |
| 8106 | |
| 8107 @override | |
| 8108 AstNode computeNode() => _baseElement.computeNode(); | |
| 8109 | |
| 8110 @override | |
| 8111 Element getAncestor(Predicate<Element> predicate) => | |
| 8112 baseElement.getAncestor(predicate); | |
| 8113 | |
| 8114 @override | |
| 8115 String getExtendedDisplayName(String shortName) => | |
| 8116 _baseElement.getExtendedDisplayName(shortName); | |
| 8117 | |
| 8118 @override | |
| 8119 bool isAccessibleIn(LibraryElement library) => | |
| 8120 _baseElement.isAccessibleIn(library); | |
| 8121 | |
| 8122 /** | |
| 8123 * If the given [child] is not `null`, use the given [visitor] to visit it. | |
| 8124 */ | |
| 8125 void safelyVisitChild(Element child, ElementVisitor visitor) { | |
| 8126 // TODO(brianwilkerson) Make this private | |
| 8127 if (child != null) { | |
| 8128 child.accept(visitor); | |
| 8129 } | |
| 8130 } | |
| 8131 | |
| 8132 /** | |
| 8133 * Use the given [visitor] to visit all of the [children]. | |
| 8134 */ | |
| 8135 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) { | |
| 8136 // TODO(brianwilkerson) Make this private | |
| 8137 if (children != null) { | |
| 8138 for (Element child in children) { | |
| 8139 child.accept(visitor); | |
| 8140 } | |
| 8141 } | |
| 8142 } | |
| 8143 | |
| 8144 /** | |
| 8145 * Return the type that results from replacing the type parameters in the | |
| 8146 * given [type] with the type arguments associated with this member. | |
| 8147 */ | |
| 8148 DartType substituteFor(DartType type) { | |
| 8149 if (type == null) { | |
| 8150 return null; | |
| 8151 } | |
| 8152 List<DartType> argumentTypes = _definingType.typeArguments; | |
| 8153 List<DartType> parameterTypes = | |
| 8154 TypeParameterTypeImpl.getTypes(_definingType.typeParameters); | |
| 8155 return type.substitute2(argumentTypes, parameterTypes); | |
| 8156 } | |
| 8157 | |
| 8158 /** | |
| 8159 * Return the list of types that results from replacing the type parameters in | |
| 8160 * the given [types] with the type arguments associated with this member. | |
| 8161 */ | |
| 8162 List<InterfaceType> substituteFor2(List<InterfaceType> types) { | |
| 8163 int count = types.length; | |
| 8164 List<InterfaceType> substitutedTypes = new List<InterfaceType>(count); | |
| 8165 for (int i = 0; i < count; i++) { | |
| 8166 substitutedTypes[i] = substituteFor(types[i]); | |
| 8167 } | |
| 8168 return substitutedTypes; | |
| 8169 } | |
| 8170 | |
| 8171 @override | |
| 8172 void visitChildren(ElementVisitor visitor) { | |
| 8173 // There are no children to visit | |
| 8174 } | |
| 8175 } | |
| 8176 | |
| 8177 /** | |
| 8178 * An element that represents a method defined within a type. | |
| 8179 */ | |
| 8180 abstract class MethodElement implements ClassMemberElement, ExecutableElement { | |
| 8181 /** | |
| 8182 * An empty list of method elements. | |
| 8183 */ | |
| 8184 static const List<MethodElement> EMPTY_LIST = const <MethodElement>[]; | |
| 8185 | |
| 8186 /** | |
| 8187 * Return the resolved [MethodDeclaration] node that declares this | |
| 8188 * [MethodElement]. | |
| 8189 * | |
| 8190 * This method is expensive, because resolved AST might be evicted from cache, | |
| 8191 * so parsing and resolving will be performed. | |
| 8192 */ | |
| 8193 @override | |
| 8194 MethodDeclaration computeNode(); | |
| 8195 } | |
| 8196 | |
| 8197 /** | |
| 8198 * A concrete implementation of a [MethodElement]. | |
| 8199 */ | |
| 8200 class MethodElementImpl extends ExecutableElementImpl implements MethodElement { | |
| 8201 /** | |
| 8202 * An empty list of method elements. | |
| 8203 */ | |
| 8204 @deprecated // Use MethodElement.EMPTY_LIST | |
| 8205 static const List<MethodElement> EMPTY_ARRAY = const <MethodElement>[]; | |
| 8206 | |
| 8207 /** | |
| 8208 * Initialize a newly created method element to have the given [name] at the | |
| 8209 * given [offset]. | |
| 8210 */ | |
| 8211 MethodElementImpl(String name, int offset) : super(name, offset); | |
| 8212 | |
| 8213 /** | |
| 8214 * Initialize a newly created method element to have the given [name]. | |
| 8215 */ | |
| 8216 MethodElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 8217 | |
| 8218 /** | |
| 8219 * Set whether this method is abstract. | |
| 8220 */ | |
| 8221 void set abstract(bool isAbstract) { | |
| 8222 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 8223 } | |
| 8224 | |
| 8225 @override | |
| 8226 String get displayName { | |
| 8227 String displayName = super.displayName; | |
| 8228 if ("unary-" == displayName) { | |
| 8229 return "-"; | |
| 8230 } | |
| 8231 return displayName; | |
| 8232 } | |
| 8233 | |
| 8234 @override | |
| 8235 ClassElement get enclosingElement => super.enclosingElement as ClassElement; | |
| 8236 | |
| 8237 @override | |
| 8238 bool get isOperator { | |
| 8239 String name = displayName; | |
| 8240 if (name.isEmpty) { | |
| 8241 return false; | |
| 8242 } | |
| 8243 int first = name.codeUnitAt(0); | |
| 8244 return !((0x61 <= first && first <= 0x7A) || | |
| 8245 (0x41 <= first && first <= 0x5A) || | |
| 8246 first == 0x5F || | |
| 8247 first == 0x24); | |
| 8248 } | |
| 8249 | |
| 8250 @override | |
| 8251 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 8252 | |
| 8253 @override | |
| 8254 ElementKind get kind => ElementKind.METHOD; | |
| 8255 | |
| 8256 @override | |
| 8257 String get name { | |
| 8258 String name = super.name; | |
| 8259 if (isOperator && name == "-") { | |
| 8260 if (parameters.length == 0) { | |
| 8261 return "unary-"; | |
| 8262 } | |
| 8263 } | |
| 8264 return super.name; | |
| 8265 } | |
| 8266 | |
| 8267 /** | |
| 8268 * Set whether this method is static. | |
| 8269 */ | |
| 8270 void set static(bool isStatic) { | |
| 8271 setModifier(Modifier.STATIC, isStatic); | |
| 8272 } | |
| 8273 | |
| 8274 @override | |
| 8275 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); | |
| 8276 | |
| 8277 @override | |
| 8278 void appendTo(StringBuffer buffer) { | |
| 8279 buffer.write(displayName); | |
| 8280 super.appendTo(buffer); | |
| 8281 } | |
| 8282 | |
| 8283 @override | |
| 8284 MethodDeclaration computeNode() => | |
| 8285 getNodeMatching((node) => node is MethodDeclaration); | |
| 8286 } | |
| 8287 | |
| 8288 /** | |
| 8289 * A method element defined in a parameterized type where the values of the type | |
| 8290 * parameters are known. | |
| 8291 */ | |
| 8292 class MethodMember extends ExecutableMember implements MethodElement { | |
| 8293 /** | |
| 8294 * Initialize a newly created element to represent a constructor, based on the | |
| 8295 * [baseElement], defined by the [definingType]. | |
| 8296 */ | |
| 8297 MethodMember(MethodElement baseElement, InterfaceType definingType) | |
| 8298 : super(baseElement, definingType); | |
| 8299 | |
| 8300 @override | |
| 8301 MethodElement get baseElement => super.baseElement as MethodElement; | |
| 8302 | |
| 8303 @override | |
| 8304 ClassElement get enclosingElement => baseElement.enclosingElement; | |
| 8305 | |
| 8306 @override | |
| 8307 accept(ElementVisitor visitor) => visitor.visitMethodElement(this); | |
| 8308 | |
| 8309 @override | |
| 8310 MethodDeclaration computeNode() => baseElement.computeNode(); | |
| 8311 | |
| 8312 @override | |
| 8313 String toString() { | |
| 8314 MethodElement baseElement = this.baseElement; | |
| 8315 List<ParameterElement> parameters = this.parameters; | |
| 8316 FunctionType type = this.type; | |
| 8317 StringBuffer buffer = new StringBuffer(); | |
| 8318 buffer.write(baseElement.enclosingElement.displayName); | |
| 8319 buffer.write("."); | |
| 8320 buffer.write(baseElement.displayName); | |
| 8321 buffer.write("("); | |
| 8322 int parameterCount = parameters.length; | |
| 8323 for (int i = 0; i < parameterCount; i++) { | |
| 8324 if (i > 0) { | |
| 8325 buffer.write(", "); | |
| 8326 } | |
| 8327 buffer.write(parameters[i]); | |
| 8328 } | |
| 8329 buffer.write(")"); | |
| 8330 if (type != null) { | |
| 8331 buffer.write(Element.RIGHT_ARROW); | |
| 8332 buffer.write(type.returnType); | |
| 8333 } | |
| 8334 return buffer.toString(); | |
| 8335 } | |
| 8336 | |
| 8337 /** | |
| 8338 * If the given [method]'s type is different when any type parameters from the | |
| 8339 * defining type's declaration are replaced with the actual type arguments | |
| 8340 * from the [definingType], create a method member representing the given | |
| 8341 * method. Return the member that was created, or the base method if no member | |
| 8342 * was created. | |
| 8343 */ | |
| 8344 static MethodElement from(MethodElement method, InterfaceType definingType) { | |
| 8345 if (method == null || definingType.typeArguments.length == 0) { | |
| 8346 return method; | |
| 8347 } | |
| 8348 FunctionType baseType = method.type; | |
| 8349 List<DartType> argumentTypes = definingType.typeArguments; | |
| 8350 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 8351 FunctionType substitutedType = | |
| 8352 baseType.substitute2(argumentTypes, parameterTypes); | |
| 8353 if (baseType == substitutedType) { | |
| 8354 return method; | |
| 8355 } | |
| 8356 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 8357 // instance. It would use more memory but speed up some operations. | |
| 8358 // We need to see how often the type is being re-computed. | |
| 8359 return new MethodMember(method, definingType); | |
| 8360 } | |
| 8361 } | |
| 8362 | |
| 8363 /** | |
| 8364 * The enumeration `Modifier` defines constants for all of the modifiers defined | |
| 8365 * by the Dart language and for a few additional flags that are useful. | |
| 8366 */ | |
| 8367 class Modifier extends Enum<Modifier> { | |
| 8368 /** | |
| 8369 * Indicates that the modifier 'abstract' was applied to the element. | |
| 8370 */ | |
| 8371 static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0); | |
| 8372 | |
| 8373 /** | |
| 8374 * Indicates that an executable element has a body marked as being | |
| 8375 * asynchronous. | |
| 8376 */ | |
| 8377 static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1); | |
| 8378 | |
| 8379 /** | |
| 8380 * Indicates that the modifier 'const' was applied to the element. | |
| 8381 */ | |
| 8382 static const Modifier CONST = const Modifier('CONST', 2); | |
| 8383 | |
| 8384 /** | |
| 8385 * Indicates that the import element represents a deferred library. | |
| 8386 */ | |
| 8387 static const Modifier DEFERRED = const Modifier('DEFERRED', 3); | |
| 8388 | |
| 8389 /** | |
| 8390 * Indicates that a class element was defined by an enum declaration. | |
| 8391 */ | |
| 8392 static const Modifier ENUM = const Modifier('ENUM', 4); | |
| 8393 | |
| 8394 /** | |
| 8395 * Indicates that a class element was defined by an enum declaration. | |
| 8396 */ | |
| 8397 static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5); | |
| 8398 | |
| 8399 /** | |
| 8400 * Indicates that the modifier 'factory' was applied to the element. | |
| 8401 */ | |
| 8402 static const Modifier FACTORY = const Modifier('FACTORY', 6); | |
| 8403 | |
| 8404 /** | |
| 8405 * Indicates that the modifier 'final' was applied to the element. | |
| 8406 */ | |
| 8407 static const Modifier FINAL = const Modifier('FINAL', 7); | |
| 8408 | |
| 8409 /** | |
| 8410 * Indicates that an executable element has a body marked as being a | |
| 8411 * generator. | |
| 8412 */ | |
| 8413 static const Modifier GENERATOR = const Modifier('GENERATOR', 8); | |
| 8414 | |
| 8415 /** | |
| 8416 * Indicates that the pseudo-modifier 'get' was applied to the element. | |
| 8417 */ | |
| 8418 static const Modifier GETTER = const Modifier('GETTER', 9); | |
| 8419 | |
| 8420 /** | |
| 8421 * A flag used for libraries indicating that the defining compilation unit | |
| 8422 * contains at least one import directive whose URI uses the "dart-ext" | |
| 8423 * scheme. | |
| 8424 */ | |
| 8425 static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10); | |
| 8426 | |
| 8427 /** | |
| 8428 * Indicates that the associated element did not have an explicit type | |
| 8429 * associated with it. If the element is an [ExecutableElement], then the | |
| 8430 * type being referred to is the return type. | |
| 8431 */ | |
| 8432 static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11); | |
| 8433 | |
| 8434 /** | |
| 8435 * Indicates that a class can validly be used as a mixin. | |
| 8436 */ | |
| 8437 static const Modifier MIXIN = const Modifier('MIXIN', 12); | |
| 8438 | |
| 8439 /** | |
| 8440 * Indicates that a class is a mixin application. | |
| 8441 */ | |
| 8442 static const Modifier MIXIN_APPLICATION = | |
| 8443 const Modifier('MIXIN_APPLICATION', 13); | |
| 8444 | |
| 8445 /** | |
| 8446 * Indicates that the value of a parameter or local variable might be mutated | |
| 8447 * within the context. | |
| 8448 */ | |
| 8449 static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT = | |
| 8450 const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 14); | |
| 8451 | |
| 8452 /** | |
| 8453 * Indicates that the value of a parameter or local variable might be mutated | |
| 8454 * within the scope. | |
| 8455 */ | |
| 8456 static const Modifier POTENTIALLY_MUTATED_IN_SCOPE = | |
| 8457 const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 15); | |
| 8458 | |
| 8459 /** | |
| 8460 * Indicates that a class contains an explicit reference to 'super'. | |
| 8461 */ | |
| 8462 static const Modifier REFERENCES_SUPER = | |
| 8463 const Modifier('REFERENCES_SUPER', 16); | |
| 8464 | |
| 8465 /** | |
| 8466 * Indicates that the pseudo-modifier 'set' was applied to the element. | |
| 8467 */ | |
| 8468 static const Modifier SETTER = const Modifier('SETTER', 17); | |
| 8469 | |
| 8470 /** | |
| 8471 * Indicates that the modifier 'static' was applied to the element. | |
| 8472 */ | |
| 8473 static const Modifier STATIC = const Modifier('STATIC', 18); | |
| 8474 | |
| 8475 /** | |
| 8476 * Indicates that the element does not appear in the source code but was | |
| 8477 * implicitly created. For example, if a class does not define any | |
| 8478 * constructors, an implicit zero-argument constructor will be created and it | |
| 8479 * will be marked as being synthetic. | |
| 8480 */ | |
| 8481 static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 19); | |
| 8482 | |
| 8483 static const List<Modifier> values = const [ | |
| 8484 ABSTRACT, | |
| 8485 ASYNCHRONOUS, | |
| 8486 CONST, | |
| 8487 DEFERRED, | |
| 8488 ENUM, | |
| 8489 EXTERNAL, | |
| 8490 FACTORY, | |
| 8491 FINAL, | |
| 8492 GENERATOR, | |
| 8493 GETTER, | |
| 8494 HAS_EXT_URI, | |
| 8495 IMPLICIT_TYPE, | |
| 8496 MIXIN, | |
| 8497 MIXIN_APPLICATION, | |
| 8498 POTENTIALLY_MUTATED_IN_CONTEXT, | |
| 8499 POTENTIALLY_MUTATED_IN_SCOPE, | |
| 8500 REFERENCES_SUPER, | |
| 8501 SETTER, | |
| 8502 STATIC, | |
| 8503 SYNTHETIC | |
| 8504 ]; | |
| 8505 | |
| 8506 const Modifier(String name, int ordinal) : super(name, ordinal); | |
| 8507 } | |
| 8508 | |
| 8509 /** | |
| 8510 * A pseudo-element that represents multiple elements defined within a single | |
| 8511 * scope that have the same name. This situation is not allowed by the language, | |
| 8512 * so objects implementing this interface always represent an error. As a | |
| 8513 * result, most of the normal operations on elements do not make sense and will | |
| 8514 * return useless results. | |
| 8515 */ | |
| 8516 abstract class MultiplyDefinedElement implements Element { | |
| 8517 /** | |
| 8518 * Return a list containing all of the elements that were defined within the | |
| 8519 * scope to have the same name. | |
| 8520 */ | |
| 8521 List<Element> get conflictingElements; | |
| 8522 | |
| 8523 /** | |
| 8524 * Return the type of this element as the dynamic type. | |
| 8525 */ | |
| 8526 DartType get type; | |
| 8527 } | |
| 8528 | |
| 8529 /** | |
| 8530 * A concrete implementation of a [MultiplyDefinedElement]. | |
| 8531 */ | |
| 8532 class MultiplyDefinedElementImpl implements MultiplyDefinedElement { | |
| 8533 /** | |
| 8534 * The unique integer identifier of this element. | |
| 8535 */ | |
| 8536 final int id = ElementImpl._NEXT_ID++; | |
| 8537 | |
| 8538 /** | |
| 8539 * The analysis context in which the multiply defined elements are defined. | |
| 8540 */ | |
| 8541 final AnalysisContext context; | |
| 8542 | |
| 8543 /** | |
| 8544 * The name of the conflicting elements. | |
| 8545 */ | |
| 8546 String _name; | |
| 8547 | |
| 8548 /** | |
| 8549 * A list containing all of the elements that conflict. | |
| 8550 */ | |
| 8551 final List<Element> conflictingElements; | |
| 8552 | |
| 8553 /** | |
| 8554 * Initialize a newly created element in the given [context] to represent a | |
| 8555 * list of [conflictingElements]. | |
| 8556 */ | |
| 8557 MultiplyDefinedElementImpl(this.context, this.conflictingElements) { | |
| 8558 _name = conflictingElements[0].name; | |
| 8559 } | |
| 8560 | |
| 8561 @override | |
| 8562 String get displayName => _name; | |
| 8563 | |
| 8564 @override | |
| 8565 SourceRange get docRange => null; | |
| 8566 | |
| 8567 @override | |
| 8568 Element get enclosingElement => null; | |
| 8569 | |
| 8570 @override | |
| 8571 bool get isDeprecated => false; | |
| 8572 | |
| 8573 @override | |
| 8574 bool get isOverride => false; | |
| 8575 | |
| 8576 @override | |
| 8577 bool get isPrivate { | |
| 8578 String name = displayName; | |
| 8579 if (name == null) { | |
| 8580 return false; | |
| 8581 } | |
| 8582 return Identifier.isPrivateName(name); | |
| 8583 } | |
| 8584 | |
| 8585 @override | |
| 8586 bool get isPublic => !isPrivate; | |
| 8587 | |
| 8588 @override | |
| 8589 bool get isSynthetic => true; | |
| 8590 | |
| 8591 @override | |
| 8592 ElementKind get kind => ElementKind.ERROR; | |
| 8593 | |
| 8594 @override | |
| 8595 LibraryElement get library => null; | |
| 8596 | |
| 8597 @override | |
| 8598 ElementLocation get location => null; | |
| 8599 | |
| 8600 @override | |
| 8601 List<ElementAnnotation> get metadata => ElementAnnotation.EMPTY_LIST; | |
| 8602 | |
| 8603 @override | |
| 8604 String get name => _name; | |
| 8605 | |
| 8606 @override | |
| 8607 int get nameLength => displayName != null ? displayName.length : 0; | |
| 8608 | |
| 8609 @override | |
| 8610 int get nameOffset => -1; | |
| 8611 | |
| 8612 @deprecated | |
| 8613 @override | |
| 8614 AstNode get node => null; | |
| 8615 | |
| 8616 @override | |
| 8617 Source get source => null; | |
| 8618 | |
| 8619 @override | |
| 8620 DartType get type => DynamicTypeImpl.instance; | |
| 8621 | |
| 8622 @override | |
| 8623 CompilationUnit get unit => null; | |
| 8624 | |
| 8625 @override | |
| 8626 accept(ElementVisitor visitor) => visitor.visitMultiplyDefinedElement(this); | |
| 8627 | |
| 8628 @override | |
| 8629 String computeDocumentationComment() => null; | |
| 8630 | |
| 8631 @override | |
| 8632 AstNode computeNode() => null; | |
| 8633 | |
| 8634 @override | |
| 8635 Element getAncestor(Predicate<Element> predicate) => null; | |
| 8636 | |
| 8637 @override | |
| 8638 String getExtendedDisplayName(String shortName) { | |
| 8639 if (shortName != null) { | |
| 8640 return shortName; | |
| 8641 } | |
| 8642 return displayName; | |
| 8643 } | |
| 8644 | |
| 8645 @override | |
| 8646 bool isAccessibleIn(LibraryElement library) { | |
| 8647 for (Element element in conflictingElements) { | |
| 8648 if (element.isAccessibleIn(library)) { | |
| 8649 return true; | |
| 8650 } | |
| 8651 } | |
| 8652 return false; | |
| 8653 } | |
| 8654 | |
| 8655 @override | |
| 8656 String toString() { | |
| 8657 StringBuffer buffer = new StringBuffer(); | |
| 8658 buffer.write("["); | |
| 8659 int count = conflictingElements.length; | |
| 8660 for (int i = 0; i < count; i++) { | |
| 8661 if (i > 0) { | |
| 8662 buffer.write(", "); | |
| 8663 } | |
| 8664 (conflictingElements[i] as ElementImpl).appendTo(buffer); | |
| 8665 } | |
| 8666 buffer.write("]"); | |
| 8667 return buffer.toString(); | |
| 8668 } | |
| 8669 | |
| 8670 @override | |
| 8671 void visitChildren(ElementVisitor visitor) { | |
| 8672 // There are no children to visit | |
| 8673 } | |
| 8674 | |
| 8675 /** | |
| 8676 * Return an element in the given [context] that represents the fact that the | |
| 8677 * [firstElement] and [secondElement] conflict. (If the elements are the same, | |
| 8678 * then one of the two will be returned directly.) | |
| 8679 */ | |
| 8680 static Element fromElements( | |
| 8681 AnalysisContext context, Element firstElement, Element secondElement) { | |
| 8682 List<Element> conflictingElements = | |
| 8683 _computeConflictingElements(firstElement, secondElement); | |
| 8684 int length = conflictingElements.length; | |
| 8685 if (length == 0) { | |
| 8686 return null; | |
| 8687 } else if (length == 1) { | |
| 8688 return conflictingElements[0]; | |
| 8689 } | |
| 8690 return new MultiplyDefinedElementImpl(context, conflictingElements); | |
| 8691 } | |
| 8692 | |
| 8693 /** | |
| 8694 * Add the given [element] to the list of [elements]. If the element is a | |
| 8695 * multiply-defined element, add all of the conflicting elements that it | |
| 8696 * represents. | |
| 8697 */ | |
| 8698 static void _add(HashSet<Element> elements, Element element) { | |
| 8699 if (element is MultiplyDefinedElementImpl) { | |
| 8700 for (Element conflictingElement in element.conflictingElements) { | |
| 8701 elements.add(conflictingElement); | |
| 8702 } | |
| 8703 } else { | |
| 8704 elements.add(element); | |
| 8705 } | |
| 8706 } | |
| 8707 | |
| 8708 /** | |
| 8709 * Use the given elements to construct a list of conflicting elements. If | |
| 8710 * either the [firstElement] or [secondElement] are multiply-defined elements | |
| 8711 * then the conflicting elements they represent will be included in the array. | |
| 8712 * Otherwise, the element itself will be included. | |
| 8713 */ | |
| 8714 static List<Element> _computeConflictingElements( | |
| 8715 Element firstElement, Element secondElement) { | |
| 8716 HashSet<Element> elements = new HashSet<Element>(); | |
| 8717 _add(elements, firstElement); | |
| 8718 _add(elements, secondElement); | |
| 8719 return new List.from(elements); | |
| 8720 } | |
| 8721 } | |
| 8722 | |
| 8723 /** | |
| 8724 * An [ExecutableElement], with the additional information of a list of | |
| 8725 * [ExecutableElement]s from which this element was composed. | |
| 8726 */ | |
| 8727 abstract class MultiplyInheritedExecutableElement implements ExecutableElement { | |
| 8728 /** | |
| 8729 * Return a list containing all of the executable elements defined within this | |
| 8730 * executable element. | |
| 8731 */ | |
| 8732 List<ExecutableElement> get inheritedElements; | |
| 8733 } | |
| 8734 | |
| 8735 /** | |
| 8736 * A [MethodElementImpl], with the additional information of a list of | |
| 8737 * [ExecutableElement]s from which this element was composed. | |
| 8738 */ | |
| 8739 class MultiplyInheritedMethodElementImpl extends MethodElementImpl | |
| 8740 implements MultiplyInheritedExecutableElement { | |
| 8741 /** | |
| 8742 * A list the array of executable elements that were used to compose this | |
| 8743 * element. | |
| 8744 */ | |
| 8745 List<ExecutableElement> _elements = MethodElement.EMPTY_LIST; | |
| 8746 | |
| 8747 MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) { | |
| 8748 synthetic = true; | |
| 8749 } | |
| 8750 | |
| 8751 @override | |
| 8752 List<ExecutableElement> get inheritedElements => _elements; | |
| 8753 | |
| 8754 void set inheritedElements(List<ExecutableElement> elements) { | |
| 8755 this._elements = elements; | |
| 8756 } | |
| 8757 } | |
| 8758 | |
| 8759 /** | |
| 8760 * A [PropertyAccessorElementImpl], with the additional information of a list of | |
| 8761 * [ExecutableElement]s from which this element was composed. | |
| 8762 */ | |
| 8763 class MultiplyInheritedPropertyAccessorElementImpl | |
| 8764 extends PropertyAccessorElementImpl | |
| 8765 implements MultiplyInheritedExecutableElement { | |
| 8766 /** | |
| 8767 * A list the array of executable elements that were used to compose this | |
| 8768 * element. | |
| 8769 */ | |
| 8770 List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST; | |
| 8771 | |
| 8772 MultiplyInheritedPropertyAccessorElementImpl(Identifier name) | |
| 8773 : super.forNode(name) { | |
| 8774 synthetic = true; | |
| 8775 } | |
| 8776 | |
| 8777 @override | |
| 8778 List<ExecutableElement> get inheritedElements => _elements; | |
| 8779 | |
| 8780 void set inheritedElements(List<ExecutableElement> elements) { | |
| 8781 this._elements = elements; | |
| 8782 } | |
| 8783 } | |
| 8784 | |
| 8785 /** | |
| 8786 * An object that controls how namespaces are combined. | |
| 8787 */ | |
| 8788 abstract class NamespaceCombinator { | |
| 8789 /** | |
| 8790 * An empty list of namespace combinators. | |
| 8791 */ | |
| 8792 @deprecated // Use NamespaceCombinator.EMPTY_LIST | |
| 8793 static const List<NamespaceCombinator> EMPTY_ARRAY = | |
| 8794 const <NamespaceCombinator>[]; | |
| 8795 | |
| 8796 /** | |
| 8797 * An empty list of namespace combinators. | |
| 8798 */ | |
| 8799 static const List<NamespaceCombinator> EMPTY_LIST = | |
| 8800 const <NamespaceCombinator>[]; | |
| 8801 } | |
| 8802 | |
| 8803 /** | |
| 8804 * A parameter defined within an executable element. | |
| 8805 */ | |
| 8806 abstract class ParameterElement | |
| 8807 implements LocalElement, VariableElement, ConstantEvaluationTarget { | |
| 8808 /** | |
| 8809 * An empty list of parameter elements. | |
| 8810 */ | |
| 8811 static const List<ParameterElement> EMPTY_LIST = const <ParameterElement>[]; | |
| 8812 | |
| 8813 /** | |
| 8814 * Return the Dart code of the default value, or `null` if no default value. | |
| 8815 */ | |
| 8816 String get defaultValueCode; | |
| 8817 | |
| 8818 /** | |
| 8819 * Return `true` if this parameter is an initializing formal parameter. | |
| 8820 */ | |
| 8821 bool get isInitializingFormal; | |
| 8822 | |
| 8823 /** | |
| 8824 * Return the kind of this parameter. | |
| 8825 */ | |
| 8826 ParameterKind get parameterKind; | |
| 8827 | |
| 8828 /** | |
| 8829 * Return a list containing all of the parameters defined by this parameter. | |
| 8830 * A parameter will only define other parameters if it is a function typed | |
| 8831 * parameter. | |
| 8832 */ | |
| 8833 List<ParameterElement> get parameters; | |
| 8834 | |
| 8835 /** | |
| 8836 * Return a list containing all of the type parameters defined by this | |
| 8837 * parameter. A parameter will only define other parameters if it is a | |
| 8838 * function typed parameter. | |
| 8839 */ | |
| 8840 List<TypeParameterElement> get typeParameters; | |
| 8841 | |
| 8842 /** | |
| 8843 * Append the type, name and possibly the default value of this parameter to | |
| 8844 * the given [buffer]. | |
| 8845 */ | |
| 8846 void appendToWithoutDelimiters(StringBuffer buffer); | |
| 8847 | |
| 8848 @override | |
| 8849 FormalParameter computeNode(); | |
| 8850 } | |
| 8851 | |
| 8852 /** | |
| 8853 * A concrete implementation of a [ParameterElement]. | |
| 8854 */ | |
| 8855 class ParameterElementImpl extends VariableElementImpl | |
| 8856 with ParameterElementMixin, PotentiallyConstVariableElement | |
| 8857 implements ParameterElement { | |
| 8858 /** | |
| 8859 * An empty list of parameter elements. | |
| 8860 */ | |
| 8861 @deprecated // Use ParameterElement.EMPTY_LIST | |
| 8862 static const List<ParameterElement> EMPTY_ARRAY = const <ParameterElement>[]; | |
| 8863 | |
| 8864 /** | |
| 8865 * A list containing all of the parameters defined by this parameter element. | |
| 8866 * There will only be parameters if this parameter is a function typed | |
| 8867 * parameter. | |
| 8868 */ | |
| 8869 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; | |
| 8870 | |
| 8871 /** | |
| 8872 * A list containing all of the type parameters defined for this parameter | |
| 8873 * element. There will only be parameters if this parameter is a function | |
| 8874 * typed parameter. | |
| 8875 */ | |
| 8876 List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST; | |
| 8877 | |
| 8878 /** | |
| 8879 * The kind of this parameter. | |
| 8880 */ | |
| 8881 ParameterKind parameterKind; | |
| 8882 | |
| 8883 /** | |
| 8884 * The Dart code of the default value. | |
| 8885 */ | |
| 8886 String _defaultValueCode; | |
| 8887 | |
| 8888 /** | |
| 8889 * The offset to the beginning of the visible range for this element. | |
| 8890 */ | |
| 8891 int _visibleRangeOffset = 0; | |
| 8892 | |
| 8893 /** | |
| 8894 * The length of the visible range for this element, or `-1` if this element | |
| 8895 * does not have a visible range. | |
| 8896 */ | |
| 8897 int _visibleRangeLength = -1; | |
| 8898 | |
| 8899 /** | |
| 8900 * Initialize a newly created parameter element to have the given [name] and | |
| 8901 * [offset]. | |
| 8902 */ | |
| 8903 ParameterElementImpl(String name, int nameOffset) : super(name, nameOffset); | |
| 8904 | |
| 8905 /** | |
| 8906 * Initialize a newly created parameter element to have the given [name]. | |
| 8907 */ | |
| 8908 ParameterElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 8909 | |
| 8910 @override | |
| 8911 String get defaultValueCode => _defaultValueCode; | |
| 8912 | |
| 8913 /** | |
| 8914 * Set Dart code of the default value. | |
| 8915 */ | |
| 8916 void set defaultValueCode(String defaultValueCode) { | |
| 8917 this._defaultValueCode = StringUtilities.intern(defaultValueCode); | |
| 8918 } | |
| 8919 | |
| 8920 @override | |
| 8921 bool get isInitializingFormal => false; | |
| 8922 | |
| 8923 @override | |
| 8924 bool get isPotentiallyMutatedInClosure => | |
| 8925 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT); | |
| 8926 | |
| 8927 @override | |
| 8928 bool get isPotentiallyMutatedInScope => | |
| 8929 hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE); | |
| 8930 | |
| 8931 @override | |
| 8932 ElementKind get kind => ElementKind.PARAMETER; | |
| 8933 | |
| 8934 @override | |
| 8935 List<ParameterElement> get parameters => _parameters; | |
| 8936 | |
| 8937 /** | |
| 8938 * Set the parameters defined by this executable element to the given | |
| 8939 * [parameters]. | |
| 8940 */ | |
| 8941 void set parameters(List<ParameterElement> parameters) { | |
| 8942 for (ParameterElement parameter in parameters) { | |
| 8943 (parameter as ParameterElementImpl).enclosingElement = this; | |
| 8944 } | |
| 8945 this._parameters = parameters; | |
| 8946 } | |
| 8947 | |
| 8948 @override | |
| 8949 List<TypeParameterElement> get typeParameters => _typeParameters; | |
| 8950 | |
| 8951 /** | |
| 8952 * Set the type parameters defined by this parameter element to the given | |
| 8953 * [typeParameters]. | |
| 8954 */ | |
| 8955 void set typeParameters(List<TypeParameterElement> typeParameters) { | |
| 8956 for (TypeParameterElement parameter in typeParameters) { | |
| 8957 (parameter as TypeParameterElementImpl).enclosingElement = this; | |
| 8958 } | |
| 8959 this._typeParameters = typeParameters; | |
| 8960 } | |
| 8961 | |
| 8962 @override | |
| 8963 SourceRange get visibleRange { | |
| 8964 if (_visibleRangeLength < 0) { | |
| 8965 return null; | |
| 8966 } | |
| 8967 return new SourceRange(_visibleRangeOffset, _visibleRangeLength); | |
| 8968 } | |
| 8969 | |
| 8970 @override | |
| 8971 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); | |
| 8972 | |
| 8973 @override | |
| 8974 void appendTo(StringBuffer buffer) { | |
| 8975 String left = ""; | |
| 8976 String right = ""; | |
| 8977 while (true) { | |
| 8978 if (parameterKind == ParameterKind.NAMED) { | |
| 8979 left = "{"; | |
| 8980 right = "}"; | |
| 8981 } else if (parameterKind == ParameterKind.POSITIONAL) { | |
| 8982 left = "["; | |
| 8983 right = "]"; | |
| 8984 } else if (parameterKind == ParameterKind.REQUIRED) {} | |
| 8985 break; | |
| 8986 } | |
| 8987 buffer.write(left); | |
| 8988 appendToWithoutDelimiters(buffer); | |
| 8989 buffer.write(right); | |
| 8990 } | |
| 8991 | |
| 8992 @override | |
| 8993 FormalParameter computeNode() => | |
| 8994 getNodeMatching((node) => node is FormalParameter); | |
| 8995 | |
| 8996 @override | |
| 8997 ElementImpl getChild(String identifier) { | |
| 8998 for (ParameterElement parameter in _parameters) { | |
| 8999 if ((parameter as ParameterElementImpl).identifier == identifier) { | |
| 9000 return parameter as ParameterElementImpl; | |
| 9001 } | |
| 9002 } | |
| 9003 return null; | |
| 9004 } | |
| 9005 | |
| 9006 /** | |
| 9007 * Specifies that this variable is potentially mutated somewhere in closure. | |
| 9008 */ | |
| 9009 void markPotentiallyMutatedInClosure() { | |
| 9010 setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true); | |
| 9011 } | |
| 9012 | |
| 9013 /** | |
| 9014 * Specifies that this variable is potentially mutated somewhere in its scope. | |
| 9015 */ | |
| 9016 void markPotentiallyMutatedInScope() { | |
| 9017 setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true); | |
| 9018 } | |
| 9019 | |
| 9020 /** | |
| 9021 * Set the visible range for this element to the range starting at the given | |
| 9022 * [offset] with the given [length]. | |
| 9023 */ | |
| 9024 void setVisibleRange(int offset, int length) { | |
| 9025 _visibleRangeOffset = offset; | |
| 9026 _visibleRangeLength = length; | |
| 9027 } | |
| 9028 | |
| 9029 @override | |
| 9030 void visitChildren(ElementVisitor visitor) { | |
| 9031 super.visitChildren(visitor); | |
| 9032 safelyVisitChildren(_parameters, visitor); | |
| 9033 } | |
| 9034 } | |
| 9035 | |
| 9036 /** | |
| 9037 * A mixin that provides a common implementation for methods defined in | |
| 9038 * [ParameterElement]. | |
| 9039 */ | |
| 9040 abstract class ParameterElementMixin implements ParameterElement { | |
| 9041 @override | |
| 9042 void appendToWithoutDelimiters(StringBuffer buffer) { | |
| 9043 buffer.write(type); | |
| 9044 buffer.write(" "); | |
| 9045 buffer.write(displayName); | |
| 9046 if (defaultValueCode != null) { | |
| 9047 if (parameterKind == ParameterKind.NAMED) { | |
| 9048 buffer.write(": "); | |
| 9049 } | |
| 9050 if (parameterKind == ParameterKind.POSITIONAL) { | |
| 9051 buffer.write(" = "); | |
| 9052 } | |
| 9053 buffer.write(defaultValueCode); | |
| 9054 } | |
| 9055 } | |
| 9056 } | |
| 9057 | |
| 9058 /** | |
| 9059 * A type with type parameters, such as a class or function type alias. | |
| 9060 */ | |
| 9061 abstract class ParameterizedType implements DartType { | |
| 9062 /** | |
| 9063 * Return a list containing the actual types of the type arguments. If this | |
| 9064 * type's element does not have type parameters, then the array should be | |
| 9065 * empty (although it is possible for type arguments to be erroneously | |
| 9066 * declared). If the element has type parameters and the actual type does not | |
| 9067 * explicitly include argument values, then the type "dynamic" will be | |
| 9068 * automatically provided. | |
| 9069 */ | |
| 9070 List<DartType> get typeArguments; | |
| 9071 | |
| 9072 /** | |
| 9073 * Return a list containing all of the type parameters declared for this type. | |
| 9074 */ | |
| 9075 List<TypeParameterElement> get typeParameters; | |
| 9076 } | |
| 9077 | |
| 9078 /** | |
| 9079 * A parameter element defined in a parameterized type where the values of the | |
| 9080 * type parameters are known. | |
| 9081 */ | |
| 9082 class ParameterMember extends VariableMember | |
| 9083 with ParameterElementMixin | |
| 9084 implements ParameterElement { | |
| 9085 /** | |
| 9086 * Initialize a newly created element to represent a constructor, based on the | |
| 9087 * [baseElement], defined by the [definingType]. | |
| 9088 */ | |
| 9089 ParameterMember(ParameterElement baseElement, ParameterizedType definingType) | |
| 9090 : super(baseElement, definingType); | |
| 9091 | |
| 9092 @override | |
| 9093 ParameterElement get baseElement => super.baseElement as ParameterElement; | |
| 9094 | |
| 9095 @override | |
| 9096 String get defaultValueCode => baseElement.defaultValueCode; | |
| 9097 | |
| 9098 @override | |
| 9099 Element get enclosingElement => baseElement.enclosingElement; | |
| 9100 | |
| 9101 @override | |
| 9102 bool get isInitializingFormal => baseElement.isInitializingFormal; | |
| 9103 | |
| 9104 @override | |
| 9105 ParameterKind get parameterKind => baseElement.parameterKind; | |
| 9106 | |
| 9107 @override | |
| 9108 List<ParameterElement> get parameters { | |
| 9109 List<ParameterElement> baseParameters = baseElement.parameters; | |
| 9110 int parameterCount = baseParameters.length; | |
| 9111 if (parameterCount == 0) { | |
| 9112 return baseParameters; | |
| 9113 } | |
| 9114 List<ParameterElement> parameterizedParameters = | |
| 9115 new List<ParameterElement>(parameterCount); | |
| 9116 for (int i = 0; i < parameterCount; i++) { | |
| 9117 parameterizedParameters[i] = | |
| 9118 ParameterMember.from(baseParameters[i], definingType); | |
| 9119 } | |
| 9120 return parameterizedParameters; | |
| 9121 } | |
| 9122 | |
| 9123 @override | |
| 9124 List<TypeParameterElement> get typeParameters => baseElement.typeParameters; | |
| 9125 | |
| 9126 @override | |
| 9127 SourceRange get visibleRange => baseElement.visibleRange; | |
| 9128 | |
| 9129 @override | |
| 9130 accept(ElementVisitor visitor) => visitor.visitParameterElement(this); | |
| 9131 | |
| 9132 @override | |
| 9133 FormalParameter computeNode() => baseElement.computeNode(); | |
| 9134 | |
| 9135 @override | |
| 9136 Element getAncestor(Predicate<Element> predicate) { | |
| 9137 Element element = baseElement.getAncestor(predicate); | |
| 9138 ParameterizedType definingType = this.definingType; | |
| 9139 if (definingType is InterfaceType) { | |
| 9140 InterfaceType definingInterfaceType = definingType; | |
| 9141 if (element is ConstructorElement) { | |
| 9142 return ConstructorMember.from(element, definingInterfaceType); | |
| 9143 } else if (element is MethodElement) { | |
| 9144 return MethodMember.from(element, definingInterfaceType); | |
| 9145 } else if (element is PropertyAccessorElement) { | |
| 9146 return PropertyAccessorMember.from(element, definingInterfaceType); | |
| 9147 } | |
| 9148 } | |
| 9149 return element; | |
| 9150 } | |
| 9151 | |
| 9152 @override | |
| 9153 String toString() { | |
| 9154 ParameterElement baseElement = this.baseElement; | |
| 9155 String left = ""; | |
| 9156 String right = ""; | |
| 9157 while (true) { | |
| 9158 if (baseElement.parameterKind == ParameterKind.NAMED) { | |
| 9159 left = "{"; | |
| 9160 right = "}"; | |
| 9161 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) { | |
| 9162 left = "["; | |
| 9163 right = "]"; | |
| 9164 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {} | |
| 9165 break; | |
| 9166 } | |
| 9167 return '$left$type ${baseElement.displayName}$right'; | |
| 9168 } | |
| 9169 | |
| 9170 @override | |
| 9171 void visitChildren(ElementVisitor visitor) { | |
| 9172 super.visitChildren(visitor); | |
| 9173 safelyVisitChildren(parameters, visitor); | |
| 9174 } | |
| 9175 | |
| 9176 /** | |
| 9177 * If the given [parameter]'s type is different when any type parameters from | |
| 9178 * the defining type's declaration are replaced with the actual type | |
| 9179 * arguments from the [definingType], create a parameter member representing | |
| 9180 * the given parameter. Return the member that was created, or the base | |
| 9181 * parameter if no member was created. | |
| 9182 */ | |
| 9183 static ParameterElement from( | |
| 9184 ParameterElement parameter, ParameterizedType definingType) { | |
| 9185 if (parameter == null || definingType.typeArguments.length == 0) { | |
| 9186 return parameter; | |
| 9187 } | |
| 9188 // Check if parameter type depends on defining type type arguments. | |
| 9189 // It is possible that we did not resolve field formal parameter yet, | |
| 9190 // so skip this check for it. | |
| 9191 bool isFieldFormal = parameter is FieldFormalParameterElement; | |
| 9192 if (!isFieldFormal) { | |
| 9193 DartType baseType = parameter.type; | |
| 9194 List<DartType> argumentTypes = definingType.typeArguments; | |
| 9195 List<DartType> parameterTypes = | |
| 9196 TypeParameterTypeImpl.getTypes(definingType.typeParameters); | |
| 9197 DartType substitutedType = | |
| 9198 baseType.substitute2(argumentTypes, parameterTypes); | |
| 9199 if (baseType == substitutedType) { | |
| 9200 return parameter; | |
| 9201 } | |
| 9202 } | |
| 9203 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 9204 // instance. It would use more memory but speed up some operations. | |
| 9205 // We need to see how often the type is being re-computed. | |
| 9206 if (isFieldFormal) { | |
| 9207 return new FieldFormalParameterMember( | |
| 9208 parameter as FieldFormalParameterElement, definingType); | |
| 9209 } | |
| 9210 return new ParameterMember(parameter, definingType); | |
| 9211 } | |
| 9212 } | |
| 9213 | |
| 9214 /** | |
| 9215 * Interface used by elements that might represent constant variables. | |
| 9216 * | |
| 9217 * This class may be used as a mixin in the case where [constInitializer] is | |
| 9218 * known to return null. | |
| 9219 * | |
| 9220 * This class is not intended to be part of the public API for analyzer. | |
| 9221 */ | |
| 9222 abstract class PotentiallyConstVariableElement | |
| 9223 implements VariableElementImpl, ConstantEvaluationTarget { | |
| 9224 /** | |
| 9225 * If this element represents a constant variable, and it has an initializer, | |
| 9226 * a copy of the initializer for the constant. Otherwise `null`. | |
| 9227 * | |
| 9228 * Note that in correct Dart code, all constant variables must have | |
| 9229 * initializers. However, analyzer also needs to handle incorrect Dart code, | |
| 9230 * in which case there might be some constant variables that lack | |
| 9231 * initializers. | |
| 9232 */ | |
| 9233 Expression get constantInitializer => null; | |
| 9234 } | |
| 9235 | |
| 9236 /** | |
| 9237 * A prefix used to import one or more libraries into another library. | |
| 9238 */ | |
| 9239 abstract class PrefixElement implements Element { | |
| 9240 /** | |
| 9241 * An empty list of prefix elements. | |
| 9242 */ | |
| 9243 static const List<PrefixElement> EMPTY_LIST = const <PrefixElement>[]; | |
| 9244 | |
| 9245 /** | |
| 9246 * Return the library into which other libraries are imported using this | |
| 9247 * prefix. | |
| 9248 */ | |
| 9249 @override | |
| 9250 LibraryElement get enclosingElement; | |
| 9251 | |
| 9252 /** | |
| 9253 * Return a list containing all of the libraries that are imported using this | |
| 9254 * prefix. | |
| 9255 */ | |
| 9256 List<LibraryElement> get importedLibraries; | |
| 9257 } | |
| 9258 | |
| 9259 /** | |
| 9260 * A concrete implementation of a [PrefixElement]. | |
| 9261 */ | |
| 9262 class PrefixElementImpl extends ElementImpl implements PrefixElement { | |
| 9263 /** | |
| 9264 * An empty list of prefix elements. | |
| 9265 */ | |
| 9266 @deprecated // Use PrefixElement.EMPTY_LIST | |
| 9267 static const List<PrefixElement> EMPTY_ARRAY = const <PrefixElement>[]; | |
| 9268 | |
| 9269 /** | |
| 9270 * A list containing all of the libraries that are imported using this prefix. | |
| 9271 */ | |
| 9272 List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST; | |
| 9273 | |
| 9274 /** | |
| 9275 * Initialize a newly created method element to have the given [name] and | |
| 9276 * [offset]. | |
| 9277 */ | |
| 9278 PrefixElementImpl(String name, int nameOffset) : super(name, nameOffset); | |
| 9279 | |
| 9280 /** | |
| 9281 * Initialize a newly created prefix element to have the given [name]. | |
| 9282 */ | |
| 9283 PrefixElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 9284 | |
| 9285 @override | |
| 9286 LibraryElement get enclosingElement => | |
| 9287 super.enclosingElement as LibraryElement; | |
| 9288 | |
| 9289 @override | |
| 9290 String get identifier => "_${super.identifier}"; | |
| 9291 | |
| 9292 @override | |
| 9293 List<LibraryElement> get importedLibraries => _importedLibraries; | |
| 9294 | |
| 9295 /** | |
| 9296 * Set the libraries that are imported using this prefix to the given | |
| 9297 * [libraries]. | |
| 9298 */ | |
| 9299 void set importedLibraries(List<LibraryElement> libraries) { | |
| 9300 for (LibraryElement library in libraries) { | |
| 9301 (library as LibraryElementImpl).enclosingElement = this; | |
| 9302 } | |
| 9303 _importedLibraries = libraries; | |
| 9304 } | |
| 9305 | |
| 9306 @override | |
| 9307 ElementKind get kind => ElementKind.PREFIX; | |
| 9308 | |
| 9309 @override | |
| 9310 accept(ElementVisitor visitor) => visitor.visitPrefixElement(this); | |
| 9311 | |
| 9312 @override | |
| 9313 void appendTo(StringBuffer buffer) { | |
| 9314 buffer.write("as "); | |
| 9315 super.appendTo(buffer); | |
| 9316 } | |
| 9317 } | |
| 9318 | |
| 9319 /** | |
| 9320 * A getter or a setter. Note that explicitly defined property accessors | |
| 9321 * implicitly define a synthetic field. Symmetrically, synthetic accessors are | |
| 9322 * implicitly created for explicitly defined fields. The following rules apply: | |
| 9323 * | |
| 9324 * * Every explicit field is represented by a non-synthetic [FieldElement]. | |
| 9325 * * Every explicit field induces a getter and possibly a setter, both of which | |
| 9326 * are represented by synthetic [PropertyAccessorElement]s. | |
| 9327 * * Every explicit getter or setter is represented by a non-synthetic | |
| 9328 * [PropertyAccessorElement]. | |
| 9329 * * Every explicit getter or setter (or pair thereof if they have the same | |
| 9330 * name) induces a field that is represented by a synthetic [FieldElement]. | |
| 9331 */ | |
| 9332 abstract class PropertyAccessorElement implements ExecutableElement { | |
| 9333 /** | |
| 9334 * An empty list of property accessor elements. | |
| 9335 */ | |
| 9336 static const List<PropertyAccessorElement> EMPTY_LIST = | |
| 9337 const <PropertyAccessorElement>[]; | |
| 9338 | |
| 9339 /** | |
| 9340 * Return the accessor representing the getter that corresponds to (has the | |
| 9341 * same name as) this setter, or `null` if this accessor is not a setter or if | |
| 9342 * there is no corresponding getter. | |
| 9343 */ | |
| 9344 PropertyAccessorElement get correspondingGetter; | |
| 9345 | |
| 9346 /** | |
| 9347 * Return the accessor representing the setter that corresponds to (has the | |
| 9348 * same name as) this getter, or `null` if this accessor is not a getter or if | |
| 9349 * there is no corresponding setter. | |
| 9350 */ | |
| 9351 PropertyAccessorElement get correspondingSetter; | |
| 9352 | |
| 9353 /** | |
| 9354 * Return `true` if this accessor represents a getter. | |
| 9355 */ | |
| 9356 bool get isGetter; | |
| 9357 | |
| 9358 /** | |
| 9359 * Return `true` if this accessor represents a setter. | |
| 9360 */ | |
| 9361 bool get isSetter; | |
| 9362 | |
| 9363 /** | |
| 9364 * Return the field or top-level variable associated with this accessor. If | |
| 9365 * this accessor was explicitly defined (is not synthetic) then the variable | |
| 9366 * associated with it will be synthetic. | |
| 9367 */ | |
| 9368 PropertyInducingElement get variable; | |
| 9369 } | |
| 9370 | |
| 9371 /** | |
| 9372 * A concrete implementation of a [PropertyAccessorElement]. | |
| 9373 */ | |
| 9374 class PropertyAccessorElementImpl extends ExecutableElementImpl | |
| 9375 implements PropertyAccessorElement { | |
| 9376 /** | |
| 9377 * An empty list of property accessor elements. | |
| 9378 */ | |
| 9379 @deprecated // Use PropertyAccessorElement.EMPTY_LIST | |
| 9380 static const List<PropertyAccessorElement> EMPTY_ARRAY = | |
| 9381 const <PropertyAccessorElement>[]; | |
| 9382 | |
| 9383 /** | |
| 9384 * The variable associated with this accessor. | |
| 9385 */ | |
| 9386 PropertyInducingElement variable; | |
| 9387 | |
| 9388 /** | |
| 9389 * Initialize a newly created property accessor element to have the given | |
| 9390 * [name]. | |
| 9391 */ | |
| 9392 PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 9393 | |
| 9394 /** | |
| 9395 * Initialize a newly created synthetic property accessor element to be | |
| 9396 * associated with the given [variable]. | |
| 9397 */ | |
| 9398 PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable) | |
| 9399 : super(variable.name, variable.nameOffset) { | |
| 9400 this.variable = variable; | |
| 9401 static = variable.isStatic; | |
| 9402 synthetic = true; | |
| 9403 } | |
| 9404 | |
| 9405 /** | |
| 9406 * Set whether this accessor is abstract. | |
| 9407 */ | |
| 9408 void set abstract(bool isAbstract) { | |
| 9409 setModifier(Modifier.ABSTRACT, isAbstract); | |
| 9410 } | |
| 9411 | |
| 9412 @override | |
| 9413 PropertyAccessorElement get correspondingGetter { | |
| 9414 if (isGetter || variable == null) { | |
| 9415 return null; | |
| 9416 } | |
| 9417 return variable.getter; | |
| 9418 } | |
| 9419 | |
| 9420 @override | |
| 9421 PropertyAccessorElement get correspondingSetter { | |
| 9422 if (isSetter || variable == null) { | |
| 9423 return null; | |
| 9424 } | |
| 9425 return variable.setter; | |
| 9426 } | |
| 9427 | |
| 9428 /** | |
| 9429 * Set whether this accessor is a getter. | |
| 9430 */ | |
| 9431 void set getter(bool isGetter) { | |
| 9432 setModifier(Modifier.GETTER, isGetter); | |
| 9433 } | |
| 9434 | |
| 9435 @override | |
| 9436 int get hashCode => JenkinsSmiHash.hash2(super.hashCode, isGetter ? 1 : 2); | |
| 9437 | |
| 9438 @override | |
| 9439 String get identifier { | |
| 9440 String name = displayName; | |
| 9441 String suffix = isGetter ? "?" : "="; | |
| 9442 return "$name$suffix"; | |
| 9443 } | |
| 9444 | |
| 9445 @override | |
| 9446 bool get isGetter => hasModifier(Modifier.GETTER); | |
| 9447 | |
| 9448 @override | |
| 9449 bool get isSetter => hasModifier(Modifier.SETTER); | |
| 9450 | |
| 9451 @override | |
| 9452 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 9453 | |
| 9454 @override | |
| 9455 ElementKind get kind { | |
| 9456 if (isGetter) { | |
| 9457 return ElementKind.GETTER; | |
| 9458 } | |
| 9459 return ElementKind.SETTER; | |
| 9460 } | |
| 9461 | |
| 9462 @override | |
| 9463 String get name { | |
| 9464 if (isSetter) { | |
| 9465 return "${super.name}="; | |
| 9466 } | |
| 9467 return super.name; | |
| 9468 } | |
| 9469 | |
| 9470 /** | |
| 9471 * Set whether this accessor is a setter. | |
| 9472 */ | |
| 9473 void set setter(bool isSetter) { | |
| 9474 setModifier(Modifier.SETTER, isSetter); | |
| 9475 } | |
| 9476 | |
| 9477 /** | |
| 9478 * Set whether this accessor is static. | |
| 9479 */ | |
| 9480 void set static(bool isStatic) { | |
| 9481 setModifier(Modifier.STATIC, isStatic); | |
| 9482 } | |
| 9483 | |
| 9484 @override | |
| 9485 bool operator ==(Object object) => super == object && | |
| 9486 isGetter == (object as PropertyAccessorElement).isGetter; | |
| 9487 | |
| 9488 @override | |
| 9489 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); | |
| 9490 | |
| 9491 @override | |
| 9492 void appendTo(StringBuffer buffer) { | |
| 9493 buffer.write(isGetter ? "get " : "set "); | |
| 9494 buffer.write(variable.displayName); | |
| 9495 super.appendTo(buffer); | |
| 9496 } | |
| 9497 | |
| 9498 @override | |
| 9499 AstNode computeNode() { | |
| 9500 if (isSynthetic) { | |
| 9501 return null; | |
| 9502 } | |
| 9503 if (enclosingElement is ClassElement) { | |
| 9504 return getNodeMatching((node) => node is MethodDeclaration); | |
| 9505 } | |
| 9506 if (enclosingElement is CompilationUnitElement) { | |
| 9507 return getNodeMatching((node) => node is FunctionDeclaration); | |
| 9508 } | |
| 9509 return null; | |
| 9510 } | |
| 9511 } | |
| 9512 | |
| 9513 /** | |
| 9514 * A property accessor element defined in a parameterized type where the values | |
| 9515 * of the type parameters are known. | |
| 9516 */ | |
| 9517 class PropertyAccessorMember extends ExecutableMember | |
| 9518 implements PropertyAccessorElement { | |
| 9519 /** | |
| 9520 * Initialize a newly created element to represent a constructor, based on the | |
| 9521 * [baseElement], defined by the [definingType]. | |
| 9522 */ | |
| 9523 PropertyAccessorMember( | |
| 9524 PropertyAccessorElement baseElement, InterfaceType definingType) | |
| 9525 : super(baseElement, definingType); | |
| 9526 | |
| 9527 @override | |
| 9528 PropertyAccessorElement get baseElement => | |
| 9529 super.baseElement as PropertyAccessorElement; | |
| 9530 | |
| 9531 @override | |
| 9532 PropertyAccessorElement get correspondingGetter => | |
| 9533 from(baseElement.correspondingGetter, definingType); | |
| 9534 | |
| 9535 @override | |
| 9536 PropertyAccessorElement get correspondingSetter => | |
| 9537 from(baseElement.correspondingSetter, definingType); | |
| 9538 | |
| 9539 @override | |
| 9540 InterfaceType get definingType => super.definingType as InterfaceType; | |
| 9541 | |
| 9542 @override | |
| 9543 Element get enclosingElement => baseElement.enclosingElement; | |
| 9544 | |
| 9545 @override | |
| 9546 bool get isGetter => baseElement.isGetter; | |
| 9547 | |
| 9548 @override | |
| 9549 bool get isSetter => baseElement.isSetter; | |
| 9550 | |
| 9551 @override | |
| 9552 PropertyInducingElement get variable { | |
| 9553 PropertyInducingElement variable = baseElement.variable; | |
| 9554 if (variable is FieldElement) { | |
| 9555 return FieldMember.from(variable, definingType); | |
| 9556 } | |
| 9557 return variable; | |
| 9558 } | |
| 9559 | |
| 9560 @override | |
| 9561 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this); | |
| 9562 | |
| 9563 @override | |
| 9564 String toString() { | |
| 9565 PropertyAccessorElement baseElement = this.baseElement; | |
| 9566 List<ParameterElement> parameters = this.parameters; | |
| 9567 FunctionType type = this.type; | |
| 9568 StringBuffer builder = new StringBuffer(); | |
| 9569 if (isGetter) { | |
| 9570 builder.write("get "); | |
| 9571 } else { | |
| 9572 builder.write("set "); | |
| 9573 } | |
| 9574 builder.write(baseElement.enclosingElement.displayName); | |
| 9575 builder.write("."); | |
| 9576 builder.write(baseElement.displayName); | |
| 9577 builder.write("("); | |
| 9578 int parameterCount = parameters.length; | |
| 9579 for (int i = 0; i < parameterCount; i++) { | |
| 9580 if (i > 0) { | |
| 9581 builder.write(", "); | |
| 9582 } | |
| 9583 builder.write(parameters[i]); | |
| 9584 } | |
| 9585 builder.write(")"); | |
| 9586 if (type != null) { | |
| 9587 builder.write(Element.RIGHT_ARROW); | |
| 9588 builder.write(type.returnType); | |
| 9589 } | |
| 9590 return builder.toString(); | |
| 9591 } | |
| 9592 | |
| 9593 /** | |
| 9594 * If the given [accessor]'s type is different when any type parameters from | |
| 9595 * the defining type's declaration are replaced with the actual type | |
| 9596 * arguments from the [definingType], create an accessor member representing | |
| 9597 * the given accessor. Return the member that was created, or the base | |
| 9598 * accessor if no member was created. | |
| 9599 */ | |
| 9600 static PropertyAccessorElement from( | |
| 9601 PropertyAccessorElement accessor, InterfaceType definingType) { | |
| 9602 if (!_isChangedByTypeSubstitution(accessor, definingType)) { | |
| 9603 return accessor; | |
| 9604 } | |
| 9605 // TODO(brianwilkerson) Consider caching the substituted type in the | |
| 9606 // instance. It would use more memory but speed up some operations. | |
| 9607 // We need to see how often the type is being re-computed. | |
| 9608 return new PropertyAccessorMember(accessor, definingType); | |
| 9609 } | |
| 9610 | |
| 9611 /** | |
| 9612 * Determine whether the given property [accessor]'s type is changed when type | |
| 9613 * parameters from the defining type's declaration are replaced with the | |
| 9614 * actual type arguments from the [definingType]. | |
| 9615 */ | |
| 9616 static bool _isChangedByTypeSubstitution( | |
| 9617 PropertyAccessorElement accessor, InterfaceType definingType) { | |
| 9618 List<DartType> argumentTypes = definingType.typeArguments; | |
| 9619 if (accessor != null && argumentTypes.length != 0) { | |
| 9620 FunctionType baseType = accessor.type; | |
| 9621 if (baseType == null) { | |
| 9622 AnalysisEngine.instance.logger.logInformation( | |
| 9623 'Type of $accessor is null in PropertyAccessorMember._isChangedByTyp
eSubstitution'); | |
| 9624 return false; | |
| 9625 } | |
| 9626 List<DartType> parameterTypes = definingType.element.type.typeArguments; | |
| 9627 FunctionType substitutedType = | |
| 9628 baseType.substitute2(argumentTypes, parameterTypes); | |
| 9629 if (baseType != substitutedType) { | |
| 9630 return true; | |
| 9631 } | |
| 9632 // If this property accessor is based on a field, that field might have a | |
| 9633 // propagated type. In which case we need to check whether the propagated | |
| 9634 // type of the field needs substitution. | |
| 9635 PropertyInducingElement field = accessor.variable; | |
| 9636 if (!field.isSynthetic) { | |
| 9637 DartType baseFieldType = field.propagatedType; | |
| 9638 if (baseFieldType != null) { | |
| 9639 DartType substitutedFieldType = | |
| 9640 baseFieldType.substitute2(argumentTypes, parameterTypes); | |
| 9641 if (baseFieldType != substitutedFieldType) { | |
| 9642 return true; | |
| 9643 } | |
| 9644 } | |
| 9645 } | |
| 9646 } | |
| 9647 return false; | |
| 9648 } | |
| 9649 } | |
| 9650 | |
| 9651 /** | |
| 9652 * A variable that has an associated getter and possibly a setter. Note that | |
| 9653 * explicitly defined variables implicitly define a synthetic getter and that | |
| 9654 * non-`final` explicitly defined variables implicitly define a synthetic | |
| 9655 * setter. Symmetrically, synthetic fields are implicitly created for explicitly | |
| 9656 * defined getters and setters. The following rules apply: | |
| 9657 * | |
| 9658 * * Every explicit variable is represented by a non-synthetic | |
| 9659 * [PropertyInducingElement]. | |
| 9660 * * Every explicit variable induces a getter and possibly a setter, both of | |
| 9661 * which are represented by synthetic [PropertyAccessorElement]s. | |
| 9662 * * Every explicit getter or setter is represented by a non-synthetic | |
| 9663 * [PropertyAccessorElement]. | |
| 9664 * * Every explicit getter or setter (or pair thereof if they have the same | |
| 9665 * name) induces a variable that is represented by a synthetic | |
| 9666 * [PropertyInducingElement]. | |
| 9667 */ | |
| 9668 abstract class PropertyInducingElement implements VariableElement { | |
| 9669 /** | |
| 9670 * An empty list of elements. | |
| 9671 */ | |
| 9672 static const List<PropertyInducingElement> EMPTY_LIST = | |
| 9673 const <PropertyInducingElement>[]; | |
| 9674 | |
| 9675 /** | |
| 9676 * Return the getter associated with this variable. If this variable was | |
| 9677 * explicitly defined (is not synthetic) then the getter associated with it | |
| 9678 * will be synthetic. | |
| 9679 */ | |
| 9680 PropertyAccessorElement get getter; | |
| 9681 | |
| 9682 /** | |
| 9683 * Return the propagated type of this variable, or `null` if type propagation | |
| 9684 * has not been performed, for example because the variable is not final. | |
| 9685 */ | |
| 9686 DartType get propagatedType; | |
| 9687 | |
| 9688 /** | |
| 9689 * Return the setter associated with this variable, or `null` if the variable | |
| 9690 * is effectively `final` and therefore does not have a setter associated with | |
| 9691 * it. (This can happen either because the variable is explicitly defined as | |
| 9692 * being `final` or because the variable is induced by an explicit getter that | |
| 9693 * does not have a corresponding setter.) If this variable was explicitly | |
| 9694 * defined (is not synthetic) then the setter associated with it will be | |
| 9695 * synthetic. | |
| 9696 */ | |
| 9697 PropertyAccessorElement get setter; | |
| 9698 } | |
| 9699 | |
| 9700 /** | |
| 9701 * A concrete implementation of a [PropertyInducingElement]. | |
| 9702 */ | |
| 9703 abstract class PropertyInducingElementImpl extends VariableElementImpl | |
| 9704 implements PropertyInducingElement { | |
| 9705 /** | |
| 9706 * An empty list of elements. | |
| 9707 */ | |
| 9708 @deprecated // Use PropertyInducingElement.EMPTY_LIST | |
| 9709 static const List<PropertyInducingElement> EMPTY_ARRAY = | |
| 9710 const <PropertyInducingElement>[]; | |
| 9711 | |
| 9712 /** | |
| 9713 * The getter associated with this element. | |
| 9714 */ | |
| 9715 PropertyAccessorElement getter; | |
| 9716 | |
| 9717 /** | |
| 9718 * The setter associated with this element, or `null` if the element is | |
| 9719 * effectively `final` and therefore does not have a setter associated with | |
| 9720 * it. | |
| 9721 */ | |
| 9722 PropertyAccessorElement setter; | |
| 9723 | |
| 9724 /** | |
| 9725 * The propagated type of this variable, or `null` if type propagation has not | |
| 9726 * been performed. | |
| 9727 */ | |
| 9728 DartType propagatedType; | |
| 9729 | |
| 9730 /** | |
| 9731 * Initialize a newly created synthetic element to have the given [name] and | |
| 9732 * [offset]. | |
| 9733 */ | |
| 9734 PropertyInducingElementImpl(String name, int offset) : super(name, offset); | |
| 9735 | |
| 9736 /** | |
| 9737 * Initialize a newly created element to have the given [name]. | |
| 9738 */ | |
| 9739 PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 9740 } | |
| 9741 | |
| 9742 /** | |
| 9743 * A visitor that will recursively visit all of the element in an element model. | |
| 9744 * For example, using an instance of this class to visit a | |
| 9745 * [CompilationUnitElement] will also cause all of the types in the compilation | |
| 9746 * unit to be visited. | |
| 9747 * | |
| 9748 * Subclasses that override a visit method must either invoke the overridden | |
| 9749 * visit method or must explicitly ask the visited element to visit its | |
| 9750 * children. Failure to do so will cause the children of the visited element to | |
| 9751 * not be visited. | |
| 9752 */ | |
| 9753 class RecursiveElementVisitor<R> implements ElementVisitor<R> { | |
| 9754 @override | |
| 9755 R visitClassElement(ClassElement element) { | |
| 9756 element.visitChildren(this); | |
| 9757 return null; | |
| 9758 } | |
| 9759 | |
| 9760 @override | |
| 9761 R visitCompilationUnitElement(CompilationUnitElement element) { | |
| 9762 element.visitChildren(this); | |
| 9763 return null; | |
| 9764 } | |
| 9765 | |
| 9766 @override | |
| 9767 R visitConstructorElement(ConstructorElement element) { | |
| 9768 element.visitChildren(this); | |
| 9769 return null; | |
| 9770 } | |
| 9771 | |
| 9772 @override | |
| 9773 @deprecated | |
| 9774 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) { | |
| 9775 element.visitChildren(this); | |
| 9776 return null; | |
| 9777 } | |
| 9778 | |
| 9779 @override | |
| 9780 R visitExportElement(ExportElement element) { | |
| 9781 element.visitChildren(this); | |
| 9782 return null; | |
| 9783 } | |
| 9784 | |
| 9785 @override | |
| 9786 @deprecated | |
| 9787 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) { | |
| 9788 element.visitChildren(this); | |
| 9789 return null; | |
| 9790 } | |
| 9791 | |
| 9792 @override | |
| 9793 R visitFieldElement(FieldElement element) { | |
| 9794 element.visitChildren(this); | |
| 9795 return null; | |
| 9796 } | |
| 9797 | |
| 9798 @override | |
| 9799 R visitFieldFormalParameterElement(FieldFormalParameterElement element) { | |
| 9800 element.visitChildren(this); | |
| 9801 return null; | |
| 9802 } | |
| 9803 | |
| 9804 @override | |
| 9805 R visitFunctionElement(FunctionElement element) { | |
| 9806 element.visitChildren(this); | |
| 9807 return null; | |
| 9808 } | |
| 9809 | |
| 9810 @override | |
| 9811 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { | |
| 9812 element.visitChildren(this); | |
| 9813 return null; | |
| 9814 } | |
| 9815 | |
| 9816 @override | |
| 9817 @deprecated | |
| 9818 R visitHtmlElement(HtmlElement element) { | |
| 9819 element.visitChildren(this); | |
| 9820 return null; | |
| 9821 } | |
| 9822 | |
| 9823 @override | |
| 9824 R visitImportElement(ImportElement element) { | |
| 9825 element.visitChildren(this); | |
| 9826 return null; | |
| 9827 } | |
| 9828 | |
| 9829 @override | |
| 9830 R visitLabelElement(LabelElement element) { | |
| 9831 element.visitChildren(this); | |
| 9832 return null; | |
| 9833 } | |
| 9834 | |
| 9835 @override | |
| 9836 R visitLibraryElement(LibraryElement element) { | |
| 9837 element.visitChildren(this); | |
| 9838 return null; | |
| 9839 } | |
| 9840 | |
| 9841 @override | |
| 9842 R visitLocalVariableElement(LocalVariableElement element) { | |
| 9843 element.visitChildren(this); | |
| 9844 return null; | |
| 9845 } | |
| 9846 | |
| 9847 @override | |
| 9848 R visitMethodElement(MethodElement element) { | |
| 9849 element.visitChildren(this); | |
| 9850 return null; | |
| 9851 } | |
| 9852 | |
| 9853 @override | |
| 9854 R visitMultiplyDefinedElement(MultiplyDefinedElement element) { | |
| 9855 element.visitChildren(this); | |
| 9856 return null; | |
| 9857 } | |
| 9858 | |
| 9859 @override | |
| 9860 R visitParameterElement(ParameterElement element) { | |
| 9861 element.visitChildren(this); | |
| 9862 return null; | |
| 9863 } | |
| 9864 | |
| 9865 @override | |
| 9866 R visitPrefixElement(PrefixElement element) { | |
| 9867 element.visitChildren(this); | |
| 9868 return null; | |
| 9869 } | |
| 9870 | |
| 9871 @override | |
| 9872 R visitPropertyAccessorElement(PropertyAccessorElement element) { | |
| 9873 element.visitChildren(this); | |
| 9874 return null; | |
| 9875 } | |
| 9876 | |
| 9877 @override | |
| 9878 R visitTopLevelVariableElement(TopLevelVariableElement element) { | |
| 9879 element.visitChildren(this); | |
| 9880 return null; | |
| 9881 } | |
| 9882 | |
| 9883 @override | |
| 9884 R visitTypeParameterElement(TypeParameterElement element) { | |
| 9885 element.visitChildren(this); | |
| 9886 return null; | |
| 9887 } | |
| 9888 } | |
| 9889 | |
| 9890 /** | |
| 9891 * A combinator that cause some of the names in a namespace to be visible (and | |
| 9892 * the rest hidden) when being imported. | |
| 9893 */ | |
| 9894 abstract class ShowElementCombinator implements NamespaceCombinator { | |
| 9895 /** | |
| 9896 * Return the offset of the character immediately following the last character | |
| 9897 * of this node. | |
| 9898 */ | |
| 9899 int get end; | |
| 9900 | |
| 9901 /** | |
| 9902 * Return the offset of the 'show' keyword of this element. | |
| 9903 */ | |
| 9904 int get offset; | |
| 9905 | |
| 9906 /** | |
| 9907 * Return a list containing the names that are to be made visible in the | |
| 9908 * importing library if they are defined in the imported library. | |
| 9909 */ | |
| 9910 List<String> get shownNames; | |
| 9911 } | |
| 9912 | |
| 9913 /** | |
| 9914 * A concrete implementation of a [ShowElementCombinator]. | |
| 9915 */ | |
| 9916 class ShowElementCombinatorImpl implements ShowElementCombinator { | |
| 9917 /** | |
| 9918 * The names that are to be made visible in the importing library if they are | |
| 9919 * defined in the imported library. | |
| 9920 */ | |
| 9921 List<String> shownNames = StringUtilities.EMPTY_ARRAY; | |
| 9922 | |
| 9923 /** | |
| 9924 * The offset of the character immediately following the last character of | |
| 9925 * this node. | |
| 9926 */ | |
| 9927 int end = -1; | |
| 9928 | |
| 9929 /** | |
| 9930 * The offset of the 'show' keyword of this element. | |
| 9931 */ | |
| 9932 int offset = 0; | |
| 9933 | |
| 9934 @override | |
| 9935 String toString() { | |
| 9936 StringBuffer buffer = new StringBuffer(); | |
| 9937 buffer.write("show "); | |
| 9938 int count = shownNames.length; | |
| 9939 for (int i = 0; i < count; i++) { | |
| 9940 if (i > 0) { | |
| 9941 buffer.write(", "); | |
| 9942 } | |
| 9943 buffer.write(shownNames[i]); | |
| 9944 } | |
| 9945 return buffer.toString(); | |
| 9946 } | |
| 9947 } | |
| 9948 | |
| 9949 /** | |
| 9950 * A visitor that will do nothing when visiting an element. It is intended to be | |
| 9951 * a superclass for classes that use the visitor pattern primarily as a dispatch | |
| 9952 * mechanism (and hence don't need to recursively visit a whole structure) and | |
| 9953 * that only need to visit a small number of element types. | |
| 9954 */ | |
| 9955 class SimpleElementVisitor<R> implements ElementVisitor<R> { | |
| 9956 @override | |
| 9957 R visitClassElement(ClassElement element) => null; | |
| 9958 | |
| 9959 @override | |
| 9960 R visitCompilationUnitElement(CompilationUnitElement element) => null; | |
| 9961 | |
| 9962 @override | |
| 9963 R visitConstructorElement(ConstructorElement element) => null; | |
| 9964 | |
| 9965 @override | |
| 9966 @deprecated | |
| 9967 R visitEmbeddedHtmlScriptElement(EmbeddedHtmlScriptElement element) => null; | |
| 9968 | |
| 9969 @override | |
| 9970 R visitExportElement(ExportElement element) => null; | |
| 9971 | |
| 9972 @override | |
| 9973 @deprecated | |
| 9974 R visitExternalHtmlScriptElement(ExternalHtmlScriptElement element) => null; | |
| 9975 | |
| 9976 @override | |
| 9977 R visitFieldElement(FieldElement element) => null; | |
| 9978 | |
| 9979 @override | |
| 9980 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => | |
| 9981 null; | |
| 9982 | |
| 9983 @override | |
| 9984 R visitFunctionElement(FunctionElement element) => null; | |
| 9985 | |
| 9986 @override | |
| 9987 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null; | |
| 9988 | |
| 9989 @override | |
| 9990 @deprecated | |
| 9991 R visitHtmlElement(HtmlElement element) => null; | |
| 9992 | |
| 9993 @override | |
| 9994 R visitImportElement(ImportElement element) => null; | |
| 9995 | |
| 9996 @override | |
| 9997 R visitLabelElement(LabelElement element) => null; | |
| 9998 | |
| 9999 @override | |
| 10000 R visitLibraryElement(LibraryElement element) => null; | |
| 10001 | |
| 10002 @override | |
| 10003 R visitLocalVariableElement(LocalVariableElement element) => null; | |
| 10004 | |
| 10005 @override | |
| 10006 R visitMethodElement(MethodElement element) => null; | |
| 10007 | |
| 10008 @override | |
| 10009 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null; | |
| 10010 | |
| 10011 @override | |
| 10012 R visitParameterElement(ParameterElement element) => null; | |
| 10013 | |
| 10014 @override | |
| 10015 R visitPrefixElement(PrefixElement element) => null; | |
| 10016 | |
| 10017 @override | |
| 10018 R visitPropertyAccessorElement(PropertyAccessorElement element) => null; | |
| 10019 | |
| 10020 @override | |
| 10021 R visitTopLevelVariableElement(TopLevelVariableElement element) => null; | |
| 10022 | |
| 10023 @override | |
| 10024 R visitTypeParameterElement(TypeParameterElement element) => null; | |
| 10025 } | |
| 10026 | |
| 10027 /** | |
| 10028 * A top-level variable. | |
| 10029 */ | |
| 10030 abstract class TopLevelVariableElement implements PropertyInducingElement { | |
| 10031 /** | |
| 10032 * An empty list of top-level variable elements. | |
| 10033 */ | |
| 10034 static const List<TopLevelVariableElement> EMPTY_LIST = | |
| 10035 const <TopLevelVariableElement>[]; | |
| 10036 | |
| 10037 @override | |
| 10038 VariableDeclaration computeNode(); | |
| 10039 } | |
| 10040 | |
| 10041 /** | |
| 10042 * A concrete implementation of a [TopLevelVariableElement]. | |
| 10043 */ | |
| 10044 class TopLevelVariableElementImpl extends PropertyInducingElementImpl | |
| 10045 with PotentiallyConstVariableElement | |
| 10046 implements TopLevelVariableElement { | |
| 10047 /** | |
| 10048 * An empty list of top-level variable elements. | |
| 10049 */ | |
| 10050 @deprecated // Use TopLevelVariableElement.EMPTY_LIST | |
| 10051 static const List<TopLevelVariableElement> EMPTY_ARRAY = | |
| 10052 const <TopLevelVariableElement>[]; | |
| 10053 | |
| 10054 /** | |
| 10055 * Initialize a newly created synthetic top-level variable element to have the | |
| 10056 * given [name] and [offset]. | |
| 10057 */ | |
| 10058 TopLevelVariableElementImpl(String name, int offset) : super(name, offset); | |
| 10059 | |
| 10060 /** | |
| 10061 * Initialize a newly created top-level variable element to have the given | |
| 10062 * [name]. | |
| 10063 */ | |
| 10064 TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 10065 | |
| 10066 @override | |
| 10067 bool get isStatic => true; | |
| 10068 | |
| 10069 @override | |
| 10070 ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE; | |
| 10071 | |
| 10072 @override | |
| 10073 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this); | |
| 10074 | |
| 10075 @override | |
| 10076 VariableDeclaration computeNode() => | |
| 10077 getNodeMatching((node) => node is VariableDeclaration); | |
| 10078 } | |
| 10079 | |
| 10080 /** | |
| 10081 * An element that defines a type. | |
| 10082 */ | |
| 10083 abstract class TypeDefiningElement implements Element { | |
| 10084 /** | |
| 10085 * Return the type defined by this element. | |
| 10086 */ | |
| 10087 DartType get type; | |
| 10088 } | |
| 10089 | |
| 10090 /** | |
| 10091 * The abstract class `TypeImpl` implements the behavior common to objects | |
| 10092 * representing the declared type of elements in the element model. | |
| 10093 */ | |
| 10094 abstract class TypeImpl implements DartType { | |
| 10095 /** | |
| 10096 * An empty list of types. | |
| 10097 */ | |
| 10098 @deprecated // Use DartType.EMPTY_LIST | |
| 10099 static const List<DartType> EMPTY_ARRAY = const <DartType>[]; | |
| 10100 | |
| 10101 /** | |
| 10102 * The element representing the declaration of this type, or `null` if the | |
| 10103 * type has not, or cannot, be associated with an element. | |
| 10104 */ | |
| 10105 final Element _element; | |
| 10106 | |
| 10107 /** | |
| 10108 * The name of this type, or `null` if the type does not have a name. | |
| 10109 */ | |
| 10110 final String name; | |
| 10111 | |
| 10112 /** | |
| 10113 * Initialize a newly created type to be declared by the given [element] and | |
| 10114 * to have the given [name]. | |
| 10115 */ | |
| 10116 TypeImpl(this._element, this.name); | |
| 10117 | |
| 10118 @override | |
| 10119 String get displayName => name; | |
| 10120 | |
| 10121 @override | |
| 10122 Element get element => _element; | |
| 10123 | |
| 10124 @override | |
| 10125 bool get isBottom => false; | |
| 10126 | |
| 10127 @override | |
| 10128 bool get isDartCoreFunction => false; | |
| 10129 | |
| 10130 @override | |
| 10131 bool get isDynamic => false; | |
| 10132 | |
| 10133 @override | |
| 10134 bool get isObject => false; | |
| 10135 | |
| 10136 @override | |
| 10137 bool get isUndefined => false; | |
| 10138 | |
| 10139 @override | |
| 10140 bool get isVoid => false; | |
| 10141 | |
| 10142 /** | |
| 10143 * Append a textual representation of this type to the given [buffer]. The set | |
| 10144 * of [visitedTypes] is used to prevent infinite recusion. | |
| 10145 */ | |
| 10146 void appendTo(StringBuffer buffer) { | |
| 10147 if (name == null) { | |
| 10148 buffer.write("<unnamed type>"); | |
| 10149 } else { | |
| 10150 buffer.write(name); | |
| 10151 } | |
| 10152 } | |
| 10153 | |
| 10154 @override | |
| 10155 DartType getLeastUpperBound(DartType type) => null; | |
| 10156 | |
| 10157 /** | |
| 10158 * Return `true` if this type is assignable to the given [type] (written in | |
| 10159 * the spec as "T <=> S", where T=[this] and S=[type]). | |
| 10160 * | |
| 10161 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of | |
| 10162 * function type aliases that have been expanded so far in the process of | |
| 10163 * reaching [this] and [type], respectively. These are used to avoid | |
| 10164 * infinite regress when analyzing invalid code; since the language spec | |
| 10165 * forbids a typedef from referring to itself directly or indirectly, we can | |
| 10166 * use these as sets of function type aliases that don't need to be expanded. | |
| 10167 */ | |
| 10168 @override | |
| 10169 bool isAssignableTo(DartType type) { | |
| 10170 // An interface type T may be assigned to a type S, written T <=> S, iff | |
| 10171 // either T <: S or S <: T. | |
| 10172 return isSubtypeOf(type) || (type as TypeImpl).isSubtypeOf(this); | |
| 10173 } | |
| 10174 | |
| 10175 /** | |
| 10176 * Return `true` if this type is more specific than the given [type] (written | |
| 10177 * in the spec as "T << S", where T=[this] and S=[type]). | |
| 10178 * | |
| 10179 * If [withDynamic] is `true`, then "dynamic" should be considered as a | |
| 10180 * subtype of any type (as though "dynamic" had been replaced with bottom). | |
| 10181 * | |
| 10182 * The set [visitedElements], if given, is the set of classes and type | |
| 10183 * parameters that have been visited so far while examining the class | |
| 10184 * hierarchy of [this]. This is used to avoid infinite regress when | |
| 10185 * analyzing invalid code; since the language spec forbids loops in the class | |
| 10186 * hierarchy, we can use this as a set of classes that don't need to be | |
| 10187 * examined when walking the class hierarchy. | |
| 10188 */ | |
| 10189 @override | |
| 10190 bool isMoreSpecificThan(DartType type, | |
| 10191 [bool withDynamic = false, Set<Element> visitedElements]); | |
| 10192 | |
| 10193 /** | |
| 10194 * Return `true` if this type is a subtype of the given [type] (written in | |
| 10195 * the spec as "T <: S", where T=[this] and S=[type]). | |
| 10196 * | |
| 10197 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of | |
| 10198 * function type aliases that have been expanded so far in the process of | |
| 10199 * reaching [this] and [type], respectively. These are used to avoid | |
| 10200 * infinite regress when analyzing invalid code; since the language spec | |
| 10201 * forbids a typedef from referring to itself directly or indirectly, we can | |
| 10202 * use these as sets of function type aliases that don't need to be expanded. | |
| 10203 */ | |
| 10204 @override | |
| 10205 bool isSubtypeOf(DartType type) { | |
| 10206 // For non-function types, T <: S iff [_|_/dynamic]T << S. | |
| 10207 return isMoreSpecificThan(type, true); | |
| 10208 } | |
| 10209 | |
| 10210 @override | |
| 10211 bool isSupertypeOf(DartType type) => type.isSubtypeOf(this); | |
| 10212 | |
| 10213 /** | |
| 10214 * Create a new [TypeImpl] that is identical to [this] except that when | |
| 10215 * visiting type parameters, function parameter types, and function return | |
| 10216 * types, function types listed in [prune] will not be expanded. This is | |
| 10217 * used to avoid creating infinite types in the presence of circular | |
| 10218 * typedefs. | |
| 10219 * | |
| 10220 * If [prune] is null, then [this] is returned unchanged. | |
| 10221 * | |
| 10222 * Only legal to call on a [TypeImpl] that is not already subject to pruning. | |
| 10223 */ | |
| 10224 TypeImpl pruned(List<FunctionTypeAliasElement> prune); | |
| 10225 | |
| 10226 /** | |
| 10227 * Return the type resulting from substituting the given [argumentTypes] for | |
| 10228 * the given [parameterTypes] in this type. | |
| 10229 * | |
| 10230 * In all classes derived from [TypeImpl], a new optional argument | |
| 10231 * [prune] is added. If specified, it is a list of function typdefs | |
| 10232 * which should not be expanded. This is used to avoid creating infinite | |
| 10233 * types in response to self-referential typedefs. | |
| 10234 */ | |
| 10235 @override | |
| 10236 DartType substitute2( | |
| 10237 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 10238 [List<FunctionTypeAliasElement> prune]); | |
| 10239 | |
| 10240 @override | |
| 10241 String toString() { | |
| 10242 StringBuffer buffer = new StringBuffer(); | |
| 10243 appendTo(buffer); | |
| 10244 return buffer.toString(); | |
| 10245 } | |
| 10246 | |
| 10247 /** | |
| 10248 * Return `true` if corresponding elements of the [first] and [second] lists | |
| 10249 * of type arguments are all equal. | |
| 10250 */ | |
| 10251 static bool equalArrays(List<DartType> first, List<DartType> second) { | |
| 10252 if (first.length != second.length) { | |
| 10253 return false; | |
| 10254 } | |
| 10255 for (int i = 0; i < first.length; i++) { | |
| 10256 if (first[i] == null) { | |
| 10257 AnalysisEngine.instance.logger | |
| 10258 .logInformation('Found null type argument in TypeImpl.equalArrays'); | |
| 10259 return second[i] == null; | |
| 10260 } else if (second[i] == null) { | |
| 10261 AnalysisEngine.instance.logger | |
| 10262 .logInformation('Found null type argument in TypeImpl.equalArrays'); | |
| 10263 return false; | |
| 10264 } | |
| 10265 if (first[i] != second[i]) { | |
| 10266 return false; | |
| 10267 } | |
| 10268 } | |
| 10269 return true; | |
| 10270 } | |
| 10271 | |
| 10272 /** | |
| 10273 * Return a list containing the results of using the given [argumentTypes] and | |
| 10274 * [parameterTypes] to perform a substitution on all of the given [types]. | |
| 10275 * | |
| 10276 * If [prune] is specified, it is a list of function typdefs which should not | |
| 10277 * be expanded. This is used to avoid creating infinite types in response to | |
| 10278 * self-referential typedefs. | |
| 10279 */ | |
| 10280 static List<DartType> substitute(List<DartType> types, | |
| 10281 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 10282 [List<FunctionTypeAliasElement> prune]) { | |
| 10283 int length = types.length; | |
| 10284 if (length == 0) { | |
| 10285 return types; | |
| 10286 } | |
| 10287 List<DartType> newTypes = new List<DartType>(length); | |
| 10288 for (int i = 0; i < length; i++) { | |
| 10289 newTypes[i] = (types[i] as TypeImpl) | |
| 10290 .substitute2(argumentTypes, parameterTypes, prune); | |
| 10291 } | |
| 10292 return newTypes; | |
| 10293 } | |
| 10294 } | |
| 10295 | |
| 10296 /** | |
| 10297 * A type parameter. | |
| 10298 */ | |
| 10299 abstract class TypeParameterElement implements TypeDefiningElement { | |
| 10300 /** | |
| 10301 * An empty list of type parameter elements. | |
| 10302 */ | |
| 10303 static const List<TypeParameterElement> EMPTY_LIST = | |
| 10304 const <TypeParameterElement>[]; | |
| 10305 | |
| 10306 /** | |
| 10307 * Return the type representing the bound associated with this parameter, or | |
| 10308 * `null` if this parameter does not have an explicit bound. | |
| 10309 */ | |
| 10310 DartType get bound; | |
| 10311 | |
| 10312 /** | |
| 10313 * Return the type defined by this type parameter. | |
| 10314 */ | |
| 10315 TypeParameterType get type; | |
| 10316 } | |
| 10317 | |
| 10318 /** | |
| 10319 * A concrete implementation of a [TypeParameterElement]. | |
| 10320 */ | |
| 10321 class TypeParameterElementImpl extends ElementImpl | |
| 10322 implements TypeParameterElement { | |
| 10323 /** | |
| 10324 * An empty list of type parameter elements. | |
| 10325 */ | |
| 10326 @deprecated // Use TypeParameterElement.EMPTY_LIST | |
| 10327 static const List<TypeParameterElement> EMPTY_ARRAY = | |
| 10328 const <TypeParameterElement>[]; | |
| 10329 | |
| 10330 /** | |
| 10331 * The type defined by this type parameter. | |
| 10332 */ | |
| 10333 TypeParameterType type; | |
| 10334 | |
| 10335 /** | |
| 10336 * The type representing the bound associated with this parameter, or `null` | |
| 10337 * if this parameter does not have an explicit bound. | |
| 10338 */ | |
| 10339 DartType bound; | |
| 10340 | |
| 10341 /** | |
| 10342 * Initialize a newly created method element to have the given [name] and | |
| 10343 * [offset]. | |
| 10344 */ | |
| 10345 TypeParameterElementImpl(String name, int offset) : super(name, offset); | |
| 10346 | |
| 10347 /** | |
| 10348 * Initialize a newly created type parameter element to have the given [name]. | |
| 10349 */ | |
| 10350 TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 10351 | |
| 10352 @override | |
| 10353 ElementKind get kind => ElementKind.TYPE_PARAMETER; | |
| 10354 | |
| 10355 @override | |
| 10356 accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this); | |
| 10357 | |
| 10358 @override | |
| 10359 void appendTo(StringBuffer buffer) { | |
| 10360 buffer.write(displayName); | |
| 10361 if (bound != null) { | |
| 10362 buffer.write(" extends "); | |
| 10363 buffer.write(bound); | |
| 10364 } | |
| 10365 } | |
| 10366 } | |
| 10367 | |
| 10368 /** | |
| 10369 * The type introduced by a type parameter. | |
| 10370 */ | |
| 10371 abstract class TypeParameterType implements DartType { | |
| 10372 /** | |
| 10373 * An empty list of type parameter types. | |
| 10374 */ | |
| 10375 static const List<TypeParameterType> EMPTY_LIST = const <TypeParameterType>[]; | |
| 10376 | |
| 10377 @override | |
| 10378 TypeParameterElement get element; | |
| 10379 } | |
| 10380 | |
| 10381 /** | |
| 10382 * A concrete implementation of a [TypeParameterType]. | |
| 10383 */ | |
| 10384 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { | |
| 10385 /** | |
| 10386 * An empty list of type parameter types. | |
| 10387 */ | |
| 10388 @deprecated // Use TypeParameterType.EMPTY_LIST | |
| 10389 static const List<TypeParameterType> EMPTY_ARRAY = | |
| 10390 const <TypeParameterType>[]; | |
| 10391 | |
| 10392 /** | |
| 10393 * Initialize a newly created type parameter type to be declared by the given | |
| 10394 * [element] and to have the given name. | |
| 10395 */ | |
| 10396 TypeParameterTypeImpl(TypeParameterElement element) | |
| 10397 : super(element, element.name); | |
| 10398 | |
| 10399 @override | |
| 10400 TypeParameterElement get element => super.element as TypeParameterElement; | |
| 10401 | |
| 10402 @override | |
| 10403 int get hashCode => element.hashCode; | |
| 10404 | |
| 10405 @override | |
| 10406 bool operator ==(Object object) => | |
| 10407 object is TypeParameterTypeImpl && (element == object.element); | |
| 10408 | |
| 10409 @override | |
| 10410 bool isMoreSpecificThan(DartType s, | |
| 10411 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 10412 // | |
| 10413 // A type T is more specific than a type S, written T << S, | |
| 10414 // if one of the following conditions is met: | |
| 10415 // | |
| 10416 // Reflexivity: T is S. | |
| 10417 // | |
| 10418 if (this == s) { | |
| 10419 return true; | |
| 10420 } | |
| 10421 // S is dynamic. | |
| 10422 // | |
| 10423 if (s.isDynamic) { | |
| 10424 return true; | |
| 10425 } | |
| 10426 // | |
| 10427 // T is a type parameter and S is the upper bound of T. | |
| 10428 // | |
| 10429 TypeImpl bound = element.bound; | |
| 10430 if (s == bound) { | |
| 10431 return true; | |
| 10432 } | |
| 10433 // | |
| 10434 // T is a type parameter and S is Object. | |
| 10435 // | |
| 10436 if (s.isObject) { | |
| 10437 return true; | |
| 10438 } | |
| 10439 // We need upper bound to continue. | |
| 10440 if (bound == null) { | |
| 10441 return false; | |
| 10442 } | |
| 10443 // | |
| 10444 // Transitivity: T << U and U << S. | |
| 10445 // | |
| 10446 // First check for infinite loops | |
| 10447 if (element == null) { | |
| 10448 return false; | |
| 10449 } | |
| 10450 if (visitedElements == null) { | |
| 10451 visitedElements = new HashSet<Element>(); | |
| 10452 } else if (visitedElements.contains(element)) { | |
| 10453 return false; | |
| 10454 } | |
| 10455 visitedElements.add(element); | |
| 10456 try { | |
| 10457 return bound.isMoreSpecificThan(s, withDynamic, visitedElements); | |
| 10458 } finally { | |
| 10459 visitedElements.remove(element); | |
| 10460 } | |
| 10461 } | |
| 10462 | |
| 10463 @override | |
| 10464 bool isSubtypeOf(DartType type) => isMoreSpecificThan(type, true); | |
| 10465 | |
| 10466 @override | |
| 10467 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 10468 | |
| 10469 @override | |
| 10470 DartType substitute2( | |
| 10471 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 10472 [List<FunctionTypeAliasElement> prune]) { | |
| 10473 int length = parameterTypes.length; | |
| 10474 for (int i = 0; i < length; i++) { | |
| 10475 if (parameterTypes[i] == this) { | |
| 10476 return argumentTypes[i]; | |
| 10477 } | |
| 10478 } | |
| 10479 return this; | |
| 10480 } | |
| 10481 | |
| 10482 /** | |
| 10483 * Return a list containing the type parameter types defined by the given | |
| 10484 * array of type parameter elements ([typeParameters]). | |
| 10485 */ | |
| 10486 static List<TypeParameterType> getTypes( | |
| 10487 List<TypeParameterElement> typeParameters) { | |
| 10488 int count = typeParameters.length; | |
| 10489 if (count == 0) { | |
| 10490 return TypeParameterType.EMPTY_LIST; | |
| 10491 } | |
| 10492 List<TypeParameterType> types = new List<TypeParameterType>(count); | |
| 10493 for (int i = 0; i < count; i++) { | |
| 10494 types[i] = typeParameters[i].type; | |
| 10495 } | |
| 10496 return types; | |
| 10497 } | |
| 10498 } | |
| 10499 | |
| 10500 /** | |
| 10501 * A pseudo-elements that represents names that are undefined. This situation is | |
| 10502 * not allowed by the language, so objects implementing this interface always | |
| 10503 * represent an error. As a result, most of the normal operations on elements do | |
| 10504 * not make sense and will return useless results. | |
| 10505 */ | |
| 10506 abstract class UndefinedElement implements Element {} | |
| 10507 | |
| 10508 /** | |
| 10509 * The unique instance of the class `UndefinedTypeImpl` implements the type of | |
| 10510 * typenames that couldn't be resolved. | |
| 10511 * | |
| 10512 * This class behaves like DynamicTypeImpl in almost every respect, to reduce | |
| 10513 * cascading errors. | |
| 10514 */ | |
| 10515 class UndefinedTypeImpl extends TypeImpl { | |
| 10516 /** | |
| 10517 * The unique instance of this class. | |
| 10518 */ | |
| 10519 static UndefinedTypeImpl _INSTANCE = new UndefinedTypeImpl._(); | |
| 10520 | |
| 10521 /** | |
| 10522 * Return the unique instance of this class. | |
| 10523 */ | |
| 10524 static UndefinedTypeImpl get instance => _INSTANCE; | |
| 10525 | |
| 10526 /** | |
| 10527 * Prevent the creation of instances of this class. | |
| 10528 */ | |
| 10529 UndefinedTypeImpl._() | |
| 10530 : super(DynamicElementImpl.instance, Keyword.DYNAMIC.syntax); | |
| 10531 | |
| 10532 @override | |
| 10533 int get hashCode => 1; | |
| 10534 | |
| 10535 @override | |
| 10536 bool get isDynamic => true; | |
| 10537 | |
| 10538 @override | |
| 10539 bool get isUndefined => true; | |
| 10540 | |
| 10541 @override | |
| 10542 bool operator ==(Object object) => identical(object, this); | |
| 10543 | |
| 10544 @override | |
| 10545 bool isMoreSpecificThan(DartType type, | |
| 10546 [bool withDynamic = false, Set<Element> visitedElements]) { | |
| 10547 // T is S | |
| 10548 if (identical(this, type)) { | |
| 10549 return true; | |
| 10550 } | |
| 10551 // else | |
| 10552 return withDynamic; | |
| 10553 } | |
| 10554 | |
| 10555 @override | |
| 10556 bool isSubtypeOf(DartType type) => true; | |
| 10557 | |
| 10558 @override | |
| 10559 bool isSupertypeOf(DartType type) => true; | |
| 10560 | |
| 10561 @override | |
| 10562 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 10563 | |
| 10564 @override | |
| 10565 DartType substitute2( | |
| 10566 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 10567 [List<FunctionTypeAliasElement> prune]) { | |
| 10568 int length = parameterTypes.length; | |
| 10569 for (int i = 0; i < length; i++) { | |
| 10570 if (parameterTypes[i] == this) { | |
| 10571 return argumentTypes[i]; | |
| 10572 } | |
| 10573 } | |
| 10574 return this; | |
| 10575 } | |
| 10576 } | |
| 10577 | |
| 10578 /** | |
| 10579 * An element included into a library using some URI. | |
| 10580 */ | |
| 10581 abstract class UriReferencedElement implements Element { | |
| 10582 /** | |
| 10583 * Return the URI that is used to include this element into the enclosing | |
| 10584 * library, or `null` if this is the defining compilation unit of a library. | |
| 10585 */ | |
| 10586 String get uri; | |
| 10587 | |
| 10588 /** | |
| 10589 * Return the offset of the character immediately following the last character | |
| 10590 * of this node's URI, or `-1` for synthetic import. | |
| 10591 */ | |
| 10592 int get uriEnd; | |
| 10593 | |
| 10594 /** | |
| 10595 * Return the offset of the URI in the file, or `-1` if this element is | |
| 10596 * synthetic. | |
| 10597 */ | |
| 10598 int get uriOffset; | |
| 10599 } | |
| 10600 | |
| 10601 /** | |
| 10602 * A concrete implementation of a [UriReferencedElement]. | |
| 10603 */ | |
| 10604 abstract class UriReferencedElementImpl extends ElementImpl | |
| 10605 implements UriReferencedElement { | |
| 10606 /** | |
| 10607 * The offset of the URI in the file, may be `-1` if synthetic. | |
| 10608 */ | |
| 10609 int uriOffset = -1; | |
| 10610 | |
| 10611 /** | |
| 10612 * The offset of the character immediately following the last character of | |
| 10613 * this node's URI, may be `-1` if synthetic. | |
| 10614 */ | |
| 10615 int uriEnd = -1; | |
| 10616 | |
| 10617 /** | |
| 10618 * The URI that is specified by this directive. | |
| 10619 */ | |
| 10620 String uri; | |
| 10621 | |
| 10622 /** | |
| 10623 * Initialize a newly created import element to heve the given [name] and | |
| 10624 * [offset]. The offset may be `-1` if the element is synthetic. | |
| 10625 */ | |
| 10626 UriReferencedElementImpl(String name, int offset) : super(name, offset); | |
| 10627 } | |
| 10628 | |
| 10629 /** | |
| 10630 * A variable. There are concrete subclasses for different kinds of variables. | |
| 10631 */ | |
| 10632 abstract class VariableElement implements Element, ConstantEvaluationTarget { | |
| 10633 /** | |
| 10634 * An empty list of variable elements. | |
| 10635 */ | |
| 10636 static const List<VariableElement> EMPTY_LIST = const <VariableElement>[]; | |
| 10637 | |
| 10638 /** | |
| 10639 * Return a representation of the value of this variable. | |
| 10640 * | |
| 10641 * Return `null` if either this variable was not declared with the 'const' | |
| 10642 * modifier or if the value of this variable could not be computed because of | |
| 10643 * errors. | |
| 10644 */ | |
| 10645 DartObject get constantValue; | |
| 10646 | |
| 10647 /** | |
| 10648 * Return `true` if this variable element did not have an explicit type | |
| 10649 * specified for it. | |
| 10650 */ | |
| 10651 bool get hasImplicitType; | |
| 10652 | |
| 10653 /** | |
| 10654 * Return a synthetic function representing this variable's initializer, or | |
| 10655 * `null` if this variable does not have an initializer. The function will | |
| 10656 * have no parameters. The return type of the function will be the | |
| 10657 * compile-time type of the initialization expression. | |
| 10658 */ | |
| 10659 FunctionElement get initializer; | |
| 10660 | |
| 10661 /** | |
| 10662 * Return `true` if this variable was declared with the 'const' modifier. | |
| 10663 */ | |
| 10664 bool get isConst; | |
| 10665 | |
| 10666 /** | |
| 10667 * Return `true` if this variable was declared with the 'final' modifier. | |
| 10668 * Variables that are declared with the 'const' modifier will return `false` | |
| 10669 * even though they are implicitly final. | |
| 10670 */ | |
| 10671 bool get isFinal; | |
| 10672 | |
| 10673 /** | |
| 10674 * Return `true` if this variable is potentially mutated somewhere in a | |
| 10675 * closure. This information is only available for local variables (including | |
| 10676 * parameters) and only after the compilation unit containing the variable has | |
| 10677 * been resolved. | |
| 10678 */ | |
| 10679 bool get isPotentiallyMutatedInClosure; | |
| 10680 | |
| 10681 /** | |
| 10682 * Return `true` if this variable is potentially mutated somewhere in its | |
| 10683 * scope. This information is only available for local variables (including | |
| 10684 * parameters) and only after the compilation unit containing the variable has | |
| 10685 * been resolved. | |
| 10686 */ | |
| 10687 bool get isPotentiallyMutatedInScope; | |
| 10688 | |
| 10689 /** | |
| 10690 * Return `true` if this element is a static variable, as per section 8 of the | |
| 10691 * Dart Language Specification: | |
| 10692 * | |
| 10693 * > A static variable is a variable that is not associated with a particular | |
| 10694 * > instance, but rather with an entire library or class. Static variables | |
| 10695 * > include library variables and class variables. Class variables are | |
| 10696 * > variables whose declaration is immediately nested inside a class | |
| 10697 * > declaration and includes the modifier static. A library variable is | |
| 10698 * > implicitly static. | |
| 10699 */ | |
| 10700 bool get isStatic; | |
| 10701 | |
| 10702 /** | |
| 10703 * Return the declared type of this variable, or `null` if the variable did | |
| 10704 * not have a declared type (such as if it was declared using the keyword | |
| 10705 * 'var'). | |
| 10706 */ | |
| 10707 DartType get type; | |
| 10708 } | |
| 10709 | |
| 10710 /** | |
| 10711 * A concrete implementation of a [VariableElement]. | |
| 10712 */ | |
| 10713 abstract class VariableElementImpl extends ElementImpl | |
| 10714 implements VariableElement { | |
| 10715 /** | |
| 10716 * An empty list of variable elements. | |
| 10717 */ | |
| 10718 @deprecated // Use VariableElement.EMPTY_LIST | |
| 10719 static const List<VariableElement> EMPTY_ARRAY = const <VariableElement>[]; | |
| 10720 | |
| 10721 /** | |
| 10722 * The declared type of this variable. | |
| 10723 */ | |
| 10724 DartType type; | |
| 10725 | |
| 10726 /** | |
| 10727 * A synthetic function representing this variable's initializer, or `null` if | |
| 10728 * this variable does not have an initializer. | |
| 10729 */ | |
| 10730 FunctionElement _initializer; | |
| 10731 | |
| 10732 /** | |
| 10733 * Initialize a newly created variable element to have the given [name] and | |
| 10734 * [offset]. | |
| 10735 */ | |
| 10736 VariableElementImpl(String name, int offset) : super(name, offset); | |
| 10737 | |
| 10738 /** | |
| 10739 * Initialize a newly created variable element to have the given [name]. | |
| 10740 */ | |
| 10741 VariableElementImpl.forNode(Identifier name) : super.forNode(name); | |
| 10742 | |
| 10743 /** | |
| 10744 * Set whether this variable is const. | |
| 10745 */ | |
| 10746 void set const3(bool isConst) { | |
| 10747 setModifier(Modifier.CONST, isConst); | |
| 10748 } | |
| 10749 | |
| 10750 @override | |
| 10751 DartObject get constantValue => null; | |
| 10752 | |
| 10753 /** | |
| 10754 * Return the result of evaluating this variable's initializer as a | |
| 10755 * compile-time constant expression, or `null` if this variable is not a | |
| 10756 * 'const' variable, if it does not have an initializer, or if the compilation | |
| 10757 * unit containing the variable has not been resolved. | |
| 10758 */ | |
| 10759 EvaluationResultImpl get evaluationResult => null; | |
| 10760 | |
| 10761 /** | |
| 10762 * Set the result of evaluating this variable's initializer as a compile-time | |
| 10763 * constant expression to the given [result]. | |
| 10764 */ | |
| 10765 void set evaluationResult(EvaluationResultImpl result) { | |
| 10766 throw new IllegalStateException( | |
| 10767 "Invalid attempt to set a compile-time constant result"); | |
| 10768 } | |
| 10769 | |
| 10770 /** | |
| 10771 * Set whether this variable is final. | |
| 10772 */ | |
| 10773 void set final2(bool isFinal) { | |
| 10774 setModifier(Modifier.FINAL, isFinal); | |
| 10775 } | |
| 10776 | |
| 10777 @override | |
| 10778 bool get hasImplicitType => hasModifier(Modifier.IMPLICIT_TYPE); | |
| 10779 | |
| 10780 /** | |
| 10781 * Set whether this variable element has an implicit type. | |
| 10782 */ | |
| 10783 void set hasImplicitType(bool hasImplicitType) { | |
| 10784 setModifier(Modifier.IMPLICIT_TYPE, hasImplicitType); | |
| 10785 } | |
| 10786 | |
| 10787 @override | |
| 10788 FunctionElement get initializer => _initializer; | |
| 10789 | |
| 10790 /** | |
| 10791 * Set the function representing this variable's initializer to the given | |
| 10792 * [function]. | |
| 10793 */ | |
| 10794 void set initializer(FunctionElement function) { | |
| 10795 if (function != null) { | |
| 10796 (function as FunctionElementImpl).enclosingElement = this; | |
| 10797 } | |
| 10798 this._initializer = function; | |
| 10799 } | |
| 10800 | |
| 10801 @override | |
| 10802 bool get isConst => hasModifier(Modifier.CONST); | |
| 10803 | |
| 10804 @override | |
| 10805 bool get isFinal => hasModifier(Modifier.FINAL); | |
| 10806 | |
| 10807 @override | |
| 10808 bool get isPotentiallyMutatedInClosure => false; | |
| 10809 | |
| 10810 @override | |
| 10811 bool get isPotentiallyMutatedInScope => false; | |
| 10812 | |
| 10813 @override | |
| 10814 bool get isStatic => hasModifier(Modifier.STATIC); | |
| 10815 | |
| 10816 @override | |
| 10817 void appendTo(StringBuffer buffer) { | |
| 10818 buffer.write(type); | |
| 10819 buffer.write(" "); | |
| 10820 buffer.write(displayName); | |
| 10821 } | |
| 10822 | |
| 10823 @override | |
| 10824 void visitChildren(ElementVisitor visitor) { | |
| 10825 super.visitChildren(visitor); | |
| 10826 safelyVisitChild(_initializer, visitor); | |
| 10827 } | |
| 10828 } | |
| 10829 | |
| 10830 /** | |
| 10831 * A variable element defined in a parameterized type where the values of the | |
| 10832 * type parameters are known. | |
| 10833 */ | |
| 10834 abstract class VariableMember extends Member implements VariableElement { | |
| 10835 /** | |
| 10836 * Initialize a newly created element to represent a constructor, based on the | |
| 10837 * [baseElement], defined by the [definingType]. | |
| 10838 */ | |
| 10839 VariableMember(VariableElement baseElement, ParameterizedType definingType) | |
| 10840 : super(baseElement, definingType); | |
| 10841 | |
| 10842 @override | |
| 10843 VariableElement get baseElement => super.baseElement as VariableElement; | |
| 10844 | |
| 10845 @override | |
| 10846 DartObject get constantValue => baseElement.constantValue; | |
| 10847 | |
| 10848 @override | |
| 10849 bool get hasImplicitType => baseElement.hasImplicitType; | |
| 10850 | |
| 10851 @override | |
| 10852 FunctionElement get initializer { | |
| 10853 // | |
| 10854 // Elements within this element should have type parameters substituted, | |
| 10855 // just like this element. | |
| 10856 // | |
| 10857 throw new UnsupportedOperationException(); | |
| 10858 // return getBaseElement().getInitializer(); | |
| 10859 } | |
| 10860 | |
| 10861 @override | |
| 10862 bool get isConst => baseElement.isConst; | |
| 10863 | |
| 10864 @override | |
| 10865 bool get isFinal => baseElement.isFinal; | |
| 10866 | |
| 10867 @override | |
| 10868 bool get isPotentiallyMutatedInClosure => | |
| 10869 baseElement.isPotentiallyMutatedInClosure; | |
| 10870 | |
| 10871 @override | |
| 10872 bool get isPotentiallyMutatedInScope => | |
| 10873 baseElement.isPotentiallyMutatedInScope; | |
| 10874 | |
| 10875 @override | |
| 10876 bool get isStatic => baseElement.isStatic; | |
| 10877 | |
| 10878 @override | |
| 10879 DartType get type => substituteFor(baseElement.type); | |
| 10880 | |
| 10881 @override | |
| 10882 void visitChildren(ElementVisitor visitor) { | |
| 10883 // TODO(brianwilkerson) We need to finish implementing the accessors used | |
| 10884 // below so that we can safely invoke them. | |
| 10885 super.visitChildren(visitor); | |
| 10886 safelyVisitChild(baseElement.initializer, visitor); | |
| 10887 } | |
| 10888 } | |
| 10889 | |
| 10890 /** | |
| 10891 * The type `void`. | |
| 10892 */ | |
| 10893 abstract class VoidType implements DartType { | |
| 10894 @override | |
| 10895 VoidType substitute2( | |
| 10896 List<DartType> argumentTypes, List<DartType> parameterTypes); | |
| 10897 } | |
| 10898 | |
| 10899 /** | |
| 10900 * A concrete implementation of a [VoidType]. | |
| 10901 */ | |
| 10902 class VoidTypeImpl extends TypeImpl implements VoidType { | |
| 10903 /** | |
| 10904 * The unique instance of this class. | |
| 10905 */ | |
| 10906 static VoidTypeImpl _INSTANCE = new VoidTypeImpl(); | |
| 10907 | |
| 10908 /** | |
| 10909 * Return the unique instance of this class. | |
| 10910 */ | |
| 10911 static VoidTypeImpl get instance => _INSTANCE; | |
| 10912 | |
| 10913 /** | |
| 10914 * Prevent the creation of instances of this class. | |
| 10915 */ | |
| 10916 VoidTypeImpl() : super(null, Keyword.VOID.syntax); | |
| 10917 | |
| 10918 @override | |
| 10919 int get hashCode => 2; | |
| 10920 | |
| 10921 @override | |
| 10922 bool get isVoid => true; | |
| 10923 | |
| 10924 @override | |
| 10925 bool operator ==(Object object) => identical(object, this); | |
| 10926 | |
| 10927 @override | |
| 10928 bool isMoreSpecificThan(DartType type, | |
| 10929 [bool withDynamic = false, Set<Element> visitedElements]) => | |
| 10930 isSubtypeOf(type); | |
| 10931 | |
| 10932 @override | |
| 10933 bool isSubtypeOf(DartType type) { | |
| 10934 // The only subtype relations that pertain to void are therefore: | |
| 10935 // void <: void (by reflexivity) | |
| 10936 // bottom <: void (as bottom is a subtype of all types). | |
| 10937 // void <: dynamic (as dynamic is a supertype of all types) | |
| 10938 return identical(type, this) || type.isDynamic; | |
| 10939 } | |
| 10940 | |
| 10941 @override | |
| 10942 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this; | |
| 10943 | |
| 10944 @override | |
| 10945 VoidTypeImpl substitute2( | |
| 10946 List<DartType> argumentTypes, List<DartType> parameterTypes, | |
| 10947 [List<FunctionTypeAliasElement> prune]) => | |
| 10948 this; | |
| 10949 } | |
| 10950 | |
| 10951 /** | |
| 10952 * A visitor that visit all the elements recursively and fill the given [map]. | |
| 10953 */ | |
| 10954 class _BuildOffsetToElementMap extends GeneralizingElementVisitor { | |
| 10955 final Map<int, Element> map; | |
| 10956 | |
| 10957 _BuildOffsetToElementMap(this.map); | |
| 10958 | |
| 10959 @override | |
| 10960 void visitElement(Element element) { | |
| 10961 int offset = element.nameOffset; | |
| 10962 if (offset != -1) { | |
| 10963 map[offset] = element; | |
| 10964 } | |
| 10965 super.visitElement(element); | |
| 10966 } | |
| 10967 } | |
| OLD | NEW |