diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleFirPluginPrototypeMultiModuleCompilerFacilityTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleFirPluginPrototypeMultiModuleCompilerFacilityTestGenerated.java index ce2326e2cfc2f..3f23c3422d9aa 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleFirPluginPrototypeMultiModuleCompilerFacilityTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleFirPluginPrototypeMultiModuleCompilerFacilityTestGenerated.java @@ -45,6 +45,18 @@ public void testAllFilesPresentInFirPluginPrototypeMultiModule() { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule"), Pattern.compile("^(.+)\\.(kt)$"), null, true); } + @Test + @TestMetadata("annotationForFunctionOutOfCodeGenTarget.kt") + public void testAnnotationForFunctionOutOfCodeGenTarget() { + runTest("analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.kt"); + } + + @Test + @TestMetadata("annotationForFunctionOutOfCodeGenTarget2.kt") + public void testAnnotationForFunctionOutOfCodeGenTarget2() { + runTest("analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.kt"); + } + @Test @TestMetadata("composableFunctionMultiModules.kt") public void testComposableFunctionMultiModules() { diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt index 7966b0e399b9d..377444464bc3e 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBase import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.backend.jvm.ir.parentClassId import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.codegen.BytecodeListingTextCollectingVisitor @@ -27,10 +28,24 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.plugin.services.PluginRuntimeAnnotationsProvider +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.psi.KtCodeFragment +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.test.Constructor import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.directives.ConfigurationDirectives @@ -38,7 +53,10 @@ import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirective import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer import org.jetbrains.kotlin.test.model.TestModule -import org.jetbrains.kotlin.test.services.* +import org.jetbrains.kotlin.test.services.EnvironmentConfigurator +import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type @@ -75,7 +93,8 @@ abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedTest() { override fun doTestByMainFile(mainFile: KtFile, mainModule: TestModule, testServices: TestServices) { val testFile = mainModule.files.single { it.name == mainFile.name } - val irCollector = CollectingIrGenerationExtension() + val annotationToCheckCalls = mainModule.directives[Directives.CHECK_CALLS_WITH_ANNOTATION].singleOrNull() + val irCollector = CollectingIrGenerationExtension(annotationToCheckCalls) val project = mainFile.project project.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName) @@ -109,6 +128,12 @@ abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedTest() { if (result is KtCompilationResult.Success) { testServices.assertions.assertEqualsToTestDataFileSibling(irCollector.result, extension = ".ir.txt") } + + if (annotationToCheckCalls != null) { + testServices.assertions.assertEqualsToTestDataFileSibling( + irCollector.functionsWithAnnotationToCheckCalls.joinToString("\n"), extension = ".check_calls.txt" + ) + } } } @@ -187,6 +212,10 @@ abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedTest() { val ATTACH_DUPLICATE_STDLIB by directive( "Attach the 'stdlib-jvm-minimal-for-test' library to simulate duplicate stdlib dependency" ) + + val CHECK_CALLS_WITH_ANNOTATION by stringDirective( + "Check whether all functions of calls and getters of properties with a given annotation are listed in *.check_calls.txt or not" + ) } } @@ -220,10 +249,12 @@ internal fun createCodeFragment(ktFile: KtFile, module: TestModule, testServices } } -private class CollectingIrGenerationExtension : IrGenerationExtension { +private class CollectingIrGenerationExtension(private val annotationToCheckCalls: String?) : IrGenerationExtension { lateinit var result: String private set + val functionsWithAnnotationToCheckCalls: MutableSet = mutableSetOf() + override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { assertFalse { ::result.isInitialized } @@ -235,5 +266,49 @@ private class CollectingIrGenerationExtension : IrGenerationExtension { ) result = moduleFragment.dump(dumpOptions) + + annotationToCheckCalls?.let { annotationFqName -> + moduleFragment.accept( + CheckCallsWithAnnotationVisitor(annotationFqName) { functionsWithAnnotationToCheckCalls.add(it.name.asString()) }, null + ) + } + } + + /** + * This class recursively visits all calls of functions and getters, and if the function or the getter used for a call has + * an annotation whose FqName is [annotationFqName], it runs [handleFunctionWithAnnotation] for the function or the getter. + */ + private class CheckCallsWithAnnotationVisitor( + private val annotationFqName: String, + private val handleFunctionWithAnnotation: (declaration: IrDeclarationWithName) -> Unit, + ) : IrElementVisitorVoid { + val annotationClassId by lazy { + val annotationFqNameUnsafe = FqNameUnsafe(annotationFqName) + ClassId(FqName(annotationFqNameUnsafe.parent()), FqName(annotationFqNameUnsafe.shortName().asString()), false) + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitCall(expression: IrCall) { + @OptIn(UnsafeDuringIrConstructionAPI::class) + val function = expression.symbol.owner + if (function.containsAnnotationToCheckCalls()) { + handleFunctionWithAnnotation(function) + } + } + + override fun visitFieldAccess(expression: IrFieldAccessExpression) { + @OptIn(UnsafeDuringIrConstructionAPI::class) + val field = expression.symbol.owner + if (field.containsAnnotationToCheckCalls()) { + handleFunctionWithAnnotation(field) + } + } + + private fun IrAnnotationContainer.containsAnnotationToCheckCalls() = + @OptIn(UnsafeDuringIrConstructionAPI::class) + annotations.any { it.symbol.owner.parentClassId == annotationClassId } } } \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.check_calls.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.check_calls.txt new file mode 100644 index 0000000000000..0e31315b8b649 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.check_calls.txt @@ -0,0 +1 @@ +BookmarkButton \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.ir.txt new file mode 100644 index 0000000000000..85d5c3270761f --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.ir.txt @@ -0,0 +1,12 @@ +MODULE_FRAGMENT + FILE fqName: fileName:main.kt + FUN name:PostCardSimple visibility:public modality:FINAL <> (navigateToArticle:kotlin.Function1, isFavorite:kotlin.Boolean, onToggleFavorite:kotlin.Function0) returnType:kotlin.Unit + annotations: + MyComposable + VALUE_PARAMETER name:navigateToArticle index:0 type:kotlin.Function1 + VALUE_PARAMETER name:isFavorite index:1 type:kotlin.Boolean + VALUE_PARAMETER name:onToggleFavorite index:2 type:kotlin.Function0 + BLOCK_BODY + CALL 'public final fun BookmarkButton (isBookmarked: kotlin.Boolean, onClick: kotlin.Function0): kotlin.Unit declared in p3.JetnewsIconsKt' type=kotlin.Unit origin=null + isBookmarked: GET_VAR 'isFavorite: kotlin.Boolean declared in .PostCardSimple' type=kotlin.Boolean origin=null + onClick: GET_VAR 'onToggleFavorite: kotlin.Function0 declared in .PostCardSimple' type=kotlin.Function0 origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.kt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.kt new file mode 100644 index 0000000000000..421f100a9aaa2 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.kt @@ -0,0 +1,31 @@ +// WITH_FIR_TEST_COMPILER_PLUGIN +// DUMP_IR +// CHECK_CALLS_WITH_ANNOTATION: org.jetbrains.kotlin.fir.plugin.MyComposable + +// MODULE: main +// FILE: main.kt +import org.jetbrains.kotlin.fir.plugin.MyComposable +import p3.BookmarkButton + +@MyComposable +fun PostCardSimple( + navigateToArticle: (String) -> Unit, + isFavorite: Boolean, + onToggleFavorite: () -> Unit +) { + BookmarkButton( + isBookmarked = isFavorite, + onClick = onToggleFavorite, + ) +} +// FILE: utils/JetnewsIcons.kt +package p3 + +import org.jetbrains.kotlin.fir.plugin.MyComposable + +@MyComposable +fun BookmarkButton( + isBookmarked: Boolean, + onClick: () -> Unit, +) { +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.txt new file mode 100644 index 0000000000000..f615d5aa82af3 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget.txt @@ -0,0 +1,4 @@ +public final class MainKt { + // source: 'main.kt' + public final static method PostCardSimple(p0: kotlin.jvm.functions.Function1, p1: boolean, p2: kotlin.jvm.functions.Function0): void +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.check_calls.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.check_calls.txt new file mode 100644 index 0000000000000..4cb07ae1e4a25 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.check_calls.txt @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.ir.txt new file mode 100644 index 0000000000000..aa60684711630 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.ir.txt @@ -0,0 +1,11 @@ +MODULE_FRAGMENT + FILE fqName: fileName:main.kt + FUN name:Greeting visibility:public modality:FINAL <> () returnType:kotlin.String + annotations: + MyComposable + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun Greeting (): kotlin.String declared in ' + STRING_CONCATENATION type=kotlin.String + CONST String type=kotlin.String value="Hi " + CALL 'public final fun (): kotlin.Int declared in p3.FooKt' type=kotlin.Int origin=GET_PROPERTY + CONST String type=kotlin.String value="!" diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.kt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.kt new file mode 100644 index 0000000000000..3cbc1ca87d9f5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.kt @@ -0,0 +1,27 @@ +// WITH_FIR_TEST_COMPILER_PLUGIN +// DUMP_IR +// CHECK_CALLS_WITH_ANNOTATION: org.jetbrains.kotlin.fir.plugin.MyComposable + +// MODULE: main +// FILE: main.kt +import org.jetbrains.kotlin.fir.plugin.MyComposable +import p3.foo + +@MyComposable +fun Greeting(): String { + return "Hi $foo!" +} + +// FILE: p3/foo.kt +package p3 + +import org.jetbrains.kotlin.fir.plugin.MyComposable + +private var foo_ = 0 + +fun setFoo(newFoo: Int) { + foo_ = newFoo +} + +val foo: Int + @MyComposable get() = foo_ + 1 \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.txt b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.txt new file mode 100644 index 0000000000000..0641507005971 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/firPluginPrototypeMultiModule/annotationForFunctionOutOfCodeGenTarget2.txt @@ -0,0 +1,4 @@ +public final class MainKt { + // source: 'main.kt' + public final static method Greeting(): java.lang.String +} diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt index 3ac07d82a87c3..dd50b26274158 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.generators.* +import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.ir.IrLock @@ -62,6 +63,24 @@ interface Fir2IrComponents { val annotationsFromPluginRegistrar: Fir2IrIrGeneratedDeclarationsRegistrar + /** + * A set of FIR files serving as input for the fir2ir ([Fir2IrConverter.createIrModuleFragment] function) for conversion to IR. + * + * We set annotations for IR objects, such as IrFunction, in two scenarios: + * 1. For FIR declared in library or precompiled: when creating IR object from FIR + * 2. For FIR declared in a source module: when filling contents of IR object in Fir2IrVisitor + * + * Since Fir2IrVisitor will recursively visit all FIR objects and generate IR objects for them, we handle the first scenario + * above as a corner case. + * + * However, when we use CodeGen analysis API, even FIRs declared in the source module can be out of the compile target files, + * because we can run the CodeGen only for a few files of the source module. We use [filesBeingCompiled] for that case + * to determine whether a given FIR is declared in a source file to be compiled or not for the CodeGen API. If it is not + * declared in a file to be compiled (i.e., target of CodeGen), we have to set annotations for IR when creating its IR like + * the first scenario above. We set [filesBeingCompiled] as `null` if we do not use the CodeGen analysis API. + */ + val filesBeingCompiled: Set? + interface Manglers { val irMangler: KotlinMangler.IrMangler val firMangler: FirMangler diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt index bf6df9d12bef5..9162549099432 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.generators.* +import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer @@ -25,6 +26,7 @@ class Fir2IrComponentsStorage( override val extensions: Fir2IrExtensions, override val configuration: Fir2IrConfiguration, override val visibilityConverter: Fir2IrVisibilityConverter, + override val filesBeingCompiled: Set?, irFakeOverrideBuilderProvider: (IrBuiltIns) -> IrFakeOverrideBuilder, moduleDescriptor: FirModuleDescriptor, commonMemberStorage: Fir2IrCommonMemberStorage, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 767a48abdadf9..d57e796126872 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -60,6 +60,7 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.utils.addToStdlib.runIf class Fir2IrConverter( private val moduleDescriptor: FirModuleDescriptor, @@ -727,7 +728,13 @@ class Fir2IrConverter( session.lazyDeclarationResolver.disableLazyResolveContractChecks() val moduleDescriptor = FirModuleDescriptor.createSourceModuleDescriptor(session, kotlinBuiltIns) val components = Fir2IrComponentsStorage( - session, scopeSession, irFactory, fir2IrExtensions, fir2IrConfiguration, visibilityConverter, + session, + scopeSession, + irFactory, + fir2IrExtensions, + fir2IrConfiguration, + visibilityConverter, + runIf(fir2IrConfiguration.allowNonCachedDeclarations) { firFiles.toSet() }, { irBuiltins -> IrFakeOverrideBuilder( typeContextProvider(irBuiltins), @@ -738,7 +745,11 @@ class Fir2IrConverter( fir2IrExtensions.externalOverridabilityConditions ) }, - moduleDescriptor, commonMemberStorage, irMangler, specialSymbolProvider, initializedIrBuiltIns + moduleDescriptor, + commonMemberStorage, + irMangler, + specialSymbolProvider, + initializedIrBuiltIns ) fir2IrExtensions.registerDeclarations(commonMemberStorage.symbolTable) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt index 32a1bad982a5d..31e802edd8f7a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.backend.generators -import com.intellij.openapi.progress.ProcessCanceledException import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.* @@ -26,6 +25,8 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke +import org.jetbrains.kotlin.fir.resolve.providers.firProvider +import org.jetbrains.kotlin.fir.resolve.providers.getContainingFile import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase @@ -965,10 +966,18 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi ) { if ((firAnnotationContainer as? FirDeclaration)?.let { it.isFromLibrary || it.isPrecompiled } == true || origin == IrDeclarationOrigin.FAKE_OVERRIDE + // When `firAnnotationContainer` is not in a compile target file, we will not fill contents for + // this annotation container later. Therefore, we have to set its annotations here. + || firAnnotationContainer.isDeclaredInFilesBeingCompiled() ) { annotationGenerator.generate(this, firAnnotationContainer) } } + + private fun FirAnnotationContainer.isDeclaredInFilesBeingCompiled(): Boolean { + if (filesBeingCompiled == null || this !is FirDeclaration) return false + return moduleData.session.firProvider.getContainingFile(symbol) !in filesBeingCompiled + } } internal fun IrDeclaration.setParent(irParent: IrDeclarationParent?) { diff --git a/plugins/fir-plugin-prototype/plugin-annotations/src/commonMain/kotlin/org/jetbrains/kotlin/fir/plugin/annotations.kt b/plugins/fir-plugin-prototype/plugin-annotations/src/commonMain/kotlin/org/jetbrains/kotlin/fir/plugin/annotations.kt index f7e48def319ac..66552ef392de2 100644 --- a/plugins/fir-plugin-prototype/plugin-annotations/src/commonMain/kotlin/org/jetbrains/kotlin/fir/plugin/annotations.kt +++ b/plugins/fir-plugin-prototype/plugin-annotations/src/commonMain/kotlin/org/jetbrains/kotlin/fir/plugin/annotations.kt @@ -38,7 +38,7 @@ annotation class SupertypeWithTypeArgument(val kClass: KClass<*>) annotation class MetaSupertype -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.PROPERTY_GETTER) annotation class MyComposable annotation class AllPropertiesConstructor