| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 Element get currentElement; | 8 Element get currentElement; |
| 9 Setlet<Node> get superUses; | 9 Setlet<Node> get superUses; |
| 10 | 10 |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 factory.redirectionTargetType = targetType; | 654 factory.redirectionTargetType = targetType; |
| 655 } | 655 } |
| 656 } | 656 } |
| 657 | 657 |
| 658 /** | 658 /** |
| 659 * Load and resolve the supertypes of [cls]. | 659 * Load and resolve the supertypes of [cls]. |
| 660 * | 660 * |
| 661 * Warning: do not call this method directly. It should only be | 661 * Warning: do not call this method directly. It should only be |
| 662 * called by [resolveClass] and [ClassSupertypeResolver]. | 662 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 663 */ | 663 */ |
| 664 void loadSupertypes(ClassElement cls, Spannable from) { | 664 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
| 665 compiler.withCurrentElement(cls, () => measure(() { | 665 compiler.withCurrentElement(cls, () => measure(() { |
| 666 if (cls.supertypeLoadState == STATE_DONE) return; | 666 if (cls.supertypeLoadState == STATE_DONE) return; |
| 667 if (cls.supertypeLoadState == STATE_STARTED) { | 667 if (cls.supertypeLoadState == STATE_STARTED) { |
| 668 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY, | 668 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 669 {'className': cls.name}); | 669 {'className': cls.name}); |
| 670 cls.supertypeLoadState = STATE_DONE; | 670 cls.supertypeLoadState = STATE_DONE; |
| 671 cls.allSupertypes = const Link<DartType>().prepend( | 671 cls.allSupertypesAndSelf = |
| 672 compiler.objectClass.computeType(compiler)); | 672 compiler.objectClass.allSupertypesAndSelf.extendClass( |
| 673 cls.computeType(compiler)); |
| 673 cls.supertype = cls.allSupertypes.head; | 674 cls.supertype = cls.allSupertypes.head; |
| 675 assert(invariant(from, cls.supertype != null, |
| 676 message: 'Missing supertype on cyclic class $cls.')); |
| 674 return; | 677 return; |
| 675 } | 678 } |
| 676 cls.supertypeLoadState = STATE_STARTED; | 679 cls.supertypeLoadState = STATE_STARTED; |
| 677 compiler.withCurrentElement(cls, () { | 680 compiler.withCurrentElement(cls, () { |
| 678 // TODO(ahe): Cache the node in cls. | 681 // TODO(ahe): Cache the node in cls. |
| 679 cls.parseNode(compiler).accept( | 682 cls.parseNode(compiler).accept( |
| 680 new ClassSupertypeResolver(compiler, cls)); | 683 new ClassSupertypeResolver(compiler, cls)); |
| 681 if (cls.supertypeLoadState != STATE_DONE) { | 684 if (cls.supertypeLoadState != STATE_DONE) { |
| 682 cls.supertypeLoadState = STATE_DONE; | 685 cls.supertypeLoadState = STATE_DONE; |
| 683 } | 686 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 } | 719 } |
| 717 | 720 |
| 718 void _ensureClassWillBeResolved(ClassElement element) { | 721 void _ensureClassWillBeResolved(ClassElement element) { |
| 719 if (currentlyResolvedClass == null) { | 722 if (currentlyResolvedClass == null) { |
| 720 element.ensureResolved(compiler); | 723 element.ensureResolved(compiler); |
| 721 } else { | 724 } else { |
| 722 pendingClassesToBeResolved.add(element); | 725 pendingClassesToBeResolved.add(element); |
| 723 } | 726 } |
| 724 } | 727 } |
| 725 | 728 |
| 726 void resolveClassInternal(ClassElement element, TreeElementMapping mapping) { | 729 void resolveClassInternal(BaseClassElementX element, |
| 730 TreeElementMapping mapping) { |
| 727 if (!element.isPatch) { | 731 if (!element.isPatch) { |
| 728 compiler.withCurrentElement(element, () => measure(() { | 732 compiler.withCurrentElement(element, () => measure(() { |
| 729 assert(element.resolutionState == STATE_NOT_STARTED); | 733 assert(element.resolutionState == STATE_NOT_STARTED); |
| 730 element.resolutionState = STATE_STARTED; | 734 element.resolutionState = STATE_STARTED; |
| 731 Node tree = element.parseNode(compiler); | 735 Node tree = element.parseNode(compiler); |
| 732 loadSupertypes(element, tree); | 736 loadSupertypes(element, tree); |
| 733 | 737 |
| 734 ClassResolverVisitor visitor = | 738 ClassResolverVisitor visitor = |
| 735 new ClassResolverVisitor(compiler, element, mapping); | 739 new ClassResolverVisitor(compiler, element, mapping); |
| 736 visitor.visit(tree); | 740 visitor.visit(tree); |
| 737 element.resolutionState = STATE_DONE; | 741 element.resolutionState = STATE_DONE; |
| 738 compiler.onClassResolved(element); | 742 compiler.onClassResolved(element); |
| 739 })); | 743 })); |
| 740 if (element.isPatched) { | 744 if (element.isPatched) { |
| 741 // Ensure handling patch after origin. | 745 // Ensure handling patch after origin. |
| 742 element.patch.ensureResolved(compiler); | 746 element.patch.ensureResolved(compiler); |
| 743 } | 747 } |
| 744 } else { // Handle patch classes: | 748 } else { // Handle patch classes: |
| 745 element.resolutionState = STATE_STARTED; | 749 element.resolutionState = STATE_STARTED; |
| 746 // Ensure handling origin before patch. | 750 // Ensure handling origin before patch. |
| 747 element.origin.ensureResolved(compiler); | 751 element.origin.ensureResolved(compiler); |
| 748 // Ensure that the type is computed. | 752 // Ensure that the type is computed. |
| 749 element.computeType(compiler); | 753 element.computeType(compiler); |
| 750 // Copy class hiearchy from origin. | 754 // Copy class hiearchy from origin. |
| 751 element.supertype = element.origin.supertype; | 755 element.supertype = element.origin.supertype; |
| 752 element.interfaces = element.origin.interfaces; | 756 element.interfaces = element.origin.interfaces; |
| 753 element.allSupertypes = element.origin.allSupertypes; | 757 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; |
| 754 // Stepwise assignment to ensure invariant. | 758 // Stepwise assignment to ensure invariant. |
| 755 element.supertypeLoadState = STATE_STARTED; | 759 element.supertypeLoadState = STATE_STARTED; |
| 756 element.supertypeLoadState = STATE_DONE; | 760 element.supertypeLoadState = STATE_DONE; |
| 757 element.resolutionState = STATE_DONE; | 761 element.resolutionState = STATE_DONE; |
| 758 // TODO(johnniwinther): Check matching type variables and | 762 // TODO(johnniwinther): Check matching type variables and |
| 759 // empty extends/implements clauses. | 763 // empty extends/implements clauses. |
| 760 } | 764 } |
| 761 for (MetadataAnnotation metadata in element.metadata) { | 765 for (MetadataAnnotation metadata in element.metadata) { |
| 762 metadata.ensureResolved(compiler); | 766 metadata.ensureResolved(compiler); |
| 763 } | 767 } |
| (...skipping 3169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3933 return constructor.name == '' && | 3937 return constructor.name == '' && |
| 3934 constructor.computeSignature(compiler).parameterCount == 0; | 3938 constructor.computeSignature(compiler).parameterCount == 0; |
| 3935 } | 3939 } |
| 3936 | 3940 |
| 3937 FunctionElement createForwardingConstructor(FunctionElement target, | 3941 FunctionElement createForwardingConstructor(FunctionElement target, |
| 3938 ClassElement enclosing) { | 3942 ClassElement enclosing) { |
| 3939 return new SynthesizedConstructorElementX( | 3943 return new SynthesizedConstructorElementX( |
| 3940 target.name, target, enclosing, false); | 3944 target.name, target, enclosing, false); |
| 3941 } | 3945 } |
| 3942 | 3946 |
| 3943 void doApplyMixinTo(MixinApplicationElement mixinApplication, | 3947 void doApplyMixinTo(MixinApplicationElementX mixinApplication, |
| 3944 DartType supertype, | 3948 DartType supertype, |
| 3945 DartType mixinType) { | 3949 DartType mixinType) { |
| 3946 Node node = mixinApplication.parseNode(compiler); | 3950 Node node = mixinApplication.parseNode(compiler); |
| 3947 | 3951 |
| 3948 if (mixinApplication.supertype != null) { | 3952 if (mixinApplication.supertype != null) { |
| 3949 // [supertype] is not null if there was a cycle. | 3953 // [supertype] is not null if there was a cycle. |
| 3950 assert(invariant(node, compiler.compilationFailed)); | 3954 assert(invariant(node, compiler.compilationFailed)); |
| 3951 supertype = mixinApplication.supertype; | 3955 supertype = mixinApplication.supertype; |
| 3952 assert(invariant(node, supertype.element == compiler.objectClass)); | 3956 assert(invariant(node, supertype.element == compiler.objectClass)); |
| 3953 } else { | 3957 } else { |
| 3954 mixinApplication.supertype = supertype; | 3958 mixinApplication.supertype = supertype; |
| 3955 } | 3959 } |
| 3956 | 3960 |
| 3957 // Named mixin application may have an 'implements' clause. | 3961 // Named mixin application may have an 'implements' clause. |
| 3958 NamedMixinApplication namedMixinApplication = | 3962 NamedMixinApplication namedMixinApplication = |
| 3959 node.asNamedMixinApplication(); | 3963 node.asNamedMixinApplication(); |
| 3960 Link<DartType> interfaces = (namedMixinApplication != null) | 3964 Link<DartType> interfaces = (namedMixinApplication != null) |
| 3961 ? resolveInterfaces(namedMixinApplication.interfaces, | 3965 ? resolveInterfaces(namedMixinApplication.interfaces, |
| 3962 namedMixinApplication.superclass) | 3966 namedMixinApplication.superclass) |
| 3963 : const Link<DartType>(); | 3967 : const Link<DartType>(); |
| 3964 | 3968 |
| 3965 // The class that is the result of a mixin application implements | 3969 // The class that is the result of a mixin application implements |
| 3966 // the interface of the class that was mixed in so always prepend | 3970 // the interface of the class that was mixed in so always prepend |
| 3967 // that to the interface list. | 3971 // that to the interface list. |
| 3972 |
| 3968 interfaces = interfaces.prepend(mixinType); | 3973 interfaces = interfaces.prepend(mixinType); |
| 3969 assert(mixinApplication.interfaces == null); | 3974 assert(mixinApplication.interfaces == null); |
| 3970 mixinApplication.interfaces = interfaces; | 3975 mixinApplication.interfaces = interfaces; |
| 3971 | 3976 |
| 3977 ClassElement superclass = supertype.element; |
| 3972 if (mixinType.kind != TypeKind.INTERFACE) { | 3978 if (mixinType.kind != TypeKind.INTERFACE) { |
| 3973 mixinApplication.allSupertypes = const Link<DartType>(); | 3979 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; |
| 3974 return; | 3980 return; |
| 3975 } | 3981 } |
| 3976 | 3982 |
| 3977 assert(mixinApplication.mixinType == null); | 3983 assert(mixinApplication.mixinType == null); |
| 3978 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); | 3984 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); |
| 3979 | 3985 |
| 3980 // Create forwarding constructors for constructor defined in the superclass | 3986 // Create forwarding constructors for constructor defined in the superclass |
| 3981 // because they are now hidden by the mixin application. | 3987 // because they are now hidden by the mixin application. |
| 3982 ClassElement superclass = supertype.element; | |
| 3983 superclass.forEachLocalMember((Element member) { | 3988 superclass.forEachLocalMember((Element member) { |
| 3984 if (!member.isGenerativeConstructor()) return; | 3989 if (!member.isGenerativeConstructor()) return; |
| 3985 FunctionElement forwarder = | 3990 FunctionElement forwarder = |
| 3986 createForwardingConstructor(member, mixinApplication); | 3991 createForwardingConstructor(member, mixinApplication); |
| 3987 mixinApplication.addConstructor(forwarder); | 3992 mixinApplication.addConstructor(forwarder); |
| 3988 }); | 3993 }); |
| 3989 calculateAllSupertypes(mixinApplication); | 3994 calculateAllSupertypes(mixinApplication); |
| 3990 } | 3995 } |
| 3991 | 3996 |
| 3992 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, | 3997 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4088 * | 4093 * |
| 4089 * For example, for a class `class C extends S implements I1, I2`, we compute | 4094 * For example, for a class `class C extends S implements I1, I2`, we compute |
| 4090 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) | 4095 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) |
| 4091 * ++ supertypes(I2), | 4096 * ++ supertypes(I2), |
| 4092 * where ++ stands for list concatenation. | 4097 * where ++ stands for list concatenation. |
| 4093 * | 4098 * |
| 4094 * This order makes sure that if a class implements an interface twice with | 4099 * This order makes sure that if a class implements an interface twice with |
| 4095 * different type arguments, the type used in the most specific class comes | 4100 * different type arguments, the type used in the most specific class comes |
| 4096 * first. | 4101 * first. |
| 4097 */ | 4102 */ |
| 4098 void calculateAllSupertypes(ClassElement cls) { | 4103 void calculateAllSupertypes(BaseClassElementX cls) { |
| 4099 if (cls.allSupertypes != null) return; | 4104 if (cls.allSupertypesAndSelf != null) return; |
| 4100 final DartType supertype = cls.supertype; | 4105 final DartType supertype = cls.supertype; |
| 4101 if (supertype != null) { | 4106 if (supertype != null) { |
| 4102 Map<Element, DartType> instantiations = new Map<Element, DartType>(); | 4107 OrderedTypeSetBuilder allSupertypes = new OrderedTypeSetBuilder(cls); |
| 4103 LinkBuilder<DartType> allSupertypes = new LinkBuilder<DartType>(); | 4108 // TODO(15296): Collapse these iterations to one when the order is not |
| 4104 | 4109 // needed. |
| 4105 void addSupertype(DartType type) { | 4110 allSupertypes.add(compiler, supertype); |
| 4106 DartType existing = | |
| 4107 instantiations.putIfAbsent(type.element, () => type); | |
| 4108 if (existing != null && existing != type) { | |
| 4109 compiler.reportError(cls, | |
| 4110 MessageKind.MULTI_INHERITANCE, | |
| 4111 {'thisType': cls.computeType(compiler), | |
| 4112 'firstType': existing, | |
| 4113 'secondType': type}); | |
| 4114 } | |
| 4115 if (type.element != compiler.objectClass) { | |
| 4116 allSupertypes.addLast(type); | |
| 4117 } | |
| 4118 } | |
| 4119 | |
| 4120 addSupertype(supertype); | |
| 4121 for (Link<DartType> interfaces = cls.interfaces; | |
| 4122 !interfaces.isEmpty; | |
| 4123 interfaces = interfaces.tail) { | |
| 4124 addSupertype(interfaces.head); | |
| 4125 } | |
| 4126 addAllSupertypes(addSupertype, supertype); | |
| 4127 for (Link<DartType> interfaces = cls.interfaces; | 4111 for (Link<DartType> interfaces = cls.interfaces; |
| 4128 !interfaces.isEmpty; | 4112 !interfaces.isEmpty; |
| 4129 interfaces = interfaces.tail) { | 4113 interfaces = interfaces.tail) { |
| 4130 addAllSupertypes(addSupertype, interfaces.head); | 4114 allSupertypes.add(compiler, interfaces.head); |
| 4131 } | 4115 } |
| 4132 | 4116 |
| 4133 allSupertypes.addLast(compiler.objectClass.rawType); | 4117 addAllSupertypes(allSupertypes, supertype); |
| 4134 cls.allSupertypes = allSupertypes.toLink(); | 4118 for (Link<DartType> interfaces = cls.interfaces; |
| 4119 !interfaces.isEmpty; |
| 4120 interfaces = interfaces.tail) { |
| 4121 addAllSupertypes(allSupertypes, interfaces.head); |
| 4122 } |
| 4123 allSupertypes.add(compiler, cls.computeType(compiler)); |
| 4124 cls.allSupertypesAndSelf = allSupertypes.toTypeSet(); |
| 4135 } else { | 4125 } else { |
| 4136 assert(identical(cls, compiler.objectClass)); | 4126 assert(identical(cls, compiler.objectClass)); |
| 4137 cls.allSupertypes = const Link<DartType>(); | 4127 cls.allSupertypesAndSelf = |
| 4128 new OrderedTypeSet.singleton(cls.computeType(compiler)); |
| 4138 } | 4129 } |
| 4139 } | 4130 } |
| 4140 | 4131 |
| 4141 /** | 4132 /** |
| 4142 * Adds [type] and all supertypes of [type] to [allSupertypes] while | 4133 * Adds [type] and all supertypes of [type] to [allSupertypes] while |
| 4143 * substituting type variables. | 4134 * substituting type variables. |
| 4144 */ | 4135 */ |
| 4145 void addAllSupertypes(void addSupertype(DartType supertype), | 4136 void addAllSupertypes(OrderedTypeSetBuilder allSupertypes, |
| 4146 InterfaceType type) { | 4137 InterfaceType type) { |
| 4147 Link<DartType> typeArguments = type.typeArguments; | 4138 Link<DartType> typeArguments = type.typeArguments; |
| 4148 ClassElement classElement = type.element; | 4139 ClassElement classElement = type.element; |
| 4149 Link<DartType> typeVariables = classElement.typeVariables; | 4140 Link<DartType> typeVariables = classElement.typeVariables; |
| 4150 Link<DartType> supertypes = classElement.allSupertypes; | 4141 Link<DartType> supertypes = classElement.allSupertypes; |
| 4151 assert(invariant(element, supertypes != null, | 4142 assert(invariant(element, supertypes != null, |
| 4152 message: "Supertypes not computed on $classElement " | 4143 message: "Supertypes not computed on $classElement " |
| 4153 "during resolution of $element")); | 4144 "during resolution of $element")); |
| 4154 while (!supertypes.isEmpty) { | 4145 while (!supertypes.isEmpty) { |
| 4155 DartType supertype = supertypes.head; | 4146 DartType supertype = supertypes.head; |
| 4156 if (supertype.element != compiler.objectClass) { | 4147 allSupertypes.add(compiler, |
| 4157 DartType substituted = supertype.subst(typeArguments, typeVariables); | 4148 supertype.subst(typeArguments, typeVariables)); |
| 4158 addSupertype(substituted); | |
| 4159 } | |
| 4160 supertypes = supertypes.tail; | 4149 supertypes = supertypes.tail; |
| 4161 } | 4150 } |
| 4162 } | 4151 } |
| 4163 | 4152 |
| 4164 isBlackListed(DartType type) { | 4153 isBlackListed(DartType type) { |
| 4165 LibraryElement lib = element.getLibrary(); | 4154 LibraryElement lib = element.getLibrary(); |
| 4166 return | 4155 return |
| 4167 !identical(lib, compiler.coreLibrary) && | 4156 !identical(lib, compiler.coreLibrary) && |
| 4168 !identical(lib, compiler.jsHelperLibrary) && | 4157 !identical(lib, compiler.jsHelperLibrary) && |
| 4169 !identical(lib, compiler.interceptorsLibrary) && | 4158 !identical(lib, compiler.interceptorsLibrary) && |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4751 return finishConstructorReference(visit(expression), | 4740 return finishConstructorReference(visit(expression), |
| 4752 expression, expression); | 4741 expression, expression); |
| 4753 } | 4742 } |
| 4754 } | 4743 } |
| 4755 | 4744 |
| 4756 /// Looks up [name] in [scope] and unwraps the result. | 4745 /// Looks up [name] in [scope] and unwraps the result. |
| 4757 Element lookupInScope(Compiler compiler, Node node, | 4746 Element lookupInScope(Compiler compiler, Node node, |
| 4758 Scope scope, String name) { | 4747 Scope scope, String name) { |
| 4759 return Elements.unwrap(scope.lookup(name), compiler, node); | 4748 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 4760 } | 4749 } |
| OLD | NEW |