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

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

Issue 1525663003: Move the remainder of generated/element.dart into better locations (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analyzer/CHANGELOG.md ('k') | pkg/analyzer/lib/src/dart/element/member.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.generated.element; 5 library analyzer.src.dart.element.element;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' show min; 8 import 'dart:math' show min;
9 9
10 import 'package:analyzer/dart/element/element.dart'; 10 import 'package:analyzer/dart/element/element.dart';
11 import 'package:analyzer/dart/element/type.dart'; 11 import 'package:analyzer/dart/element/type.dart';
12 import 'package:analyzer/dart/element/visitor.dart'; 12 import 'package:analyzer/dart/element/visitor.dart';
13 import 'package:analyzer/src/dart/element/type.dart';
13 import 'package:analyzer/src/generated/ast.dart'; 14 import 'package:analyzer/src/generated/ast.dart';
14 import 'package:analyzer/src/generated/constant.dart' 15 import 'package:analyzer/src/generated/constant.dart'
15 show DartObject, EvaluationResultImpl; 16 show DartObject, EvaluationResultImpl;
16 import 'package:analyzer/src/generated/engine.dart' 17 import 'package:analyzer/src/generated/engine.dart'
17 show AnalysisContext, AnalysisEngine, AnalysisException; 18 show AnalysisContext, AnalysisEngine, AnalysisException;
18 import 'package:analyzer/src/generated/java_core.dart'; 19 import 'package:analyzer/src/generated/java_core.dart';
19 import 'package:analyzer/src/generated/java_engine.dart'; 20 import 'package:analyzer/src/generated/java_engine.dart';
20 import 'package:analyzer/src/generated/resolver.dart'; 21 import 'package:analyzer/src/generated/resolver.dart';
21 import 'package:analyzer/src/generated/scanner.dart' show Keyword; 22 import 'package:analyzer/src/generated/scanner.dart' show Keyword;
22 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; 23 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
23 import 'package:analyzer/src/generated/source.dart'; 24 import 'package:analyzer/src/generated/source.dart';
24 import 'package:analyzer/src/generated/utilities_collection.dart'; 25 import 'package:analyzer/src/generated/utilities_collection.dart';
25 import 'package:analyzer/src/generated/utilities_dart.dart'; 26 import 'package:analyzer/src/generated/utilities_dart.dart';
26 import 'package:analyzer/src/generated/utilities_general.dart'; 27 import 'package:analyzer/src/generated/utilities_general.dart';
27 28
28 export 'package:analyzer/dart/element/element.dart';
29 export 'package:analyzer/dart/element/type.dart';
30 export 'package:analyzer/dart/element/visitor.dart';
31
32 /** 29 /**
33 * For AST nodes that could be in both the getter and setter contexts 30 * For AST nodes that could be in both the getter and setter contexts
34 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved 31 * ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved
35 * elements are stored in the AST node, in an [AuxiliaryElements]. Because 32 * elements are stored in the AST node, in an [AuxiliaryElements]. Because
36 * resolved elements are either statically resolved or resolved using propagated 33 * resolved elements are either statically resolved or resolved using propagated
37 * type information, this class is a wrapper for a pair of [ExecutableElement]s, 34 * type information, this class is a wrapper for a pair of [ExecutableElement]s,
38 * not just a single [ExecutableElement]. 35 * not just a single [ExecutableElement].
39 */ 36 */
40 class AuxiliaryElements { 37 class AuxiliaryElements {
41 /** 38 /**
42 * The element based on propagated type information, or `null` if the AST 39 * The element based on propagated type information, or `null` if the AST
43 * structure has not been resolved or if the node could not be resolved. 40 * structure has not been resolved or if the node could not be resolved.
44 */ 41 */
45 final ExecutableElement propagatedElement; 42 final ExecutableElement propagatedElement;
46 43
47 /** 44 /**
48 * The element based on static type information, or `null` if the AST 45 * The element based on static type information, or `null` if the AST
49 * structure has not been resolved or if the node could not be resolved. 46 * structure has not been resolved or if the node could not be resolved.
50 */ 47 */
51 final ExecutableElement staticElement; 48 final ExecutableElement staticElement;
52 49
53 /** 50 /**
54 * Initialize a newly created pair to have both the [staticElement] and the 51 * Initialize a newly created pair to have both the [staticElement] and the
55 * [propagatedElement]. 52 * [propagatedElement].
56 */ 53 */
57 AuxiliaryElements(this.staticElement, this.propagatedElement); 54 AuxiliaryElements(this.staticElement, this.propagatedElement);
58 } 55 }
59 56
60 /** 57 /**
61 * A [Type] that represents the type 'bottom'.
62 */
63 class BottomTypeImpl extends TypeImpl {
64 /**
65 * The unique instance of this class.
66 */
67 static BottomTypeImpl _INSTANCE = new BottomTypeImpl._();
68
69 /**
70 * Return the unique instance of this class.
71 */
72 static BottomTypeImpl get instance => _INSTANCE;
73
74 /**
75 * Prevent the creation of instances of this class.
76 */
77 BottomTypeImpl._() : super(null, "<bottom>");
78
79 @override
80 int get hashCode => 0;
81
82 @override
83 bool get isBottom => true;
84
85 @override
86 bool operator ==(Object object) => identical(object, this);
87
88 @override
89 bool isMoreSpecificThan(DartType type,
90 [bool withDynamic = false, Set<Element> visitedElements]) =>
91 true;
92
93 @override
94 bool isSubtypeOf(DartType type) => true;
95
96 @override
97 bool isSupertypeOf(DartType type) => false;
98
99 @override
100 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
101
102 @override
103 BottomTypeImpl substitute2(
104 List<DartType> argumentTypes, List<DartType> parameterTypes,
105 [List<FunctionTypeAliasElement> prune]) =>
106 this;
107 }
108
109 /**
110 * Type created internally if a circular reference is ever detected. Behaves
111 * like `dynamic`, except that when converted to a string it is displayed as
112 * `...`.
113 */
114 class CircularTypeImpl extends DynamicTypeImpl {
115 CircularTypeImpl() : super._circular();
116
117 @override
118 int get hashCode => 1;
119
120 @override
121 bool operator ==(Object object) => object is CircularTypeImpl;
122
123 @override
124 void appendTo(StringBuffer buffer) {
125 buffer.write('...');
126 }
127
128 @override
129 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
130 }
131
132 /**
133 * A concrete implementation of a [ClassElement]. 58 * A concrete implementation of a [ClassElement].
134 */ 59 */
135 class ClassElementImpl extends ElementImpl implements ClassElement { 60 class ClassElementImpl extends ElementImpl implements ClassElement {
136 /** 61 /**
137 * A list containing all of the accessors (getters and setters) contained in 62 * A list containing all of the accessors (getters and setters) contained in
138 * this class. 63 * this class.
139 */ 64 */
140 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; 65 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST;
141 66
142 /** 67 /**
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 } 1369 }
1445 super.appendTo(buffer); 1370 super.appendTo(buffer);
1446 } 1371 }
1447 1372
1448 @override 1373 @override
1449 ConstructorDeclaration computeNode() => 1374 ConstructorDeclaration computeNode() =>
1450 getNodeMatching((node) => node is ConstructorDeclaration); 1375 getNodeMatching((node) => node is ConstructorDeclaration);
1451 } 1376 }
1452 1377
1453 /** 1378 /**
1454 * A constructor element defined in a parameterized type where the values of the
1455 * type parameters are known.
1456 */
1457 class ConstructorMember extends ExecutableMember implements ConstructorElement {
1458 /**
1459 * Initialize a newly created element to represent a constructor, based on the
1460 * [baseElement], defined by the [definingType]. If [type] is passed, it
1461 * represents the full type of the member, and will take precedence over
1462 * the [definingType].
1463 */
1464 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType,
1465 [FunctionType type])
1466 : super(baseElement, definingType, type);
1467
1468 @override
1469 ConstructorElement get baseElement => super.baseElement as ConstructorElement;
1470
1471 @override
1472 InterfaceType get definingType => super.definingType as InterfaceType;
1473
1474 @override
1475 ClassElement get enclosingElement => baseElement.enclosingElement;
1476
1477 @override
1478 bool get isConst => baseElement.isConst;
1479
1480 @override
1481 bool get isDefaultConstructor => baseElement.isDefaultConstructor;
1482
1483 @override
1484 bool get isFactory => baseElement.isFactory;
1485
1486 @override
1487 int get nameEnd => baseElement.nameEnd;
1488
1489 @override
1490 int get periodOffset => baseElement.periodOffset;
1491
1492 @override
1493 ConstructorElement get redirectedConstructor =>
1494 from(baseElement.redirectedConstructor, definingType);
1495
1496 @override
1497 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
1498
1499 @override
1500 ConstructorDeclaration computeNode() => baseElement.computeNode();
1501
1502 @override
1503 String toString() {
1504 ConstructorElement baseElement = this.baseElement;
1505 List<ParameterElement> parameters = this.parameters;
1506 FunctionType type = this.type;
1507 StringBuffer buffer = new StringBuffer();
1508 buffer.write(baseElement.enclosingElement.displayName);
1509 String name = displayName;
1510 if (name != null && !name.isEmpty) {
1511 buffer.write(".");
1512 buffer.write(name);
1513 }
1514 buffer.write("(");
1515 int parameterCount = parameters.length;
1516 for (int i = 0; i < parameterCount; i++) {
1517 if (i > 0) {
1518 buffer.write(", ");
1519 }
1520 buffer.write(parameters[i]);
1521 }
1522 buffer.write(")");
1523 if (type != null) {
1524 buffer.write(ElementImpl.RIGHT_ARROW);
1525 buffer.write(type.returnType);
1526 }
1527 return buffer.toString();
1528 }
1529
1530 /**
1531 * If the given [constructor]'s type is different when any type parameters
1532 * from the defining type's declaration are replaced with the actual type
1533 * arguments from the [definingType], create a constructor member representing
1534 * the given constructor. Return the member that was created, or the original
1535 * constructor if no member was created.
1536 */
1537 static ConstructorElement from(
1538 ConstructorElement constructor, InterfaceType definingType) {
1539 if (constructor == null || definingType.typeArguments.length == 0) {
1540 return constructor;
1541 }
1542 FunctionType baseType = constructor.type;
1543 if (baseType == null) {
1544 // TODO(brianwilkerson) We need to understand when this can happen.
1545 return constructor;
1546 }
1547 List<DartType> argumentTypes = definingType.typeArguments;
1548 List<DartType> parameterTypes = definingType.element.type.typeArguments;
1549 FunctionType substitutedType =
1550 baseType.substitute2(argumentTypes, parameterTypes);
1551 if (baseType == substitutedType) {
1552 return constructor;
1553 }
1554 return new ConstructorMember(constructor, definingType, substitutedType);
1555 }
1556 }
1557
1558 /**
1559 * A [TopLevelVariableElement] for a top-level 'const' variable that has an 1379 * A [TopLevelVariableElement] for a top-level 'const' variable that has an
1560 * initializer. 1380 * initializer.
1561 */ 1381 */
1562 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl 1382 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
1563 with ConstVariableElement { 1383 with ConstVariableElement {
1564 /** 1384 /**
1565 * The result of evaluating this variable's initializer. 1385 * The result of evaluating this variable's initializer.
1566 */ 1386 */
1567 EvaluationResultImpl _result; 1387 EvaluationResultImpl _result;
1568 1388
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1690 } 1510 }
1691 1511
1692 @override 1512 @override
1693 ElementKind get kind => ElementKind.DYNAMIC; 1513 ElementKind get kind => ElementKind.DYNAMIC;
1694 1514
1695 @override 1515 @override
1696 accept(ElementVisitor visitor) => null; 1516 accept(ElementVisitor visitor) => null;
1697 } 1517 }
1698 1518
1699 /** 1519 /**
1700 * The [Type] representing the type `dynamic`.
1701 */
1702 class DynamicTypeImpl extends TypeImpl {
1703 /**
1704 * The unique instance of this class.
1705 */
1706 static DynamicTypeImpl _INSTANCE = new DynamicTypeImpl._();
1707
1708 /**
1709 * Return the unique instance of this class.
1710 */
1711 static DynamicTypeImpl get instance => _INSTANCE;
1712
1713 /**
1714 * Prevent the creation of instances of this class.
1715 */
1716 DynamicTypeImpl._()
1717 : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) {
1718 (element as DynamicElementImpl).type = this;
1719 }
1720
1721 /**
1722 * Constructor used by [CircularTypeImpl].
1723 */
1724 DynamicTypeImpl._circular()
1725 : super(_INSTANCE.element, Keyword.DYNAMIC.syntax);
1726
1727 @override
1728 int get hashCode => 1;
1729
1730 @override
1731 bool get isDynamic => true;
1732
1733 @override
1734 bool operator ==(Object object) => identical(object, this);
1735
1736 @override
1737 bool isMoreSpecificThan(DartType type,
1738 [bool withDynamic = false, Set<Element> visitedElements]) {
1739 // T is S
1740 if (identical(this, type)) {
1741 return true;
1742 }
1743 // else
1744 return withDynamic;
1745 }
1746
1747 @override
1748 bool isSubtypeOf(DartType type) => true;
1749
1750 @override
1751 bool isSupertypeOf(DartType type) => true;
1752
1753 @override
1754 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
1755
1756 @override
1757 DartType substitute2(
1758 List<DartType> argumentTypes, List<DartType> parameterTypes,
1759 [List<FunctionTypeAliasElement> prune]) {
1760 int length = parameterTypes.length;
1761 for (int i = 0; i < length; i++) {
1762 if (parameterTypes[i] == this) {
1763 return argumentTypes[i];
1764 }
1765 }
1766 return this;
1767 }
1768 }
1769
1770 /**
1771 * A concrete implementation of an [ElementAnnotation]. 1520 * A concrete implementation of an [ElementAnnotation].
1772 */ 1521 */
1773 class ElementAnnotationImpl implements ElementAnnotation { 1522 class ElementAnnotationImpl implements ElementAnnotation {
1774 /** 1523 /**
1775 * The name of the class used to mark an element as being deprecated. 1524 * The name of the class used to mark an element as being deprecated.
1776 */ 1525 */
1777 static String _DEPRECATED_CLASS_NAME = "Deprecated"; 1526 static String _DEPRECATED_CLASS_NAME = "Deprecated";
1778 1527
1779 /** 1528 /**
1780 * The name of the top-level variable used to mark an element as being 1529 * The name of the top-level variable used to mark an element as being
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 void visitChildren(ElementVisitor visitor) { 2392 void visitChildren(ElementVisitor visitor) {
2644 super.visitChildren(visitor); 2393 super.visitChildren(visitor);
2645 safelyVisitChildren(_functions, visitor); 2394 safelyVisitChildren(_functions, visitor);
2646 safelyVisitChildren(_labels, visitor); 2395 safelyVisitChildren(_labels, visitor);
2647 safelyVisitChildren(_localVariables, visitor); 2396 safelyVisitChildren(_localVariables, visitor);
2648 safelyVisitChildren(_parameters, visitor); 2397 safelyVisitChildren(_parameters, visitor);
2649 } 2398 }
2650 } 2399 }
2651 2400
2652 /** 2401 /**
2653 * An executable element defined in a parameterized type where the values of the
2654 * type parameters are known.
2655 */
2656 abstract class ExecutableMember extends Member implements ExecutableElement {
2657 @override
2658 final FunctionType type;
2659
2660 /**
2661 * Initialize a newly created element to represent a callable element (like a
2662 * method or function or property), based on the [baseElement], defined by the
2663 * [definingType]. If [type] is passed, it represents the full type of the
2664 * member, and will take precedence over the [definingType].
2665 */
2666 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType,
2667 [FunctionType type])
2668 : type = type ??
2669 baseElement.type.substitute2(definingType.typeArguments,
2670 TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
2671 super(baseElement, definingType);
2672
2673 @override
2674 ExecutableElement get baseElement => super.baseElement as ExecutableElement;
2675
2676 @override
2677 List<FunctionElement> get functions {
2678 //
2679 // Elements within this element should have type parameters substituted,
2680 // just like this element.
2681 //
2682 throw new UnsupportedOperationException();
2683 // return getBaseElement().getFunctions();
2684 }
2685
2686 @override
2687 bool get hasImplicitReturnType => baseElement.hasImplicitReturnType;
2688
2689 @override
2690 bool get isAbstract => baseElement.isAbstract;
2691
2692 @override
2693 bool get isAsynchronous => baseElement.isAsynchronous;
2694
2695 @override
2696 bool get isExternal => baseElement.isExternal;
2697
2698 @override
2699 bool get isGenerator => baseElement.isGenerator;
2700
2701 @override
2702 bool get isOperator => baseElement.isOperator;
2703
2704 @override
2705 bool get isStatic => baseElement.isStatic;
2706
2707 @override
2708 bool get isSynchronous => baseElement.isSynchronous;
2709
2710 @override
2711 List<LabelElement> get labels => baseElement.labels;
2712
2713 @override
2714 List<LocalVariableElement> get localVariables {
2715 //
2716 // Elements within this element should have type parameters substituted,
2717 // just like this element.
2718 //
2719 throw new UnsupportedOperationException();
2720 // return getBaseElement().getLocalVariables();
2721 }
2722
2723 @override
2724 List<ParameterElement> get parameters => type.parameters;
2725
2726 @override
2727 DartType get returnType => type.returnType;
2728
2729 @override
2730 List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
2731
2732 @override
2733 void visitChildren(ElementVisitor visitor) {
2734 // TODO(brianwilkerson) We need to finish implementing the accessors used
2735 // below so that we can safely invoke them.
2736 super.visitChildren(visitor);
2737 safelyVisitChildren(baseElement.functions, visitor);
2738 safelyVisitChildren(labels, visitor);
2739 safelyVisitChildren(baseElement.localVariables, visitor);
2740 safelyVisitChildren(parameters, visitor);
2741 }
2742 }
2743
2744 /**
2745 * A concrete implementation of an [ExportElement]. 2402 * A concrete implementation of an [ExportElement].
2746 */ 2403 */
2747 class ExportElementImpl extends UriReferencedElementImpl 2404 class ExportElementImpl extends UriReferencedElementImpl
2748 implements ExportElement { 2405 implements ExportElement {
2749 /** 2406 /**
2750 * The library that is exported from this library by this export directive. 2407 * The library that is exported from this library by this export directive.
2751 */ 2408 */
2752 LibraryElement exportedLibrary; 2409 LibraryElement exportedLibrary;
2753 2410
2754 /** 2411 /**
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2842 2499
2843 @override 2500 @override
2844 bool get isInitializingFormal => true; 2501 bool get isInitializingFormal => true;
2845 2502
2846 @override 2503 @override
2847 accept(ElementVisitor visitor) => 2504 accept(ElementVisitor visitor) =>
2848 visitor.visitFieldFormalParameterElement(this); 2505 visitor.visitFieldFormalParameterElement(this);
2849 } 2506 }
2850 2507
2851 /** 2508 /**
2852 * A parameter element defined in a parameterized type where the values of the
2853 * type parameters are known.
2854 */
2855 class FieldFormalParameterMember extends ParameterMember
2856 implements FieldFormalParameterElement {
2857 /**
2858 * Initialize a newly created element to represent a field formal parameter,
2859 * based on the [baseElement], defined by the [definingType]. If [type]
2860 * is passed it will be used as the substituted type for this member.
2861 */
2862 FieldFormalParameterMember(
2863 FieldFormalParameterElement baseElement, ParameterizedType definingType,
2864 [DartType type])
2865 : super(baseElement, definingType, type);
2866
2867 @override
2868 FieldElement get field {
2869 FieldElement field = (baseElement as FieldFormalParameterElement).field;
2870 if (field is FieldElement) {
2871 return FieldMember.from(
2872 field, substituteFor(field.enclosingElement.type));
2873 }
2874 return field;
2875 }
2876
2877 @override
2878 accept(ElementVisitor visitor) =>
2879 visitor.visitFieldFormalParameterElement(this);
2880 }
2881
2882 /**
2883 * A field element defined in a parameterized type where the values of the type
2884 * parameters are known.
2885 */
2886 class FieldMember extends VariableMember implements FieldElement {
2887 /**
2888 * Initialize a newly created element to represent a field, based on the
2889 * [baseElement], defined by the [definingType].
2890 */
2891 FieldMember(FieldElement baseElement, InterfaceType definingType)
2892 : super(baseElement, definingType);
2893
2894 @override
2895 FieldElement get baseElement => super.baseElement as FieldElement;
2896
2897 @override
2898 ClassElement get enclosingElement => baseElement.enclosingElement;
2899
2900 @override
2901 PropertyAccessorElement get getter =>
2902 PropertyAccessorMember.from(baseElement.getter, definingType);
2903
2904 @override
2905 bool get isEnumConstant => baseElement.isEnumConstant;
2906
2907 @override
2908 DartType get propagatedType => substituteFor(baseElement.propagatedType);
2909
2910 @override
2911 PropertyAccessorElement get setter =>
2912 PropertyAccessorMember.from(baseElement.setter, definingType);
2913
2914 @override
2915 accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
2916
2917 @override
2918 VariableDeclaration computeNode() => baseElement.computeNode();
2919
2920 @override
2921 String toString() => '$type $displayName';
2922
2923 /**
2924 * If the given [field]'s type is different when any type parameters from the
2925 * defining type's declaration are replaced with the actual type arguments
2926 * from the [definingType], create a field member representing the given
2927 * field. Return the member that was created, or the base field if no member
2928 * was created.
2929 */
2930 static FieldElement from(FieldElement field, ParameterizedType definingType) {
2931 if (!_isChangedByTypeSubstitution(field, definingType)) {
2932 return field;
2933 }
2934 // TODO(brianwilkerson) Consider caching the substituted type in the
2935 // instance. It would use more memory but speed up some operations.
2936 // We need to see how often the type is being re-computed.
2937 return new FieldMember(field, definingType);
2938 }
2939
2940 /**
2941 * Determine whether the given [field]'s type is changed when type parameters
2942 * from the [definingType]'s declaration are replaced with the actual type
2943 * arguments from the defining type.
2944 */
2945 static bool _isChangedByTypeSubstitution(
2946 FieldElement field, ParameterizedType definingType) {
2947 List<DartType> argumentTypes = definingType.typeArguments;
2948 if (field != null && argumentTypes.length != 0) {
2949 DartType baseType = field.type;
2950 List<DartType> parameterTypes =
2951 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
2952 if (baseType != null) {
2953 DartType substitutedType =
2954 baseType.substitute2(argumentTypes, parameterTypes);
2955 if (baseType != substitutedType) {
2956 return true;
2957 }
2958 }
2959 // If the field has a propagated type, then we need to check whether the
2960 // propagated type needs substitution.
2961 DartType basePropagatedType = field.propagatedType;
2962 if (basePropagatedType != null) {
2963 DartType substitutedPropagatedType =
2964 basePropagatedType.substitute2(argumentTypes, parameterTypes);
2965 if (basePropagatedType != substitutedPropagatedType) {
2966 return true;
2967 }
2968 }
2969 }
2970 return false;
2971 }
2972 }
2973
2974 /**
2975 * A concrete implementation of a [FunctionElement]. 2509 * A concrete implementation of a [FunctionElement].
2976 */ 2510 */
2977 class FunctionElementImpl extends ExecutableElementImpl 2511 class FunctionElementImpl extends ExecutableElementImpl
2978 implements FunctionElement { 2512 implements FunctionElement {
2979 /** 2513 /**
2980 * The offset to the beginning of the visible range for this element. 2514 * The offset to the beginning of the visible range for this element.
2981 */ 2515 */
2982 int _visibleRangeOffset = 0; 2516 int _visibleRangeOffset = 0;
2983 2517
2984 /** 2518 /**
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3061 * Set the parameters defined by this type alias to the given [parameters] 2595 * Set the parameters defined by this type alias to the given [parameters]
3062 * without becoming the parent of the parameters. This should only be used by 2596 * without becoming the parent of the parameters. This should only be used by
3063 * the [TypeResolverVisitor] when creating a synthetic type alias. 2597 * the [TypeResolverVisitor] when creating a synthetic type alias.
3064 */ 2598 */
3065 void shareParameters(List<ParameterElement> parameters) { 2599 void shareParameters(List<ParameterElement> parameters) {
3066 this._parameters = parameters; 2600 this._parameters = parameters;
3067 } 2601 }
3068 } 2602 }
3069 2603
3070 /** 2604 /**
3071 * An element of a generic function, where the type parameters are known.
3072 */
3073 // TODO(jmesserly): the term "function member" is a bit weird, but it allows
3074 // a certain consistency.
3075 class FunctionMember extends ExecutableMember implements FunctionElement {
3076 /**
3077 * Initialize a newly created element to represent a function, based on the
3078 * [baseElement], with the corresponding function [type].
3079 */
3080 FunctionMember(FunctionElement baseElement, [DartType type])
3081 : super(baseElement, null, type);
3082
3083 @override
3084 FunctionElement get baseElement => super.baseElement as FunctionElement;
3085
3086 @override
3087 Element get enclosingElement => baseElement.enclosingElement;
3088
3089 @override
3090 bool get isEntryPoint => baseElement.isEntryPoint;
3091
3092 @override
3093 SourceRange get visibleRange => baseElement.visibleRange;
3094
3095 @override
3096 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
3097
3098 @override
3099 FunctionDeclaration computeNode() => baseElement.computeNode();
3100
3101 @override
3102 String toString() {
3103 StringBuffer buffer = new StringBuffer();
3104 buffer.write(baseElement.displayName);
3105 (type as FunctionTypeImpl).appendTo(buffer);
3106 return buffer.toString();
3107 }
3108
3109 /**
3110 * If the given [method]'s type is different when any type parameters from the
3111 * defining type's declaration are replaced with the actual type arguments
3112 * from the [definingType], create a method member representing the given
3113 * method. Return the member that was created, or the base method if no member
3114 * was created.
3115 */
3116 static MethodElement from(
3117 MethodElement method, ParameterizedType definingType) {
3118 if (method == null || definingType.typeArguments.length == 0) {
3119 return method;
3120 }
3121 FunctionType baseType = method.type;
3122 List<DartType> argumentTypes = definingType.typeArguments;
3123 List<DartType> parameterTypes =
3124 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
3125 FunctionType substitutedType =
3126 baseType.substitute2(argumentTypes, parameterTypes);
3127 if (baseType == substitutedType) {
3128 return method;
3129 }
3130 return new MethodMember(method, definingType, substitutedType);
3131 }
3132 }
3133
3134 /**
3135 * A concrete implementation of a [FunctionTypeAliasElement]. 2605 * A concrete implementation of a [FunctionTypeAliasElement].
3136 */ 2606 */
3137 class FunctionTypeAliasElementImpl extends ElementImpl 2607 class FunctionTypeAliasElementImpl extends ElementImpl
3138 implements FunctionTypeAliasElement { 2608 implements FunctionTypeAliasElement {
3139 /** 2609 /**
3140 * A list containing all of the parameters defined by this type alias. 2610 * A list containing all of the parameters defined by this type alias.
3141 */ 2611 */
3142 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST; 2612 List<ParameterElement> _parameters = ParameterElement.EMPTY_LIST;
3143 2613
3144 /** 2614 /**
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
3265 2735
3266 @override 2736 @override
3267 void visitChildren(ElementVisitor visitor) { 2737 void visitChildren(ElementVisitor visitor) {
3268 super.visitChildren(visitor); 2738 super.visitChildren(visitor);
3269 safelyVisitChildren(_parameters, visitor); 2739 safelyVisitChildren(_parameters, visitor);
3270 safelyVisitChildren(_typeParameters, visitor); 2740 safelyVisitChildren(_typeParameters, visitor);
3271 } 2741 }
3272 } 2742 }
3273 2743
3274 /** 2744 /**
3275 * The type of a function, method, constructor, getter, or setter.
3276 */
3277 class FunctionTypeImpl extends TypeImpl implements FunctionType {
3278 /**
3279 * The list of [typeArguments].
3280 */
3281 List<DartType> _typeArguments;
3282
3283 /**
3284 * The list of [typeParameters].
3285 */
3286 List<TypeParameterElement> _typeParameters;
3287
3288 /**
3289 * The list of [boundTypeParameters].
3290 */
3291 List<TypeParameterElement> _boundTypeParameters;
3292
3293 /**
3294 * The set of typedefs which should not be expanded when exploring this type,
3295 * to avoid creating infinite types in response to self-referential typedefs.
3296 */
3297 final List<FunctionTypeAliasElement> prunedTypedefs;
3298
3299 /**
3300 * Initialize a newly created function type to be declared by the given
3301 * [element], and also initialize [typeArguments] to match the
3302 * [typeParameters], which permits later substitution.
3303 */
3304 FunctionTypeImpl(ExecutableElement element,
3305 [List<FunctionTypeAliasElement> prunedTypedefs])
3306 : this._(element, null, prunedTypedefs, null, null, null);
3307
3308 /**
3309 * Initialize a newly created function type to be declared by the given
3310 * [element].
3311 */
3312 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
3313 [List<FunctionTypeAliasElement> prunedTypedefs])
3314 : this._(element, element?.name, prunedTypedefs, null, null, null);
3315
3316 /**
3317 * Private constructor.
3318 */
3319 FunctionTypeImpl._(
3320 TypeParameterizedElement element,
3321 String name,
3322 this.prunedTypedefs,
3323 List<DartType> typeArguments,
3324 List<TypeParameterElement> typeParameters,
3325 List<TypeParameterElement> boundTypeParameters)
3326 : super(element, name) {
3327 _boundTypeParameters = boundTypeParameters ??
3328 element?.typeParameters ??
3329 TypeParameterElement.EMPTY_LIST;
3330
3331 if (typeParameters == null) {
3332 // Combine the generic type variables from all enclosing contexts, except
3333 // for this generic function's type variables. Those variables are
3334 // tracked in [boundTypeParameters].
3335 typeParameters = <TypeParameterElement>[];
3336 Element e = element?.enclosingElement;
3337 while (e != null) {
3338 if (e is TypeParameterizedElement) {
3339 typeParameters.addAll((e as TypeParameterizedElement).typeParameters);
3340 }
3341 e = e.enclosingElement;
3342 }
3343 }
3344 _typeParameters = typeParameters;
3345
3346 if (typeArguments == null) {
3347 // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
3348 // make it generic, which will allow it to return List<DartType> instead
3349 // of List<TypeParameterType>.
3350 if (typeParameters.isEmpty) {
3351 typeArguments = DartType.EMPTY_LIST;
3352 } else {
3353 typeArguments = new List<DartType>.from(
3354 typeParameters.map((t) => t.type),
3355 growable: false);
3356 }
3357 }
3358 _typeArguments = typeArguments;
3359 }
3360
3361 /**
3362 * Return the base parameter elements of this function element.
3363 */
3364 List<ParameterElement> get baseParameters => element.parameters;
3365
3366 /**
3367 * Return the return type defined by this function's element.
3368 */
3369 DartType get baseReturnType => element.returnType;
3370
3371 @override
3372 List<TypeParameterElement> get boundTypeParameters => _boundTypeParameters;
3373
3374 @override
3375 String get displayName {
3376 String name = this.name;
3377 if (name == null || name.length == 0) {
3378 // Function types have an empty name when they are defined implicitly by
3379 // either a closure or as part of a parameter declaration.
3380 List<DartType> normalParameterTypes = this.normalParameterTypes;
3381 List<DartType> optionalParameterTypes = this.optionalParameterTypes;
3382 Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
3383 DartType returnType = this.returnType;
3384 StringBuffer buffer = new StringBuffer();
3385 buffer.write("(");
3386 bool needsComma = false;
3387 if (normalParameterTypes.length > 0) {
3388 for (DartType type in normalParameterTypes) {
3389 if (needsComma) {
3390 buffer.write(", ");
3391 } else {
3392 needsComma = true;
3393 }
3394 buffer.write(type.displayName);
3395 }
3396 }
3397 if (optionalParameterTypes.length > 0) {
3398 if (needsComma) {
3399 buffer.write(", ");
3400 needsComma = false;
3401 }
3402 buffer.write("[");
3403 for (DartType type in optionalParameterTypes) {
3404 if (needsComma) {
3405 buffer.write(", ");
3406 } else {
3407 needsComma = true;
3408 }
3409 buffer.write(type.displayName);
3410 }
3411 buffer.write("]");
3412 needsComma = true;
3413 }
3414 if (namedParameterTypes.length > 0) {
3415 if (needsComma) {
3416 buffer.write(", ");
3417 needsComma = false;
3418 }
3419 buffer.write("{");
3420 namedParameterTypes.forEach((String name, DartType type) {
3421 if (needsComma) {
3422 buffer.write(", ");
3423 } else {
3424 needsComma = true;
3425 }
3426 buffer.write(name);
3427 buffer.write(": ");
3428 buffer.write(type.displayName);
3429 });
3430 buffer.write("}");
3431 needsComma = true;
3432 }
3433 buffer.write(")");
3434 buffer.write(ElementImpl.RIGHT_ARROW);
3435 if (returnType == null) {
3436 buffer.write("null");
3437 } else {
3438 buffer.write(returnType.displayName);
3439 }
3440 name = buffer.toString();
3441 }
3442 return name;
3443 }
3444
3445 @override
3446 FunctionTypedElement get element => super.element;
3447
3448 @override
3449 int get hashCode {
3450 if (element == null) {
3451 return 0;
3452 }
3453 // Reference the arrays of parameters
3454 List<DartType> normalParameterTypes = this.normalParameterTypes;
3455 List<DartType> optionalParameterTypes = this.optionalParameterTypes;
3456 Iterable<DartType> namedParameterTypes = this.namedParameterTypes.values;
3457 // Generate the hashCode
3458 int code = (returnType as TypeImpl).hashCode;
3459 for (int i = 0; i < normalParameterTypes.length; i++) {
3460 code = (code << 1) + (normalParameterTypes[i] as TypeImpl).hashCode;
3461 }
3462 for (int i = 0; i < optionalParameterTypes.length; i++) {
3463 code = (code << 1) + (optionalParameterTypes[i] as TypeImpl).hashCode;
3464 }
3465 for (DartType type in namedParameterTypes) {
3466 code = (code << 1) + (type as TypeImpl).hashCode;
3467 }
3468 return code;
3469 }
3470
3471 /**
3472 * The type arguments that were used to instantiate this function type, if
3473 * any, otherwise this will return an empty list.
3474 *
3475 * Given a function type `f`:
3476 *
3477 * f == f.originalFunction.instantiate(f.instantiatedTypeArguments)
3478 *
3479 * Will always hold.
3480 */
3481 List<DartType> get instantiatedTypeArguments {
3482 int typeParameterCount = element.type.boundTypeParameters.length;
3483 if (typeParameterCount == 0) {
3484 return DartType.EMPTY_LIST;
3485 }
3486 // The substituted types at the end should be our bound type parameters.
3487 int skipCount = typeArguments.length - typeParameterCount;
3488 return new List<DartType>.from(typeArguments.skip(skipCount));
3489 }
3490
3491 @override
3492 Map<String, DartType> get namedParameterTypes {
3493 LinkedHashMap<String, DartType> namedParameterTypes =
3494 new LinkedHashMap<String, DartType>();
3495 List<ParameterElement> parameters = baseParameters;
3496 if (parameters.length == 0) {
3497 return namedParameterTypes;
3498 }
3499 List<DartType> typeParameters =
3500 TypeParameterTypeImpl.getTypes(this.typeParameters);
3501 for (ParameterElement parameter in parameters) {
3502 if (parameter.parameterKind == ParameterKind.NAMED) {
3503 DartType type = parameter.type;
3504 if (typeArguments.length != 0 &&
3505 typeArguments.length == typeParameters.length) {
3506 type = (type as TypeImpl)
3507 .substitute2(typeArguments, typeParameters, newPrune);
3508 } else {
3509 type = (type as TypeImpl).pruned(newPrune);
3510 }
3511 namedParameterTypes[parameter.name] = type;
3512 }
3513 }
3514 return namedParameterTypes;
3515 }
3516
3517 /**
3518 * Determine the new set of typedefs which should be pruned when expanding
3519 * this function type.
3520 */
3521 List<FunctionTypeAliasElement> get newPrune {
3522 Element element = this.element;
3523 if (element is FunctionTypeAliasElement && !element.isSynthetic) {
3524 // This typedef should be pruned, along with anything that was previously
3525 // pruned.
3526 if (prunedTypedefs == null) {
3527 return <FunctionTypeAliasElement>[element];
3528 } else {
3529 return new List<FunctionTypeAliasElement>.from(prunedTypedefs)
3530 ..add(element);
3531 }
3532 } else {
3533 // This is not a typedef, so nothing additional needs to be pruned.
3534 return prunedTypedefs;
3535 }
3536 }
3537
3538 @override
3539 List<DartType> get normalParameterTypes {
3540 List<ParameterElement> parameters = baseParameters;
3541 if (parameters.length == 0) {
3542 return DartType.EMPTY_LIST;
3543 }
3544 List<DartType> typeParameters =
3545 TypeParameterTypeImpl.getTypes(this.typeParameters);
3546 List<DartType> types = new List<DartType>();
3547 for (ParameterElement parameter in parameters) {
3548 if (parameter.parameterKind == ParameterKind.REQUIRED) {
3549 DartType type = parameter.type;
3550 if (typeArguments.length != 0 &&
3551 typeArguments.length == typeParameters.length) {
3552 type = (type as TypeImpl)
3553 .substitute2(typeArguments, typeParameters, newPrune);
3554 } else {
3555 type = (type as TypeImpl).pruned(newPrune);
3556 }
3557 types.add(type);
3558 }
3559 }
3560 return types;
3561 }
3562
3563 @override
3564 List<DartType> get optionalParameterTypes {
3565 List<ParameterElement> parameters = baseParameters;
3566 if (parameters.length == 0) {
3567 return DartType.EMPTY_LIST;
3568 }
3569 List<DartType> typeParameters =
3570 TypeParameterTypeImpl.getTypes(this.typeParameters);
3571 List<DartType> types = new List<DartType>();
3572 for (ParameterElement parameter in parameters) {
3573 if (parameter.parameterKind == ParameterKind.POSITIONAL) {
3574 DartType type = parameter.type;
3575 if (typeArguments.length != 0 &&
3576 typeArguments.length == typeParameters.length) {
3577 type = (type as TypeImpl)
3578 .substitute2(typeArguments, typeParameters, newPrune);
3579 } else {
3580 type = (type as TypeImpl).pruned(newPrune);
3581 }
3582 types.add(type);
3583 }
3584 }
3585 return types;
3586 }
3587
3588 /**
3589 * If this is an instantiation of a generic function type, this will get
3590 * the original function from which it was instantiated.
3591 *
3592 * Otherwise, this will return `this`.
3593 */
3594 FunctionTypeImpl get originalFunction {
3595 if (element.type.boundTypeParameters.isEmpty) {
3596 return this;
3597 }
3598 return (element.type as FunctionTypeImpl).substitute2(typeArguments,
3599 TypeParameterTypeImpl.getTypes(typeParameters), prunedTypedefs);
3600 }
3601
3602 @override
3603 List<ParameterElement> get parameters {
3604 List<ParameterElement> baseParameters = this.baseParameters;
3605 // no parameters, quick return
3606 int parameterCount = baseParameters.length;
3607 if (parameterCount == 0) {
3608 return baseParameters;
3609 }
3610 // create specialized parameters
3611 List<ParameterElement> specializedParameters =
3612 new List<ParameterElement>(parameterCount);
3613 for (int i = 0; i < parameterCount; i++) {
3614 specializedParameters[i] = ParameterMember.from(baseParameters[i], this);
3615 }
3616 return specializedParameters;
3617 }
3618
3619 @override
3620 DartType get returnType {
3621 DartType baseReturnType = this.baseReturnType;
3622 if (baseReturnType == null) {
3623 // TODO(brianwilkerson) This is a patch. The return type should never be
3624 // null and we need to understand why it is and fix it.
3625 return DynamicTypeImpl.instance;
3626 }
3627 // If there are no arguments to substitute, or if the arguments size doesn't
3628 // match the parameter size, return the base return type.
3629 if (typeArguments.length == 0 ||
3630 typeArguments.length != typeParameters.length) {
3631 return (baseReturnType as TypeImpl).pruned(newPrune);
3632 }
3633 return (baseReturnType as TypeImpl).substitute2(typeArguments,
3634 TypeParameterTypeImpl.getTypes(typeParameters), newPrune);
3635 }
3636
3637 /**
3638 * A list containing the actual types of the type arguments.
3639 */
3640 List<DartType> get typeArguments => _typeArguments;
3641
3642 @override
3643 List<TypeParameterElement> get typeParameters => _typeParameters;
3644
3645 @override
3646 bool operator ==(Object object) {
3647 if (object is! FunctionTypeImpl) {
3648 return false;
3649 }
3650 FunctionTypeImpl otherType = object as FunctionTypeImpl;
3651 if (boundTypeParameters.length != otherType.boundTypeParameters.length) {
3652 return false;
3653 }
3654 // `<T>T -> T` should be equal to `<U>U -> U`
3655 // To test this, we instantiate both types with the same (unique) type
3656 // variables, and see if the result is equal.
3657 if (boundTypeParameters.isNotEmpty) {
3658 List<DartType> instantiateTypeArgs = new List<DartType>();
3659 List<DartType> variablesThis = new List<DartType>();
3660 List<DartType> variablesOther = new List<DartType>();
3661 for (int i = 0; i < boundTypeParameters.length; i++) {
3662 TypeParameterElement pThis = boundTypeParameters[i];
3663 TypeParameterElement pOther = otherType.boundTypeParameters[i];
3664 TypeParameterTypeImpl pFresh = new TypeParameterTypeImpl(
3665 new TypeParameterElementImpl(pThis.name, -1));
3666 instantiateTypeArgs.add(pFresh);
3667 variablesThis.add(pThis.type);
3668 variablesOther.add(pOther.type);
3669 // Check that the bounds are equal after equating the previous
3670 // bound variables.
3671 if (pThis.bound?.substitute2(instantiateTypeArgs, variablesThis) !=
3672 pOther.bound?.substitute2(instantiateTypeArgs, variablesOther)) {
3673 return false;
3674 }
3675 }
3676 // After instantiation, they will no longer have boundTypeParameters,
3677 // so we will continue below.
3678 return this.instantiate(instantiateTypeArgs) ==
3679 otherType.instantiate(instantiateTypeArgs);
3680 }
3681
3682 return returnType == otherType.returnType &&
3683 TypeImpl.equalArrays(
3684 normalParameterTypes, otherType.normalParameterTypes) &&
3685 TypeImpl.equalArrays(
3686 optionalParameterTypes, otherType.optionalParameterTypes) &&
3687 _equals(namedParameterTypes, otherType.namedParameterTypes);
3688 }
3689
3690 @override
3691 void appendTo(StringBuffer buffer) {
3692 if (boundTypeParameters.isNotEmpty) {
3693 // To print a type with type variables, first make sure we have unique
3694 // variable names to print.
3695 Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>();
3696 _freeVariablesInFunctionType(this, freeVariables);
3697
3698 Set<String> namesToAvoid = new HashSet<String>();
3699 for (DartType arg in freeVariables) {
3700 if (arg is TypeParameterType) {
3701 namesToAvoid.add(arg.displayName);
3702 }
3703 }
3704
3705 List<DartType> instantiateTypeArgs = new List<DartType>();
3706 List<DartType> variables = new List<DartType>();
3707 buffer.write("<");
3708 for (TypeParameterElement e in boundTypeParameters) {
3709 if (e != boundTypeParameters[0]) {
3710 buffer.write(",");
3711 }
3712 String name = e.name;
3713 int counter = 0;
3714 while (!namesToAvoid.add(name)) {
3715 // Unicode subscript-zero is U+2080, zero is U+0030. Other digits
3716 // are sequential from there. Thus +0x2050 will get us the subscript.
3717 String subscript = new String.fromCharCodes(
3718 counter.toString().codeUnits.map((n) => n + 0x2050));
3719
3720 name = e.name + subscript;
3721 counter++;
3722 }
3723 TypeParameterTypeImpl t =
3724 new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
3725 t.appendTo(buffer);
3726 instantiateTypeArgs.add(t);
3727 variables.add(e.type);
3728 if (e.bound != null) {
3729 buffer.write(" extends ");
3730 TypeImpl renamed =
3731 e.bound.substitute2(instantiateTypeArgs, variables);
3732 renamed.appendTo(buffer);
3733 }
3734 }
3735 buffer.write(">");
3736
3737 // Instantiate it and print the resulting type. After instantiation, it
3738 // will no longer have boundTypeParameters, so we will continue below.
3739 this.instantiate(instantiateTypeArgs).appendTo(buffer);
3740 return;
3741 }
3742
3743 List<DartType> normalParameterTypes = this.normalParameterTypes;
3744 List<DartType> optionalParameterTypes = this.optionalParameterTypes;
3745 Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
3746 DartType returnType = this.returnType;
3747 buffer.write("(");
3748 bool needsComma = false;
3749 if (normalParameterTypes.isNotEmpty) {
3750 for (DartType type in normalParameterTypes) {
3751 if (needsComma) {
3752 buffer.write(", ");
3753 } else {
3754 needsComma = true;
3755 }
3756 (type as TypeImpl).appendTo(buffer);
3757 }
3758 }
3759 if (optionalParameterTypes.isNotEmpty) {
3760 if (needsComma) {
3761 buffer.write(", ");
3762 needsComma = false;
3763 }
3764 buffer.write("[");
3765 for (DartType type in optionalParameterTypes) {
3766 if (needsComma) {
3767 buffer.write(", ");
3768 } else {
3769 needsComma = true;
3770 }
3771 (type as TypeImpl).appendTo(buffer);
3772 }
3773 buffer.write("]");
3774 needsComma = true;
3775 }
3776 if (namedParameterTypes.isNotEmpty) {
3777 if (needsComma) {
3778 buffer.write(", ");
3779 needsComma = false;
3780 }
3781 buffer.write("{");
3782 namedParameterTypes.forEach((String name, DartType type) {
3783 if (needsComma) {
3784 buffer.write(", ");
3785 } else {
3786 needsComma = true;
3787 }
3788 buffer.write(name);
3789 buffer.write(": ");
3790 (type as TypeImpl).appendTo(buffer);
3791 });
3792 buffer.write("}");
3793 needsComma = true;
3794 }
3795 buffer.write(")");
3796 buffer.write(ElementImpl.RIGHT_ARROW);
3797 if (returnType == null) {
3798 buffer.write("null");
3799 } else {
3800 (returnType as TypeImpl).appendTo(buffer);
3801 }
3802 }
3803
3804 @override
3805 FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
3806 if (argumentTypes.length != boundTypeParameters.length) {
3807 throw new IllegalArgumentException(
3808 "argumentTypes.length (${argumentTypes.length}) != "
3809 "boundTypeParameters.length (${boundTypeParameters.length})");
3810 }
3811 if (argumentTypes.isEmpty) {
3812 return this;
3813 }
3814
3815 // Given:
3816 // {U/T} <S> T -> S
3817 // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
3818 // and <S> represents the boundTypeParameters.
3819 //
3820 // Now instantiate([V]), and the result should be:
3821 // {U/T, V/S} T -> S.
3822 List<TypeParameterElement> newTypeParams = typeParameters.toList();
3823 List<DartType> newTypeArgs = typeArguments.toList();
3824 newTypeParams.addAll(boundTypeParameters);
3825 newTypeArgs.addAll(argumentTypes);
3826
3827 return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs,
3828 newTypeParams, TypeParameterElement.EMPTY_LIST);
3829 }
3830
3831 @override
3832 bool isAssignableTo(DartType type) {
3833 // A function type T may be assigned to a function type S, written T <=> S,
3834 // iff T <: S.
3835 return isSubtypeOf(type);
3836 }
3837
3838 @override
3839 bool isMoreSpecificThan(DartType type,
3840 [bool withDynamic = false, Set<Element> visitedElements]) {
3841 // Note: visitedElements is only used for breaking recursion in the type
3842 // hierarchy; we don't use it when recursing into the function type.
3843
3844 // trivial base cases
3845 if (type == null) {
3846 return false;
3847 } else if (identical(this, type) ||
3848 type.isDynamic ||
3849 type.isDartCoreFunction ||
3850 type.isObject) {
3851 return true;
3852 } else if (type is! FunctionType) {
3853 return false;
3854 } else if (this == type) {
3855 return true;
3856 }
3857 FunctionType t = this;
3858 FunctionType s = type as FunctionType;
3859 List<DartType> tTypes = t.normalParameterTypes;
3860 List<DartType> tOpTypes = t.optionalParameterTypes;
3861 List<DartType> sTypes = s.normalParameterTypes;
3862 List<DartType> sOpTypes = s.optionalParameterTypes;
3863 // If one function has positional and the other has named parameters,
3864 // return false.
3865 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
3866 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
3867 return false;
3868 }
3869 // named parameters case
3870 if (t.namedParameterTypes.length > 0) {
3871 // check that the number of required parameters are equal, and check that
3872 // every t_i is more specific than every s_i
3873 if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
3874 return false;
3875 } else if (t.normalParameterTypes.length > 0) {
3876 for (int i = 0; i < tTypes.length; i++) {
3877 if (!(tTypes[i] as TypeImpl)
3878 .isMoreSpecificThan(sTypes[i], withDynamic)) {
3879 return false;
3880 }
3881 }
3882 }
3883 Map<String, DartType> namedTypesT = t.namedParameterTypes;
3884 Map<String, DartType> namedTypesS = s.namedParameterTypes;
3885 // if k >= m is false, return false: the passed function type has more
3886 // named parameter types than this
3887 if (namedTypesT.length < namedTypesS.length) {
3888 return false;
3889 }
3890 // Loop through each element in S verifying that T has a matching
3891 // parameter name and that the corresponding type is more specific then
3892 // the type in S.
3893 for (String keyS in namedTypesS.keys) {
3894 DartType typeT = namedTypesT[keyS];
3895 if (typeT == null) {
3896 return false;
3897 }
3898 if (!(typeT as TypeImpl)
3899 .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) {
3900 return false;
3901 }
3902 }
3903 } else if (s.namedParameterTypes.length > 0) {
3904 return false;
3905 } else {
3906 // positional parameter case
3907 int tArgLength = tTypes.length + tOpTypes.length;
3908 int sArgLength = sTypes.length + sOpTypes.length;
3909 // Check that the total number of parameters in t is greater than or equal
3910 // to the number of parameters in s and that the number of required
3911 // parameters in s is greater than or equal to the number of required
3912 // parameters in t.
3913 if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
3914 return false;
3915 }
3916 if (tOpTypes.length == 0 && sOpTypes.length == 0) {
3917 // No positional arguments, don't copy contents to new array
3918 for (int i = 0; i < sTypes.length; i++) {
3919 if (!(tTypes[i] as TypeImpl)
3920 .isMoreSpecificThan(sTypes[i], withDynamic)) {
3921 return false;
3922 }
3923 }
3924 } else {
3925 // Else, we do have positional parameters, copy required and positional
3926 // parameter types into arrays to do the compare (for loop below).
3927 List<DartType> tAllTypes = new List<DartType>(sArgLength);
3928 for (int i = 0; i < tTypes.length; i++) {
3929 tAllTypes[i] = tTypes[i];
3930 }
3931 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
3932 tAllTypes[i] = tOpTypes[j];
3933 }
3934 List<DartType> sAllTypes = new List<DartType>(sArgLength);
3935 for (int i = 0; i < sTypes.length; i++) {
3936 sAllTypes[i] = sTypes[i];
3937 }
3938 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
3939 sAllTypes[i] = sOpTypes[j];
3940 }
3941 for (int i = 0; i < sAllTypes.length; i++) {
3942 if (!(tAllTypes[i] as TypeImpl)
3943 .isMoreSpecificThan(sAllTypes[i], withDynamic)) {
3944 return false;
3945 }
3946 }
3947 }
3948 }
3949 DartType tRetType = t.returnType;
3950 DartType sRetType = s.returnType;
3951 return sRetType.isVoid ||
3952 (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic);
3953 }
3954
3955 @override
3956 bool isSubtypeOf(DartType type) {
3957 // trivial base cases
3958 if (type == null) {
3959 return false;
3960 } else if (identical(this, type) ||
3961 type.isDynamic ||
3962 type.isDartCoreFunction ||
3963 type.isObject) {
3964 return true;
3965 } else if (type is! FunctionType) {
3966 return false;
3967 } else if (this == type) {
3968 return true;
3969 }
3970 FunctionType t = this;
3971 FunctionType s = type as FunctionType;
3972 List<DartType> tTypes = t.normalParameterTypes;
3973 List<DartType> tOpTypes = t.optionalParameterTypes;
3974 List<DartType> sTypes = s.normalParameterTypes;
3975 List<DartType> sOpTypes = s.optionalParameterTypes;
3976 // If one function has positional and the other has named parameters,
3977 // return false.
3978 if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
3979 (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
3980 return false;
3981 }
3982 // named parameters case
3983 if (t.namedParameterTypes.length > 0) {
3984 // check that the number of required parameters are equal,
3985 // and check that every t_i is assignable to every s_i
3986 if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
3987 return false;
3988 } else if (t.normalParameterTypes.length > 0) {
3989 for (int i = 0; i < tTypes.length; i++) {
3990 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) {
3991 return false;
3992 }
3993 }
3994 }
3995 Map<String, DartType> namedTypesT = t.namedParameterTypes;
3996 Map<String, DartType> namedTypesS = s.namedParameterTypes;
3997 // if k >= m is false, return false: the passed function type has more
3998 // named parameter types than this
3999 if (namedTypesT.length < namedTypesS.length) {
4000 return false;
4001 }
4002 // Loop through each element in S verifying that T has a matching
4003 // parameter name and that the corresponding type is assignable to the
4004 // type in S.
4005 for (String keyS in namedTypesS.keys) {
4006 DartType typeT = namedTypesT[keyS];
4007 if (typeT == null) {
4008 return false;
4009 }
4010 if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) {
4011 return false;
4012 }
4013 }
4014 } else if (s.namedParameterTypes.length > 0) {
4015 return false;
4016 } else {
4017 // positional parameter case
4018 int tArgLength = tTypes.length + tOpTypes.length;
4019 int sArgLength = sTypes.length + sOpTypes.length;
4020 // Check that the total number of parameters in t is greater than or
4021 // equal to the number of parameters in s and that the number of
4022 // required parameters in s is greater than or equal to the number of
4023 // required parameters in t.
4024 if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
4025 return false;
4026 }
4027 if (tOpTypes.length == 0 && sOpTypes.length == 0) {
4028 // No positional arguments, don't copy contents to new array
4029 for (int i = 0; i < sTypes.length; i++) {
4030 if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) {
4031 return false;
4032 }
4033 }
4034 } else {
4035 // Else, we do have positional parameters, copy required and
4036 // positional parameter types into arrays to do the compare (for loop
4037 // below).
4038 List<DartType> tAllTypes = new List<DartType>(sArgLength);
4039 for (int i = 0; i < tTypes.length; i++) {
4040 tAllTypes[i] = tTypes[i];
4041 }
4042 for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
4043 tAllTypes[i] = tOpTypes[j];
4044 }
4045 List<DartType> sAllTypes = new List<DartType>(sArgLength);
4046 for (int i = 0; i < sTypes.length; i++) {
4047 sAllTypes[i] = sTypes[i];
4048 }
4049 for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
4050 sAllTypes[i] = sOpTypes[j];
4051 }
4052 for (int i = 0; i < sAllTypes.length; i++) {
4053 if (!(tAllTypes[i] as TypeImpl).isAssignableTo(sAllTypes[i])) {
4054 return false;
4055 }
4056 }
4057 }
4058 }
4059 DartType tRetType = t.returnType;
4060 DartType sRetType = s.returnType;
4061 return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType);
4062 }
4063
4064 @override
4065 TypeImpl pruned(List<FunctionTypeAliasElement> prune) {
4066 if (prune == null) {
4067 return this;
4068 } else if (prune.contains(element)) {
4069 // Circularity found. Prune the type declaration.
4070 return new CircularTypeImpl();
4071 } else {
4072 // There should never be a reason to prune a type that has already been
4073 // pruned, since pruning is only done when expanding a function type
4074 // alias, and function type aliases are always expanded by starting with
4075 // base types.
4076 assert(this.prunedTypedefs == null);
4077 List<DartType> typeArgs = typeArguments
4078 .map((TypeImpl t) => t.pruned(prune))
4079 .toList(growable: false);
4080 return new FunctionTypeImpl._(element, name, prune, typeArgs,
4081 _typeParameters, _boundTypeParameters);
4082 }
4083 }
4084
4085 @override
4086 DartType substitute2(
4087 List<DartType> argumentTypes, List<DartType> parameterTypes,
4088 [List<FunctionTypeAliasElement> prune]) {
4089 // Pruned types should only ever result from performing type variable
4090 // substitution, and it doesn't make sense to substitute again after
4091 // substituting once.
4092 assert(this.prunedTypedefs == null);
4093 if (argumentTypes.length != parameterTypes.length) {
4094 throw new IllegalArgumentException(
4095 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng th (${parameterTypes.length})");
4096 }
4097 Element element = this.element;
4098 if (prune != null && prune.contains(element)) {
4099 // Circularity found. Prune the type declaration.
4100 return new CircularTypeImpl();
4101 }
4102 if (argumentTypes.length == 0) {
4103 return this.pruned(prune);
4104 }
4105 List<DartType> typeArgs =
4106 TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
4107 return new FunctionTypeImpl._(
4108 element, name, prune, typeArgs, _typeParameters, _boundTypeParameters);
4109 }
4110
4111 @override
4112 FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
4113 substitute2(argumentTypes, typeArguments);
4114
4115 void _freeVariablesInFunctionType(
4116 FunctionType type, Set<TypeParameterType> free) {
4117 // Make some fresh variables to avoid capture.
4118 List<DartType> typeArgs = DartType.EMPTY_LIST;
4119 if (type.boundTypeParameters.isNotEmpty) {
4120 typeArgs = new List<DartType>.from(type.boundTypeParameters.map((e) =>
4121 new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
4122
4123 type = type.instantiate(typeArgs);
4124 }
4125
4126 for (ParameterElement p in type.parameters) {
4127 _freeVariablesInType(p.type, free);
4128 }
4129 _freeVariablesInType(type.returnType, free);
4130
4131 // Remove all of our bound variables.
4132 free.removeAll(typeArgs);
4133 }
4134
4135 void _freeVariablesInInterfaceType(
4136 InterfaceType type, Set<TypeParameterType> free) {
4137 for (DartType typeArg in type.typeArguments) {
4138 _freeVariablesInType(typeArg, free);
4139 }
4140 }
4141
4142 void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
4143 if (type is TypeParameterType) {
4144 free.add(type);
4145 } else if (type is FunctionType) {
4146 _freeVariablesInFunctionType(type, free);
4147 } else if (type is InterfaceType) {
4148 _freeVariablesInInterfaceType(type, free);
4149 }
4150 }
4151
4152 /**
4153 * Compute the least upper bound of types [f] and [g], both of which are
4154 * known to be function types.
4155 *
4156 * In the event that f and g have different numbers of required parameters,
4157 * `null` is returned, in which case the least upper bound is the interface
4158 * type `Function`.
4159 */
4160 static FunctionType computeLeastUpperBound(FunctionType f, FunctionType g) {
4161 // TODO(paulberry): implement this.
4162 return null;
4163 }
4164
4165 /**
4166 * Return `true` if all of the name/type pairs in the first map ([firstTypes])
4167 * are equal to the corresponding name/type pairs in the second map
4168 * ([secondTypes]). The maps are expected to iterate over their entries in the
4169 * same order in which those entries were added to the map.
4170 */
4171 static bool _equals(
4172 Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) {
4173 if (secondTypes.length != firstTypes.length) {
4174 return false;
4175 }
4176 Iterator<String> firstKeys = firstTypes.keys.iterator;
4177 Iterator<String> secondKeys = secondTypes.keys.iterator;
4178 while (firstKeys.moveNext() && secondKeys.moveNext()) {
4179 String firstKey = firstKeys.current;
4180 String secondKey = secondKeys.current;
4181 TypeImpl firstType = firstTypes[firstKey];
4182 TypeImpl secondType = secondTypes[secondKey];
4183 if (firstKey != secondKey || firstType != secondType) {
4184 return false;
4185 }
4186 }
4187 return true;
4188 }
4189 }
4190
4191 /**
4192 * A concrete implementation of a [HideElementCombinator]. 2745 * A concrete implementation of a [HideElementCombinator].
4193 */ 2746 */
4194 class HideElementCombinatorImpl implements HideElementCombinator { 2747 class HideElementCombinatorImpl implements HideElementCombinator {
4195 /** 2748 /**
4196 * The names that are not to be made visible in the importing library even if 2749 * The names that are not to be made visible in the importing library even if
4197 * they are defined in the imported library. 2750 * they are defined in the imported library.
4198 */ 2751 */
4199 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY; 2752 List<String> hiddenNames = StringUtilities.EMPTY_ARRAY;
4200 2753
4201 @override 2754 @override
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
4273 (importedLibrary as LibraryElementImpl).appendTo(buffer); 2826 (importedLibrary as LibraryElementImpl).appendTo(buffer);
4274 } 2827 }
4275 2828
4276 @override 2829 @override
4277 void visitChildren(ElementVisitor visitor) { 2830 void visitChildren(ElementVisitor visitor) {
4278 super.visitChildren(visitor); 2831 super.visitChildren(visitor);
4279 safelyVisitChild(prefix, visitor); 2832 safelyVisitChild(prefix, visitor);
4280 } 2833 }
4281 } 2834 }
4282 2835
4283 /**
4284 * A concrete implementation of an [InterfaceType].
4285 */
4286 class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
4287 /**
4288 * A list containing the actual types of the type arguments.
4289 */
4290 List<DartType> typeArguments = DartType.EMPTY_LIST;
4291
4292 /**
4293 * The set of typedefs which should not be expanded when exploring this type,
4294 * to avoid creating infinite types in response to self-referential typedefs.
4295 */
4296 final List<FunctionTypeAliasElement> prunedTypedefs;
4297
4298 /**
4299 * Initialize a newly created type to be declared by the given [element].
4300 */
4301 InterfaceTypeImpl(ClassElement element, [this.prunedTypedefs])
4302 : super(element, element.displayName);
4303
4304 /**
4305 * Initialize a newly created type to have the given [name]. This constructor
4306 * should only be used in cases where there is no declaration of the type.
4307 */
4308 InterfaceTypeImpl.named(String name)
4309 : prunedTypedefs = null,
4310 super(null, name);
4311
4312 /**
4313 * Private constructor.
4314 */
4315 InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs)
4316 : super(element, name);
4317
4318 @override
4319 List<PropertyAccessorElement> get accessors {
4320 List<PropertyAccessorElement> accessors = element.accessors;
4321 List<PropertyAccessorElement> members =
4322 new List<PropertyAccessorElement>(accessors.length);
4323 for (int i = 0; i < accessors.length; i++) {
4324 members[i] = PropertyAccessorMember.from(accessors[i], this);
4325 }
4326 return members;
4327 }
4328
4329 @override
4330 List<ConstructorElement> get constructors {
4331 List<ConstructorElement> constructors = element.constructors;
4332 List<ConstructorElement> members =
4333 new List<ConstructorElement>(constructors.length);
4334 for (int i = 0; i < constructors.length; i++) {
4335 members[i] = ConstructorMember.from(constructors[i], this);
4336 }
4337 return members;
4338 }
4339
4340 @override
4341 String get displayName {
4342 String name = this.name;
4343 List<DartType> typeArguments = this.typeArguments;
4344 bool allDynamic = true;
4345 for (DartType type in typeArguments) {
4346 if (type != null && !type.isDynamic) {
4347 allDynamic = false;
4348 break;
4349 }
4350 }
4351 // If there is at least one non-dynamic type, then list them out
4352 if (!allDynamic) {
4353 StringBuffer buffer = new StringBuffer();
4354 buffer.write(name);
4355 buffer.write("<");
4356 for (int i = 0; i < typeArguments.length; i++) {
4357 if (i != 0) {
4358 buffer.write(", ");
4359 }
4360 DartType typeArg = typeArguments[i];
4361 buffer.write(typeArg.displayName);
4362 }
4363 buffer.write(">");
4364 name = buffer.toString();
4365 }
4366 return name;
4367 }
4368
4369 @override
4370 ClassElement get element => super.element as ClassElement;
4371
4372 @override
4373 int get hashCode {
4374 ClassElement element = this.element;
4375 if (element == null) {
4376 return 0;
4377 }
4378 return element.hashCode;
4379 }
4380
4381 @override
4382 List<InterfaceType> get interfaces {
4383 ClassElement classElement = element;
4384 List<InterfaceType> interfaces = classElement.interfaces;
4385 List<TypeParameterElement> typeParameters = classElement.typeParameters;
4386 List<DartType> parameterTypes = classElement.type.typeArguments;
4387 if (typeParameters.length == 0) {
4388 return interfaces;
4389 }
4390 int count = interfaces.length;
4391 List<InterfaceType> typedInterfaces = new List<InterfaceType>(count);
4392 for (int i = 0; i < count; i++) {
4393 typedInterfaces[i] =
4394 interfaces[i].substitute2(typeArguments, parameterTypes);
4395 }
4396 return typedInterfaces;
4397 }
4398
4399 @override
4400 bool get isDartCoreFunction {
4401 ClassElement element = this.element;
4402 if (element == null) {
4403 return false;
4404 }
4405 return element.name == "Function" && element.library.isDartCore;
4406 }
4407
4408 @override
4409 bool get isObject => element.supertype == null;
4410
4411 @override
4412 List<MethodElement> get methods {
4413 List<MethodElement> methods = element.methods;
4414 List<MethodElement> members = new List<MethodElement>(methods.length);
4415 for (int i = 0; i < methods.length; i++) {
4416 members[i] = MethodMember.from(methods[i], this);
4417 }
4418 return members;
4419 }
4420
4421 @override
4422 List<InterfaceType> get mixins {
4423 ClassElement classElement = element;
4424 List<InterfaceType> mixins = classElement.mixins;
4425 List<TypeParameterElement> typeParameters = classElement.typeParameters;
4426 List<DartType> parameterTypes = classElement.type.typeArguments;
4427 if (typeParameters.length == 0) {
4428 return mixins;
4429 }
4430 int count = mixins.length;
4431 List<InterfaceType> typedMixins = new List<InterfaceType>(count);
4432 for (int i = 0; i < count; i++) {
4433 typedMixins[i] = mixins[i].substitute2(typeArguments, parameterTypes);
4434 }
4435 return typedMixins;
4436 }
4437
4438 @override
4439 InterfaceType get superclass {
4440 ClassElement classElement = element;
4441 InterfaceType supertype = classElement.supertype;
4442 if (supertype == null) {
4443 return null;
4444 }
4445 List<DartType> typeParameters = classElement.type.typeArguments;
4446 if (typeArguments.length == 0 ||
4447 typeArguments.length != typeParameters.length) {
4448 return supertype;
4449 }
4450 return supertype.substitute2(typeArguments, typeParameters);
4451 }
4452
4453 @override
4454 List<TypeParameterElement> get typeParameters => element.typeParameters;
4455
4456 @override
4457 bool operator ==(Object object) {
4458 if (identical(object, this)) {
4459 return true;
4460 }
4461 if (object is! InterfaceTypeImpl) {
4462 return false;
4463 }
4464 InterfaceTypeImpl otherType = object as InterfaceTypeImpl;
4465 return (element == otherType.element) &&
4466 TypeImpl.equalArrays(typeArguments, otherType.typeArguments);
4467 }
4468
4469 @override
4470 void appendTo(StringBuffer buffer) {
4471 buffer.write(name);
4472 int argumentCount = typeArguments.length;
4473 if (argumentCount > 0) {
4474 buffer.write("<");
4475 for (int i = 0; i < argumentCount; i++) {
4476 if (i > 0) {
4477 buffer.write(", ");
4478 }
4479 (typeArguments[i] as TypeImpl).appendTo(buffer);
4480 }
4481 buffer.write(">");
4482 }
4483 }
4484
4485 @override
4486 PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember
4487 .from((element as ClassElementImpl).getGetter(getterName), this);
4488
4489 @override
4490 MethodElement getMethod(String methodName) => MethodMember.from(
4491 (element as ClassElementImpl).getMethod(methodName), this);
4492
4493 @override
4494 PropertyAccessorElement getSetter(String setterName) => PropertyAccessorMember
4495 .from((element as ClassElementImpl).getSetter(setterName), this);
4496
4497 @override
4498 bool isDirectSupertypeOf(InterfaceType type) {
4499 InterfaceType i = this;
4500 InterfaceType j = type;
4501 ClassElement jElement = j.element;
4502 InterfaceType supertype = jElement.supertype;
4503 //
4504 // If J has no direct supertype then it is Object, and Object has no direct
4505 // supertypes.
4506 //
4507 if (supertype == null) {
4508 return false;
4509 }
4510 //
4511 // I is listed in the extends clause of J.
4512 //
4513 List<DartType> jArgs = j.typeArguments;
4514 List<DartType> jVars = jElement.type.typeArguments;
4515 supertype = supertype.substitute2(jArgs, jVars);
4516 if (supertype == i) {
4517 return true;
4518 }
4519 //
4520 // I is listed in the implements clause of J.
4521 //
4522 for (InterfaceType interfaceType in jElement.interfaces) {
4523 interfaceType = interfaceType.substitute2(jArgs, jVars);
4524 if (interfaceType == i) {
4525 return true;
4526 }
4527 }
4528 //
4529 // I is listed in the with clause of J.
4530 //
4531 for (InterfaceType mixinType in jElement.mixins) {
4532 mixinType = mixinType.substitute2(jArgs, jVars);
4533 if (mixinType == i) {
4534 return true;
4535 }
4536 }
4537 //
4538 // J is a mixin application of the mixin of I.
4539 //
4540 // TODO(brianwilkerson) Determine whether this needs to be implemented or
4541 // whether it is covered by the case above.
4542 return false;
4543 }
4544
4545 @override
4546 bool isMoreSpecificThan(DartType type,
4547 [bool withDynamic = false, Set<Element> visitedElements]) {
4548 //
4549 // S is dynamic.
4550 // The test to determine whether S is dynamic is done here because dynamic
4551 // is not an instance of InterfaceType.
4552 //
4553 if (type.isDynamic) {
4554 return true;
4555 }
4556 //
4557 // A type T is more specific than a type S, written T << S,
4558 // if one of the following conditions is met:
4559 //
4560 // Reflexivity: T is S.
4561 //
4562 if (this == type) {
4563 return true;
4564 }
4565 if (type is InterfaceType) {
4566 //
4567 // T is bottom. (This case is handled by the class BottomTypeImpl.)
4568 //
4569 // Direct supertype: S is a direct supertype of T.
4570 //
4571 if (type.isDirectSupertypeOf(this)) {
4572 return true;
4573 }
4574 //
4575 // Covariance: T is of the form I<T1, ..., Tn> and S is of the form
4576 // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
4577 //
4578 ClassElement tElement = this.element;
4579 ClassElement sElement = type.element;
4580 if (tElement == sElement) {
4581 List<DartType> tArguments = typeArguments;
4582 List<DartType> sArguments = type.typeArguments;
4583 if (tArguments.length != sArguments.length) {
4584 return false;
4585 }
4586 for (int i = 0; i < tArguments.length; i++) {
4587 if (!(tArguments[i] as TypeImpl)
4588 .isMoreSpecificThan(sArguments[i], withDynamic)) {
4589 return false;
4590 }
4591 }
4592 return true;
4593 }
4594 }
4595 //
4596 // Transitivity: T << U and U << S.
4597 //
4598 // First check for infinite loops
4599 if (element == null) {
4600 return false;
4601 }
4602 if (visitedElements == null) {
4603 visitedElements = new HashSet<ClassElement>();
4604 } else if (visitedElements.contains(element)) {
4605 return false;
4606 }
4607 visitedElements.add(element);
4608 try {
4609 // Iterate over all of the types U that are more specific than T because
4610 // they are direct supertypes of T and return true if any of them are more
4611 // specific than S.
4612 InterfaceTypeImpl supertype = superclass;
4613 if (supertype != null &&
4614 supertype.isMoreSpecificThan(type, withDynamic, visitedElements)) {
4615 return true;
4616 }
4617 for (InterfaceType interfaceType in interfaces) {
4618 if ((interfaceType as InterfaceTypeImpl)
4619 .isMoreSpecificThan(type, withDynamic, visitedElements)) {
4620 return true;
4621 }
4622 }
4623 for (InterfaceType mixinType in mixins) {
4624 if ((mixinType as InterfaceTypeImpl)
4625 .isMoreSpecificThan(type, withDynamic, visitedElements)) {
4626 return true;
4627 }
4628 }
4629 // If a type I includes an instance method named `call`, and the type of
4630 // `call` is the function type F, then I is considered to be more specific
4631 // than F.
4632 MethodElement callMethod = getMethod('call');
4633 if (callMethod != null && !callMethod.isStatic) {
4634 FunctionTypeImpl callType = callMethod.type;
4635 if (callType.isMoreSpecificThan(type, withDynamic, visitedElements)) {
4636 return true;
4637 }
4638 }
4639 return false;
4640 } finally {
4641 visitedElements.remove(element);
4642 }
4643 }
4644
4645 @override
4646 ConstructorElement lookUpConstructor(
4647 String constructorName, LibraryElement library) {
4648 // prepare base ConstructorElement
4649 ConstructorElement constructorElement;
4650 if (constructorName == null) {
4651 constructorElement = element.unnamedConstructor;
4652 } else {
4653 constructorElement = element.getNamedConstructor(constructorName);
4654 }
4655 // not found or not accessible
4656 if (constructorElement == null ||
4657 !constructorElement.isAccessibleIn(library)) {
4658 return null;
4659 }
4660 // return member
4661 return ConstructorMember.from(constructorElement, this);
4662 }
4663
4664 @override
4665 PropertyAccessorElement lookUpGetter(
4666 String getterName, LibraryElement library) {
4667 PropertyAccessorElement element = getGetter(getterName);
4668 if (element != null && element.isAccessibleIn(library)) {
4669 return element;
4670 }
4671 return lookUpGetterInSuperclass(getterName, library);
4672 }
4673
4674 @override
4675 PropertyAccessorElement lookUpGetterInSuperclass(
4676 String getterName, LibraryElement library) {
4677 for (InterfaceType mixin in mixins.reversed) {
4678 PropertyAccessorElement element = mixin.getGetter(getterName);
4679 if (element != null && element.isAccessibleIn(library)) {
4680 return element;
4681 }
4682 }
4683 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
4684 InterfaceType supertype = superclass;
4685 ClassElement supertypeElement =
4686 supertype == null ? null : supertype.element;
4687 while (supertype != null && !visitedClasses.contains(supertypeElement)) {
4688 visitedClasses.add(supertypeElement);
4689 PropertyAccessorElement element = supertype.getGetter(getterName);
4690 if (element != null && element.isAccessibleIn(library)) {
4691 return element;
4692 }
4693 for (InterfaceType mixin in supertype.mixins.reversed) {
4694 element = mixin.getGetter(getterName);
4695 if (element != null && element.isAccessibleIn(library)) {
4696 return element;
4697 }
4698 }
4699 supertype = supertype.superclass;
4700 supertypeElement = supertype == null ? null : supertype.element;
4701 }
4702 return null;
4703 }
4704
4705 @override
4706 PropertyAccessorElement lookUpInheritedGetter(String name,
4707 {LibraryElement library, bool thisType: true}) {
4708 PropertyAccessorElement result;
4709 if (thisType) {
4710 result = lookUpGetter(name, library);
4711 } else {
4712 result = lookUpGetterInSuperclass(name, library);
4713 }
4714 if (result != null) {
4715 return result;
4716 }
4717 return _lookUpMemberInInterfaces(this, false, library,
4718 new HashSet<ClassElement>(), (InterfaceType t) => t.getGetter(name));
4719 }
4720
4721 @override
4722 ExecutableElement lookUpInheritedGetterOrMethod(String name,
4723 {LibraryElement library}) {
4724 ExecutableElement result =
4725 lookUpGetter(name, library) ?? lookUpMethod(name, library);
4726
4727 if (result != null) {
4728 return result;
4729 }
4730 return _lookUpMemberInInterfaces(
4731 this,
4732 false,
4733 library,
4734 new HashSet<ClassElement>(),
4735 (InterfaceType t) => t.getGetter(name) ?? t.getMethod(name));
4736 }
4737
4738 @override
4739 MethodElement lookUpInheritedMethod(String name,
4740 {LibraryElement library, bool thisType: true}) {
4741 MethodElement result;
4742 if (thisType) {
4743 result = lookUpMethod(name, library);
4744 } else {
4745 result = lookUpMethodInSuperclass(name, library);
4746 }
4747 if (result != null) {
4748 return result;
4749 }
4750 return _lookUpMemberInInterfaces(this, false, library,
4751 new HashSet<ClassElement>(), (InterfaceType t) => t.getMethod(name));
4752 }
4753
4754 @override
4755 PropertyAccessorElement lookUpInheritedSetter(String name,
4756 {LibraryElement library, bool thisType: true}) {
4757 PropertyAccessorElement result;
4758 if (thisType) {
4759 result = lookUpSetter(name, library);
4760 } else {
4761 result = lookUpSetterInSuperclass(name, library);
4762 }
4763 if (result != null) {
4764 return result;
4765 }
4766 return _lookUpMemberInInterfaces(this, false, library,
4767 new HashSet<ClassElement>(), (t) => t.getSetter(name));
4768 }
4769
4770 @override
4771 MethodElement lookUpMethod(String methodName, LibraryElement library) {
4772 MethodElement element = getMethod(methodName);
4773 if (element != null && element.isAccessibleIn(library)) {
4774 return element;
4775 }
4776 return lookUpMethodInSuperclass(methodName, library);
4777 }
4778
4779 @override
4780 MethodElement lookUpMethodInSuperclass(
4781 String methodName, LibraryElement library) {
4782 for (InterfaceType mixin in mixins.reversed) {
4783 MethodElement element = mixin.getMethod(methodName);
4784 if (element != null && element.isAccessibleIn(library)) {
4785 return element;
4786 }
4787 }
4788 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
4789 InterfaceType supertype = superclass;
4790 ClassElement supertypeElement =
4791 supertype == null ? null : supertype.element;
4792 while (supertype != null && !visitedClasses.contains(supertypeElement)) {
4793 visitedClasses.add(supertypeElement);
4794 MethodElement element = supertype.getMethod(methodName);
4795 if (element != null && element.isAccessibleIn(library)) {
4796 return element;
4797 }
4798 for (InterfaceType mixin in supertype.mixins.reversed) {
4799 element = mixin.getMethod(methodName);
4800 if (element != null && element.isAccessibleIn(library)) {
4801 return element;
4802 }
4803 }
4804 supertype = supertype.superclass;
4805 supertypeElement = supertype == null ? null : supertype.element;
4806 }
4807 return null;
4808 }
4809
4810 @override
4811 PropertyAccessorElement lookUpSetter(
4812 String setterName, LibraryElement library) {
4813 PropertyAccessorElement element = getSetter(setterName);
4814 if (element != null && element.isAccessibleIn(library)) {
4815 return element;
4816 }
4817 return lookUpSetterInSuperclass(setterName, library);
4818 }
4819
4820 @override
4821 PropertyAccessorElement lookUpSetterInSuperclass(
4822 String setterName, LibraryElement library) {
4823 for (InterfaceType mixin in mixins.reversed) {
4824 PropertyAccessorElement element = mixin.getSetter(setterName);
4825 if (element != null && element.isAccessibleIn(library)) {
4826 return element;
4827 }
4828 }
4829 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
4830 InterfaceType supertype = superclass;
4831 ClassElement supertypeElement =
4832 supertype == null ? null : supertype.element;
4833 while (supertype != null && !visitedClasses.contains(supertypeElement)) {
4834 visitedClasses.add(supertypeElement);
4835 PropertyAccessorElement element = supertype.getSetter(setterName);
4836 if (element != null && element.isAccessibleIn(library)) {
4837 return element;
4838 }
4839 for (InterfaceType mixin in supertype.mixins.reversed) {
4840 element = mixin.getSetter(setterName);
4841 if (element != null && element.isAccessibleIn(library)) {
4842 return element;
4843 }
4844 }
4845 supertype = supertype.superclass;
4846 supertypeElement = supertype == null ? null : supertype.element;
4847 }
4848 return null;
4849 }
4850
4851 @override
4852 InterfaceTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
4853 if (prune == null) {
4854 return this;
4855 } else {
4856 // There should never be a reason to prune a type that has already been
4857 // pruned, since pruning is only done when expanding a function type
4858 // alias, and function type aliases are always expanded by starting with
4859 // base types.
4860 assert(this.prunedTypedefs == null);
4861 InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune);
4862 result.typeArguments =
4863 typeArguments.map((TypeImpl t) => t.pruned(prune)).toList();
4864 return result;
4865 }
4866 }
4867
4868 @override
4869 InterfaceTypeImpl substitute2(
4870 List<DartType> argumentTypes, List<DartType> parameterTypes,
4871 [List<FunctionTypeAliasElement> prune]) {
4872 if (argumentTypes.length != parameterTypes.length) {
4873 throw new IllegalArgumentException(
4874 "argumentTypes.length (${argumentTypes.length}) != parameterTypes.leng th (${parameterTypes.length})");
4875 }
4876 if (argumentTypes.length == 0 || typeArguments.length == 0) {
4877 return this.pruned(prune);
4878 }
4879 List<DartType> newTypeArguments = TypeImpl.substitute(
4880 typeArguments, argumentTypes, parameterTypes, prune);
4881 if (JavaArrays.equals(newTypeArguments, typeArguments)) {
4882 return this;
4883 }
4884 InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune);
4885 newType.typeArguments = newTypeArguments;
4886 return newType;
4887 }
4888
4889 @override
4890 InterfaceTypeImpl substitute4(List<DartType> argumentTypes) =>
4891 substitute2(argumentTypes, typeArguments);
4892
4893 /**
4894 * Compute the least upper bound of types [i] and [j], both of which are
4895 * known to be interface types.
4896 *
4897 * In the event that the algorithm fails (which might occur due to a bug in
4898 * the analyzer), `null` is returned.
4899 */
4900 static InterfaceType computeLeastUpperBound(
4901 InterfaceType i, InterfaceType j) {
4902 // compute set of supertypes
4903 Set<InterfaceType> si = computeSuperinterfaceSet(i);
4904 Set<InterfaceType> sj = computeSuperinterfaceSet(j);
4905 // union si with i and sj with j
4906 si.add(i);
4907 sj.add(j);
4908 // compute intersection, reference as set 's'
4909 List<InterfaceType> s = _intersection(si, sj);
4910 // for each element in Set s, compute the largest inheritance path to Object
4911 List<int> depths = new List<int>.filled(s.length, 0);
4912 int maxDepth = 0;
4913 for (int n = 0; n < s.length; n++) {
4914 depths[n] = computeLongestInheritancePathToObject(s[n]);
4915 if (depths[n] > maxDepth) {
4916 maxDepth = depths[n];
4917 }
4918 }
4919 // ensure that the currently computed maxDepth is unique,
4920 // otherwise, decrement and test for uniqueness again
4921 for (; maxDepth >= 0; maxDepth--) {
4922 int indexOfLeastUpperBound = -1;
4923 int numberOfTypesAtMaxDepth = 0;
4924 for (int m = 0; m < depths.length; m++) {
4925 if (depths[m] == maxDepth) {
4926 numberOfTypesAtMaxDepth++;
4927 indexOfLeastUpperBound = m;
4928 }
4929 }
4930 if (numberOfTypesAtMaxDepth == 1) {
4931 return s[indexOfLeastUpperBound];
4932 }
4933 }
4934 // Should be impossible--there should always be exactly one type with the
4935 // maximum depth.
4936 assert(false);
4937 return null;
4938 }
4939
4940 /**
4941 * Return the length of the longest inheritance path from the given [type] to
4942 * Object.
4943 *
4944 * See [computeLeastUpperBound].
4945 */
4946 static int computeLongestInheritancePathToObject(InterfaceType type) =>
4947 _computeLongestInheritancePathToObject(
4948 type, 0, new HashSet<ClassElement>());
4949
4950 /**
4951 * Returns the set of all superinterfaces of the given [type].
4952 *
4953 * See [computeLeastUpperBound].
4954 */
4955 static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) =>
4956 _computeSuperinterfaceSet(type, new HashSet<InterfaceType>());
4957
4958 /**
4959 * Returns a "smart" version of the "least upper bound" of the given types.
4960 *
4961 * If these types have the same element and differ only in terms of the type
4962 * arguments, attempts to find a compatible set of type arguments.
4963 *
4964 * Otherwise, calls [DartType.getLeastUpperBound].
4965 */
4966 static InterfaceType getSmartLeastUpperBound(
4967 InterfaceType first, InterfaceType second) {
4968 // TODO(paulberry): this needs to be deprecated and replaced with a method
4969 // in [TypeSystem], since it relies on the deprecated functionality of
4970 // [DartType.getLeastUpperBound].
4971 if (first.element == second.element) {
4972 return _leastUpperBound(first, second);
4973 }
4974 AnalysisContext context = first.element.context;
4975 return context.typeSystem
4976 .getLeastUpperBound(context.typeProvider, first, second);
4977 }
4978
4979 /**
4980 * Return the length of the longest inheritance path from a subtype of the
4981 * given [type] to Object, where the given [depth] is the length of the
4982 * longest path from the subtype to this type. The set of [visitedTypes] is
4983 * used to prevent infinite recursion in the case of a cyclic type structure.
4984 *
4985 * See [computeLongestInheritancePathToObject], and [computeLeastUpperBound].
4986 */
4987 static int _computeLongestInheritancePathToObject(
4988 InterfaceType type, int depth, HashSet<ClassElement> visitedTypes) {
4989 ClassElement classElement = type.element;
4990 // Object case
4991 if (classElement.supertype == null || visitedTypes.contains(classElement)) {
4992 return depth;
4993 }
4994 int longestPath = 1;
4995 try {
4996 visitedTypes.add(classElement);
4997 List<InterfaceType> superinterfaces = classElement.interfaces;
4998 int pathLength;
4999 if (superinterfaces.length > 0) {
5000 // loop through each of the superinterfaces recursively calling this
5001 // method and keeping track of the longest path to return
5002 for (InterfaceType superinterface in superinterfaces) {
5003 pathLength = _computeLongestInheritancePathToObject(
5004 superinterface, depth + 1, visitedTypes);
5005 if (pathLength > longestPath) {
5006 longestPath = pathLength;
5007 }
5008 }
5009 }
5010 // finally, perform this same check on the super type
5011 // TODO(brianwilkerson) Does this also need to add in the number of mixin
5012 // classes?
5013 InterfaceType supertype = classElement.supertype;
5014 pathLength = _computeLongestInheritancePathToObject(
5015 supertype, depth + 1, visitedTypes);
5016 if (pathLength > longestPath) {
5017 longestPath = pathLength;
5018 }
5019 } finally {
5020 visitedTypes.remove(classElement);
5021 }
5022 return longestPath;
5023 }
5024
5025 /**
5026 * Add all of the superinterfaces of the given [type] to the given [set].
5027 * Return the [set] as a convenience.
5028 *
5029 * See [computeSuperinterfaceSet], and [computeLeastUpperBound].
5030 */
5031 static Set<InterfaceType> _computeSuperinterfaceSet(
5032 InterfaceType type, HashSet<InterfaceType> set) {
5033 Element element = type.element;
5034 if (element != null) {
5035 List<InterfaceType> superinterfaces = type.interfaces;
5036 for (InterfaceType superinterface in superinterfaces) {
5037 if (set.add(superinterface)) {
5038 _computeSuperinterfaceSet(superinterface, set);
5039 }
5040 }
5041 InterfaceType supertype = type.superclass;
5042 if (supertype != null) {
5043 if (set.add(supertype)) {
5044 _computeSuperinterfaceSet(supertype, set);
5045 }
5046 }
5047 }
5048 return set;
5049 }
5050
5051 /**
5052 * Return the intersection of the [first] and [second] sets of types, where
5053 * intersection is based on the equality of the types themselves.
5054 */
5055 static List<InterfaceType> _intersection(
5056 Set<InterfaceType> first, Set<InterfaceType> second) {
5057 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first);
5058 result.retainAll(second);
5059 return new List.from(result);
5060 }
5061
5062 /**
5063 * Return the "least upper bound" of the given types under the assumption that
5064 * the types have the same element and differ only in terms of the type
5065 * arguments.
5066 *
5067 * The resulting type is composed by comparing the corresponding type
5068 * arguments, keeping those that are the same, and using 'dynamic' for those
5069 * that are different.
5070 */
5071 static InterfaceType _leastUpperBound(
5072 InterfaceType firstType, InterfaceType secondType) {
5073 ClassElement firstElement = firstType.element;
5074 ClassElement secondElement = secondType.element;
5075 if (firstElement != secondElement) {
5076 throw new IllegalArgumentException('The same elements expected, but '
5077 '$firstElement and $secondElement are given.');
5078 }
5079 if (firstType == secondType) {
5080 return firstType;
5081 }
5082 List<DartType> firstArguments = firstType.typeArguments;
5083 List<DartType> secondArguments = secondType.typeArguments;
5084 int argumentCount = firstArguments.length;
5085 if (argumentCount == 0) {
5086 return firstType;
5087 }
5088 List<DartType> lubArguments = new List<DartType>(argumentCount);
5089 for (int i = 0; i < argumentCount; i++) {
5090 //
5091 // Ideally we would take the least upper bound of the two argument types,
5092 // but this can cause an infinite recursion (such as when finding the
5093 // least upper bound of String and num).
5094 //
5095 if (firstArguments[i] == secondArguments[i]) {
5096 lubArguments[i] = firstArguments[i];
5097 }
5098 if (lubArguments[i] == null) {
5099 lubArguments[i] = DynamicTypeImpl.instance;
5100 }
5101 }
5102 InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement);
5103 lub.typeArguments = lubArguments;
5104 return lub;
5105 }
5106
5107 /**
5108 * Look up the getter with the given [name] in the interfaces
5109 * implemented by the given [targetType], either directly or indirectly.
5110 * Return the element representing the getter that was found, or `null` if
5111 * there is no getter with the given name. The flag [includeTargetType] should
5112 * be `true` if the search should include the target type. The
5113 * [visitedInterfaces] is a set containing all of the interfaces that have
5114 * been examined, used to prevent infinite recursion and to optimize the
5115 * search.
5116 */
5117 static ExecutableElement _lookUpMemberInInterfaces(
5118 InterfaceType targetType,
5119 bool includeTargetType,
5120 LibraryElement library,
5121 HashSet<ClassElement> visitedInterfaces,
5122 ExecutableElement getMember(InterfaceType type)) {
5123 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
5124 // specification (titled "Inheritance and Overriding" under "Interfaces")
5125 // describes a much more complex scheme for finding the inherited member.
5126 // We need to follow that scheme. The code below should cover the 80% case.
5127 ClassElement targetClass = targetType.element;
5128 if (!visitedInterfaces.add(targetClass)) {
5129 return null;
5130 }
5131 if (includeTargetType) {
5132 ExecutableElement member = getMember(targetType);
5133 if (member != null && member.isAccessibleIn(library)) {
5134 return member;
5135 }
5136 }
5137 for (InterfaceType interfaceType in targetType.interfaces) {
5138 ExecutableElement member = _lookUpMemberInInterfaces(
5139 interfaceType, true, library, visitedInterfaces, getMember);
5140 if (member != null) {
5141 return member;
5142 }
5143 }
5144 for (InterfaceType mixinType in targetType.mixins.reversed) {
5145 ExecutableElement member = _lookUpMemberInInterfaces(
5146 mixinType, true, library, visitedInterfaces, getMember);
5147 if (member != null) {
5148 return member;
5149 }
5150 }
5151 InterfaceType superclass = targetType.superclass;
5152 if (superclass == null) {
5153 return null;
5154 }
5155 return _lookUpMemberInInterfaces(
5156 superclass, true, library, visitedInterfaces, getMember);
5157 }
5158 }
5159
5160 /** 2836 /**
5161 * A concrete implementation of a [LabelElement]. 2837 * A concrete implementation of a [LabelElement].
5162 */ 2838 */
5163 class LabelElementImpl extends ElementImpl implements LabelElement { 2839 class LabelElementImpl extends ElementImpl implements LabelElement {
5164 /** 2840 /**
5165 * A flag indicating whether this label is associated with a `switch` 2841 * A flag indicating whether this label is associated with a `switch`
5166 * statement. 2842 * statement.
5167 */ 2843 */
5168 // TODO(brianwilkerson) Make this a modifier. 2844 // TODO(brianwilkerson) Make this a modifier.
5169 final bool _onSwitchStatement; 2845 final bool _onSwitchStatement;
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 * Set the visible range for this element to the range starting at the given 3526 * Set the visible range for this element to the range starting at the given
5851 * [offset] with the given [length]. 3527 * [offset] with the given [length].
5852 */ 3528 */
5853 void setVisibleRange(int offset, int length) { 3529 void setVisibleRange(int offset, int length) {
5854 _visibleRangeOffset = offset; 3530 _visibleRangeOffset = offset;
5855 _visibleRangeLength = length; 3531 _visibleRangeLength = length;
5856 } 3532 }
5857 } 3533 }
5858 3534
5859 /** 3535 /**
5860 * An element defined in a parameterized type where the values of the type
5861 * parameters are known.
5862 */
5863 abstract class Member implements Element {
5864 /**
5865 * The element on which the parameterized element was created.
5866 */
5867 final Element _baseElement;
5868
5869 /**
5870 * The type in which the element is defined.
5871 */
5872 final ParameterizedType _definingType;
5873
5874 /**
5875 * Initialize a newly created element to represent a member, based on the
5876 * [baseElement], defined by the [definingType].
5877 */
5878 Member(this._baseElement, this._definingType);
5879
5880 /**
5881 * Return the element on which the parameterized element was created.
5882 */
5883 Element get baseElement => _baseElement;
5884
5885 @override
5886 AnalysisContext get context => _baseElement.context;
5887
5888 /**
5889 * Return the type in which the element is defined.
5890 */
5891 ParameterizedType get definingType => _definingType;
5892
5893 @override
5894 String get displayName => _baseElement.displayName;
5895
5896 @override
5897 SourceRange get docRange => _baseElement.docRange;
5898
5899 int get id => _baseElement.id;
5900
5901 @override
5902 bool get isDeprecated => _baseElement.isDeprecated;
5903
5904 @override
5905 bool get isOverride => _baseElement.isOverride;
5906
5907 @override
5908 bool get isPrivate => _baseElement.isPrivate;
5909
5910 @override
5911 bool get isPublic => _baseElement.isPublic;
5912
5913 @override
5914 bool get isSynthetic => _baseElement.isSynthetic;
5915
5916 @override
5917 ElementKind get kind => _baseElement.kind;
5918
5919 @override
5920 LibraryElement get library => _baseElement.library;
5921
5922 @override
5923 ElementLocation get location => _baseElement.location;
5924
5925 @override
5926 List<ElementAnnotation> get metadata => _baseElement.metadata;
5927
5928 @override
5929 String get name => _baseElement.name;
5930
5931 @override
5932 int get nameLength => _baseElement.nameLength;
5933
5934 @override
5935 int get nameOffset => _baseElement.nameOffset;
5936
5937 @override
5938 Source get source => _baseElement.source;
5939
5940 @override
5941 CompilationUnit get unit => _baseElement.unit;
5942
5943 @override
5944 String computeDocumentationComment() =>
5945 _baseElement.computeDocumentationComment();
5946
5947 @override
5948 AstNode computeNode() => _baseElement.computeNode();
5949
5950 @override
5951 Element getAncestor(Predicate<Element> predicate) =>
5952 baseElement.getAncestor(predicate);
5953
5954 @override
5955 String getExtendedDisplayName(String shortName) =>
5956 _baseElement.getExtendedDisplayName(shortName);
5957
5958 @override
5959 bool isAccessibleIn(LibraryElement library) =>
5960 _baseElement.isAccessibleIn(library);
5961
5962 /**
5963 * If the given [child] is not `null`, use the given [visitor] to visit it.
5964 */
5965 void safelyVisitChild(Element child, ElementVisitor visitor) {
5966 // TODO(brianwilkerson) Make this private
5967 if (child != null) {
5968 child.accept(visitor);
5969 }
5970 }
5971
5972 /**
5973 * Use the given [visitor] to visit all of the [children].
5974 */
5975 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
5976 // TODO(brianwilkerson) Make this private
5977 if (children != null) {
5978 for (Element child in children) {
5979 child.accept(visitor);
5980 }
5981 }
5982 }
5983
5984 /**
5985 * Return the type that results from replacing the type parameters in the
5986 * given [type] with the type arguments associated with this member.
5987 */
5988 DartType substituteFor(DartType type) {
5989 if (type == null) {
5990 return null;
5991 }
5992 List<DartType> argumentTypes = _definingType.typeArguments;
5993 List<DartType> parameterTypes =
5994 TypeParameterTypeImpl.getTypes(_definingType.typeParameters);
5995 return type.substitute2(argumentTypes, parameterTypes);
5996 }
5997
5998 @override
5999 void visitChildren(ElementVisitor visitor) {
6000 // There are no children to visit
6001 }
6002 }
6003
6004 /**
6005 * A concrete implementation of a [MethodElement]. 3536 * A concrete implementation of a [MethodElement].
6006 */ 3537 */
6007 class MethodElementImpl extends ExecutableElementImpl implements MethodElement { 3538 class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
6008 /** 3539 /**
6009 * Initialize a newly created method element to have the given [name] at the 3540 * Initialize a newly created method element to have the given [name] at the
6010 * given [offset]. 3541 * given [offset].
6011 */ 3542 */
6012 MethodElementImpl(String name, int offset) : super(name, offset); 3543 MethodElementImpl(String name, int offset) : super(name, offset);
6013 3544
6014 /** 3545 /**
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
6080 buffer.write(displayName); 3611 buffer.write(displayName);
6081 super.appendTo(buffer); 3612 super.appendTo(buffer);
6082 } 3613 }
6083 3614
6084 @override 3615 @override
6085 MethodDeclaration computeNode() => 3616 MethodDeclaration computeNode() =>
6086 getNodeMatching((node) => node is MethodDeclaration); 3617 getNodeMatching((node) => node is MethodDeclaration);
6087 } 3618 }
6088 3619
6089 /** 3620 /**
6090 * A method element defined in a parameterized type where the values of the type
6091 * parameters are known.
6092 */
6093 class MethodMember extends ExecutableMember implements MethodElement {
6094 /**
6095 * Initialize a newly created element to represent a method, based on the
6096 * [baseElement], defined by the [definingType]. If [type] is passed, it
6097 * represents the full type of the member, and will take precedence over
6098 * the [definingType].
6099 */
6100 MethodMember(MethodElement baseElement, InterfaceType definingType,
6101 [DartType type])
6102 : super(baseElement, definingType, type);
6103
6104 @override
6105 MethodElement get baseElement => super.baseElement as MethodElement;
6106
6107 @override
6108 ClassElement get enclosingElement => baseElement.enclosingElement;
6109
6110 @override
6111 accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
6112
6113 @override
6114 MethodDeclaration computeNode() => baseElement.computeNode();
6115
6116 @override
6117 String toString() {
6118 MethodElement baseElement = this.baseElement;
6119 List<ParameterElement> parameters = this.parameters;
6120 FunctionType type = this.type;
6121 StringBuffer buffer = new StringBuffer();
6122 buffer.write(baseElement.enclosingElement.displayName);
6123 buffer.write(".");
6124 buffer.write(baseElement.displayName);
6125 buffer.write("(");
6126 int parameterCount = parameters.length;
6127 for (int i = 0; i < parameterCount; i++) {
6128 if (i > 0) {
6129 buffer.write(", ");
6130 }
6131 buffer.write(parameters[i]);
6132 }
6133 buffer.write(")");
6134 if (type != null) {
6135 buffer.write(ElementImpl.RIGHT_ARROW);
6136 buffer.write(type.returnType);
6137 }
6138 return buffer.toString();
6139 }
6140
6141 /**
6142 * If the given [method]'s type is different when any type parameters from the
6143 * defining type's declaration are replaced with the actual type arguments
6144 * from the [definingType], create a method member representing the given
6145 * method. Return the member that was created, or the base method if no member
6146 * was created.
6147 */
6148 static MethodElement from(MethodElement method, InterfaceType definingType) {
6149 if (method == null || definingType.typeArguments.length == 0) {
6150 return method;
6151 }
6152 FunctionType baseType = method.type;
6153 List<DartType> argumentTypes = definingType.typeArguments;
6154 List<DartType> parameterTypes = definingType.element.type.typeArguments;
6155 FunctionType substitutedType =
6156 baseType.substitute2(argumentTypes, parameterTypes);
6157 if (baseType == substitutedType) {
6158 return method;
6159 }
6160 return new MethodMember(method, definingType, substitutedType);
6161 }
6162 }
6163
6164 /**
6165 * A concrete implementation of a [MultiplyDefinedElement]. 3621 * A concrete implementation of a [MultiplyDefinedElement].
6166 */ 3622 */
6167 class MultiplyDefinedElementImpl implements MultiplyDefinedElement { 3623 class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
6168 /** 3624 /**
6169 * The unique integer identifier of this element. 3625 * The unique integer identifier of this element.
6170 */ 3626 */
6171 final int id = ElementImpl._NEXT_ID++; 3627 final int id = ElementImpl._NEXT_ID++;
6172 3628
6173 /** 3629 /**
6174 * The analysis context in which the multiply defined elements are defined. 3630 * The analysis context in which the multiply defined elements are defined.
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
6595 } 4051 }
6596 if (parameterKind == ParameterKind.POSITIONAL) { 4052 if (parameterKind == ParameterKind.POSITIONAL) {
6597 buffer.write(" = "); 4053 buffer.write(" = ");
6598 } 4054 }
6599 buffer.write(defaultValueCode); 4055 buffer.write(defaultValueCode);
6600 } 4056 }
6601 } 4057 }
6602 } 4058 }
6603 4059
6604 /** 4060 /**
6605 * A parameter element defined in a parameterized type where the values of the
6606 * type parameters are known.
6607 */
6608 class ParameterMember extends VariableMember
6609 with ParameterElementMixin
6610 implements ParameterElement {
6611 /**
6612 * Initialize a newly created element to represent a parameter, based on the
6613 * [baseElement], defined by the [definingType]. If [type] is passed it will
6614 * represent the already substituted type.
6615 */
6616 ParameterMember(ParameterElement baseElement, ParameterizedType definingType,
6617 [DartType type])
6618 : super._(baseElement, definingType, type);
6619
6620 @override
6621 ParameterElement get baseElement => super.baseElement as ParameterElement;
6622
6623 @override
6624 String get defaultValueCode => baseElement.defaultValueCode;
6625
6626 @override
6627 Element get enclosingElement => baseElement.enclosingElement;
6628
6629 @override
6630 int get hashCode => baseElement.hashCode;
6631
6632 @override
6633 bool get isInitializingFormal => baseElement.isInitializingFormal;
6634
6635 @override
6636 ParameterKind get parameterKind => baseElement.parameterKind;
6637
6638 @override
6639 List<ParameterElement> get parameters {
6640 DartType type = this.type;
6641 if (type is FunctionType) {
6642 return type.parameters;
6643 }
6644 return ParameterElement.EMPTY_LIST;
6645 }
6646
6647 @override
6648 List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
6649
6650 @override
6651 SourceRange get visibleRange => baseElement.visibleRange;
6652
6653 // TODO(jmesserly): this equality is broken. It should consider the defining
6654 // type as well, otherwise we're dropping the substitution.
6655 @override
6656 bool operator ==(Object object) =>
6657 object is ParameterMember && baseElement == object.baseElement;
6658
6659 @override
6660 accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
6661
6662 @override
6663 FormalParameter computeNode() => baseElement.computeNode();
6664
6665 @override
6666 Element getAncestor(Predicate<Element> predicate) {
6667 Element element = baseElement.getAncestor(predicate);
6668 ParameterizedType definingType = this.definingType;
6669 if (definingType is InterfaceType) {
6670 InterfaceType definingInterfaceType = definingType;
6671 if (element is ConstructorElement) {
6672 return ConstructorMember.from(element, definingInterfaceType);
6673 } else if (element is MethodElement) {
6674 return MethodMember.from(element, definingInterfaceType);
6675 } else if (element is PropertyAccessorElement) {
6676 return PropertyAccessorMember.from(element, definingInterfaceType);
6677 }
6678 }
6679 return element;
6680 }
6681
6682 @override
6683 String toString() {
6684 ParameterElement baseElement = this.baseElement;
6685 String left = "";
6686 String right = "";
6687 while (true) {
6688 if (baseElement.parameterKind == ParameterKind.NAMED) {
6689 left = "{";
6690 right = "}";
6691 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) {
6692 left = "[";
6693 right = "]";
6694 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {}
6695 break;
6696 }
6697 return '$left$type ${baseElement.displayName}$right';
6698 }
6699
6700 @override
6701 void visitChildren(ElementVisitor visitor) {
6702 super.visitChildren(visitor);
6703 safelyVisitChildren(parameters, visitor);
6704 }
6705
6706 /**
6707 * If the given [parameter]'s type is different when any type parameters from
6708 * the defining type's declaration are replaced with the actual type
6709 * arguments from the [definingType], create a parameter member representing
6710 * the given parameter. Return the member that was created, or the base
6711 * parameter if no member was created.
6712 */
6713 static ParameterElement from(
6714 ParameterElement parameter, ParameterizedType definingType) {
6715 if (parameter == null || definingType.typeArguments.length == 0) {
6716 return parameter;
6717 }
6718 // Check if parameter type depends on defining type type arguments.
6719 // It is possible that we did not resolve field formal parameter yet,
6720 // so skip this check for it.
6721 if (parameter is FieldFormalParameterElement) {
6722 return new FieldFormalParameterMember(parameter, definingType);
6723 } else {
6724 DartType baseType = parameter.type;
6725 List<DartType> argumentTypes = definingType.typeArguments;
6726 List<DartType> parameterTypes =
6727 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
6728 DartType substitutedType =
6729 baseType.substitute2(argumentTypes, parameterTypes);
6730 if (baseType == substitutedType) {
6731 return parameter;
6732 }
6733 return new ParameterMember(parameter, definingType, substitutedType);
6734 }
6735 }
6736 }
6737
6738 /**
6739 * A concrete implementation of a [PrefixElement]. 4061 * A concrete implementation of a [PrefixElement].
6740 */ 4062 */
6741 class PrefixElementImpl extends ElementImpl implements PrefixElement { 4063 class PrefixElementImpl extends ElementImpl implements PrefixElement {
6742 /** 4064 /**
6743 * A list containing all of the libraries that are imported using this prefix. 4065 * A list containing all of the libraries that are imported using this prefix.
6744 */ 4066 */
6745 List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST; 4067 List<LibraryElement> _importedLibraries = LibraryElement.EMPTY_LIST;
6746 4068
6747 /** 4069 /**
6748 * Initialize a newly created method element to have the given [name] and 4070 * Initialize a newly created method element to have the given [name] and
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
6919 return getNodeMatching((node) => node is MethodDeclaration); 4241 return getNodeMatching((node) => node is MethodDeclaration);
6920 } 4242 }
6921 if (enclosingElement is CompilationUnitElement) { 4243 if (enclosingElement is CompilationUnitElement) {
6922 return getNodeMatching((node) => node is FunctionDeclaration); 4244 return getNodeMatching((node) => node is FunctionDeclaration);
6923 } 4245 }
6924 return null; 4246 return null;
6925 } 4247 }
6926 } 4248 }
6927 4249
6928 /** 4250 /**
6929 * A property accessor element defined in a parameterized type where the values
6930 * of the type parameters are known.
6931 */
6932 class PropertyAccessorMember extends ExecutableMember
6933 implements PropertyAccessorElement {
6934 /**
6935 * Initialize a newly created element to represent a property, based on the
6936 * [baseElement], defined by the [definingType].
6937 */
6938 PropertyAccessorMember(
6939 PropertyAccessorElement baseElement, InterfaceType definingType)
6940 : super(baseElement, definingType);
6941
6942 @override
6943 PropertyAccessorElement get baseElement =>
6944 super.baseElement as PropertyAccessorElement;
6945
6946 @override
6947 PropertyAccessorElement get correspondingGetter =>
6948 from(baseElement.correspondingGetter, definingType);
6949
6950 @override
6951 PropertyAccessorElement get correspondingSetter =>
6952 from(baseElement.correspondingSetter, definingType);
6953
6954 @override
6955 InterfaceType get definingType => super.definingType as InterfaceType;
6956
6957 @override
6958 Element get enclosingElement => baseElement.enclosingElement;
6959
6960 @override
6961 bool get isGetter => baseElement.isGetter;
6962
6963 @override
6964 bool get isSetter => baseElement.isSetter;
6965
6966 @override
6967 PropertyInducingElement get variable {
6968 PropertyInducingElement variable = baseElement.variable;
6969 if (variable is FieldElement) {
6970 return FieldMember.from(variable, definingType);
6971 }
6972 return variable;
6973 }
6974
6975 @override
6976 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
6977
6978 @override
6979 String toString() {
6980 PropertyAccessorElement baseElement = this.baseElement;
6981 List<ParameterElement> parameters = this.parameters;
6982 FunctionType type = this.type;
6983 StringBuffer builder = new StringBuffer();
6984 if (isGetter) {
6985 builder.write("get ");
6986 } else {
6987 builder.write("set ");
6988 }
6989 builder.write(baseElement.enclosingElement.displayName);
6990 builder.write(".");
6991 builder.write(baseElement.displayName);
6992 builder.write("(");
6993 int parameterCount = parameters.length;
6994 for (int i = 0; i < parameterCount; i++) {
6995 if (i > 0) {
6996 builder.write(", ");
6997 }
6998 builder.write(parameters[i]);
6999 }
7000 builder.write(")");
7001 if (type != null) {
7002 builder.write(ElementImpl.RIGHT_ARROW);
7003 builder.write(type.returnType);
7004 }
7005 return builder.toString();
7006 }
7007
7008 /**
7009 * If the given [accessor]'s type is different when any type parameters from
7010 * the defining type's declaration are replaced with the actual type
7011 * arguments from the [definingType], create an accessor member representing
7012 * the given accessor. Return the member that was created, or the base
7013 * accessor if no member was created.
7014 */
7015 static PropertyAccessorElement from(
7016 PropertyAccessorElement accessor, InterfaceType definingType) {
7017 if (!_isChangedByTypeSubstitution(accessor, definingType)) {
7018 return accessor;
7019 }
7020 // TODO(brianwilkerson) Consider caching the substituted type in the
7021 // instance. It would use more memory but speed up some operations.
7022 // We need to see how often the type is being re-computed.
7023 return new PropertyAccessorMember(accessor, definingType);
7024 }
7025
7026 /**
7027 * Determine whether the given property [accessor]'s type is changed when type
7028 * parameters from the defining type's declaration are replaced with the
7029 * actual type arguments from the [definingType].
7030 */
7031 static bool _isChangedByTypeSubstitution(
7032 PropertyAccessorElement accessor, InterfaceType definingType) {
7033 List<DartType> argumentTypes = definingType.typeArguments;
7034 if (accessor != null && argumentTypes.length != 0) {
7035 FunctionType baseType = accessor.type;
7036 if (baseType == null) {
7037 AnalysisEngine.instance.logger.logInformation(
7038 'Type of $accessor is null in PropertyAccessorMember._isChangedByTyp eSubstitution');
7039 return false;
7040 }
7041 List<DartType> parameterTypes = definingType.element.type.typeArguments;
7042 FunctionType substitutedType =
7043 baseType.substitute2(argumentTypes, parameterTypes);
7044 if (baseType != substitutedType) {
7045 return true;
7046 }
7047 // If this property accessor is based on a field, that field might have a
7048 // propagated type. In which case we need to check whether the propagated
7049 // type of the field needs substitution.
7050 PropertyInducingElement field = accessor.variable;
7051 if (!field.isSynthetic) {
7052 DartType baseFieldType = field.propagatedType;
7053 if (baseFieldType != null) {
7054 DartType substitutedFieldType =
7055 baseFieldType.substitute2(argumentTypes, parameterTypes);
7056 if (baseFieldType != substitutedFieldType) {
7057 return true;
7058 }
7059 }
7060 }
7061 }
7062 return false;
7063 }
7064 }
7065
7066 /**
7067 * A concrete implementation of a [PropertyInducingElement]. 4251 * A concrete implementation of a [PropertyInducingElement].
7068 */ 4252 */
7069 abstract class PropertyInducingElementImpl extends VariableElementImpl 4253 abstract class PropertyInducingElementImpl extends VariableElementImpl
7070 implements PropertyInducingElement { 4254 implements PropertyInducingElement {
7071 /** 4255 /**
7072 * The getter associated with this element. 4256 * The getter associated with this element.
7073 */ 4257 */
7074 PropertyAccessorElement getter; 4258 PropertyAccessorElement getter;
7075 4259
7076 /** 4260 /**
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
7159 4343
7160 @override 4344 @override
7161 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this); 4345 accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
7162 4346
7163 @override 4347 @override
7164 VariableDeclaration computeNode() => 4348 VariableDeclaration computeNode() =>
7165 getNodeMatching((node) => node is VariableDeclaration); 4349 getNodeMatching((node) => node is VariableDeclaration);
7166 } 4350 }
7167 4351
7168 /** 4352 /**
7169 * The abstract class `TypeImpl` implements the behavior common to objects
7170 * representing the declared type of elements in the element model.
7171 */
7172 abstract class TypeImpl implements DartType {
7173 /**
7174 * The element representing the declaration of this type, or `null` if the
7175 * type has not, or cannot, be associated with an element.
7176 */
7177 final Element _element;
7178
7179 /**
7180 * The name of this type, or `null` if the type does not have a name.
7181 */
7182 final String name;
7183
7184 /**
7185 * Initialize a newly created type to be declared by the given [element] and
7186 * to have the given [name].
7187 */
7188 TypeImpl(this._element, this.name);
7189
7190 @override
7191 String get displayName => name;
7192
7193 @override
7194 Element get element => _element;
7195
7196 @override
7197 bool get isBottom => false;
7198
7199 @override
7200 bool get isDartCoreFunction => false;
7201
7202 @override
7203 bool get isDynamic => false;
7204
7205 @override
7206 bool get isObject => false;
7207
7208 @override
7209 bool get isUndefined => false;
7210
7211 @override
7212 bool get isVoid => false;
7213
7214 /**
7215 * Append a textual representation of this type to the given [buffer]. The set
7216 * of [visitedTypes] is used to prevent infinite recursion.
7217 */
7218 void appendTo(StringBuffer buffer) {
7219 if (name == null) {
7220 buffer.write("<unnamed type>");
7221 } else {
7222 buffer.write(name);
7223 }
7224 }
7225
7226 /**
7227 * Return `true` if this type is assignable to the given [type] (written in
7228 * the spec as "T <=> S", where T=[this] and S=[type]).
7229 *
7230 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
7231 * function type aliases that have been expanded so far in the process of
7232 * reaching [this] and [type], respectively. These are used to avoid
7233 * infinite regress when analyzing invalid code; since the language spec
7234 * forbids a typedef from referring to itself directly or indirectly, we can
7235 * use these as sets of function type aliases that don't need to be expanded.
7236 */
7237 @override
7238 bool isAssignableTo(DartType type) {
7239 // An interface type T may be assigned to a type S, written T <=> S, iff
7240 // either T <: S or S <: T.
7241 return isSubtypeOf(type) || (type as TypeImpl).isSubtypeOf(this);
7242 }
7243
7244 /**
7245 * Return `true` if this type is more specific than the given [type] (written
7246 * in the spec as "T << S", where T=[this] and S=[type]).
7247 *
7248 * If [withDynamic] is `true`, then "dynamic" should be considered as a
7249 * subtype of any type (as though "dynamic" had been replaced with bottom).
7250 *
7251 * The set [visitedElements], if given, is the set of classes and type
7252 * parameters that have been visited so far while examining the class
7253 * hierarchy of [this]. This is used to avoid infinite regress when
7254 * analyzing invalid code; since the language spec forbids loops in the class
7255 * hierarchy, we can use this as a set of classes that don't need to be
7256 * examined when walking the class hierarchy.
7257 */
7258 @override
7259 bool isMoreSpecificThan(DartType type,
7260 [bool withDynamic = false, Set<Element> visitedElements]);
7261
7262 /**
7263 * Return `true` if this type is a subtype of the given [type] (written in
7264 * the spec as "T <: S", where T=[this] and S=[type]).
7265 *
7266 * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
7267 * function type aliases that have been expanded so far in the process of
7268 * reaching [this] and [type], respectively. These are used to avoid
7269 * infinite regress when analyzing invalid code; since the language spec
7270 * forbids a typedef from referring to itself directly or indirectly, we can
7271 * use these as sets of function type aliases that don't need to be expanded.
7272 */
7273 @override
7274 bool isSubtypeOf(DartType type) {
7275 // For non-function types, T <: S iff [_|_/dynamic]T << S.
7276 return isMoreSpecificThan(type, true);
7277 }
7278
7279 @override
7280 bool isSupertypeOf(DartType type) => type.isSubtypeOf(this);
7281
7282 /**
7283 * Create a new [TypeImpl] that is identical to [this] except that when
7284 * visiting type parameters, function parameter types, and function return
7285 * types, function types listed in [prune] will not be expanded. This is
7286 * used to avoid creating infinite types in the presence of circular
7287 * typedefs.
7288 *
7289 * If [prune] is null, then [this] is returned unchanged.
7290 *
7291 * Only legal to call on a [TypeImpl] that is not already subject to pruning.
7292 */
7293 TypeImpl pruned(List<FunctionTypeAliasElement> prune);
7294
7295 /**
7296 * Return the type resulting from substituting the given [argumentTypes] for
7297 * the given [parameterTypes] in this type.
7298 *
7299 * In all classes derived from [TypeImpl], a new optional argument
7300 * [prune] is added. If specified, it is a list of function typdefs
7301 * which should not be expanded. This is used to avoid creating infinite
7302 * types in response to self-referential typedefs.
7303 */
7304 @override
7305 DartType substitute2(
7306 List<DartType> argumentTypes, List<DartType> parameterTypes,
7307 [List<FunctionTypeAliasElement> prune]);
7308
7309 @override
7310 String toString() {
7311 StringBuffer buffer = new StringBuffer();
7312 appendTo(buffer);
7313 return buffer.toString();
7314 }
7315
7316 /**
7317 * Return `true` if corresponding elements of the [first] and [second] lists
7318 * of type arguments are all equal.
7319 */
7320 static bool equalArrays(List<DartType> first, List<DartType> second) {
7321 if (first.length != second.length) {
7322 return false;
7323 }
7324 for (int i = 0; i < first.length; i++) {
7325 if (first[i] == null) {
7326 AnalysisEngine.instance.logger
7327 .logInformation('Found null type argument in TypeImpl.equalArrays');
7328 return second[i] == null;
7329 } else if (second[i] == null) {
7330 AnalysisEngine.instance.logger
7331 .logInformation('Found null type argument in TypeImpl.equalArrays');
7332 return false;
7333 }
7334 if (first[i] != second[i]) {
7335 return false;
7336 }
7337 }
7338 return true;
7339 }
7340
7341 /**
7342 * Return a list containing the results of using the given [argumentTypes] and
7343 * [parameterTypes] to perform a substitution on all of the given [types].
7344 *
7345 * If [prune] is specified, it is a list of function typdefs which should not
7346 * be expanded. This is used to avoid creating infinite types in response to
7347 * self-referential typedefs.
7348 */
7349 static List<DartType> substitute(List<DartType> types,
7350 List<DartType> argumentTypes, List<DartType> parameterTypes,
7351 [List<FunctionTypeAliasElement> prune]) {
7352 int length = types.length;
7353 if (length == 0) {
7354 return types;
7355 }
7356 List<DartType> newTypes = new List<DartType>(length);
7357 for (int i = 0; i < length; i++) {
7358 newTypes[i] = (types[i] as TypeImpl)
7359 .substitute2(argumentTypes, parameterTypes, prune);
7360 }
7361 return newTypes;
7362 }
7363 }
7364
7365 /**
7366 * A concrete implementation of a [TypeParameterElement]. 4353 * A concrete implementation of a [TypeParameterElement].
7367 */ 4354 */
7368 class TypeParameterElementImpl extends ElementImpl 4355 class TypeParameterElementImpl extends ElementImpl
7369 implements TypeParameterElement { 4356 implements TypeParameterElement {
7370 /** 4357 /**
7371 * The type defined by this type parameter. 4358 * The type defined by this type parameter.
7372 */ 4359 */
7373 TypeParameterType type; 4360 TypeParameterType type;
7374 4361
7375 /** 4362 /**
(...skipping 23 matching lines...) Expand all
7399 void appendTo(StringBuffer buffer) { 4386 void appendTo(StringBuffer buffer) {
7400 buffer.write(displayName); 4387 buffer.write(displayName);
7401 if (bound != null) { 4388 if (bound != null) {
7402 buffer.write(" extends "); 4389 buffer.write(" extends ");
7403 buffer.write(bound); 4390 buffer.write(bound);
7404 } 4391 }
7405 } 4392 }
7406 } 4393 }
7407 4394
7408 /** 4395 /**
7409 * A concrete implementation of a [TypeParameterType].
7410 */
7411 class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
7412 /**
7413 * Initialize a newly created type parameter type to be declared by the given
7414 * [element] and to have the given name.
7415 */
7416 TypeParameterTypeImpl(TypeParameterElement element)
7417 : super(element, element.name);
7418
7419 @override
7420 TypeParameterElement get element => super.element as TypeParameterElement;
7421
7422 @override
7423 int get hashCode => element.hashCode;
7424
7425 @override
7426 bool operator ==(Object object) =>
7427 object is TypeParameterTypeImpl && (element == object.element);
7428
7429 @override
7430 bool isMoreSpecificThan(DartType s,
7431 [bool withDynamic = false, Set<Element> visitedElements]) {
7432 //
7433 // A type T is more specific than a type S, written T << S,
7434 // if one of the following conditions is met:
7435 //
7436 // Reflexivity: T is S.
7437 //
7438 if (this == s) {
7439 return true;
7440 }
7441 // S is dynamic.
7442 //
7443 if (s.isDynamic) {
7444 return true;
7445 }
7446 //
7447 // T is a type parameter and S is the upper bound of T.
7448 //
7449 TypeImpl bound = element.bound;
7450 if (s == bound) {
7451 return true;
7452 }
7453 //
7454 // T is a type parameter and S is Object.
7455 //
7456 if (s.isObject) {
7457 return true;
7458 }
7459 // We need upper bound to continue.
7460 if (bound == null) {
7461 return false;
7462 }
7463 //
7464 // Transitivity: T << U and U << S.
7465 //
7466 // First check for infinite loops
7467 if (element == null) {
7468 return false;
7469 }
7470 if (visitedElements == null) {
7471 visitedElements = new HashSet<Element>();
7472 } else if (visitedElements.contains(element)) {
7473 return false;
7474 }
7475 visitedElements.add(element);
7476 try {
7477 return bound.isMoreSpecificThan(s, withDynamic, visitedElements);
7478 } finally {
7479 visitedElements.remove(element);
7480 }
7481 }
7482
7483 @override
7484 bool isSubtypeOf(DartType type) => isMoreSpecificThan(type, true);
7485
7486 @override
7487 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
7488
7489 @override
7490 DartType substitute2(
7491 List<DartType> argumentTypes, List<DartType> parameterTypes,
7492 [List<FunctionTypeAliasElement> prune]) {
7493 int length = parameterTypes.length;
7494 for (int i = 0; i < length; i++) {
7495 if (parameterTypes[i] == this) {
7496 return argumentTypes[i];
7497 }
7498 }
7499 return this;
7500 }
7501
7502 /**
7503 * Return a list containing the type parameter types defined by the given
7504 * array of type parameter elements ([typeParameters]).
7505 */
7506 static List<TypeParameterType> getTypes(
7507 List<TypeParameterElement> typeParameters) {
7508 int count = typeParameters.length;
7509 if (count == 0) {
7510 return TypeParameterType.EMPTY_LIST;
7511 }
7512 List<TypeParameterType> types = new List<TypeParameterType>(count);
7513 for (int i = 0; i < count; i++) {
7514 types[i] = typeParameters[i].type;
7515 }
7516 return types;
7517 }
7518 }
7519
7520 /**
7521 * The unique instance of the class `UndefinedTypeImpl` implements the type of
7522 * type names that couldn't be resolved.
7523 *
7524 * This class behaves like DynamicTypeImpl in almost every respect, to reduce
7525 * cascading errors.
7526 */
7527 class UndefinedTypeImpl extends TypeImpl {
7528 /**
7529 * The unique instance of this class.
7530 */
7531 static UndefinedTypeImpl _INSTANCE = new UndefinedTypeImpl._();
7532
7533 /**
7534 * Return the unique instance of this class.
7535 */
7536 static UndefinedTypeImpl get instance => _INSTANCE;
7537
7538 /**
7539 * Prevent the creation of instances of this class.
7540 */
7541 UndefinedTypeImpl._()
7542 : super(DynamicElementImpl.instance, Keyword.DYNAMIC.syntax);
7543
7544 @override
7545 int get hashCode => 1;
7546
7547 @override
7548 bool get isDynamic => true;
7549
7550 @override
7551 bool get isUndefined => true;
7552
7553 @override
7554 bool operator ==(Object object) => identical(object, this);
7555
7556 @override
7557 bool isMoreSpecificThan(DartType type,
7558 [bool withDynamic = false, Set<Element> visitedElements]) {
7559 // T is S
7560 if (identical(this, type)) {
7561 return true;
7562 }
7563 // else
7564 return withDynamic;
7565 }
7566
7567 @override
7568 bool isSubtypeOf(DartType type) => true;
7569
7570 @override
7571 bool isSupertypeOf(DartType type) => true;
7572
7573 @override
7574 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
7575
7576 @override
7577 DartType substitute2(
7578 List<DartType> argumentTypes, List<DartType> parameterTypes,
7579 [List<FunctionTypeAliasElement> prune]) {
7580 int length = parameterTypes.length;
7581 for (int i = 0; i < length; i++) {
7582 if (parameterTypes[i] == this) {
7583 return argumentTypes[i];
7584 }
7585 }
7586 return this;
7587 }
7588 }
7589
7590 /**
7591 * A concrete implementation of a [UriReferencedElement]. 4396 * A concrete implementation of a [UriReferencedElement].
7592 */ 4397 */
7593 abstract class UriReferencedElementImpl extends ElementImpl 4398 abstract class UriReferencedElementImpl extends ElementImpl
7594 implements UriReferencedElement { 4399 implements UriReferencedElement {
7595 /** 4400 /**
7596 * The offset of the URI in the file, may be `-1` if synthetic. 4401 * The offset of the URI in the file, may be `-1` if synthetic.
7597 */ 4402 */
7598 int uriOffset = -1; 4403 int uriOffset = -1;
7599 4404
7600 /** 4405 /**
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
7734 } 4539 }
7735 4540
7736 @override 4541 @override
7737 void visitChildren(ElementVisitor visitor) { 4542 void visitChildren(ElementVisitor visitor) {
7738 super.visitChildren(visitor); 4543 super.visitChildren(visitor);
7739 safelyVisitChild(_initializer, visitor); 4544 safelyVisitChild(_initializer, visitor);
7740 } 4545 }
7741 } 4546 }
7742 4547
7743 /** 4548 /**
7744 * A variable element defined in a parameterized type where the values of the
7745 * type parameters are known.
7746 */
7747 abstract class VariableMember extends Member implements VariableElement {
7748 @override
7749 final DartType type;
7750
7751 /**
7752 * Initialize a newly created element to represent a variable, based on the
7753 * [baseElement], defined by the [definingType].
7754 */
7755 VariableMember(VariableElement baseElement, ParameterizedType definingType,
7756 [DartType type])
7757 : type = type ??
7758 baseElement.type.substitute2(definingType.typeArguments,
7759 TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
7760 super(baseElement, definingType);
7761
7762 // TODO(jmesserly): this is temporary to allow the ParameterMember subclass.
7763 // Apparently mixins don't work with optional params.
7764 VariableMember._(VariableElement baseElement, ParameterizedType definingType,
7765 DartType type)
7766 : this(baseElement, definingType, type);
7767
7768 @override
7769 VariableElement get baseElement => super.baseElement as VariableElement;
7770
7771 @override
7772 DartObject get constantValue => baseElement.constantValue;
7773
7774 @override
7775 bool get hasImplicitType => baseElement.hasImplicitType;
7776
7777 @override
7778 FunctionElement get initializer {
7779 //
7780 // Elements within this element should have type parameters substituted,
7781 // just like this element.
7782 //
7783 throw new UnsupportedOperationException();
7784 // return getBaseElement().getInitializer();
7785 }
7786
7787 @override
7788 bool get isConst => baseElement.isConst;
7789
7790 @override
7791 bool get isFinal => baseElement.isFinal;
7792
7793 @override
7794 bool get isPotentiallyMutatedInClosure =>
7795 baseElement.isPotentiallyMutatedInClosure;
7796
7797 @override
7798 bool get isPotentiallyMutatedInScope =>
7799 baseElement.isPotentiallyMutatedInScope;
7800
7801 @override
7802 bool get isStatic => baseElement.isStatic;
7803
7804 @override
7805 void visitChildren(ElementVisitor visitor) {
7806 // TODO(brianwilkerson) We need to finish implementing the accessors used
7807 // below so that we can safely invoke them.
7808 super.visitChildren(visitor);
7809 safelyVisitChild(baseElement.initializer, visitor);
7810 }
7811 }
7812
7813 /**
7814 * The type `void`.
7815 */
7816 abstract class VoidType implements DartType {
7817 @override
7818 VoidType substitute2(
7819 List<DartType> argumentTypes, List<DartType> parameterTypes);
7820 }
7821
7822 /**
7823 * A concrete implementation of a [VoidType].
7824 */
7825 class VoidTypeImpl extends TypeImpl implements VoidType {
7826 /**
7827 * The unique instance of this class.
7828 */
7829 static VoidTypeImpl _INSTANCE = new VoidTypeImpl();
7830
7831 /**
7832 * Return the unique instance of this class.
7833 */
7834 static VoidTypeImpl get instance => _INSTANCE;
7835
7836 /**
7837 * Prevent the creation of instances of this class.
7838 */
7839 VoidTypeImpl() : super(null, Keyword.VOID.syntax);
7840
7841 @override
7842 int get hashCode => 2;
7843
7844 @override
7845 bool get isVoid => true;
7846
7847 @override
7848 bool operator ==(Object object) => identical(object, this);
7849
7850 @override
7851 bool isMoreSpecificThan(DartType type,
7852 [bool withDynamic = false, Set<Element> visitedElements]) =>
7853 isSubtypeOf(type);
7854
7855 @override
7856 bool isSubtypeOf(DartType type) {
7857 // The only subtype relations that pertain to void are therefore:
7858 // void <: void (by reflexivity)
7859 // bottom <: void (as bottom is a subtype of all types).
7860 // void <: dynamic (as dynamic is a supertype of all types)
7861 return identical(type, this) || type.isDynamic;
7862 }
7863
7864 @override
7865 TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
7866
7867 @override
7868 VoidTypeImpl substitute2(
7869 List<DartType> argumentTypes, List<DartType> parameterTypes,
7870 [List<FunctionTypeAliasElement> prune]) =>
7871 this;
7872 }
7873
7874 /**
7875 * A visitor that visit all the elements recursively and fill the given [map]. 4549 * A visitor that visit all the elements recursively and fill the given [map].
7876 */ 4550 */
7877 class _BuildOffsetToElementMap extends GeneralizingElementVisitor { 4551 class _BuildOffsetToElementMap extends GeneralizingElementVisitor {
7878 final Map<int, Element> map; 4552 final Map<int, Element> map;
7879 4553
7880 _BuildOffsetToElementMap(this.map); 4554 _BuildOffsetToElementMap(this.map);
7881 4555
7882 @override 4556 @override
7883 void visitElement(Element element) { 4557 void visitElement(Element element) {
7884 int offset = element.nameOffset; 4558 int offset = element.nameOffset;
7885 if (offset != -1) { 4559 if (offset != -1) {
7886 map[offset] = element; 4560 map[offset] = element;
7887 } 4561 }
7888 super.visitElement(element); 4562 super.visitElement(element);
7889 } 4563 }
7890 } 4564 }
OLDNEW
« no previous file with comments | « pkg/analyzer/CHANGELOG.md ('k') | pkg/analyzer/lib/src/dart/element/member.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698