Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: pkg/analyzer/lib/src/dart/element/type.dart

Issue 1662873002: Remove some duplicate code in FunctionTypeImpl. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Revise with feedback. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/dart/element/type.dart
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index a5ced4844ab4627de8bccc3d74666ac170d6873d..7c2aebe16b2886a777760b3050ef04c56917c2ff 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -378,28 +378,11 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
@override
Map<String, DartType> get namedParameterTypes {
- LinkedHashMap<String, DartType> namedParameterTypes =
- new LinkedHashMap<String, DartType>();
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return namedParameterTypes;
- }
- List<DartType> typeParameters =
- TypeParameterTypeImpl.getTypes(this.typeParameters);
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.NAMED) {
- DartType type = parameter.type;
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- type = (type as TypeImpl)
- .substitute2(typeArguments, typeParameters, newPrune);
- } else {
- type = (type as TypeImpl).pruned(newPrune);
- }
- namedParameterTypes[parameter.name] = type;
- }
- }
- return namedParameterTypes;
+ Map<String, DartType> types = <String, DartType>{};
+ _forEachParameterType(ParameterKind.NAMED, (name, type) {
+ types[name] = type;
+ });
+ return types;
}
/**
@@ -425,26 +408,10 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
@override
List<DartType> get normalParameterTypes {
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return DartType.EMPTY_LIST;
- }
- List<DartType> typeParameters =
- TypeParameterTypeImpl.getTypes(this.typeParameters);
- List<DartType> types = new List<DartType>();
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.REQUIRED) {
- DartType type = parameter.type;
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- type = (type as TypeImpl)
- .substitute2(typeArguments, typeParameters, newPrune);
- } else {
- type = (type as TypeImpl).pruned(newPrune);
- }
- types.add(type);
- }
- }
+ List<DartType> types = <DartType>[];
+ _forEachParameterType(ParameterKind.REQUIRED, (name, type) {
+ types.add(type);
+ });
return types;
}
@@ -458,26 +425,10 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
@override
List<DartType> get optionalParameterTypes {
- List<ParameterElement> parameters = baseParameters;
- if (parameters.length == 0) {
- return DartType.EMPTY_LIST;
- }
- List<DartType> typeParameters =
- TypeParameterTypeImpl.getTypes(this.typeParameters);
- List<DartType> types = new List<DartType>();
- for (ParameterElement parameter in parameters) {
- if (parameter.parameterKind == ParameterKind.POSITIONAL) {
- DartType type = parameter.type;
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- type = (type as TypeImpl)
- .substitute2(typeArguments, typeParameters, newPrune);
- } else {
- type = (type as TypeImpl).pruned(newPrune);
- }
- types.add(type);
- }
- }
+ List<DartType> types = <DartType>[];
+ _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
+ types.add(type);
+ });
return types;
}
@@ -776,8 +727,25 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
[bool withDynamic = false, Set<Element> visitedElements]) {
// Note: visitedElements is only used for breaking recursion in the type
// hierarchy; we don't use it when recursing into the function type.
+ return _testTypeRelation(
+ type, (TypeImpl t, TypeImpl s) => t.isMoreSpecificThan(s, withDynamic));
+ }
+
+ @override
+ bool isSubtypeOf(DartType type) {
+ return _testTypeRelation(
+ type, (TypeImpl t, TypeImpl s) => t.isAssignableTo(s));
+ }
- // trivial base cases
+ /**
+ * Determines if this function type has a [relation] with [type].
+ *
+ * Used for both [isMoreSpecificThan] and [isSubtypeOf] which are structurally
+ * identical but use their own relation when recursing into parameters and
+ * return types.
+ */
+ bool _testTypeRelation(DartType type, bool relation(TypeImpl t, TypeImpl s)) {
+ // Trivial base cases.
if (type == null) {
return false;
} else if (identical(this, type) ||
@@ -790,211 +758,71 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
} else if (this == type) {
return true;
}
- FunctionType t = this;
+
FunctionType s = type as FunctionType;
- List<DartType> tTypes = t.normalParameterTypes;
- List<DartType> tOpTypes = t.optionalParameterTypes;
- List<DartType> sTypes = s.normalParameterTypes;
- List<DartType> sOpTypes = s.optionalParameterTypes;
+ List<DartType> tRequired = normalParameterTypes;
+ List<DartType> sRequired = s.normalParameterTypes;
+ List<DartType> tOptional = optionalParameterTypes;
+ List<DartType> sOptional = s.optionalParameterTypes;
+ Map<String, DartType> tNamed = namedParameterTypes;
+ Map<String, DartType> sNamed = s.namedParameterTypes;
+
// If one function has positional and the other has named parameters,
- // return false.
- if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
- (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
+ // they don't relate.
+ if (sOptional.isNotEmpty && tNamed.isNotEmpty ||
+ tOptional.isNotEmpty && sNamed.isNotEmpty) {
return false;
}
- // named parameters case
- if (t.namedParameterTypes.length > 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.normalParameterTypes.length != s.normalParameterTypes.length) {
- return false;
- } else if (t.normalParameterTypes.length > 0) {
- for (int i = 0; i < tTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl)
- .isMoreSpecificThan(sTypes[i], withDynamic)) {
- return false;
- }
- }
- }
- Map<String, DartType> namedTypesT = t.namedParameterTypes;
- Map<String, DartType> namedTypesS = s.namedParameterTypes;
- // if k >= m is false, return false: the passed function type has more
- // named parameter types than this
- if (namedTypesT.length < namedTypesS.length) {
- 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.
- for (String keyS in namedTypesS.keys) {
- DartType typeT = namedTypesT[keyS];
- if (typeT == null) {
- return false;
- }
- if (!(typeT as TypeImpl)
- .isMoreSpecificThan(namedTypesS[keyS], withDynamic)) {
- return false;
- }
- }
- } else if (s.namedParameterTypes.length > 0) {
+
+ // If the passed function includes more named parameters than we do, we
+ // don't relate.
+ if (tNamed.length < sNamed.length) {
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) {
+ }
+
+ // For each named parameter in s, make sure we have a corresponding one
+ // that relates.
+ for (String key in sNamed.keys) {
+ var tParamType = tNamed[key];
+ if (tParamType == null) {
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] as TypeImpl)
- .isMoreSpecificThan(sTypes[i], withDynamic)) {
- return false;
- }
- }
- } else {
- // Else, we do have positional parameters, copy required and positional
- // parameter types into arrays to do the compare (for loop below).
- List<DartType> tAllTypes = new List<DartType>(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];
- }
- List<DartType> sAllTypes = new List<DartType>(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] as TypeImpl)
- .isMoreSpecificThan(sAllTypes[i], withDynamic)) {
- return false;
- }
- }
+ if (!relation(tParamType, sNamed[key])) {
+ return false;
}
}
- DartType tRetType = t.returnType;
- DartType sRetType = s.returnType;
- return sRetType.isVoid ||
- (tRetType as TypeImpl).isMoreSpecificThan(sRetType, withDynamic);
- }
- @override
- bool isSubtypeOf(DartType type) {
- // trivial base cases
- if (type == null) {
- return false;
- } else if (identical(this, type) ||
- type.isDynamic ||
- type.isDartCoreFunction ||
- type.isObject) {
- return true;
- } else if (type is! FunctionType) {
- return false;
- } else if (this == type) {
- return true;
+ // Make sure all of the positional parameters (both required and optional)
+ // relate to each other.
+ List<DartType> tPositional = tRequired;
+ List<DartType> sPositional = sRequired;
+
+ if (tOptional.isNotEmpty) {
+ tPositional = tPositional.toList()..addAll(tOptional);
}
- FunctionType t = this;
- FunctionType s = type as FunctionType;
- List<DartType> tTypes = t.normalParameterTypes;
- List<DartType> tOpTypes = t.optionalParameterTypes;
- List<DartType> sTypes = s.normalParameterTypes;
- List<DartType> sOpTypes = s.optionalParameterTypes;
- // If one function has positional and the other has named parameters,
- // return false.
- if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
- (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
+
+ if (sOptional.isNotEmpty) {
+ sPositional = sPositional.toList()..addAll(sOptional);
+ }
+
+ // Check that s has enough required parameters.
+ if (sRequired.length < tRequired.length) {
return false;
}
- // named parameters case
- if (t.namedParameterTypes.length > 0) {
- // check that the number of required parameters are equal,
- // and check that every t_i is assignable to every s_i
- if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
- return false;
- } else if (t.normalParameterTypes.length > 0) {
- for (int i = 0; i < tTypes.length; i++) {
- if (!(tTypes[i] as TypeImpl).isAssignableTo(sTypes[i])) {
- return false;
- }
- }
- }
- Map<String, DartType> namedTypesT = t.namedParameterTypes;
- Map<String, DartType> namedTypesS = s.namedParameterTypes;
- // if k >= m is false, return false: the passed function type has more
- // named parameter types than this
- if (namedTypesT.length < namedTypesS.length) {
- return false;
- }
- // Loop through each element in S verifying that T has a matching
- // parameter name and that the corresponding type is assignable to the
- // type in S.
- for (String keyS in namedTypesS.keys) {
- DartType typeT = namedTypesT[keyS];
- if (typeT == null) {
- return false;
- }
- if (!(typeT as TypeImpl).isAssignableTo(namedTypesS[keyS])) {
- return false;
- }
- }
- } else if (s.namedParameterTypes.length > 0) {
+
+ // Check that s does not include more positional parameters than we do.
+ if (tPositional.length < sPositional.length) {
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) {
+ }
+
+ for (int i = 0; i < sPositional.length; i++) {
+ if (!relation(tPositional[i], sPositional[i])) {
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] as TypeImpl).isAssignableTo(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).
- List<DartType> tAllTypes = new List<DartType>(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];
- }
- List<DartType> sAllTypes = new List<DartType>(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] as TypeImpl).isAssignableTo(sAllTypes[i])) {
- return false;
- }
- }
- }
}
- DartType tRetType = t.returnType;
+
DartType sRetType = s.returnType;
- return sRetType.isVoid || (tRetType as TypeImpl).isAssignableTo(sRetType);
+ return sRetType.isVoid || relation(returnType, sRetType);
}
@override
@@ -1109,6 +937,33 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
}
return true;
}
+
+ /**
+ * Invokes [callback] for each parameter of [kind] with the parameter's [name]
+ * and [type] after any type parameters have been applied.
+ */
+ void _forEachParameterType(
+ ParameterKind kind, callback(String name, DartType type)) {
+ if (baseParameters.isEmpty) {
+ return;
+ }
+
+ List<DartType> typeParameters =
+ TypeParameterTypeImpl.getTypes(this.typeParameters);
+ for (ParameterElement parameter in baseParameters) {
+ if (parameter.parameterKind == kind) {
+ TypeImpl type = parameter.type;
+ if (typeArguments.length != 0 &&
+ typeArguments.length == typeParameters.length) {
+ type = type.substitute2(typeArguments, typeParameters, newPrune);
+ } else {
+ type = type.pruned(newPrune);
+ }
+
+ callback(parameter.name, type);
+ }
+ }
+ }
}
/**
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698