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