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

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

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

Powered by Google App Engine
This is Rietveld 408576698