[KAPT] Correct error types in annotations (KT-32596)

This commit is contained in:
Steven Schäfer
2021-09-17 15:58:35 +02:00
committed by TeamCityServer
parent 701446ad25
commit 4f3debdec6
10 changed files with 112 additions and 16 deletions
@@ -40,8 +40,7 @@ import org.jetbrains.kotlin.kapt3.base.stubs.KotlinPosition
import org.jetbrains.kotlin.kapt3.base.util.TopLevelJava9Aware
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
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.*
import org.jetbrains.kotlin.kapt3.util.*
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
@@ -63,6 +62,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isError
@@ -1144,12 +1144,18 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
descriptorAnnotations: Annotations
): JCModifiers {
var seenOverride = false
val seenAnnotations = mutableSetOf<AnnotationDescriptor>()
fun convertAndAdd(list: JavacList<JCAnnotation>, annotation: AnnotationNode): JavacList<JCAnnotation> {
if (annotation.desc == "Ljava/lang/Override;") {
if (seenOverride) return list // KT-34569: skip duplicate @Override annotations
seenOverride = true
}
val annotationDescriptor = descriptorAnnotations.singleOrNull { checkIfAnnotationValueMatches(annotation, AnnotationValue(it)) }
// Missing annotation classes can match against multiple annotation descriptors
val annotationDescriptor = descriptorAnnotations.firstOrNull {
it !in seenAnnotations && checkIfAnnotationValueMatches(annotation, AnnotationValue(it))
}?.also {
seenAnnotations += it
}
val annotationTree = convertAnnotation(containingClass, annotation, packageFqName, annotationDescriptor) ?: return list
return list.prepend(annotationTree)
}
@@ -1188,19 +1194,26 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
if (stripMetadata && fqName == KOTLIN_METADATA_ANNOTATION) return null
}
val ktAnnotation = (annotationDescriptor?.source as? PsiSourceElement)?.psi as? KtAnnotationEntry
val ktAnnotation = annotationDescriptor?.source?.getPsi() as? KtAnnotationEntry
val annotationFqName = getNonErrorType(
annotationDescriptor?.type,
ANNOTATION,
{ ktAnnotation?.typeReference },
{
val useSimpleName = '.' in fqName && fqName.substringBeforeLast('.', "") == packageFqName
when {
useSimpleName -> treeMaker.FqName(fqName.substring(packageFqName!!.length + 1))
else -> treeMaker.Type(annotationType)
}
}
)
val argMapping = ktAnnotation?.calleeExpression
?.getResolvedCall(kaptContext.bindingContext)?.valueArguments
?.mapKeys { it.key.name.asString() }
?: emptyMap()
val useSimpleName = '.' in fqName && fqName.substringBeforeLast('.', "") == packageFqName
val annotationFqName = when {
useSimpleName -> treeMaker.FqName(fqName.substring(packageFqName!!.length + 1))
else -> treeMaker.Type(annotationType)
}
val constantValues = pairedListToMap(annotation.values)
val values = if (argMapping.isNotEmpty()) {
@@ -64,7 +64,7 @@ class ErrorTypeCorrector(
}
enum class TypeKind {
RETURN_TYPE, METHOD_PARAMETER_TYPE, SUPER_TYPE
RETURN_TYPE, METHOD_PARAMETER_TYPE, SUPER_TYPE, ANNOTATION
}
fun convert(type: KtTypeElement, substitutions: SubstitutionMap): JCTree.JCExpression {
@@ -147,6 +147,7 @@ class ErrorTypeCorrector(
RETURN_TYPE -> typeSystem.getOptimalModeForReturnType(kotlinType, false)
METHOD_PARAMETER_TYPE -> typeSystem.getOptimalModeForValueParameter(kotlinType)
SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
ANNOTATION -> TypeMappingMode.DEFAULT // see genAnnotation in org/jetbrains/kotlin/codegen/AnnotationCodegen.java
}.updateArgumentModeFromAnnotations(kotlinType, typeSystem)
val typeParameters = (target as? ClassifierDescriptor)?.typeConstructor?.parameters
@@ -354,6 +354,11 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt28306.kt");
}
@TestMetadata("kt32596.kt")
public void testKt32596() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt");
}
@TestMetadata("kt34569.kt")
public void testKt34569() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt34569.kt");
@@ -355,6 +355,11 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt28306.kt");
}
@TestMetadata("kt32596.kt")
public void testKt32596() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt32596.kt");
}
@TestMetadata("kt34569.kt")
public void testKt34569() throws Exception {
runTest("plugins/kapt3/kapt3-compiler/testData/converter/kt34569.kt");
@@ -0,0 +1,19 @@
// CORRECT_ERROR_TYPES
@file:Suppress("UNRESOLVED_REFERENCE", "ANNOTATION_ARGUMENT_MUST_BE_CONST")
import kotlin.reflect.KClass
@ABC
class ErrorMissingAnnotation
@ABC @CDE
class ErrorMultipleMissingAnnotations
@CDE @Anno(ABC::class) @ABC
class ErrorSomeMissingAnnotations
annotation class Anno(val klass: KClass<*>)
// EXPECTED_ERROR(kotlin:12:1) cannot find symbol
// EXPECTED_ERROR(kotlin:6:1) cannot find symbol
// EXPECTED_ERROR(kotlin:9:1) cannot find symbol
@@ -0,0 +1,53 @@
import kotlin.reflect.KClass;
@kotlin.Metadata()
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public abstract @interface Anno {
public abstract java.lang.Class<?> klass();
}
////////////////////
import kotlin.reflect.KClass;
@kotlin.Metadata()
@ABC()
public final class ErrorMissingAnnotation {
public ErrorMissingAnnotation() {
super();
}
}
////////////////////
import kotlin.reflect.KClass;
@kotlin.Metadata()
@CDE()
@ABC()
public final class ErrorMultipleMissingAnnotations {
public ErrorMultipleMissingAnnotations() {
super();
}
}
////////////////////
import kotlin.reflect.KClass;
@kotlin.Metadata()
@ABC()
@Anno(klass = ABC.class)
@CDE()
public final class ErrorSomeMissingAnnotations {
public ErrorSomeMissingAnnotations() {
super();
}
}
@@ -2,7 +2,7 @@
// NON_EXISTENT_CLASS
// NO_VALIDATION
@Suppress("UNRESOLVED_REFERENCE")
@Suppress("CANNOT_INFER_PARAMETER_TYPE", "UNRESOLVED_REFERENCE")
object NonExistentType {
val a: ABCDEF? = null
val b: List<ABCDEF>? = null
@@ -1,6 +1,6 @@
import java.lang.System;
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
@kotlin.Suppress(names = {"CANNOT_INFER_PARAMETER_TYPE", "UNRESOLVED_REFERENCE"})
@kotlin.Metadata()
public final class NonExistentType {
@org.jetbrains.annotations.NotNull()
@@ -1,7 +1,7 @@
// NON_EXISTENT_CLASS
// NO_VALIDATION
@file:Suppress("UNRESOLVED_REFERENCE")
@file:Suppress("CANNOT_INFER_PARAMETER_TYPE", "UNRESOLVED_REFERENCE")
typealias String2 = String
typealias Coocoo = ABC
@@ -1,6 +1,6 @@
import java.lang.System;
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
@kotlin.Suppress(names = {"CANNOT_INFER_PARAMETER_TYPE", "UNRESOLVED_REFERENCE"})
@kotlin.Metadata()
public final class NonExistentClassWIthoutCorrectionKt {
}