Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: pkg/analyzer/lib/src/generated/element.dart

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

Powered by Google App Engine
This is Rietveld 408576698