Simplified calculateTypeArgumentsFromSuper and added samples in comments.
This commit is contained in:
+37
-16
@@ -92,15 +92,16 @@ public class SignaturesPropagation {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static List<TypeProjection> getTypeArgsOfReturnType(@NotNull JetType autoType, @NotNull Collection<JetType> typesFromSuper) {
|
private static List<TypeProjection> getTypeArgsOfReturnType(@NotNull JetType autoType, @NotNull Collection<JetType> typesFromSuper) {
|
||||||
TypeConstructor typeConstructor = autoType.getConstructor();
|
TypeConstructor typeConstructor = autoType.getConstructor();
|
||||||
|
ClassifierDescriptor classifier = typeConstructor.getDeclarationDescriptor();
|
||||||
List<TypeProjection> autoArguments = autoType.getArguments();
|
List<TypeProjection> autoArguments = autoType.getArguments();
|
||||||
|
|
||||||
if (!(typeConstructor.getDeclarationDescriptor() instanceof ClassDescriptor)) {
|
if (!(classifier instanceof ClassDescriptor)) {
|
||||||
assert autoArguments.isEmpty() :
|
assert autoArguments.isEmpty() :
|
||||||
"Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType;
|
"Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType;
|
||||||
return autoArguments;
|
return autoArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<List<TypeProjection>> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper(autoType, typesFromSuper);
|
List<List<TypeProjection>> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper((ClassDescriptor) classifier, typesFromSuper);
|
||||||
|
|
||||||
// Modify type arguments using info from typesFromSuper
|
// Modify type arguments using info from typesFromSuper
|
||||||
List<TypeProjection> resultArguments = Lists.newArrayList();
|
List<TypeProjection> resultArguments = Lists.newArrayList();
|
||||||
@@ -159,40 +160,60 @@ public class SignaturesPropagation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns list with type arguments info from supertypes
|
// Returns list with type arguments info from supertypes
|
||||||
|
// Example:
|
||||||
|
// - Foo<A, B> is a subtype of Bar<A, List<B>>, Baz<Boolean, A>
|
||||||
|
// - input: klass = Foo, typesFromSuper = [Bar<String, List<Int>>, Baz<Boolean, CharSequence>]
|
||||||
|
// - output[0] = [String, CharSequence], output[1] = []
|
||||||
private static List<List<TypeProjection>> calculateTypeArgumentsFromSuper(
|
private static List<List<TypeProjection>> calculateTypeArgumentsFromSuper(
|
||||||
@NotNull JetType autoType,
|
@NotNull ClassDescriptor klass,
|
||||||
@NotNull Collection<JetType> typesFromSuper
|
@NotNull Collection<JetType> typesFromSuper
|
||||||
) {
|
) {
|
||||||
ClassDescriptor klass = (ClassDescriptor) autoType.getConstructor().getDeclarationDescriptor();
|
// For each superclass of klass and its parameters, hold their mapping to klass' parameters
|
||||||
|
// #0 of Bar -> A
|
||||||
// For each superclass of autoType's class and its parameters, hold their mapping to autoType's parameters
|
// #1 of Bar -> List<B>
|
||||||
|
// #0 of Baz -> Boolean
|
||||||
|
// #1 of Baz -> A
|
||||||
|
// #0 of Foo -> A (mapped to itself)
|
||||||
|
// #1 of Foo -> B (mapped to itself)
|
||||||
Multimap<TypeConstructor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
|
Multimap<TypeConstructor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
|
||||||
TypeUtils.makeUnsubstitutedType(klass, JetScope.EMPTY));
|
TypeUtils.makeUnsubstitutedType(klass, JetScope.EMPTY));
|
||||||
|
|
||||||
// for each parameter of autoType, hold arguments in corresponding supertypes
|
// for each parameter of klass, hold arguments in corresponding supertypes
|
||||||
List<List<TypeProjection>> parameterToArgTypesFromSuper = Lists.newArrayList();
|
List<List<TypeProjection>> parameterToArgumentsFromSuper = Lists.newArrayList();
|
||||||
for (TypeProjection ignored : autoType.getArguments()) {
|
for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) {
|
||||||
parameterToArgTypesFromSuper.add(new ArrayList<TypeProjection>());
|
parameterToArgumentsFromSuper.add(new ArrayList<TypeProjection>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumerate all types from super and all its parameters
|
// Enumerate all types from super and all its parameters
|
||||||
for (JetType typeFromSuper : typesFromSuper) {
|
for (JetType typeFromSuper : typesFromSuper) {
|
||||||
List<TypeParameterDescriptor> typeFromSuperParameters = typeFromSuper.getConstructor().getParameters();
|
List<TypeParameterDescriptor> typeFromSuperParameters = typeFromSuper.getConstructor().getParameters();
|
||||||
for (int i = 0; i < typeFromSuperParameters.size(); i++) {
|
for (int i = 0; i < typeFromSuperParameters.size(); i++) {
|
||||||
TypeParameterDescriptor typeFromSuperParam = typeFromSuperParameters.get(i);
|
TypeParameterDescriptor parameter = typeFromSuperParameters.get(i);
|
||||||
TypeProjection typeFromSuperArgType = typeFromSuper.getArguments().get(i);
|
TypeProjection argument = typeFromSuper.getArguments().get(i);
|
||||||
|
|
||||||
// if it is mapped to autoType's parameter, then store it into map
|
// for given example, this block is executed four times:
|
||||||
for (TypeProjection projection : substitution.get(typeFromSuperParam.getTypeConstructor())) {
|
// 1. typeFromSuper = Bar<String, List<Int>>, i = 0, parameter = "#0 of Bar", argument = String
|
||||||
|
// 2. typeFromSuper = Bar<String, List<Int>>, i = 1, parameter = "#1 of Bar", argument = List<Int>
|
||||||
|
// 3. typeFromSuper = Baz<Boolean, CharSequence>, i = 0, parameter = "#0 of Baz", argument = Boolean
|
||||||
|
// 4. typeFromSuper = Baz<Boolean, CharSequence>, i = 1, parameter = "#1 of Baz", argument = CharSequence
|
||||||
|
|
||||||
|
// if it is mapped to klass' parameter, then store it into map
|
||||||
|
for (TypeProjection projection : substitution.get(parameter.getTypeConstructor())) {
|
||||||
|
// 1. projection = A
|
||||||
|
// 2. projection = List<B>
|
||||||
|
// 3. projection = Boolean
|
||||||
|
// 4. projection = A
|
||||||
ClassifierDescriptor classifier = projection.getType().getConstructor().getDeclarationDescriptor();
|
ClassifierDescriptor classifier = projection.getType().getConstructor().getDeclarationDescriptor();
|
||||||
|
|
||||||
|
// this condition is true for 1 and 4, false for 2 and 3
|
||||||
if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == klass) {
|
if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == klass) {
|
||||||
parameterToArgTypesFromSuper.get(((TypeParameterDescriptor) classifier).getIndex()).add(typeFromSuperArgType);
|
int parameterIndex = ((TypeParameterDescriptor) classifier).getIndex();
|
||||||
|
parameterToArgumentsFromSuper.get(parameterIndex).add(argument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parameterToArgTypesFromSuper;
|
return parameterToArgumentsFromSuper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean returnTypeMustBeNullable(JetType autoType, Collection<JetType> typesFromSuper, boolean covariantPosition) {
|
private static boolean returnTypeMustBeNullable(JetType autoType, Collection<JetType> typesFromSuper, boolean covariantPosition) {
|
||||||
|
|||||||
Reference in New Issue
Block a user