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

Side by Side Diff: mojo/public/dart/third_party/analyzer/lib/src/generated/element.dart

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

Powered by Google App Engine
This is Rietveld 408576698