Fix written generic signature in case of inner types
This commit is contained in:
@@ -118,6 +118,15 @@ public class BothSignatureWriter {
|
||||
writeAsmType0(asmType);
|
||||
}
|
||||
|
||||
public void writeOuterClassBegin(Type resultingAsmType, String outerInternalName) {
|
||||
signatureVisitor().visitClassType(outerInternalName);
|
||||
writeAsmType0(resultingAsmType);
|
||||
}
|
||||
|
||||
public void writeInnerClass(String name) {
|
||||
signatureVisitor().visitInnerClassType(name);
|
||||
}
|
||||
|
||||
public void writeClassEnd() {
|
||||
signatureVisitor().visitEnd();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.state;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Pair;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -628,45 +629,91 @@ public class JetTypeMapper {
|
||||
private void writeGenericType(
|
||||
BothSignatureWriter signatureVisitor,
|
||||
Type asmType,
|
||||
KotlinType jetType,
|
||||
KotlinType type,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (hasNothingInArguments(jetType)) {
|
||||
if (hasNothingInArguments(type) || type.getArguments().isEmpty()) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
return;
|
||||
}
|
||||
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
|
||||
assert possiblyInnerType != null : "possiblyInnerType with arguments should not be null";
|
||||
|
||||
List<TypeProjection> arguments = jetType.getArguments();
|
||||
for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
|
||||
if (parameter.isCopyFromOuterDeclaration()) continue;
|
||||
List<PossiblyInnerType> innerTypesAsList = possiblyInnerType.segments();
|
||||
PossiblyInnerType outermostInnerType = innerTypesAsList.get(0);
|
||||
ClassDescriptor outermostClass = outermostInnerType.getClassDescriptor();
|
||||
|
||||
TypeProjection argument = arguments.get(parameter.getIndex());
|
||||
|
||||
if (projectionsAllowed && argument.isStarProjection()) {
|
||||
signatureVisitor.writeUnboundedWildcard();
|
||||
}
|
||||
else {
|
||||
Variance projectionKind = projectionsAllowed
|
||||
? getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
)
|
||||
: Variance.INVARIANT;
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
|
||||
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
}
|
||||
if (innerTypesAsList.size() == 1) {
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
}
|
||||
else {
|
||||
signatureVisitor.writeOuterClassBegin(
|
||||
asmType,
|
||||
mapType(outermostClass.getDefaultType()).getInternalName());
|
||||
}
|
||||
|
||||
writeGenericArguments(
|
||||
signatureVisitor,
|
||||
outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(),
|
||||
howThisTypeIsUsed, projectionsAllowed);
|
||||
|
||||
for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
|
||||
ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
|
||||
signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
|
||||
writeGenericArguments(
|
||||
signatureVisitor, innerPart.getArguments(),
|
||||
classDescriptor.getDeclaredTypeParameters(),
|
||||
howThisTypeIsUsed, projectionsAllowed
|
||||
);
|
||||
}
|
||||
|
||||
signatureVisitor.writeClassEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getJvmShortName(@NotNull ClassDescriptor klass) {
|
||||
ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(klass));
|
||||
if (classId != null) {
|
||||
return classId.getShortClassName().asString();
|
||||
}
|
||||
|
||||
return SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
|
||||
}
|
||||
|
||||
private void writeGenericArguments(
|
||||
BothSignatureWriter signatureVisitor,
|
||||
List<? extends TypeProjection> arguments,
|
||||
List<? extends TypeParameterDescriptor> parameters,
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
for (Pair<? extends TypeParameterDescriptor, ? extends TypeProjection> item : CollectionsKt.zip(parameters, arguments)) {
|
||||
TypeParameterDescriptor parameter = item.getFirst();
|
||||
TypeProjection argument = item.getSecond();
|
||||
|
||||
if (projectionsAllowed && argument.isStarProjection()) {
|
||||
signatureVisitor.writeUnboundedWildcard();
|
||||
}
|
||||
else {
|
||||
Variance projectionKind = projectionsAllowed
|
||||
? getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
)
|
||||
: Variance.INVARIANT;
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
|
||||
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNothingInArguments(KotlinType jetType) {
|
||||
boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class Outer<E, F : Number> {
|
||||
inner class Inner<G, H>
|
||||
}
|
||||
|
||||
object Foo {
|
||||
fun <Y> foo(x: Outer<String, Int>.Inner<Y, CharSequence>) = 1
|
||||
}
|
||||
|
||||
// class: Outer
|
||||
// jvm signature: Outer
|
||||
// generic signature: <E:Ljava/lang/Object;F:Ljava/lang/Number;>Ljava/lang/Object;
|
||||
|
||||
// class: Outer$Inner
|
||||
// jvm signature: Outer$Inner
|
||||
// generic signature: <G:Ljava/lang/Object;H:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
|
||||
// method: Foo::foo
|
||||
// jvm signature: (LOuter$Inner;)I
|
||||
// generic signature: <Y:Ljava/lang/Object;>(LOuter<Ljava/lang/String;Ljava/lang/Integer;>.Inner<TY;Ljava/lang/CharSequence;>;)I
|
||||
@@ -53,6 +53,12 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GenericInnerClass.kt")
|
||||
public void testGenericInnerClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/GenericInnerClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Int.kt")
|
||||
public void testInt() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/Int.kt");
|
||||
|
||||
Reference in New Issue
Block a user