From 5a1a23afacb3f1a3e78d053f9c762d75a204f1b7 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Fri, 27 Oct 2023 15:21:42 +0300 Subject: [PATCH] [FIR] Don't miss annotations on inits ^KT-59874 --- .../fir/transformers/LLFirTypeLazyResolver.kt | 7 +- .../lazyResolve/initWithAnnotation.kt | 17 + .../lazyResolve/initWithAnnotation.txt | 323 ++++++++++++++++++ ...otLazyDeclarationResolveTestGenerated.java | 6 + ...ceLazyDeclarationResolveTestGenerated.java | 6 + .../LightTreeRawFirDeclarationBuilder.kt | 3 + .../kotlin/fir/builder/PsiRawFirBuilder.kt | 1 + .../transformers/FirTypeResolveTransformer.kt | 6 + .../FirAnnotationArgumentsTransformer.kt | 1 + .../builder/FirAnonymousInitializerBuilder.kt | 6 +- .../impl/FirAnonymousInitializerImpl.kt | 13 +- .../kotlin/fir/renderer/FirRenderer.kt | 1 + .../generator/ImplementationConfigurator.kt | 4 +- .../tests/annotations/onInitializer.fir.kt | 8 +- .../annotations/options/targets/init.fir.kt | 6 - .../tests/annotations/options/targets/init.kt | 1 + .../tests/modifiers/IllegalModifiers.fir.kt | 4 +- 17 files changed, 390 insertions(+), 23 deletions(-) create mode 100644 analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt create mode 100644 analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.txt delete mode 100644 compiler/testData/diagnostics/tests/annotations/options/targets/init.fir.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt index 20d9a758c0f..222f5e5490b 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt @@ -112,9 +112,10 @@ private class LLFirTypeTargetResolver( is FirTypeAlias, is FirScript, is FirRegularClass, + is FirAnonymousInitializer, -> rawResolve(target) - is FirFile, is FirAnonymousInitializer, is FirCodeFragment -> {} + is FirFile, is FirCodeFragment -> {} else -> errorWithAttachment("Unknown declaration ${target::class.simpleName}") { withFirEntry("declaration", target) } @@ -150,7 +151,9 @@ private class LLFirTypeTargetResolver( target.accept(transformer, null) } is FirScript -> resolveScriptTypes(target) - is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirCallableDeclaration, is FirTypeAlias -> { + is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirCallableDeclaration, is FirTypeAlias, + is FirAnonymousInitializer, + -> { target.accept(transformer, null) } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt b/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt new file mode 100644 index 00000000000..116196a0d46 --- /dev/null +++ b/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt @@ -0,0 +1,17 @@ +package low + +@Target(AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) +annotation class Anno(val position: String) + +const val constant = 0 + +class MyClass { + @Anno("init annotation: $constant") init { + @Anno("annotation inside") + funInsideInit() + } +} + +fun anotherFun(): String = "str" +fun funInsideInit() = anotherFun() \ No newline at end of file diff --git a/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.txt b/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.txt new file mode 100644 index 00000000000..8125a6c6c67 --- /dev/null +++ b/analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.txt @@ -0,0 +1,323 @@ +RAW_FIR: +FILE: [ResolvedTo(RAW_FIR)] initWithAnnotation.kt + @Target[Unresolved](LAZY_EXPRESSION) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(RAW_FIR)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(RAW_FIR)] @Anno[Unresolved](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +IMPORTS: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @Target[Unresolved](LAZY_EXPRESSION) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(RAW_FIR)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(RAW_FIR)] @Anno[Unresolved](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @Target[Unresolved](LAZY_EXPRESSION) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(RAW_FIR)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] @Anno[Unresolved](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +COMPANION_GENERATION: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @Target[Unresolved](LAZY_EXPRESSION) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(RAW_FIR)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(COMPANION_GENERATION)] @Anno[Unresolved](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +SUPER_TYPES: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @Target[Unresolved](LAZY_EXPRESSION) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(RAW_FIR)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(SUPER_TYPES)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(SUPER_TYPES)] @Anno[Unresolved](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +TYPES: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public? final? [ResolvedTo(TYPES)] class MyClass : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(TYPES)] @R|low/Anno|[Types](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +STATUS: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(STATUS)] @R|low/Anno|[Types](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +EXPECT_ACTUAL_MATCHING: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(EXPECT_ACTUAL_MATCHING)] @R|low/Anno|[Types](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +CONTRACTS: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(CONTRACTS)] @R|low/Anno|[Types](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[CompilerRequiredAnnotations](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @Retention[Unresolved](LAZY_EXPRESSION) public? final? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] annotation class Anno : R|kotlin/Annotation| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] constructor([ResolvedTo(RAW_FIR)] [CorrespondingProperty=low/Anno.position] position: String): R|low/Anno| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] [IsFromPrimaryConstructor=true] val position: String = R|/position| + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Anno] get(): String + + } + public? final? const [ResolvedTo(RAW_FIR)] val constant: = LAZY_EXPRESSION + public? [ResolvedTo(RAW_FIR)] get(): + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] @R|low/Anno|[Types](LAZY_EXPRESSION) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +ANNOTATION_ARGUMENTS: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @R|kotlin/annotation/Retention|[Types](LAZY_EXPRESSION) public final [ResolvedTo(STATUS)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=low/Anno.position] position: R|kotlin/String|): R|low/Anno| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val position: R|kotlin/String| = R|/position| + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val constant: R|kotlin/Int| = Int(0) + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] get(): R|kotlin/Int| + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(ANNOTATION_ARGUMENTS)] @R|low/Anno|[Types](position = (String(init annotation: ), R|low/constant|)) init { LAZY_BLOCK } + + } + public? final? [ResolvedTo(RAW_FIR)] fun anotherFun(): String { LAZY_BLOCK } + public? final? [ResolvedTo(RAW_FIR)] fun funInsideInit(): { LAZY_BLOCK } + +BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[Types](Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|) @R|kotlin/annotation/Retention|[Types](LAZY_EXPRESSION) public final [ResolvedTo(STATUS)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=low/Anno.position] position: R|kotlin/String|): R|low/Anno| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [IsFromPrimaryConstructor=true] val position: R|kotlin/String| = R|/position| + public [ResolvedTo(STATUS)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } + public final const [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] val constant: R|kotlin/Int| = Int(0) + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] get(): R|kotlin/Int| + public final [ResolvedTo(STATUS)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + LAZY_super + } + + [ResolvedTo(BODY_RESOLVE)] @R|low/Anno|[Types](position = (String(init annotation: ), R|low/constant|)) init { + @R|low/Anno|[Types](position = String(annotation inside)) R|low/funInsideInit|() + } + + } + public final [ResolvedTo(CONTRACTS)] fun anotherFun(): R|kotlin/String| { + ^anotherFun String(str) + } + public final [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] fun funInsideInit(): R|kotlin/String| { + ^funInsideInit R|low/anotherFun|() + } + +FILE RAW TO BODY: +FILE: [ResolvedTo(BODY_RESOLVE)] initWithAnnotation.kt + @R|kotlin/annotation/Target|[Types](allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.EXPRESSION|)) @R|kotlin/annotation/Retention|[Types](value = Q|kotlin/annotation/AnnotationRetention|.R|kotlin/annotation/AnnotationRetention.SOURCE|) public final [ResolvedTo(BODY_RESOLVE)] annotation class Anno : R|kotlin/Annotation| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Anno] constructor([ResolvedTo(BODY_RESOLVE)] [CorrespondingProperty=low/Anno.position] position: R|kotlin/String|): R|low/Anno| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] [IsFromPrimaryConstructor=true] val position: R|kotlin/String| = R|/position| + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Anno] get(): R|kotlin/String| + + } + public final const [ResolvedTo(BODY_RESOLVE)] val constant: R|kotlin/Int| = Int(0) + public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| + public final [ResolvedTo(BODY_RESOLVE)] class MyClass : R|kotlin/Any| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor(): R|low/MyClass| { + super() + } + + [ResolvedTo(BODY_RESOLVE)] @R|low/Anno|[Types](position = (String(init annotation: ), R|low/constant|)) init { + @R|low/Anno|[Types](position = String(annotation inside)) R|low/funInsideInit|() + } + + } + public final [ResolvedTo(BODY_RESOLVE)] fun anotherFun(): R|kotlin/String| { + ^anotherFun String(str) + } + public final [ResolvedTo(BODY_RESOLVE)] fun funInsideInit(): R|kotlin/String| { + ^funInsideInit R|low/anotherFun|() + } 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 e402995ce27..ab5d543765e 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 @@ -342,6 +342,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst runTest("analysis/low-level-api-fir/testData/lazyResolve/implicitTypeWithInaccessibleAnnotation.kt"); } + @Test + @TestMetadata("initWithAnnotation.kt") + public void testInitWithAnnotation() throws Exception { + runTest("analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt"); + } + @Test @TestMetadata("lambdaAsSAMInterface.kt") public void testLambdaAsSAMInterface() 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 c01688cdc72..1c2671fc686 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 @@ -342,6 +342,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou runTest("analysis/low-level-api-fir/testData/lazyResolve/implicitTypeWithInaccessibleAnnotation.kt"); } + @Test + @TestMetadata("initWithAnnotation.kt") + public void testInitWithAnnotation() throws Exception { + runTest("analysis/low-level-api-fir/testData/lazyResolve/initWithAnnotation.kt"); + } + @Test @TestMetadata("lambdaAsSAMInterface.kt") public void testLambdaAsSAMInterface() throws Exception { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt index c68503f50ad..c35c13bf7ce 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt @@ -1004,8 +1004,10 @@ class LightTreeRawFirDeclarationBuilder( */ private fun convertAnonymousInitializer(anonymousInitializer: LighterASTNode): FirDeclaration { var firBlock: FirBlock? = null + var modifiers = Modifier() anonymousInitializer.forEachChildren { when (it.tokenType) { + MODIFIER_LIST -> modifiers = convertModifierList(it, isInClass = true) BLOCK -> withForcedLocalContext { firBlock = convertBlock(it) } @@ -1018,6 +1020,7 @@ class LightTreeRawFirDeclarationBuilder( origin = FirDeclarationOrigin.Source body = firBlock ?: buildEmptyExpressionBlock() dispatchReceiverType = context.dispatchReceiverTypesStack.lastOrNull() + annotations += modifiers.annotations } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index 1aad2802f8c..9181684dc1a 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -2110,6 +2110,7 @@ open class PsiRawFirBuilder( } } dispatchReceiverType = context.dispatchReceiverTypesStack.lastOrNull() + initializer.extractAnnotationsTo(this) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index b0394c852d8..d44e5d39620 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -164,6 +164,12 @@ open class FirTypeResolveTransformer( } } + override fun transformAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): FirAnonymousInitializer { + return withScopeCleanup { + transformDeclaration(anonymousInitializer, data) as FirAnonymousInitializer + } + } + override fun transformErrorPrimaryConstructor(errorPrimaryConstructor: FirErrorPrimaryConstructor, data: Any?) = transformConstructor(errorPrimaryConstructor, data) 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 cfecd100d54..70cdc2c27bb 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 @@ -207,6 +207,7 @@ private class FirDeclarationsResolveTransformerForAnnotationArguments( anonymousInitializer: FirAnonymousInitializer, data: ResolutionMode ): FirAnonymousInitializer { + anonymousInitializer.transformAnnotations(this, ResolutionMode.ContextIndependent) return anonymousInitializer } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousInitializerBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousInitializerBuilder.kt index d097a78e386..9bde022de1d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousInitializerBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirAnonymousInitializerBuilder.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirBuilderDsl +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.declarations.FirAnonymousInitializer import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType class FirAnonymousInitializerBuilder : FirDeclarationBuilder, FirAnnotationContainerBuilder { override var source: KtSourceElement? = null override var resolvePhase: FirResolvePhase = FirResolvePhase.RAW_FIR + override val annotations: MutableList = mutableListOf() override lateinit var moduleData: FirModuleData override lateinit var origin: FirDeclarationOrigin override var attributes: FirDeclarationAttributes = FirDeclarationAttributes() @@ -40,6 +42,7 @@ class FirAnonymousInitializerBuilder : FirDeclarationBuilder, FirAnnotationConta return FirAnonymousInitializerImpl( source, resolvePhase, + annotations.toMutableOrEmpty(), moduleData, origin, attributes, @@ -49,9 +52,6 @@ class FirAnonymousInitializerBuilder : FirDeclarationBuilder, FirAnnotationConta ) } - - @Deprecated("Modification of 'annotations' has no impact for FirAnonymousInitializerBuilder", level = DeprecationLevel.HIDDEN) - override val annotations: MutableList = mutableListOf() } @OptIn(ExperimentalContracts::class) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousInitializerImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousInitializerImpl.kt index 63c3c5f114b..0b564294a29 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousInitializerImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirAnonymousInitializerImpl.kt @@ -12,6 +12,8 @@ package org.jetbrains.kotlin.fir.declarations.impl import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.MutableOrEmptyList +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirBlock @@ -20,11 +22,13 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor +import org.jetbrains.kotlin.fir.visitors.transformInplace @OptIn(ResolveStateAccess::class) internal class FirAnonymousInitializerImpl( override val source: KtSourceElement?, resolvePhase: FirResolvePhase, + override var annotations: MutableOrEmptyList, override val moduleData: FirModuleData, override val origin: FirDeclarationOrigin, override val attributes: FirDeclarationAttributes, @@ -32,8 +36,6 @@ internal class FirAnonymousInitializerImpl( override val symbol: FirAnonymousInitializerSymbol, override val dispatchReceiverType: ConeClassLikeType?, ) : FirAnonymousInitializer() { - override val annotations: List - get() = emptyList() override var controlFlowGraphReference: FirControlFlowGraphReference? = null init { @@ -42,21 +44,26 @@ internal class FirAnonymousInitializerImpl( } override fun acceptChildren(visitor: FirVisitor, data: D) { + annotations.forEach { it.accept(visitor, data) } controlFlowGraphReference?.accept(visitor, data) body?.accept(visitor, data) } override fun transformChildren(transformer: FirTransformer, data: D): FirAnonymousInitializerImpl { + transformAnnotations(transformer, data) controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data) body = body?.transform(transformer, data) return this } override fun transformAnnotations(transformer: FirTransformer, data: D): FirAnonymousInitializerImpl { + annotations.transformInplace(transformer, data) return this } - override fun replaceAnnotations(newAnnotations: List) {} + override fun replaceAnnotations(newAnnotations: List) { + annotations = newAnnotations.toMutableOrEmpty() + } override fun replaceControlFlowGraphReference(newControlFlowGraphReference: FirControlFlowGraphReference?) { controlFlowGraphReference = newControlFlowGraphReference diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index 3418d064430..4748f94413b 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -479,6 +479,7 @@ class FirRenderer( override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer) { resolvePhaseRenderer?.render(anonymousInitializer) + annotationRenderer?.render(anonymousInitializer) print("init") bodyRenderer?.renderBody(anonymousInitializer.body) } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index ac1a5319aff..5d23e97de0e 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -43,9 +43,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() defaultFalse("hasLazyNestedClassifiers", withGetter = true) } - impl(anonymousInitializer) { - defaultEmptyList("annotations") - } + impl(anonymousInitializer) impl(anonymousObject) impl(danglingModifierList) diff --git a/compiler/testData/diagnostics/tests/annotations/onInitializer.fir.kt b/compiler/testData/diagnostics/tests/annotations/onInitializer.fir.kt index ae9955da41e..e1b7d94c08d 100644 --- a/compiler/testData/diagnostics/tests/annotations/onInitializer.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/onInitializer.fir.kt @@ -1,11 +1,11 @@ class A { - @ann init {} - @aaa init {} + @ann init {} + @aaa init {} } interface T { - @ann init {} - @aaa init {} + @ann init {} + @aaa init {} } annotation class ann diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/init.fir.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/init.fir.kt deleted file mode 100644 index b69a5251d59..00000000000 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/init.fir.kt +++ /dev/null @@ -1,6 +0,0 @@ -annotation class base - -@base class My { - @base init { - } -} diff --git a/compiler/testData/diagnostics/tests/annotations/options/targets/init.kt b/compiler/testData/diagnostics/tests/annotations/options/targets/init.kt index a213d178a1d..a7f5e77e81f 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/targets/init.kt +++ b/compiler/testData/diagnostics/tests/annotations/options/targets/init.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL annotation class base @base class My { diff --git a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt index d04f1568309..6714467839f 100644 --- a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt @@ -85,9 +85,9 @@ abstract class IllegalModifiers6() { open init {} final init {} - public @annotated init {} + public @annotated init {} - private @IllegalModifiers6() init {} + private @IllegalModifiers6() init {} } // strange inappropriate modifiers usages