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 2e235b10e5e..3f5935897b7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -99,20 +99,6 @@ public class KotlinTypeMapper { private final boolean isJvm8TargetWithDefaults; 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) { @@ -122,7 +108,7 @@ public class KotlinTypeMapper { @NotNull @Override public Function2 getInnerClassNameFactory() { - return innerClassNameFactory; + return TypeMappingConfiguration.DefaultImpls.getInnerClassNameFactory(this); } @Nullable diff --git a/compiler/testData/codegen/kapt/innerClasses.txt b/compiler/testData/codegen/kapt/innerClasses.txt index 67452ed0579..9a572929bae 100644 --- a/compiler/testData/codegen/kapt/innerClasses.txt +++ b/compiler/testData/codegen/kapt/innerClasses.txt @@ -1,23 +1,6 @@ @kotlin.Metadata -public final class test/TopLevel { - public final static field Companion: test.TopLevel.Companion - private final static @org.jetbrains.annotations.NotNull field q: java.lang.String - private final @org.jetbrains.annotations.NotNull field x: java.lang.String - private final field y: int - inner class test/TopLevel/Companion - inner class test/TopLevel/InnerInterface - inner class test/TopLevel/InnerObject - inner class test/TopLevel/NestedClass - public method (): void - public final method b(): void - public final static @org.jetbrains.annotations.NotNull method getQ(): java.lang.String - public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String - public final method getY(): int -} - -@kotlin.Metadata -public final class test/TopLevel/Companion { - inner class test/TopLevel/Companion +public final class test/TopLevel$Companion { + inner class test/TopLevel$Companion private method (): void public final method a(): void public final @org.jetbrains.annotations.NotNull method getQ(): java.lang.String @@ -25,28 +8,45 @@ public final class test/TopLevel/Companion { } @kotlin.Metadata -public interface test/TopLevel/InnerInterface { - inner class test/TopLevel/InnerInterface +public interface test/TopLevel$InnerInterface { + inner class test/TopLevel$InnerInterface } @kotlin.Metadata -public final class test/TopLevel/InnerObject { - public final static field INSTANCE: test.TopLevel.InnerObject - inner class test/TopLevel/InnerObject +public final class test/TopLevel$InnerObject { + public final static field INSTANCE: test.TopLevel$InnerObject + inner class test/TopLevel$InnerObject private method (): void } @kotlin.Metadata -public final class test/TopLevel/NestedClass { - inner class test/TopLevel/NestedClass - inner class test/TopLevel/NestedClass/NestedInnerClass +public final class test/TopLevel$NestedClass$NestedInnerClass { + synthetic final field this$0: test.TopLevel$NestedClass + inner class test/TopLevel$NestedClass + inner class test/TopLevel$NestedClass$NestedInnerClass + public method (p0: test.TopLevel$NestedClass): void +} + +@kotlin.Metadata +public final class test/TopLevel$NestedClass { + inner class test/TopLevel$NestedClass + inner class test/TopLevel$NestedClass$NestedInnerClass public method (): void } @kotlin.Metadata -public final class test/TopLevel/NestedClass/NestedInnerClass { - synthetic final field this$0: test.TopLevel.NestedClass - inner class test/TopLevel/NestedClass - inner class test/TopLevel/NestedClass/NestedInnerClass - public method (p0: test.TopLevel.NestedClass): void +public final class test/TopLevel { + public final static field Companion: test.TopLevel$Companion + private final static @org.jetbrains.annotations.NotNull field q: java.lang.String + private final @org.jetbrains.annotations.NotNull field x: java.lang.String + private final field y: int + inner class test/TopLevel$Companion + inner class test/TopLevel$InnerInterface + inner class test/TopLevel$InnerObject + inner class test/TopLevel$NestedClass + public method (): void + public final method b(): void + public final static @org.jetbrains.annotations.NotNull method getQ(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String + public final method getY(): int } diff --git a/compiler/testData/codegen/kapt/interfaceImpls.txt b/compiler/testData/codegen/kapt/interfaceImpls.txt index f4be136a40a..3a3b6c30b13 100644 --- a/compiler/testData/codegen/kapt/interfaceImpls.txt +++ b/compiler/testData/codegen/kapt/interfaceImpls.txt @@ -1,14 +1,14 @@ @kotlin.Metadata -public interface A { - inner class A/DefaultImpls - public abstract method a(): void - public abstract method b(): void +public final class A$DefaultImpls { + inner class A$DefaultImpls + public static method a(p0: A): void } @kotlin.Metadata -public final class A/DefaultImpls { - inner class A/DefaultImpls - public static method a(p0: A): void +public interface A { + inner class A$DefaultImpls + public abstract method a(): void + public abstract method b(): void } @kotlin.Metadata 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 821b274e034..065be129497 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 @@ -47,8 +47,8 @@ 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 + private companion object { + private val DEFAULT_INNER_CLASS_NAME_FACTORY = fun(outer: String, inner: String) = outer + "$" + inner } val innerClassNameFactory: (outer: String, inner: String) -> String diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt index 2f1871380c0..8980ad395b5 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt @@ -186,7 +186,7 @@ abstract class AbstractKapt3Extension( private fun generateStubs(project: Project, module: ModuleDescriptor, context: BindingContext, files: Collection): KaptContext<*> { if (!aptMode.generateStubs) { - return KaptContext(logger, BindingContext.EMPTY, emptyList(), emptyMap(), null, options, javacOptions) + return KaptContext(logger, project, BindingContext.EMPTY, emptyList(), emptyMap(), null, options, javacOptions) } logger.info { "Kotlin files to compile: " + files.map { it.virtualFile?.name ?: "" } } @@ -241,7 +241,7 @@ abstract class AbstractKapt3Extension( logger.info { "Stubs compilation took $classFilesCompilationTime ms" } logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } } - return KaptContext(logger, bindingContext, compiledClasses, origins, generationState, options, javacOptions) + return KaptContext(logger, project, bindingContext, compiledClasses, origins, generationState, options, javacOptions) } private fun generateKotlinSourceStubs(kaptContext: KaptContext) { diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt index 77913e2c005..65e7590661e 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.kapt3 +import com.intellij.openapi.project.Project import com.sun.tools.javac.file.JavacFileManager import com.sun.tools.javac.jvm.ClassReader import com.sun.tools.javac.main.JavaCompiler @@ -34,6 +35,7 @@ import javax.tools.JavaFileManager class KaptContext( val logger: KaptLogger, + val project: Project, val bindingContext: BindingContext, val compiledClasses: List, val origins: Map, @@ -50,7 +52,7 @@ class KaptContext( init { KaptJavaLog.preRegister(context, logger.messageCollector) JavacFileManager.preRegister(context) - KaptTreeMaker.preRegister(context) + KaptTreeMaker.preRegister(context, this) KaptJavaCompiler.preRegister(context) fileManager = context.get(JavaFileManager::class.java) as JavacFileManager diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt index dd11f9a3d20..d5956400613 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt @@ -16,28 +16,34 @@ package org.jetbrains.kotlin.kapt3.javac +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import com.intellij.psi.search.GlobalSearchScope import com.sun.tools.javac.code.TypeTag import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.TreeMaker import com.sun.tools.javac.util.Context +import com.sun.tools.javac.util.Name import com.sun.tools.javac.util.Names import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.kapt3.KaptContext import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type.* +import org.jetbrains.org.objectweb.asm.tree.ClassNode -class KaptTreeMaker(context: Context) : TreeMaker(context) { - val nameTable = Names.instance(context).table +class KaptTreeMaker(context: Context, private val kaptContext: KaptContext<*>) : TreeMaker(context) { + val nameTable: Name.Table = Names.instance(context).table fun Type(type: Type): JCTree.JCExpression { convertBuiltinType(type)?.let { return it } if (type.sort == ARRAY) { return TypeArray(Type(AsmUtil.correctElementType(type))) } - return FqName(type.className) + return FqName(type.internalName) } fun FqName(internalOrFqName: String): JCTree.JCExpression { - val path = internalOrFqName.replace('/', '.').convertSpecialFqName().split('.') + val path = getQualifiedName(internalOrFqName.replace('/', '.')).convertSpecialFqName().split('.') assert(path.isNotEmpty()) if (path.size == 1) return SimpleName(path.single()) @@ -48,6 +54,74 @@ class KaptTreeMaker(context: Context) : TreeMaker(context) { return expr } + fun getQualifiedName(type: Type) = getQualifiedName(type.internalName) + + fun getSimpleName(clazz: ClassNode) = getQualifiedName(clazz.name).substringAfterLast('.') + + fun getQualifiedName(internalName: String): String { + val nameWithDots = internalName.replace('/', '.') + // This is a top-level class + if ('$' !in nameWithDots) return nameWithDots + + // Maybe it's in our sources? + val classFromSources = kaptContext.compiledClasses.firstOrNull { it.name == internalName } + if (classFromSources != null) { + // Get inner class node pointing to the outer class + val innerClassNode = classFromSources.innerClasses.firstOrNull { it.name == classFromSources.name } + return innerClassNode?.let { getQualifiedName(it.outerName) + "." + it.innerName } ?: nameWithDots + } + + // Search in the classpath + val javaPsiFacade = JavaPsiFacade.getInstance(kaptContext.project) + val scope = GlobalSearchScope.allScope(javaPsiFacade.project) + + val fqNameFromClassWithPreciseName = javaPsiFacade.findClass(nameWithDots, scope)?.qualifiedName + if (fqNameFromClassWithPreciseName != null) { + return fqNameFromClassWithPreciseName + } + + nameWithDots.iterateDollars { outerName, innerName -> + if (innerName.isEmpty()) return@iterateDollars // We already checked an exact match + + val outerClass = javaPsiFacade.findClass(outerName, scope) ?: return@iterateDollars + return tryToFindNestedClass(outerClass, innerName)?.qualifiedName ?: return@iterateDollars + } + + return nameWithDots + } + + private fun tryToFindNestedClass(outerClass: PsiClass, innerClassName: String): PsiClass? { + outerClass.findInnerClassByName(innerClassName, false)?.let { return it } + + innerClassName.iterateDollars { name1, name2 -> + if (name2.isEmpty()) return outerClass.findInnerClassByName(name1, false) + + val nestedClass = outerClass.findInnerClassByName(name1, false) + if (nestedClass != null) { + tryToFindNestedClass(nestedClass, name2)?.let { return it } + } + } + + return null + } + + private inline fun String.iterateDollars(variantHandler: (outerName: String, innerName: String) -> Unit) { + var dollarIndex = this.indexOf('$') + if (dollarIndex < 0) { + variantHandler(this, "") + return + } + + while (dollarIndex > 0 && dollarIndex < this.lastIndex) { + val outerName = this.take(dollarIndex) + val innerName = this.drop(dollarIndex + 1) + + variantHandler(outerName, innerName) + + dollarIndex = this.indexOf('$', startIndex = dollarIndex + 1) + } + } + private fun String.convertSpecialFqName(): String { // Hard-coded in ImplementationBodyCodegen, KOTLIN_MARKER_INTERFACES if (this == "kotlin.jvm.internal.markers.KMutableMap\$Entry") { @@ -57,7 +131,7 @@ class KaptTreeMaker(context: Context) : TreeMaker(context) { return this } - fun convertBuiltinType(type: Type): JCTree.JCExpression? { + private fun convertBuiltinType(type: Type): JCTree.JCExpression? { val typeTag = when (type) { BYTE_TYPE -> TypeTag.BYTE BOOLEAN_TYPE -> TypeTag.BOOLEAN @@ -75,11 +149,11 @@ class KaptTreeMaker(context: Context) : TreeMaker(context) { fun SimpleName(name: String): JCTree.JCExpression = Ident(name(name)) - fun name(name: String) = nameTable.fromString(name) + fun name(name: String): Name = nameTable.fromString(name) companion object { - internal fun preRegister(context: Context) { - context.put(treeMakerKey, Context.Factory(::KaptTreeMaker)) + internal fun preRegister(context: Context, kaptContext: KaptContext<*>) { + context.put(treeMakerKey, Context.Factory { KaptTreeMaker(it, kaptContext) }) } } } \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index ac4ba724e22..4280ff12d10 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -204,7 +204,7 @@ class ClassFileToSourceStubConverter( if (isEnum) ElementKind.ENUM else ElementKind.CLASS, packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations) - val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}/DefaultImpls") + val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}\$DefaultImpls") && isPublic(clazz.access) && isFinal(clazz.access) && descriptor is ClassDescriptor && descriptor.kind == ClassKind.INTERFACE @@ -218,10 +218,10 @@ class ClassFileToSourceStubConverter( val interfaces = mapJList(clazz.interfaces) { if (isAnnotation && it == "java/lang/annotation/Annotation") return@mapJList null - treeMaker.FqName(it) + treeMaker.FqName(treeMaker.getQualifiedName(it)) } - val superClass = treeMaker.FqName(clazz.superName) + val superClass = treeMaker.FqName(treeMaker.getQualifiedName(clazz.superName)) val hasSuperClass = clazz.superName != "java/lang/Object" && !isEnum val genericType = signatureParser.parseClassSignature(clazz.signature, superClass, interfaces) @@ -322,15 +322,12 @@ class ClassFileToSourceStubConverter( outerClass: ClassNode? = findContainingClassNode(clazz) ): Boolean { if (outerClass == null) return false - if (clazz.simpleName == outerClass.simpleName) return true + if (treeMaker.getSimpleName(clazz) == treeMaker.getSimpleName(outerClass)) return true // Try to find the containing class for outerClassNode (to check the whole tree recursively) val containingClassForOuterClass = findContainingClassNode(outerClass) ?: return false return checkIfInnerClassNameConflictsWithOuter(clazz, containingClassForOuterClass) } - private val ClassNode.simpleName: String - get() = name.substringAfterLast(".").substringAfterLast("/") - private fun getClassAccessFlags(clazz: ClassNode, descriptor: DeclarationDescriptor, isInner: Boolean, isNested: Boolean) = when { (descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE -> { // Classes inside interfaces should always be public and static. @@ -373,7 +370,7 @@ class ClassFileToSourceStubConverter( // Enum type must be an identifier (Javac requirement) val typeExpression = if (isEnum(field.access)) - treeMaker.SimpleName(type.className.substringAfterLast('.')) + treeMaker.SimpleName(treeMaker.getQualifiedName(type).substringAfterLast('.')) else anonymousTypeHandler.getNonAnonymousType(descriptor) { getNonErrorType((descriptor as? CallableDescriptor)?.returnType, @@ -606,7 +603,7 @@ class ClassFileToSourceStubConverter( private fun convertAnnotation(annotation: AnnotationNode, packageFqName: String? = "", filtered: Boolean = true): JCAnnotation? { val annotationType = Type.getType(annotation.desc) - val fqName = annotationType.className + val fqName = treeMaker.getQualifiedName(annotationType) if (filtered) { if (BLACKLISTED_ANNOTATIONS.any { fqName.startsWith(it) }) return null diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt index a1c6456b529..84b964cb69d 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt @@ -203,7 +203,7 @@ class SignatureParser(val treeMaker: KaptTreeMaker) { val innerClasses = mutableListOf() node.split(typeArgs, TypeArgument, innerClasses, InnerClass) - var expression = makeExpressionForClassTypeWithArguments(treeMaker.FqName(node.name!!.replace('/', '.')), typeArgs) + var expression = makeExpressionForClassTypeWithArguments(treeMaker.FqName(node.name!!), typeArgs) if (innerClasses.isEmpty()) return expression for (innerClass in innerClasses) { diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt index 3e592ba0452..6170487ef1e 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/errorTypeConversion.kt @@ -74,7 +74,7 @@ private fun convertUserType(type: KtUserType, converter: ClassFileToSourceStubCo // This could be List or similar. List should be converted to java.util.List in this case. val referenceTarget = converter.kaptContext.bindingContext[BindingContext.REFERENCE_TARGET, type.referenceExpression] if (referenceTarget is ClassDescriptor) { - treeMaker.FqName(converter.kaptContext.generationState.typeMapper.mapType(referenceTarget.defaultType).className) + treeMaker.FqName(converter.kaptContext.generationState.typeMapper.mapType(referenceTarget.defaultType).internalName) } else { treeMaker.SimpleName(referencedName) diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt index 953c7857463..8981b1abcf0 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt @@ -61,7 +61,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() { val generationState = GenerationUtils.compileFiles(myFiles.psiFiles, myEnvironment, classBuilderFactory) val logger = KaptLogger(isVerbose = true, messageCollector = messageCollector) - val kaptContext = KaptContext(logger, generationState.bindingContext, classBuilderFactory.compiledClasses, + val kaptContext = KaptContext(logger, generationState.project, generationState.bindingContext, classBuilderFactory.compiledClasses, classBuilderFactory.origins, generationState, processorOptions = emptyMap()) try { check(kaptContext, txtFile, wholeFile) 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 9e8be9f4008..c6536c0a6e6 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -228,6 +228,18 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi doTest(fileName); } + @TestMetadata("nestedClasses2.kt") + public void testNestedClasses2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClasses2.kt"); + doTest(fileName); + } + + @TestMetadata("nestedClassesNonRootPackage.kt") + public void testNestedClassesNonRootPackage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClassesNonRootPackage.kt"); + doTest(fileName); + } + @TestMetadata("nonExistentClass.kt") public void testNonExistentClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nonExistentClass.kt"); diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JavaKaptContextTest.kt b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JavaKaptContextTest.kt index 67baa69f5e2..806b282f06c 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JavaKaptContextTest.kt +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JavaKaptContextTest.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.kapt3.test +import com.intellij.openapi.command.impl.DummyProject import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.kapt3.KaptContext @@ -80,6 +81,7 @@ class JavaKaptContextTest { private fun doAnnotationProcessing(javaSourceFile: File, processor: Processor, outputDir: File) { KaptContext(KaptLogger(isVerbose = true, messageCollector = messageCollector), + DummyProject.getInstance(), bindingContext = BindingContext.EMPTY, compiledClasses = emptyList(), origins = emptyMap(), diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt index 26958e31986..84730351aea 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt @@ -52,10 +52,10 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest() { assert(!File(stubsOutputDir, "test/Simple/InnerClass.java").exists()) assert(File(incrementalDataOutputDir, "test/Simple.class").exists()) - assert(File(incrementalDataOutputDir, "test/Simple/Companion.class").exists()) - assert(File(incrementalDataOutputDir, "test/Simple/InnerClass.class").exists()) - assert(File(incrementalDataOutputDir, "test/Simple/NestedClass.class").exists()) - assert(File(incrementalDataOutputDir, "test/Simple/NestedClass/NestedNestedClass.class").exists()) + assert(File(incrementalDataOutputDir, "test/Simple\$Companion.class").exists()) + assert(File(incrementalDataOutputDir, "test/Simple\$InnerClass.class").exists()) + assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass.class").exists()) + assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass\$NestedNestedClass.class").exists()) assert(bindings.any { it.key == "test/Simple" && it.value.name == "test/Simple.java" }) assert(bindings.none { it.key.contains("Companion") }) diff --git a/plugins/kapt3/testData/converter/nestedClasses2.kt b/plugins/kapt3/testData/converter/nestedClasses2.kt new file mode 100644 index 00000000000..e156a4841e3 --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClasses2.kt @@ -0,0 +1,78 @@ +// FILE: JavaClass.java +public class JavaClass { + public class Foo { + public class Bar {} + } +} + +//FILE: J$B.java +public class J$B { + public class C {} + + public class D$E { + class F {} + class F$G {} + } + + public class D$$E {} + public class D$$$E {} +} + +// FILE: a.kt +interface IFoo { + interface IBar { + annotation class Anno(vararg val value: kotlin.reflect.KClass<*>) + + @Anno(IZoo::class) + interface IZoo + } +} + +class Experiment { + annotation class Type + + @Type + data class Group(s: String) +} + +class Foo { + open class Bar { + object Zoo + } +} + +class `A$B` { + class C + + @JvmField lateinit var c: C + @JvmField lateinit var de: `D$E` + + @JvmField lateinit var jc: `J$B`.C + @JvmField lateinit var jde: `J$B`.`D$E` + + class `D$E` { + class F + class `F$G` + + @JvmField lateinit var f: F + @JvmField lateinit var fg: `F$G` + + @JvmField lateinit var jf: `J$B`.`D$E`.F + @JvmField lateinit var jfg: `J$B`.`D$E`.`F$G` + } + + class `D$$E` + class `D$$$E` + + @JvmField lateinit var dee: `D$$E` + @JvmField lateinit var deee: `D$$$E` + + @JvmField lateinit var jdee: `J$B`.`D$$E` + @JvmField lateinit var jdeee: `J$B`.`D$$$E` +} + +@IFoo.IBar.Anno(IFoo.IBar.IZoo::class, Foo.Bar::class) +class Test1(val zoo: Foo.Bar.Zoo) : Foo.Bar(), IFoo.IBar, IFoo.IBar.IZoo { + fun a(): Thread.State = Thread.State.NEW + fun b(foo: JavaClass.Foo, bar: JavaClass.Foo.Bar) {} +} \ No newline at end of file diff --git a/plugins/kapt3/testData/converter/nestedClasses2.txt b/plugins/kapt3/testData/converter/nestedClasses2.txt new file mode 100644 index 00000000000..aea2d1e950c --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClasses2.txt @@ -0,0 +1,192 @@ +@kotlin.Metadata() +public final class A$B { + @org.jetbrains.annotations.NotNull() + public A$B.C c; + @org.jetbrains.annotations.NotNull() + public A$B.D$E de; + @org.jetbrains.annotations.NotNull() + public J$B.C jc; + @org.jetbrains.annotations.NotNull() + public J$B.D$E jde; + @org.jetbrains.annotations.NotNull() + public A$B.D$$E dee; + @org.jetbrains.annotations.NotNull() + public A$B.D$$$E deee; + @org.jetbrains.annotations.NotNull() + public J$B.D$$E jdee; + @org.jetbrains.annotations.NotNull() + public J$B.D$$$E jdeee; + + public A$B() { + super(); + } + + @kotlin.Metadata() + public static final class C { + + public C() { + super(); + } + } + + @kotlin.Metadata() + public static final class D$E { + @org.jetbrains.annotations.NotNull() + public A$B.D$E.F f; + @org.jetbrains.annotations.NotNull() + public A$B.D$E.F$G fg; + @org.jetbrains.annotations.NotNull() + public J$B.D$E.F jf; + @org.jetbrains.annotations.NotNull() + public J$B.D$E.F$G jfg; + + public D$E() { + super(); + } + + @kotlin.Metadata() + public static final class F { + + public F() { + super(); + } + } + + @kotlin.Metadata() + public static final class F$G { + + public F$G() { + super(); + } + } + } + + @kotlin.Metadata() + public static final class D$$E { + + public D$$E() { + super(); + } + } + + @kotlin.Metadata() + public static final class D$$$E { + + public D$$$E() { + super(); + } + } +} + +//////////////////// + + +@kotlin.Metadata() +public final class Experiment { + + public Experiment() { + super(); + } + + @kotlin.Metadata() + @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) + public static abstract @interface Type { + } + + @kotlin.Metadata() + @Experiment.Type() + public static final class Group { + + public Group(@org.jetbrains.annotations.NotNull() + java.lang.String s) { + super(); + } + + @org.jetbrains.annotations.NotNull() + public final Experiment.Group copy(@org.jetbrains.annotations.NotNull() + java.lang.String s) { + return null; + } + } +} + +//////////////////// + + +@kotlin.Metadata() +public final class Foo { + + public Foo() { + super(); + } + + @kotlin.Metadata() + public static class Bar { + + public Bar() { + super(); + } + + @kotlin.Metadata() + public static final class Zoo { + public static final Foo.Bar.Zoo INSTANCE = null; + + private Zoo() { + super(); + } + } + } +} + +//////////////////// + + +@kotlin.Metadata() +public abstract interface IFoo { + + @kotlin.Metadata() + public static abstract interface IBar { + + @kotlin.Metadata() + @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) + public static abstract @interface Anno { + + public abstract java.lang.Class[] value(); + } + + @kotlin.Metadata() + @IFoo.IBar.Anno(value = {IFoo.IBar.IZoo.class}) + public static abstract interface IZoo { + } + } +} + +//////////////////// + + +@kotlin.Metadata() +@IFoo.IBar.Anno(value = {IFoo.IBar.IZoo.class, Foo.Bar.class}) +public final class Test1 extends Foo.Bar implements IFoo.IBar, IFoo.IBar.IZoo { + @org.jetbrains.annotations.NotNull() + private final Foo.Bar.Zoo zoo = null; + + @org.jetbrains.annotations.NotNull() + public final java.lang.Thread.State a() { + return null; + } + + public final void b(@org.jetbrains.annotations.NotNull() + JavaClass.Foo foo, @org.jetbrains.annotations.NotNull() + JavaClass.Foo.Bar bar) { + } + + @org.jetbrains.annotations.NotNull() + public final Foo.Bar.Zoo getZoo() { + return null; + } + + public Test1(@org.jetbrains.annotations.NotNull() + Foo.Bar.Zoo zoo) { + super(); + } +} diff --git a/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.kt b/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.kt new file mode 100644 index 00000000000..9a8218aba97 --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.kt @@ -0,0 +1,84 @@ +// FILE: test/JavaClass.java +package test; + +class JavaClass { + class Foo { + class Bar {} + } +} + +//FILE: test/J$B.java +package test; + +public class J$B { + public class C {} + + public class D$E { + class F {} + class F$G {} + } + + public class D$$E {} + public class D$$$E {} +} + +// FILE: a.kt +package test + +interface IFoo { + interface IBar { + annotation class Anno(vararg val value: kotlin.reflect.KClass<*>) + + @Anno(IZoo::class) + interface IZoo + } +} + +class Experiment { + annotation class Type + + @Type + data class Group(s: String) +} + +class Foo { + open class Bar { + object Zoo + } +} + +class `A$B` { + class C + + @JvmField lateinit var c: C + @JvmField lateinit var de: `D$E` + + @JvmField lateinit var jc: `J$B`.C + @JvmField lateinit var jde: `J$B`.`D$E` + + class `D$E` { + class F + class `F$G` + + @JvmField lateinit var f: F + @JvmField lateinit var fg: `F$G` + + @JvmField lateinit var jf: `J$B`.`D$E`.F + @JvmField lateinit var jfg: `J$B`.`D$E`.`F$G` + } + + class `D$$E` + class `D$$$E` + + @JvmField lateinit var dee: `D$$E` + @JvmField lateinit var deee: `D$$$E` + + @JvmField lateinit var jdee: `J$B`.`D$$E` + @JvmField lateinit var jdeee: `J$B`.`D$$$E` +} + +@IFoo.IBar.Anno(IFoo.IBar.IZoo::class, Foo.Bar::class) +class Test1(val zoo: Foo.Bar.Zoo) : Foo.Bar(), IFoo.IBar, IFoo.IBar.IZoo { + fun a(): Thread.State = Thread.State.NEW + fun b(foo: JavaClass.Foo, bar: JavaClass.Foo.Bar) {} +} \ No newline at end of file diff --git a/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.txt b/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.txt new file mode 100644 index 00000000000..a9041858fc6 --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClassesNonRootPackage.txt @@ -0,0 +1,198 @@ +package test; + +@kotlin.Metadata() +public final class A$B { + @org.jetbrains.annotations.NotNull() + public test.A$B.C c; + @org.jetbrains.annotations.NotNull() + public test.A$B.D$E de; + @org.jetbrains.annotations.NotNull() + public test.J$B.C jc; + @org.jetbrains.annotations.NotNull() + public test.J$B.D$E jde; + @org.jetbrains.annotations.NotNull() + public test.A$B.D$$E dee; + @org.jetbrains.annotations.NotNull() + public test.A$B.D$$$E deee; + @org.jetbrains.annotations.NotNull() + public test.J$B.D$$E jdee; + @org.jetbrains.annotations.NotNull() + public test.J$B.D$$$E jdeee; + + public A$B() { + super(); + } + + @kotlin.Metadata() + public static final class C { + + public C() { + super(); + } + } + + @kotlin.Metadata() + public static final class D$E { + @org.jetbrains.annotations.NotNull() + public test.A$B.D$E.F f; + @org.jetbrains.annotations.NotNull() + public test.A$B.D$E.F$G fg; + @org.jetbrains.annotations.NotNull() + public test.J$B.D$E.F jf; + @org.jetbrains.annotations.NotNull() + public test.J$B.D$E.F$G jfg; + + public D$E() { + super(); + } + + @kotlin.Metadata() + public static final class F { + + public F() { + super(); + } + } + + @kotlin.Metadata() + public static final class F$G { + + public F$G() { + super(); + } + } + } + + @kotlin.Metadata() + public static final class D$$E { + + public D$$E() { + super(); + } + } + + @kotlin.Metadata() + public static final class D$$$E { + + public D$$$E() { + super(); + } + } +} + +//////////////////// + +package test; + +@kotlin.Metadata() +public final class Experiment { + + public Experiment() { + super(); + } + + @kotlin.Metadata() + @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) + public static abstract @interface Type { + } + + @kotlin.Metadata() + @test.Experiment.Type() + public static final class Group { + + public Group(@org.jetbrains.annotations.NotNull() + java.lang.String s) { + super(); + } + + @org.jetbrains.annotations.NotNull() + public final test.Experiment.Group copy(@org.jetbrains.annotations.NotNull() + java.lang.String s) { + return null; + } + } +} + +//////////////////// + +package test; + +@kotlin.Metadata() +public final class Foo { + + public Foo() { + super(); + } + + @kotlin.Metadata() + public static class Bar { + + public Bar() { + super(); + } + + @kotlin.Metadata() + public static final class Zoo { + public static final test.Foo.Bar.Zoo INSTANCE = null; + + private Zoo() { + super(); + } + } + } +} + +//////////////////// + +package test; + +@kotlin.Metadata() +public abstract interface IFoo { + + @kotlin.Metadata() + public static abstract interface IBar { + + @kotlin.Metadata() + @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) + public static abstract @interface Anno { + + public abstract java.lang.Class[] value(); + } + + @kotlin.Metadata() + @test.IFoo.IBar.Anno(value = {test.IFoo.IBar.IZoo.class}) + public static abstract interface IZoo { + } + } +} + +//////////////////// + +package test; + +@kotlin.Metadata() +@test.IFoo.IBar.Anno(value = {test.IFoo.IBar.IZoo.class, test.Foo.Bar.class}) +public final class Test1 extends test.Foo.Bar implements test.IFoo.IBar, test.IFoo.IBar.IZoo { + @org.jetbrains.annotations.NotNull() + private final test.Foo.Bar.Zoo zoo = null; + + @org.jetbrains.annotations.NotNull() + public final java.lang.Thread.State a() { + return null; + } + + public final void b(@org.jetbrains.annotations.NotNull() + test.JavaClass.Foo foo, @org.jetbrains.annotations.NotNull() + test.JavaClass.Foo.Bar bar) { + } + + @org.jetbrains.annotations.NotNull() + public final test.Foo.Bar.Zoo getZoo() { + return null; + } + + public Test1(@org.jetbrains.annotations.NotNull() + test.Foo.Bar.Zoo zoo) { + super(); + } +}