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

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

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

Powered by Google App Engine
This is Rietveld 408576698