Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/InheritanceManager.java |
diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/InheritanceManager.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/InheritanceManager.java |
index 12d6ecb1d2efe5d8c88b4359ef1bded559f1060e..2971630fcf592acec9e8d4479b38d48d1dda9ba4 100644 |
--- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/InheritanceManager.java |
+++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/resolver/InheritanceManager.java |
@@ -209,6 +209,22 @@ public class InheritanceManager { |
} |
/** |
+ * Given some {@link ExecutableElement} returns {@code true} if it is an abstract member of a |
+ * class. |
+ * |
+ * @param executableElement some {@link ExecutableElement} to evaluate |
+ * @return {@code true} if the given element is an abstract member of a class |
+ */ |
+ private static boolean isAbstract(ExecutableElement executableElement) { |
+ if (executableElement instanceof MethodElement) { |
+ return ((MethodElement) executableElement).isAbstract(); |
+ } else if (executableElement instanceof PropertyAccessorElement) { |
+ return ((PropertyAccessorElement) executableElement).isAbstract(); |
+ } |
+ return false; |
+ } |
+ |
+ /** |
* The {@link LibraryElement} that is managed by this manager. |
*/ |
private LibraryElement library; |
@@ -417,24 +433,28 @@ public class InheritanceManager { |
} |
if (superclassElt != null) { |
if (!visitedClasses.contains(superclassElt)) { |
- visitedClasses.add(classElt); |
- resultMap = new MemberMap(computeClassChainLookupMap(superclassElt, visitedClasses)); |
+ visitedClasses.add(superclassElt); |
+ try { |
+ resultMap = new MemberMap(computeClassChainLookupMap(superclassElt, visitedClasses)); |
+ |
+ // |
+ // Substitute the super types down the hierarchy. |
+ // |
+ substituteTypeParametersDownHierarchy(supertype, resultMap); |
+ |
+ // |
+ // Include the members from the superclass in the resultMap. |
+ // |
+ recordMapWithClassMembers(resultMap, supertype); |
+ } finally { |
+ visitedClasses.remove(superclassElt); |
+ } |
} else { |
// This case happens only when the superclass was previously visited and not in the lookup, |
// meaning this is meant to shorten the compute for recursive cases. |
classLookup.put(superclassElt, resultMap); |
return resultMap; |
} |
- |
- // |
- // Substitute the supertypes down the hierarchy |
- // |
- substituteTypeParametersDownHierarchy(supertype, resultMap); |
- |
- // |
- // Include the members from the superclass in the resultMap |
- // |
- recordMapWithClassMembers(resultMap, supertype); |
} |
// |
@@ -442,7 +462,47 @@ public class InheritanceManager { |
// |
InterfaceType[] mixins = classElt.getMixins(); |
for (int i = mixins.length - 1; i >= 0; i--) { |
- recordMapWithClassMembersFromMixin(resultMap, mixins[i]); |
+ ClassElement mixinElement = mixins[i].getElement(); |
+ |
+ if (mixinElement != null) { |
+ if (!visitedClasses.contains(mixinElement)) { |
+ visitedClasses.add(mixinElement); |
+ try { |
+ MemberMap map = new MemberMap(computeClassChainLookupMap(mixinElement, visitedClasses)); |
+ |
+ // |
+ // Substitute the super types down the hierarchy. |
+ // |
+ substituteTypeParametersDownHierarchy(mixins[i], map); |
+ |
+ // |
+ // Include the members from the superclass in the resultMap. |
+ // |
+ recordMapWithClassMembersFromMixin(map, mixins[i]); |
+ |
+ // |
+ // Add the members from map into result map. |
+ // |
+ for (int j = 0; j < map.getSize(); j++) { |
+ String key = map.getKey(j); |
+ ExecutableElement value = map.getValue(j); |
+ if (key != null) { |
+ if (resultMap.get(key) == null |
+ || (resultMap.get(key) != null && !isAbstract(value))) { |
+ resultMap.put(key, value); |
+ } |
+ } |
+ } |
+ } finally { |
+ visitedClasses.remove(mixinElement); |
+ } |
+ } else { |
+ // This case happens only when the superclass was previously visited and not in the lookup, |
+ // meaning this is meant to shorten the compute for recursive cases. |
+ classLookup.put(mixinElement, resultMap); |
+ return resultMap; |
+ } |
+ } |
} |
classLookup.put(classElt, resultMap); |
@@ -545,25 +605,27 @@ public class InheritanceManager { |
ArrayList<MemberMap> lookupMaps = new ArrayList<MemberMap>(interfaces.length + mixins.length |
+ 1); |
+ // |
// Superclass element |
+ // |
if (superclassElement != null) { |
if (!visitedInterfaces.contains(superclassElement)) { |
try { |
visitedInterfaces.add(superclassElement); |
// |
- // Recursively compute the map for the supertype. |
+ // Recursively compute the map for the super type. |
// |
MemberMap map = computeInterfaceLookupMap(superclassElement, visitedInterfaces); |
map = new MemberMap(map); |
// |
- // Substitute the supertypes down the hierarchy |
+ // Substitute the super type down the hierarchy. |
// |
substituteTypeParametersDownHierarchy(supertype, map); |
// |
- // Add any members from the supertype into the map as well. |
+ // Add any members from the super type into the map as well. |
// |
recordMapWithClassMembers(map, supertype); |
@@ -582,14 +644,52 @@ public class InheritanceManager { |
} |
} |
+ // |
// Mixin elements |
- for (InterfaceType mixinType : mixins) { |
- MemberMap mapWithMixinMembers = new MemberMap(); |
- recordMapWithClassMembers(mapWithMixinMembers, mixinType); |
- lookupMaps.add(mapWithMixinMembers); |
+ // |
+ for (int i = mixins.length - 1; i >= 0; i--) { |
+ InterfaceType mixinType = mixins[i]; |
+ ClassElement mixinElement = mixinType.getElement(); |
+ if (mixinElement != null) { |
+ if (!visitedInterfaces.contains(mixinElement)) { |
+ try { |
+ visitedInterfaces.add(mixinElement); |
+ |
+ // |
+ // Recursively compute the map for the mixin. |
+ // |
+ MemberMap map = computeInterfaceLookupMap(mixinElement, visitedInterfaces); |
+ map = new MemberMap(map); |
+ |
+ // |
+ // Substitute the mixin type down the hierarchy. |
+ // |
+ substituteTypeParametersDownHierarchy(mixinType, map); |
+ |
+ // |
+ // Add any members from the mixin type into the map as well. |
+ // |
+ recordMapWithClassMembers(map, mixinType); |
+ |
+ lookupMaps.add(map); |
+ } finally { |
+ visitedInterfaces.remove(mixinElement); |
+ } |
+ } else { |
+ MemberMap map = interfaceLookup.get(classElt); |
+ if (map != null) { |
+ lookupMaps.add(map); |
+ } else { |
+ interfaceLookup.put(mixinElement, resultMap); |
+ return resultMap; |
+ } |
+ } |
+ } |
} |
+ // |
// Interface elements |
+ // |
for (InterfaceType interfaceType : interfaces) { |
ClassElement interfaceElement = interfaceType.getElement(); |
if (interfaceElement != null) { |