Index: pkg/analyzer/lib/src/generated/type_system.dart |
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart |
index 940ee83c5ef5dffe18db9aee9a9083c89518fb2c..ff70e899be87bccc9ba815f3379da9b8c0c10d17 100644 |
--- a/pkg/analyzer/lib/src/generated/type_system.dart |
+++ b/pkg/analyzer/lib/src/generated/type_system.dart |
@@ -24,8 +24,6 @@ typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); |
class StrongTypeSystemImpl extends TypeSystem { |
final _specTypeSystem = new TypeSystemImpl(); |
- StrongTypeSystemImpl(); |
- |
bool anyParameterType(FunctionType ft, bool predicate(DartType t)) { |
return ft.parameters.any((p) => predicate(p.type)); |
} |
@@ -509,6 +507,47 @@ abstract class TypeSystem { |
bool isSubtypeOf(DartType leftType, DartType rightType); |
/** |
+ * Searches the superinterfaces of [type] for implementations of [genericType] |
+ * and returns the most specific type argument used for that generic type. |
+ * |
+ * For example, given [type] `List<int>` and [genericType] `Iterable<T>`, |
+ * returns [int]. |
+ * |
+ * Returns `null` if [type] does not implement [genericType]. |
+ */ |
+ // TODO(jmesserly): this is very similar to code used for flattening futures. |
+ // The only difference is, because of a lack of TypeProvider, the other method |
+ // has to match the Future type by its name and library. Here was are passed |
+ // in the correct type. |
+ DartType mostSpecificTypeArgument(DartType type, DartType genericType) { |
+ if (type is! InterfaceType) return null; |
+ |
+ // Walk the superinterface hierarchy looking for [genericType]. |
+ List<DartType> candidates = <DartType>[]; |
+ HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
+ void recurse(InterfaceTypeImpl interface) { |
+ if (interface.element == genericType.element && |
+ interface.typeArguments.isNotEmpty) { |
+ candidates.add(interface.typeArguments[0]); |
+ } |
+ if (visitedClasses.add(interface.element)) { |
+ if (interface.superclass != null) { |
+ recurse(interface.superclass); |
+ } |
+ interface.mixins.forEach(recurse); |
+ interface.interfaces.forEach(recurse); |
+ visitedClasses.remove(interface.element); |
+ } |
+ } |
+ |
+ recurse(type); |
+ |
+ // Since the interface may be implemented multiple times with different |
+ // type arguments, choose the best one. |
+ return InterfaceTypeImpl.findMostSpecificType(candidates, this); |
+ } |
+ |
+ /** |
* Given a [DartType] type, return the [TypeParameterElement]s corresponding |
* to its formal type parameters (if any). |
* |