diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java index 2b75a4dc449..1d6dfcff082 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassBuilderMode.java @@ -62,4 +62,12 @@ public class ClassBuilderMode { /* bodies = */ false, /* metadata = */ true, /* sourceRetention = */ true); + + /** + * Function signatures + metadata (to support incremental compilation with kapt) + */ + public final static ClassBuilderMode KAPT3 = new ClassBuilderMode( + /* bodies = */ false, + /* metadata = */ true, + /* sourceRetention = */ true); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 9c5036abb83..ab59eab0e5f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; import org.jetbrains.kotlin.fileClasses.FileClasses; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; +import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; @@ -81,6 +82,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { private final GenerationState.GenerateClassFilter filter; private final JvmRuntimeTypes runtimeTypes; private final JvmFileClassesProvider fileClassesProvider; + private final TypeMappingConfiguration typeMappingConfiguration; public CodegenAnnotatingVisitor(@NotNull GenerationState state) { this.bindingTrace = state.getBindingTrace(); @@ -88,6 +90,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { this.filter = state.getGenerateDeclaredClassFilter(); this.runtimeTypes = state.getJvmRuntimeTypes(); this.fileClassesProvider = state.getFileClassesProvider(); + this.typeMappingConfiguration = state.getTypeMapper().getTypeMappingConfiguration(); } @NotNull @@ -232,8 +235,12 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { private String getName(ClassDescriptor classDescriptor) { String base = peekFromStack(nameStack); Name descriptorName = safeIdentifier(classDescriptor.getName()); - return DescriptorUtils.isTopLevelDeclaration(classDescriptor) ? base.isEmpty() ? descriptorName - .asString() : base + '/' + descriptorName : base + '$' + descriptorName; + if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) { + return base.isEmpty() ? descriptorName.asString() : base + '/' + descriptorName; + } + else { + return typeMappingConfiguration.getInnerClassNameFactory().invoke(base, descriptorName.asString()); + } } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 96be20e292b..c5fe3b6a7f6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -325,7 +325,7 @@ public class InlineCodegen extends CallGenerator { assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor; KotlinTypeMapper.ContainingClassesInfo containingClasses = - KotlinTypeMapper.getContainingClassesForDeserializedCallable((DeserializedCallableMemberDescriptor) callableDescriptor); + state.getTypeMapper().getContainingClassesForDeserializedCallable((DeserializedCallableMemberDescriptor) callableDescriptor); final ClassId containerId = containingClasses.getImplClassId(); 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 05a40722295..f363837796e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import kotlin.Pair; import kotlin.Unit; import kotlin.collections.CollectionsKt; +import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -103,12 +104,32 @@ public class KotlinTypeMapper { private final boolean isJvm8Target; private final TypeMappingConfiguration typeMappingConfiguration = new TypeMappingConfiguration() { + private final Function2 defaultClassNameFactory + = TypeMappingConfiguration.Companion.getDEFAULT_INNER_CLASS_NAME_FACTORY(); + + private final Function2 innerClassNameFactory = new Function2() { + @Override + public String invoke(String outer, String inner) { + if (classBuilderMode == ClassBuilderMode.KAPT3) { + return outer + '/' + inner; + } + + return defaultClassNameFactory.invoke(outer, inner); + } + }; + @NotNull @Override public KotlinType commonSupertype(@NotNull Collection types) { return CommonSupertypes.commonSupertype(types); } + @NotNull + @Override + public Function2 getInnerClassNameFactory() { + return innerClassNameFactory; + } + @Nullable @Override public Type getPredefinedTypeForClass(@NotNull ClassDescriptor classDescriptor) { @@ -139,6 +160,11 @@ public class KotlinTypeMapper { this.isJvm8Target = isJvm8Target; } + @NotNull + public TypeMappingConfiguration getTypeMappingConfiguration() { + return typeMappingConfiguration; + } + @NotNull public BindingContext getBindingContext() { return bindingContext; @@ -250,7 +276,7 @@ public class KotlinTypeMapper { } @NotNull - public static ContainingClassesInfo getContainingClassesForDeserializedCallable( + public ContainingClassesInfo getContainingClassesForDeserializedCallable( @NotNull DeserializedCallableMemberDescriptor deserializedDescriptor ) { DeclarationDescriptor parentDeclaration = deserializedDescriptor.getContainingDeclaration(); @@ -269,14 +295,16 @@ public class KotlinTypeMapper { } @NotNull - private static ClassId getContainerClassIdForClassDescriptor(@NotNull ClassDescriptor classDescriptor) { + private ClassId getContainerClassIdForClassDescriptor(@NotNull ClassDescriptor classDescriptor) { ClassId classId = DescriptorUtilsKt.getClassId(classDescriptor); assert classId != null : "Deserialized class should have a ClassId: " + classDescriptor; if (isInterface(classDescriptor)) { FqName relativeClassName = classId.getRelativeClassName(); //TODO test nested trait fun inlining - return new ClassId(classId.getPackageFqName(), Name.identifier(relativeClassName.shortName().asString() + JvmAbi.DEFAULT_IMPLS_SUFFIX)); + String defaultImplsClassName = typeMappingConfiguration.getInnerClassNameFactory() + .invoke(relativeClassName.shortName().asString(), JvmAbi.DEFAULT_IMPLS_CLASS_NAME); + return new ClassId(classId.getPackageFqName(), Name.identifier(defaultImplsClassName)); } return classId; @@ -437,7 +465,9 @@ public class KotlinTypeMapper { @NotNull public Type mapDefaultImpls(@NotNull ClassDescriptor descriptor) { - return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.DEFAULT_IMPLS_SUFFIX); + String defaultImplsClassName = typeMappingConfiguration.getInnerClassNameFactory().invoke( + mapType(descriptor).getInternalName(), JvmAbi.DEFAULT_IMPLS_CLASS_NAME); + return Type.getObjectType(defaultImplsClassName); } @NotNull diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index 56156c04917..6984ac27d44 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -33,6 +33,11 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; public final class JvmAbi { public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; + + /** + * Warning: use DEFAULT_IMPLS_CLASS_NAME and TypeMappingConfiguration.innerClassNameFactory when possible. + * This is false for KAPT3 mode. + */ public static final String DEFAULT_IMPLS_SUFFIX = "$" + DEFAULT_IMPLS_CLASS_NAME; public static final String DEFAULT_IMPLS_DELEGATE_SUFFIX = "$defaultImpl"; 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 0a75c16d8ba..0050c76da9b 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 @@ -42,6 +42,13 @@ private fun JvmTypeFactory.boxTypeIfNeeded(possiblyPrimitiveType: T if (needBoxedType) boxType(possiblyPrimitiveType) else possiblyPrimitiveType interface TypeMappingConfiguration { + companion object { + val DEFAULT_INNER_CLASS_NAME_FACTORY = fun(outer: String, inner: String) = outer + "$" + inner + } + + val innerClassNameFactory: (outer: String, inner: String) -> String + get() = DEFAULT_INNER_CLASS_NAME_FACTORY + fun commonSupertype(types: Collection<@JvmSuppressWildcards KotlinType>): KotlinType fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): T? fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) @@ -126,7 +133,7 @@ fun mapType( factory.javaLangClassType else typeMappingConfiguration.getPredefinedTypeForClass(descriptor.original) - ?: factory.createObjectType(computeInternalName(descriptor.original)) + ?: factory.createObjectType(computeInternalName(descriptor.original, typeMappingConfiguration.innerClassNameFactory)) writeGenericType(kotlinType, jvmType, mode) @@ -179,7 +186,10 @@ private fun mapBuiltInType( return null } -internal fun computeInternalName(klass: ClassDescriptor): String { +internal fun computeInternalName( + klass: ClassDescriptor, + innerClassNameFactory: (outer: String, inner: String) -> String = TypeMappingConfiguration.DEFAULT_INNER_CLASS_NAME_FACTORY +): String { val container = klass.containingDeclaration val name = SpecialNames.safeIdentifier(klass.name).identifier @@ -190,8 +200,8 @@ internal fun computeInternalName(klass: ClassDescriptor): String { assert(container is ClassDescriptor) { "Unexpected container: $container for $klass" } - val containerInternalName = computeInternalName(container as ClassDescriptor) - return if (klass.kind == ClassKind.ENUM_ENTRY) containerInternalName else containerInternalName + "$" + name + val containerInternalName = computeInternalName(container as ClassDescriptor, innerClassNameFactory) + return if (klass.kind == ClassKind.ENUM_ENTRY) containerInternalName else innerClassNameFactory(containerInternalName, name) } private fun getRepresentativeUpperBound(descriptor: TypeParameterDescriptor): KotlinType {