KT-26540: Support generated superclasses in KAPT

https://youtrack.jetbrains.net/issue/KT-26540

Included an integration test that relies on a generated superclass.
This commit is contained in:
Martin Petrov
2018-09-03 22:28:14 -04:00
committed by Yan Zhulanow
parent f147b8d2b2
commit dfff00d55f
5 changed files with 71 additions and 3 deletions
@@ -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
}
}
@@ -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
@@ -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))
@@ -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 {
}
@@ -0,0 +1,7 @@
package test
internal annotation class MyAnnotation
@MyAnnotation
internal class ClassWithParent: FooBar() {
}