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