From 62b89655b99c4ca7df90f2a61c53170b316a3725 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Wed, 14 Nov 2012 18:07:27 +0400 Subject: [PATCH] Simplified calculateTypeArgumentsFromSuper and added samples in comments. --- .../SignaturesPropagation.java | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java index 15acc75a2fb..25e6d4b1de4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java @@ -92,15 +92,16 @@ public class SignaturesPropagation { @NotNull private static List getTypeArgsOfReturnType(@NotNull JetType autoType, @NotNull Collection typesFromSuper) { TypeConstructor typeConstructor = autoType.getConstructor(); + ClassifierDescriptor classifier = typeConstructor.getDeclarationDescriptor(); List autoArguments = autoType.getArguments(); - if (!(typeConstructor.getDeclarationDescriptor() instanceof ClassDescriptor)) { + if (!(classifier instanceof ClassDescriptor)) { assert autoArguments.isEmpty() : "Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType; return autoArguments; } - List> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper(autoType, typesFromSuper); + List> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper((ClassDescriptor) classifier, typesFromSuper); // Modify type arguments using info from typesFromSuper List resultArguments = Lists.newArrayList(); @@ -159,40 +160,60 @@ public class SignaturesPropagation { } // Returns list with type arguments info from supertypes + // Example: + // - Foo is a subtype of Bar>, Baz + // - input: klass = Foo, typesFromSuper = [Bar>, Baz] + // - output[0] = [String, CharSequence], output[1] = [] private static List> calculateTypeArgumentsFromSuper( - @NotNull JetType autoType, + @NotNull ClassDescriptor klass, @NotNull Collection typesFromSuper ) { - ClassDescriptor klass = (ClassDescriptor) autoType.getConstructor().getDeclarationDescriptor(); - - // For each superclass of autoType's class and its parameters, hold their mapping to autoType's parameters + // For each superclass of klass and its parameters, hold their mapping to klass' parameters + // #0 of Bar -> A + // #1 of Bar -> List + // #0 of Baz -> Boolean + // #1 of Baz -> A + // #0 of Foo -> A (mapped to itself) + // #1 of Foo -> B (mapped to itself) Multimap substitution = SubstitutionUtils.buildDeepSubstitutionMultimap( TypeUtils.makeUnsubstitutedType(klass, JetScope.EMPTY)); - // for each parameter of autoType, hold arguments in corresponding supertypes - List> parameterToArgTypesFromSuper = Lists.newArrayList(); - for (TypeProjection ignored : autoType.getArguments()) { - parameterToArgTypesFromSuper.add(new ArrayList()); + // for each parameter of klass, hold arguments in corresponding supertypes + List> parameterToArgumentsFromSuper = Lists.newArrayList(); + for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) { + parameterToArgumentsFromSuper.add(new ArrayList()); } // Enumerate all types from super and all its parameters for (JetType typeFromSuper : typesFromSuper) { List typeFromSuperParameters = typeFromSuper.getConstructor().getParameters(); for (int i = 0; i < typeFromSuperParameters.size(); i++) { - TypeParameterDescriptor typeFromSuperParam = typeFromSuperParameters.get(i); - TypeProjection typeFromSuperArgType = typeFromSuper.getArguments().get(i); + TypeParameterDescriptor parameter = typeFromSuperParameters.get(i); + TypeProjection argument = typeFromSuper.getArguments().get(i); - // if it is mapped to autoType's parameter, then store it into map - for (TypeProjection projection : substitution.get(typeFromSuperParam.getTypeConstructor())) { + // for given example, this block is executed four times: + // 1. typeFromSuper = Bar>, i = 0, parameter = "#0 of Bar", argument = String + // 2. typeFromSuper = Bar>, i = 1, parameter = "#1 of Bar", argument = List + // 3. typeFromSuper = Baz, i = 0, parameter = "#0 of Baz", argument = Boolean + // 4. typeFromSuper = Baz, 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 + // 3. projection = Boolean + // 4. projection = A 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) { - 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 typesFromSuper, boolean covariantPosition) {