From 71f48ede53b0f4efd446299ad12f619ff17c23cf Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Wed, 5 Apr 2023 17:53:45 +0200 Subject: [PATCH] [LL FIR] resolve compiler required annotations correctly Original AbstractFirSpecificAnnotationResolveTransformer can jump to other classes and resolve them outside our transformers, so it leads to problems with locks and lazy bodies ^KT-56543 --- .../LLFirCompilerAnnotationsLazyResolver.kt | 34 +- .../classes/annotationWithTarget.kt | 4 + .../classes/annotationWithTarget.txt | 308 ++++++++++++++++++ ...otLazyDeclarationResolveTestGenerated.java | 6 + ...ceLazyDeclarationResolveTestGenerated.java | 6 + ...FirSpecificAnnotationResolveTransformer.kt | 13 +- ...erRequiredAnnotationsResolveTransformer.kt | 22 +- 7 files changed, 377 insertions(+), 16 deletions(-) create mode 100644 analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt create mode 100644 analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.txt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt index 212a89a10f9..107cb898851 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt @@ -5,10 +5,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater +import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirSession @@ -16,10 +19,13 @@ import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirTypeAlias +import org.jetbrains.kotlin.fir.declarations.resolvePhase import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) { override fun resolve( @@ -44,15 +50,37 @@ internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirReso } } - private class LLFirCompilerRequiredAnnotationsTargetResolver( target: LLFirResolveTarget, lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, + computationSession: LLFirCompilerRequiredAnnotationsComputationSession? = null, ) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS, isJumpingPhase = true) { - private val transformer = - FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession, CompilerRequiredAnnotationsComputationSession()) + inner class LLFirCompilerRequiredAnnotationsComputationSession : CompilerRequiredAnnotationsComputationSession() { + override fun resolveAnnotationSymbol(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) { + val regularClass = symbol.fir + if (regularClass.resolvePhase >= resolverPhase) return + + symbol.lazyResolveToPhase(resolverPhase.previous) + val designation = regularClass.collectDesignationWithFile().asResolveTarget() + val resolver = LLFirCompilerRequiredAnnotationsTargetResolver( + designation, + lockProvider, + designation.target.llFirSession, + scopeSession, + this, + ) + + resolver.resolveDesignation() + } + } + + private val transformer = FirCompilerRequiredAnnotationsResolveTransformer( + session, + scopeSession, + computationSession ?: LLFirCompilerRequiredAnnotationsComputationSession(), + ) override fun withFile(firFile: FirFile, action: () -> Unit) { transformer.annotationTransformer.withFileAndFileScopes(firFile) { diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt b/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt new file mode 100644 index 00000000000..bdbb5e01f2b --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt @@ -0,0 +1,4 @@ +@Target(AnnotationTarget.CLASS) @Anno("string") +annotation class ResolveMe(val value: Int) + +annotation class Anno(val s: String) \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.txt b/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.txt new file mode 100644 index 00000000000..5ba3c1e9ab0 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.txt @@ -0,0 +1,308 @@ + +RAW_FIR: +FILE: [ResolvedTo(RAW_FIR)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @Target[Unresolved](LAZY_EXPRESSION) @Anno[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +IMPORTS: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @Target[Unresolved](LAZY_EXPRESSION) @Anno[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @Anno[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +COMPANION_GENERATION: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @Anno[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPANION_GENERATION)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +SUPER_TYPES: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @Anno[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(SUPER_TYPES)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +TYPES: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](LAZY_EXPRESSION) public? final? [ResolvedTo(TYPES)] annotation class ResolveMe : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/ResolveMe.value] value: Int): R|ResolveMe| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=ResolveMe] get(): Int + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +STATUS: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](LAZY_EXPRESSION) public final [ResolvedTo(STATUS)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +EXPECT_ACTUAL_MATCHING: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](LAZY_EXPRESSION) public final [ResolvedTo(EXPECT_ACTUAL_MATCHING)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +ARGUMENTS_OF_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](String(string)) public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +CONTRACTS: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](String(string)) public final [ResolvedTo(CONTRACTS)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|) @R|Anno|[Types](String(string)) public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=/Anno.s] s: String): R|Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val s: String = R|/s| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + +ANNOTATIONS_ARGUMENTS_MAPPING: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|)) @R|Anno|[Types](s = String(string)) public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(STATUS)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public final [ResolvedTo(STATUS)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/Anno.s] s: R|kotlin/String|): R|Anno| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val s: R|kotlin/String| = R|/s| + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } + +BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(RAW_FIR)] annotations container + @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|)) @R|Anno|[Types](s = String(string)) public final [ResolvedTo(BODY_RESOLVE)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(BODY_RESOLVE)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public final [ResolvedTo(STATUS)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/Anno.s] s: R|kotlin/String|): R|Anno| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val s: R|kotlin/String| = R|/s| + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } + +FILE RAW TO BODY: +FILE: [ResolvedTo(IMPORTS)] annotationWithTarget.kt + [ResolvedTo(BODY_RESOLVE)] annotations container + @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS|)) @R|Anno|[Types](s = String(string)) public final [ResolvedTo(BODY_RESOLVE)] annotation class ResolveMe : R|kotlin/Annotation| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=ResolveMe] constructor([ResolvedTo(BODY_RESOLVE)] [CorrespondingProperty=/ResolveMe.value] value: R|kotlin/Int|): R|ResolveMe| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=ResolveMe] get(): R|kotlin/Int| + + } + public final [ResolvedTo(BODY_RESOLVE)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Anno] constructor([ResolvedTo(BODY_RESOLVE)] [CorrespondingProperty=/Anno.s] s: R|kotlin/String|): R|Anno| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] [IsFromPrimaryConstructor=true] val s: R|kotlin/String| = R|/s| + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java index 9d282d27971..4fe76974eff 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java @@ -165,6 +165,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/lazyResolve/classes"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("annotationWithTarget.kt") + public void testAnnotationWithTarget() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt"); + } + @Test @TestMetadata("classWithTypeParameters.kt") public void testClassWithTypeParameters() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java index fe63154fec9..1eab277df55 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java @@ -165,6 +165,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/lazyResolve/classes"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @Test + @TestMetadata("annotationWithTarget.kt") + public void testAnnotationWithTarget() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/classes/annotationWithTarget.kt"); + } + @Test @TestMetadata("classWithTypeParameters.kt") public void testClassWithTypeParameters() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt index 11d5de094c5..4707f2a7ed2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/AbstractFirSpecificAnnotationResolveTransformer.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.transformers.DesignationState import org.jetbrains.kotlin.fir.resolve.transformers.FirSpecificTypeResolverTransformer import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher @@ -39,7 +38,6 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer -import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -242,16 +240,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer( private fun resolveAnnotationsOnAnnotationIfNeeded(annotationTypeRef: FirResolvedTypeRef) { val symbol = annotationTypeRef.coneType.toRegularClassSymbol(session) ?: return - val regularClass = symbol.fir - if (computationSession.annotationsAreResolved(regularClass)) return - val designation = DesignationState.create(symbol, emptyMap(), includeFile = true) ?: return - val transformer = FirDesignatedCompilerRequiredAnnotationsResolveTransformer( - designation.firstDeclaration.moduleData.session, - scopeSession, - computationSession, - designation - ) - designation.firstDeclaration.transformSingle(transformer, null) + computationSession.resolveAnnotationsOnAnnotationIfNeeded(symbol, scopeSession) } override fun transformAnnotation(annotation: FirAnnotation, data: Nothing?): FirStatement { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt index 61dc7af20c7..4d2168d33cc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.DesignationState import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping import org.jetbrains.kotlin.name.FqName @@ -127,7 +128,7 @@ class FirDesignatedCompilerRequiredAnnotationsResolveTransformer( FirDesignatedSpecificAnnotationResolveTransformer(session, scopeSession, computationSession, designation) } -class CompilerRequiredAnnotationsComputationSession { +open class CompilerRequiredAnnotationsComputationSession { private val filesWithResolvedImports = mutableSetOf() fun importsAreResolved(file: FirFile): Boolean { @@ -153,6 +154,25 @@ class CompilerRequiredAnnotationsComputationSession { error("Annotations are resolved twice") } } + + fun resolveAnnotationsOnAnnotationIfNeeded(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) { + val regularClass = symbol.fir + if (annotationsAreResolved(regularClass)) return + + resolveAnnotationSymbol(symbol, scopeSession) + } + + open fun resolveAnnotationSymbol(symbol: FirRegularClassSymbol, scopeSession: ScopeSession) { + val designation = DesignationState.create(symbol, emptyMap(), includeFile = true) ?: return + val transformer = FirDesignatedCompilerRequiredAnnotationsResolveTransformer( + designation.firstDeclaration.moduleData.session, + scopeSession, + this, + designation, + ) + + designation.firstDeclaration.transformSingle(transformer, null) + } } private class FirPartialImportResolveTransformer(