Simplified calculateTypeArgumentsFromSuper and added samples in comments.

This commit is contained in:
Evgeny Gerashchenko
2012-11-14 18:07:27 +04:00
parent f20c4dac15
commit 62b89655b9
@@ -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) {