From 06811dfc2ff9616be9d01cad7ed29caa9aef56e7 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Fri, 24 Nov 2023 14:49:46 +0100 Subject: [PATCH] [FIR] Add enum entry to body resolve context containers This fixes processing of annotations on enum entries. Before, the check in BodyResolveContext.forAnnotation would set the tower data mode to CLASS_HEADER_ANNOTATIONS because no containers were present. This would lead to some tower data elements like nested classifiers missing, which would lead to false positive unresolved references. #KT-63761 Fixed --- .../level/api/fir/util/ContextCollector.kt | 2 +- .../body/resolve/BodyResolveContext.kt | 7 +++-- .../FirDeclarationsResolveTransformer.kt | 2 +- .../FirAnnotationArgumentsTransformer.kt | 2 +- .../nestedClassAsAnnotationParameter.kt | 30 +++++++++++++++++-- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt index eb726bdd07b..dfef5358dc4 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt @@ -441,7 +441,7 @@ private class ContextCollectorVisitor( onActiveBody { enumEntry.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) - context.forEnumEntry { + context.withEnumEntry(enumEntry) { dumpContext(enumEntry, ContextKind.BODY) onActive { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index 37c8323049f..4089ca7ef71 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -770,9 +770,12 @@ class BodyResolveContext( } @OptIn(PrivateForInline::class) - inline fun forEnumEntry( + inline fun withEnumEntry( + enumEntry: FirEnumEntry, f: () -> T - ): T = withTowerDataMode(FirTowerDataMode.ENUM_ENTRY, f) + ): T = withTowerDataMode(FirTowerDataMode.ENUM_ENTRY) { + withContainer(enumEntry, f) + } @OptIn(PrivateForInline::class) inline fun forAnnotation( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index ad96b3ea3d3..699a0d2b6df 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -106,7 +106,7 @@ open class FirDeclarationsResolveTransformer( override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry { if (implicitTypeOnly || enumEntry.initializerResolved) return enumEntry - return context.forEnumEntry { + return context.withEnumEntry(enumEntry) { (enumEntry.transformChildren(this, data) as FirEnumEntry) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsTransformer.kt index 931c5c20b6a..e361fb56eb3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsTransformer.kt @@ -294,7 +294,7 @@ private class FirDeclarationsResolveTransformerForAnnotationArguments( } override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry { - context.forEnumEntry { + context.withEnumEntry(enumEntry) { enumEntry .transformAnnotations(transformer, data) .transformReceiverParameter(transformer, data) diff --git a/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.kt b/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.kt index ac0cbae3566..402fb02514b 100644 --- a/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.kt +++ b/compiler/testData/diagnostics/tests/annotations/nestedClassAsAnnotationParameter.kt @@ -1,12 +1,38 @@ // FIR_IDENTICAL import kotlin.reflect.KClass -@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE) +@Target( + AnnotationTarget.CLASS, + AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.TYPE, + AnnotationTarget.PROPERTY, + AnnotationTarget.FUNCTION, + AnnotationTarget.CONSTRUCTOR +) annotation class Special(val why: KClass<*>) interface Interface -class Outer { +class Outer @Special(Nested::class) constructor( + @Special(Nested::class) + val why: KClass<*> +) { @Special(Nested::class) class Nested<@Special(Nested::class) T> : @Special(Nested::class) Interface + + @Special(Nested::class) + val why2: KClass<*>? = null + + @Special(Nested::class) + fun why3() {} } + +enum class E( + @Special(Nested::class) + val why: KClass<*> +) { + @Special(Nested::class) + Foo(Nested::class); + + class Nested +} \ No newline at end of file