From c046bedfc259bcbfe4b43bbba80714f13f44c2fd Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Mon, 20 Mar 2023 15:05:30 +0100 Subject: [PATCH] [AA FIR] FirLazyAnnotationTransformer: fix resolve contract violation We can't reduce resolve to COMPILER_REQUIRED_ANNOTATIONS phase for annotations with arguments, because currently they don't have argument mapping ```stracktrace org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments: By now the annotations argument mapping should have been resolved at org.jetbrains.kotlin.analysis.api.fir.annotations.FirAnnotationUtilsKt.mapAnnotationParameters(firAnnotationUtils.kt:137) at org.jetbrains.kotlin.analysis.api.fir.FirUtilsKt.toKtAnnotationApplication(FirUtils.kt:79) at org.jetbrains.kotlin.analysis.api.fir.annotations.FirAnnotationUtilsKt.annotationsByClassId(firAnnotationUtils.kt:60) at org.jetbrains.kotlin.analysis.api.fir.annotations.FirAnnotationUtilsKt.annotationsByClassId$default(firAnnotationUtils.kt:46) ``` ^KT-57424 Fixed --- .../api/fir/annotations/firAnnotationUtils.kt | 24 +++++-------------- .../annotations/GranularAnnotationsBox.kt | 15 +++++++++--- .../annotationsEquality/Deprecated.java | 4 ++++ .../annotationsEquality/Deprecated.kt | 5 ++++ .../KotlinTargetFirst.java | 5 ++++ .../annotationsEquality/KotlinTargetFirst.kt | 5 ++++ ...otationEqualityForSourceTestGenerated.java | 12 ++++++++++ 7 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.java create mode 100644 analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.kt create mode 100644 analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.java create mode 100644 analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt index 04d656ce1dd..a857a8bdab6 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/annotations/firAnnotationUtils.kt @@ -49,27 +49,15 @@ internal fun annotationsByClassId( useSiteTargetFilter: AnnotationUseSiteTargetFilter, useSiteSession: FirSession, annotationContainer: FirAnnotationContainer = firSymbol.fir, -): List = - if (firSymbol.isFromCompilerRequiredAnnotationsPhase(classId)) { - buildList { - // this loop by index is required to avoid possible ConcurrentModificationException - val annotations = annotationContainer.resolvedCompilerRequiredAnnotations(firSymbol) - for (index in annotations.indices) { - val annotation = annotations[index] - if (useSiteTargetFilter.isAllowed(annotation.useSiteTarget) && annotation.toAnnotationClassIdSafe(useSiteSession) == classId) { - add(annotation.toKtAnnotationApplication(useSiteSession, index)) - } - } +): List { + return annotationContainer.resolvedAnnotationsWithArguments(firSymbol).mapIndexedNotNull { index, annotation -> + if (!useSiteTargetFilter.isAllowed(annotation.useSiteTarget) || annotation.toAnnotationClassId(useSiteSession) != classId) { + return@mapIndexedNotNull null } - } else { - annotationContainer.resolvedAnnotationsWithArguments(firSymbol).mapIndexedNotNull { index, annotation -> - if (!useSiteTargetFilter.isAllowed(annotation.useSiteTarget) || annotation.toAnnotationClassId(useSiteSession) != classId) { - return@mapIndexedNotNull null - } - annotation.toKtAnnotationApplication(useSiteSession, index) - } + annotation.toKtAnnotationApplication(useSiteSession, index) } +} internal fun annotations( firSymbol: FirBasedSymbol<*>, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/GranularAnnotationsBox.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/GranularAnnotationsBox.kt index 86b63430825..1eafdcfa242 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/GranularAnnotationsBox.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/GranularAnnotationsBox.kt @@ -55,7 +55,7 @@ internal class GranularAnnotationsBox( return annotations.find { it.qualifiedName == qualifiedName } } - specialAnnotationsList[qualifiedName]?.let { specialAnnotationClassId -> + specialAnnotationsListWithSafeArgumentsResolve[qualifiedName]?.let { specialAnnotationClassId -> val annotationApplication = annotationsProvider[specialAnnotationClassId].firstOrNull() ?: return null return SymbolLightLazyAnnotation(annotationsProvider, annotationApplication, owner) } @@ -89,6 +89,15 @@ internal class GranularAnnotationsBox( /* fieldName = */ "cachedAnnotations", ) + /** + * We can safety reduce resolve only for annotations without arguments + * + * @see org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper + */ + private val specialAnnotationsListWithSafeArgumentsResolve: Map = listOf( + StandardClassIds.Annotations.JvmRecord, + ).associateBy { it.asFqNameString() } + /** * @see org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsHelper */ @@ -96,7 +105,7 @@ internal class GranularAnnotationsBox( StandardClassIds.Annotations.Deprecated, StandardClassIds.Annotations.DeprecatedSinceKotlin, StandardClassIds.Annotations.WasExperimental, - StandardClassIds.Annotations.JvmRecord, - ).associateBy { it.asFqNameString() } + StandardClassIds.Annotations.Target, + ).associateBy { it.asFqNameString() } + specialAnnotationsListWithSafeArgumentsResolve } } diff --git a/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.java b/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.java new file mode 100644 index 00000000000..cb5daaa099c --- /dev/null +++ b/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.java @@ -0,0 +1,4 @@ +@kotlin.Deprecated(message = "", replaceWith = @ReplaceWith(expression = ""), level = kotlin.DeprecationLevel.ERROR) +public final class MyClass /* MyClass*/ { + public MyClass();// .ctor() +} diff --git a/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.kt b/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.kt new file mode 100644 index 00000000000..004e30df11c --- /dev/null +++ b/analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.kt @@ -0,0 +1,5 @@ +// PSI: org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassOrObject +// EXPECTED: kotlin.Deprecated + +@Deprecated("", ReplaceWith(""), level = DeprecationLevel.ERROR) +class MyClass diff --git a/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.java b/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.java new file mode 100644 index 00000000000..2c48d08151d --- /dev/null +++ b/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.java @@ -0,0 +1,5 @@ +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.PARAMETER}) +@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.VALUE_PARAMETER}) +public abstract @interface AnnotationClass /* AnnotationClass*/ { +} diff --git a/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.kt b/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.kt new file mode 100644 index 00000000000..479c75bcab8 --- /dev/null +++ b/analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.kt @@ -0,0 +1,5 @@ +// PSI: org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForAnnotationClass +// EXPECTED: kotlin.annotation.Target + +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class AnnotationClass diff --git a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesAnnotationEqualityForSourceTestGenerated.java b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesAnnotationEqualityForSourceTestGenerated.java index d227f8383b1..cc75aef35a0 100644 --- a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesAnnotationEqualityForSourceTestGenerated.java +++ b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesAnnotationEqualityForSourceTestGenerated.java @@ -24,6 +24,12 @@ public class SymbolLightClassesAnnotationEqualityForSourceTestGenerated extends KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/symbol-light-classes/testData/annotationsEquality"), Pattern.compile("^(.+)\\.(kt)$"), null, true); } + @Test + @TestMetadata("Deprecated.kt") + public void testDeprecated() throws Exception { + runTest("analysis/symbol-light-classes/testData/annotationsEquality/Deprecated.kt"); + } + @Test @TestMetadata("ExplicitRetension.kt") public void testExplicitRetension() throws Exception { @@ -48,6 +54,12 @@ public class SymbolLightClassesAnnotationEqualityForSourceTestGenerated extends runTest("analysis/symbol-light-classes/testData/annotationsEquality/JvmRepeatable.kt"); } + @Test + @TestMetadata("KotlinTargetFirst.kt") + public void testKotlinTargetFirst() throws Exception { + runTest("analysis/symbol-light-classes/testData/annotationsEquality/KotlinTargetFirst.kt"); + } + @Test @TestMetadata("OverrideMethod.kt") public void testOverrideMethod() throws Exception {