Kapt: Do not use awkward ('$' -> '/') logic for KAPT3 class builder mode
So (for the most often reproduction case) #KT-19433 Fixed Before this commit, internal names for nested classes were written as test/Foo/Bar (comparing to test/Foo$Bar in the normal mode), as getting qualified names from such internal names was trivial. But, because of IC, we needed to write class files to the disk, so our decompiler could find such "broken" classes and read it in a wrong way.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
e5e5b56af0
commit
57d209f599
@@ -99,20 +99,6 @@ public class KotlinTypeMapper {
|
||||
private final boolean isJvm8TargetWithDefaults;
|
||||
|
||||
private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
|
||||
private final Function2<String, String, String> defaultClassNameFactory
|
||||
= TypeMappingConfiguration.Companion.getDEFAULT_INNER_CLASS_NAME_FACTORY();
|
||||
|
||||
private final Function2<String, String, String> innerClassNameFactory = new Function2<String, String, String>() {
|
||||
@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<KotlinType> types) {
|
||||
@@ -122,7 +108,7 @@ public class KotlinTypeMapper {
|
||||
@NotNull
|
||||
@Override
|
||||
public Function2<String, String, String> getInnerClassNameFactory() {
|
||||
return innerClassNameFactory;
|
||||
return TypeMappingConfiguration.DefaultImpls.getInnerClassNameFactory(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+32
-32
@@ -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 <init>(): 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 <init>(): 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 <init>(): 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 <init>(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 <init>(): 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 <init>(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 <init>(): 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
|
||||
}
|
||||
|
||||
+7
-7
@@ -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
|
||||
|
||||
+2
-2
@@ -47,8 +47,8 @@ private fun <T : Any> JvmTypeFactory<T>.boxTypeIfNeeded(possiblyPrimitiveType: T
|
||||
if (needBoxedType) boxType(possiblyPrimitiveType) else possiblyPrimitiveType
|
||||
|
||||
interface TypeMappingConfiguration<out T : Any> {
|
||||
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
|
||||
|
||||
@@ -186,7 +186,7 @@ abstract class AbstractKapt3Extension(
|
||||
|
||||
private fun generateStubs(project: Project, module: ModuleDescriptor, context: BindingContext, files: Collection<KtFile>): 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 ?: "<in memory ${it.hashCode()}>" } }
|
||||
@@ -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<GenerationState>) {
|
||||
|
||||
@@ -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<out GState : GenerationState?>(
|
||||
val logger: KaptLogger,
|
||||
val project: Project,
|
||||
val bindingContext: BindingContext,
|
||||
val compiledClasses: List<ClassNode>,
|
||||
val origins: Map<Any, JvmDeclarationOrigin>,
|
||||
@@ -50,7 +52,7 @@ class KaptContext<out GState : GenerationState?>(
|
||||
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
|
||||
|
||||
@@ -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<TreeMaker>(::KaptTreeMaker))
|
||||
internal fun preRegister(context: Context, kaptContext: KaptContext<*>) {
|
||||
context.put(treeMakerKey, Context.Factory<TreeMaker> { KaptTreeMaker(it, kaptContext) })
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-9
@@ -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
|
||||
|
||||
@@ -203,7 +203,7 @@ class SignatureParser(val treeMaker: KaptTreeMaker) {
|
||||
val innerClasses = mutableListOf<SignatureNode>()
|
||||
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) {
|
||||
|
||||
@@ -74,7 +74,7 @@ private fun convertUserType(type: KtUserType, converter: ClassFileToSourceStubCo
|
||||
// This could be List<SomeErrorType> 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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+12
@@ -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");
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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") })
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
+192
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user