From 3f8accc2bf824549429041df0e0085e6657af210 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 8 Dec 2016 19:10:21 +0300 Subject: [PATCH] Kapt3: Fix '$' in function generic signatures (KT-15148) --- .../codegen/state/KotlinTypeMapper.java | 4 +-- .../load/kotlin/typeSignatureMapping.kt | 7 +++-- .../kotlin/resolve/jvm/JvmClassName.java | 30 ++++++++++++++++++- ...ileToSourceStubConverterTestGenerated.java | 6 ++++ plugins/kapt3/testData/converter/mapEntry.kt | 4 +++ plugins/kapt3/testData/converter/mapEntry.txt | 6 ++++ 6 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 plugins/kapt3/testData/converter/mapEntry.kt create mode 100644 plugins/kapt3/testData/converter/mapEntry.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index ec274392835..af997d2f1f0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -311,7 +311,7 @@ public class KotlinTypeMapper { } @Nullable - private static String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor, boolean publicFacade) { + private String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor, boolean publicFacade) { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); assert containingDeclaration instanceof PackageFragmentDescriptor : "Not a top-level member: " + descriptor; @@ -322,7 +322,7 @@ public class KotlinTypeMapper { ClassId ownerClassId = publicFacade ? containingClasses.getFacadeClassId() : containingClasses.getImplClassId(); - return JvmClassName.byClassId(ownerClassId).getInternalName(); + return JvmClassName.byClassId(ownerClassId, typeMappingConfiguration).getInternalName(); } private static final ClassId FAKE_CLASS_ID_FOR_BUILTINS = ClassId.topLevel(new FqName("kotlin.KotlinPackage")); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index 0050c76da9b..65a83a888ed 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -64,7 +64,7 @@ fun mapType( descriptorTypeWriter: JvmDescriptorTypeWriter?, writeGenericType: (KotlinType, T, TypeMappingMode) -> Unit = DO_NOTHING_3 ): T { - mapBuiltInType(kotlinType, factory)?.let { builtInType -> + mapBuiltInType(kotlinType, factory, typeMappingConfiguration)?.let { builtInType -> val jvmType = factory.boxTypeIfNeeded(builtInType, mode.needPrimitiveBoxing) writeGenericType(kotlinType, jvmType, mode) return jvmType @@ -160,7 +160,8 @@ fun hasVoidReturnType(descriptor: CallableDescriptor): Boolean { private fun mapBuiltInType( type: KotlinType, - typeFactory: JvmTypeFactory + typeFactory: JvmTypeFactory, + typeMappingConfiguration: TypeMappingConfiguration ): T? { val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null @@ -180,7 +181,7 @@ private fun mapBuiltInType( val classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName) if (classId != null) { - return typeFactory.createObjectType(JvmClassName.byClassId(classId).internalName) + return typeFactory.createObjectType(JvmClassName.byClassId(classId, typeMappingConfiguration).internalName) } return null diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java index d6dd234b583..1e42d0a3036 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java @@ -16,10 +16,15 @@ package org.jetbrains.kotlin.resolve.jvm; +import kotlin.jvm.functions.Function2; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; +import java.util.regex.Pattern; + public class JvmClassName { @NotNull public static JvmClassName byInternalName(@NotNull String internalName) { @@ -28,8 +33,31 @@ public class JvmClassName { @NotNull public static JvmClassName byClassId(@NotNull ClassId classId) { + return byClassId(classId, null); + } + + @NotNull + public static JvmClassName byClassId(@NotNull ClassId classId, @Nullable TypeMappingConfiguration typeMappingConfiguration) { FqName packageFqName = classId.getPackageFqName(); - String relativeClassName = classId.getRelativeClassName().asString().replace('.', '$'); + + String[] relativeClassNameSegments = classId.getRelativeClassName().asString().split(Pattern.quote(".")); + String relativeClassName; + + if (relativeClassNameSegments.length == 1) { + relativeClassName = relativeClassNameSegments[0]; + } + else if (relativeClassNameSegments.length > 1 && typeMappingConfiguration != null) { + Function2 innerClassNameFactory = typeMappingConfiguration.getInnerClassNameFactory(); + relativeClassName = innerClassNameFactory.invoke(relativeClassNameSegments[0], relativeClassNameSegments[1]); + for (int i = 2; i < relativeClassNameSegments.length; ++i) { + relativeClassName = innerClassNameFactory.invoke(relativeClassName, relativeClassNameSegments[i]); + } + } + else { + // Default behavior if we don't have an inner class name factory + relativeClassName = classId.getRelativeClassName().asString().replace('.', '$'); + } + return packageFqName.isRoot() ? new JvmClassName(relativeClassName) : new JvmClassName(packageFqName.asString().replace('.', '/') + "/" + relativeClassName); diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index 1b3f66e25b6..9e115d389cc 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -138,6 +138,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi doTest(fileName); } + @TestMetadata("mapEntry.kt") + public void testMapEntry() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/mapEntry.kt"); + doTest(fileName); + } + @TestMetadata("methodPropertySignatureClash.kt") public void testMethodPropertySignatureClash() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/methodPropertySignatureClash.kt"); diff --git a/plugins/kapt3/testData/converter/mapEntry.kt b/plugins/kapt3/testData/converter/mapEntry.kt new file mode 100644 index 00000000000..402ff7dc58f --- /dev/null +++ b/plugins/kapt3/testData/converter/mapEntry.kt @@ -0,0 +1,4 @@ +interface EntryHolder { + fun entry(p: Map.Entry>): Map.Entry + val entryProperty: Map.Entry +} \ No newline at end of file diff --git a/plugins/kapt3/testData/converter/mapEntry.txt b/plugins/kapt3/testData/converter/mapEntry.txt new file mode 100644 index 00000000000..1d2b8ae2430 --- /dev/null +++ b/plugins/kapt3/testData/converter/mapEntry.txt @@ -0,0 +1,6 @@ +public abstract interface EntryHolder { + + public abstract java.util.Map.Entry entry(java.util.Map.Entry> p); + + public abstract java.util.Map.Entry getEntryProperty(); +}