diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index e02b844b8f3..d3fb0d4ec1c 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -390,11 +390,26 @@ class ClassFileToSourceStubConverter( modifiers, treeMaker.name(simpleName), genericType.typeParameters, - if (hasSuperClass) genericType.superClass else null, + if (hasSuperClass) genericType.superClass else getSuperType(descriptor as? ClassDescriptor), genericType.interfaces, enumValues + fields + methods + nestedClasses).keepKdocComments(clazz) } + private inline fun getSuperType(classDescriptor: ClassDescriptor?): JCExpression? { + if (!correctErrorTypes) { + return null + } + val ktClass = (classDescriptor?.source as? PsiSourceElement)?.psi as? KtClass + val superTypeCallEntry = + ktClass?.getSuperTypeList()?.entries?.mapNotNull { it as? KtSuperTypeCallEntry }?.first() + val typeFromSource = superTypeCallEntry?.typeReference?.typeElement + val ktFile = typeFromSource?.containingKtFile + if (ktFile != null) { + return ErrorTypeCorrector(this, SUPER_TYPE, ktFile).convert(typeFromSource, emptyMap()) + } + return null + } + private tailrec fun checkIfValidTypeName(containingClass: ClassNode, type: Type): Boolean { if (type.sort == Type.ARRAY) { return checkIfValidTypeName(containingClass, type.elementType) @@ -1034,4 +1049,4 @@ internal tailrec fun getReferenceExpression(expression: KtExpression?): KtRefere is KtReferenceExpression -> expression is KtQualifiedExpression -> getReferenceExpression(expression.selectorExpression) else -> null -} \ No newline at end of file +} diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt index 082b10c7435..7609501558c 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.kapt3.base.mapJList import org.jetbrains.kotlin.kapt3.base.mapJListIndexed import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.METHOD_PARAMETER_TYPE import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.RETURN_TYPE +import org.jetbrains.kotlin.kapt3.stubs.ErrorTypeCorrector.TypeKind.SUPER_TYPE import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext @@ -62,7 +63,7 @@ class ErrorTypeCorrector( } enum class TypeKind { - RETURN_TYPE, METHOD_PARAMETER_TYPE + RETURN_TYPE, METHOD_PARAMETER_TYPE, SUPER_TYPE } fun convert(type: KtTypeElement, substitutions: SubstitutionMap): JCTree.JCExpression { @@ -131,6 +132,7 @@ class ErrorTypeCorrector( //TODO figure out if the containing method is an annotation method RETURN_TYPE -> TypeMappingMode.getOptimalModeForReturnType(kotlinType, false) METHOD_PARAMETER_TYPE -> TypeMappingMode.getOptimalModeForValueParameter(kotlinType) + SUPER_TYPE -> TypeMappingMode.getOptimalModeForValueParameter(kotlinType) }.updateArgumentModeFromAnnotations(kotlinType) val typeParameters = (target as? ClassifierDescriptor)?.typeConstructor?.parameters diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt index 93d8ef88ff9..d7ab0123ca8 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/KotlinKapt3IntegrationTests.kt @@ -50,6 +50,20 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T assertEquals("myMethod", annotatedElements.single().simpleName.toString()) } + @Test + fun testSuperclass() = test("Superclass", "test.MyAnnotation") { set, roundEnv, env -> + if (set.size == 1) { + val annotatedElements = roundEnv.getElementsAnnotatedWith(set.single()) + assertEquals(1, annotatedElements.size) + val typeElement = annotatedElements.single() as TypeElement + assertEquals("FooBar", typeElement.superclass.toString()) + env.filer.createSourceFile("test.FooBar").openWriter().use { writer -> + writer.write("package test;") + writer.write("public class FooBar {}") + } + } + } + @Test fun testComments() = test("Simple", "test.MyAnnotation") { set, roundEnv, env -> fun commentOf(className: String) = env.elementUtils.getDocComment(env.elementUtils.getTypeElement(className)) diff --git a/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.it.txt b/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.it.txt new file mode 100644 index 00000000000..cd61087cea6 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.it.txt @@ -0,0 +1,30 @@ +package error; + +public final class NonExistentClass { +} + +//////////////////// + +package test; + +import java.lang.System; + +@kotlin.Metadata() +@MyAnnotation() +public final class ClassWithParent extends FooBar { + + public ClassWithParent() { + super(); + } +} + +//////////////////// + +package test; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface MyAnnotation { +} diff --git a/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.kt b/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.kt new file mode 100644 index 00000000000..5e39ff4c1e4 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/kotlinRunner/Superclass.kt @@ -0,0 +1,7 @@ +package test + +internal annotation class MyAnnotation + +@MyAnnotation +internal class ClassWithParent: FooBar() { +}