Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/type/FunctionTypeImpl.java |
diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/type/FunctionTypeImpl.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/type/FunctionTypeImpl.java |
index b575a817053ecf5ac1bc400ff71af2d4deda3c4e..6c2d96934ca4ae490ce944fd2345c5096880b509 100644 |
--- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/type/FunctionTypeImpl.java |
+++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/type/FunctionTypeImpl.java |
@@ -286,6 +286,112 @@ public class FunctionTypeImpl extends TypeImpl implements FunctionType { |
} |
@Override |
+ public boolean isMoreSpecificThan(Type type) { |
+ // trivial base cases |
+ if (type == null) { |
+ return false; |
+ } else if (this == type || type.isDynamic() || type.isDartCoreFunction() || type.isObject()) { |
+ return true; |
+ } else if (!(type instanceof FunctionType)) { |
+ return false; |
+ } else if (this.equals(type)) { |
+ return true; |
+ } |
+ FunctionType t = this; |
+ FunctionType s = (FunctionType) type; |
+ |
+ Type[] tTypes = t.getNormalParameterTypes(); |
+ Type[] tOpTypes = t.getOptionalParameterTypes(); |
+ Type[] sTypes = s.getNormalParameterTypes(); |
+ Type[] sOpTypes = s.getOptionalParameterTypes(); |
+ |
+ // If one function has positional and the other has named parameters, return false. |
+ if ((sOpTypes.length > 0 && t.getNamedParameterTypes().size() > 0) |
+ || (tOpTypes.length > 0 && s.getNamedParameterTypes().size() > 0)) { |
+ return false; |
+ } |
+ |
+ // named parameters case |
+ if (t.getNamedParameterTypes().size() > 0) { |
+ // check that the number of required parameters are equal, and check that every t_i is |
+ // more specific than every s_i |
+ if (t.getNormalParameterTypes().length != s.getNormalParameterTypes().length) { |
+ return false; |
+ } else if (t.getNormalParameterTypes().length > 0) { |
+ for (int i = 0; i < tTypes.length; i++) { |
+ if (!tTypes[i].isMoreSpecificThan(sTypes[i])) { |
+ return false; |
+ } |
+ } |
+ } |
+ Map<String, Type> namedTypesT = t.getNamedParameterTypes(); |
+ Map<String, Type> namedTypesS = s.getNamedParameterTypes(); |
+ // if k >= m is false, return false: the passed function type has more named parameter types than this |
+ if (namedTypesT.size() < namedTypesS.size()) { |
+ return false; |
+ } |
+ // Loop through each element in S verifying that T has a matching parameter name and that the |
+ // corresponding type is more specific then the type in S. |
+ Iterator<Entry<String, Type>> iteratorS = namedTypesS.entrySet().iterator(); |
+ while (iteratorS.hasNext()) { |
+ Entry<String, Type> entryS = iteratorS.next(); |
+ Type typeT = namedTypesT.get(entryS.getKey()); |
+ if (typeT == null) { |
+ return false; |
+ } |
+ if (!typeT.isMoreSpecificThan(entryS.getValue())) { |
+ return false; |
+ } |
+ } |
+ } else if (s.getNamedParameterTypes().size() > 0) { |
+ return false; |
+ } else { |
+ // positional parameter case |
+ int tArgLength = tTypes.length + tOpTypes.length; |
+ int sArgLength = sTypes.length + sOpTypes.length; |
+ // Check that the total number of parameters in t is greater than or equal to the number of |
+ // parameters in s and that the number of required parameters in s is greater than or equal to |
+ // the number of required parameters in t. |
+ if (tArgLength < sArgLength || sTypes.length < tTypes.length) { |
+ return false; |
+ } |
+ if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
+ // No positional arguments, don't copy contents to new array |
+ for (int i = 0; i < sTypes.length; i++) { |
+ if (!tTypes[i].isMoreSpecificThan(sTypes[i])) { |
+ return false; |
+ } |
+ } |
+ } else { |
+ // Else, we do have positional parameters, copy required and positional parameter types into |
+ // arrays to do the compare (for loop below). |
+ Type[] tAllTypes = new Type[sArgLength]; |
+ for (int i = 0; i < tTypes.length; i++) { |
+ tAllTypes[i] = tTypes[i]; |
+ } |
+ for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) { |
+ tAllTypes[i] = tOpTypes[j]; |
+ } |
+ Type[] sAllTypes = new Type[sArgLength]; |
+ for (int i = 0; i < sTypes.length; i++) { |
+ sAllTypes[i] = sTypes[i]; |
+ } |
+ for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) { |
+ sAllTypes[i] = sOpTypes[j]; |
+ } |
+ for (int i = 0; i < sAllTypes.length; i++) { |
+ if (!tAllTypes[i].isMoreSpecificThan(sAllTypes[i])) { |
+ return false; |
+ } |
+ } |
+ } |
+ } |
+ Type tRetType = t.getReturnType(); |
+ Type sRetType = s.getReturnType(); |
+ return sRetType.isVoid() || tRetType.isMoreSpecificThan(sRetType); |
+ } |
+ |
+ @Override |
public boolean isSubtypeOf(Type type) { |
// trivial base cases |
if (type == null) { |
@@ -339,7 +445,7 @@ public class FunctionTypeImpl extends TypeImpl implements FunctionType { |
if (typeT == null) { |
return false; |
} |
- if (!entryS.getValue().isAssignableTo(typeT)) { |
+ if (!typeT.isAssignableTo(entryS.getValue())) { |
return false; |
} |
} |
@@ -358,7 +464,7 @@ public class FunctionTypeImpl extends TypeImpl implements FunctionType { |
if (tOpTypes.length == 0 && sOpTypes.length == 0) { |
// No positional arguments, don't copy contents to new array |
for (int i = 0; i < sTypes.length; i++) { |
- if (!sTypes[i].isAssignableTo(tTypes[i])) { |
+ if (!tTypes[i].isAssignableTo(sTypes[i])) { |
return false; |
} |
} |
@@ -380,14 +486,15 @@ public class FunctionTypeImpl extends TypeImpl implements FunctionType { |
sAllTypes[i] = sOpTypes[j]; |
} |
for (int i = 0; i < sAllTypes.length; i++) { |
- if (!sAllTypes[i].isAssignableTo(tAllTypes[i])) { |
+ if (!tAllTypes[i].isAssignableTo(sAllTypes[i])) { |
return false; |
} |
} |
} |
} |
- return s.getReturnType().equals(VoidTypeImpl.getInstance()) |
- || t.getReturnType().isAssignableTo(s.getReturnType()); |
+ Type tRetType = t.getReturnType(); |
+ Type sRetType = s.getReturnType(); |
+ return sRetType.isVoid() || tRetType.isAssignableTo(sRetType); |
} |
/** |