| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |