diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt index 811dbf68956..12da444c9ab 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.backend +import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.ir.declarations.* @@ -53,4 +54,14 @@ class Fir2IrCommonMemberStorage( val fakeOverridesInClass: MutableMap> = mutableMapOf() val irForFirSessionDependantDeclarationMap: MutableMap = mutableMapOf() + + fun registerFirProvider(moduleData: FirModuleData, firProvider: FirProviderWithGeneratedFiles) { + require(moduleData !in _previousFirProviders) { "FirProvider for $moduleData already registered"} + _previousFirProviders[moduleData] = firProvider + } + + val previousFirProviders: Map + get() = _previousFirProviders + + private val _previousFirProviders: MutableMap = mutableMapOf() } 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 5992973a68a..6ba7a1e6005 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 @@ -32,7 +32,11 @@ class Fir2IrComponentsStorage( specialSymbolProvider: Fir2IrSpecialSymbolProvider, initializedIrBuiltIns: IrBuiltInsOverFir? ) : Fir2IrComponents { - override val firProvider: FirProviderWithGeneratedFiles = FirProviderWithGeneratedFiles(session) + override val firProvider: FirProviderWithGeneratedFiles = FirProviderWithGeneratedFiles( + session, + commonMemberStorage.previousFirProviders + ) + override val signatureComposer: FirBasedSignatureComposer = commonMemberStorage.firSignatureComposer override val symbolTable: SymbolTable = commonMemberStorage.symbolTable 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 ab5bf82e10f..ce5547d7dd2 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 @@ -743,6 +743,8 @@ class Fir2IrConverter( components.fir2IrVisitor ) + commonMemberStorage.registerFirProvider(session.moduleData, components.firProvider) + return Fir2IrResult(irModuleFragment, components, moduleDescriptor) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirProviderWithGeneratedFiles.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirProviderWithGeneratedFiles.kt index 73033e2374e..339cfadcc12 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirProviderWithGeneratedFiles.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirProviderWithGeneratedFiles.kt @@ -5,9 +5,11 @@ package org.jetbrains.kotlin.fir.backend +import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider @@ -20,10 +22,14 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -class FirProviderWithGeneratedFiles(val session: FirSession) : FirProvider() { +class FirProviderWithGeneratedFiles(val session: FirSession, previousProviders: Map) : FirProvider() { private val generatedFilesProvider = FirProviderImpl(session, session.kotlinScopeProvider) - private val providers: List = listOf(session.firProvider, generatedFilesProvider) + private val providers: List = buildList { + add(session.firProvider) + add(generatedFilesProvider) + session.moduleData.dependsOnDependencies.mapNotNullTo(this) { previousProviders[it] } + } override val symbolProvider: FirSymbolProvider get() = providers.first().symbolProvider 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 d74e4f867d7..5afa326d737 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 @@ -42,6 +42,7 @@ annotation class AllPropertiesConstructor annotation class AddAnnotations +@Retention(AnnotationRetention.RUNTIME) annotation class AnnotationToAdd( val booleanValue: Boolean, val byteValue: Byte, diff --git a/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.fir.txt b/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.fir.txt new file mode 100644 index 00000000000..32e579a44fa --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.fir.txt @@ -0,0 +1,100 @@ +Module: common +FILE: module_common_annotationsGeneratedInBackend_mpp.kt + package test + + @R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() public final class Some : R|kotlin/Any| { + public constructor(): R|test/Some| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } +FILE: module_platform_annotationsGeneratedInBackend_mpp.kt + package test + + @R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() public final class Other : R|kotlin/Any| { + public constructor(): R|test/Other| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } + public final fun checkClass(klass: R|kotlin/reflect/KClass<*>|): R|kotlin/Boolean| { + lval foo: R|kotlin/reflect/KFunction<*>| = R|/klass|.R|kotlin/reflect/full/declaredFunctions|.R|kotlin/collections/first||>( = first@fun (it: R|kotlin/reflect/KFunction<*>|): R|kotlin/Boolean| { + ^ ==(R|/it|.R|SubstitutionOverride|, String(foo)) + } + ) + ^checkClass R|/foo|.R|kotlin/reflect/KAnnotatedElement.annotations|.R|kotlin/collections/any|( = any@fun (it: R|kotlin/Annotation|): R|kotlin/Boolean| { + ^ ==(R|/it|.R|kotlin/jvm/annotationClass|.R|SubstitutionOverride|, String(AnnotationToAdd)) + } + ) + } + public final fun box(): R|kotlin/String| { + when () { + R|test/checkClass|((Q|test/Some|)).R|kotlin/Boolean.not|() -> { + ^box String(Fail: Some) + } + } + + when () { + R|test/checkClass|((Q|test/Other|)).R|kotlin/Boolean.not|() -> { + ^box String(Fail: Other) + } + } + + ^box String(OK) + } +Module: platform +FILE: module_common_annotationsGeneratedInBackend_mpp.kt + package test + + @R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() public final class Some : R|kotlin/Any| { + public constructor(): R|test/Some| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } +FILE: module_platform_annotationsGeneratedInBackend_mpp.kt + package test + + @R|org/jetbrains/kotlin/fir/plugin/AddAnnotations|() public final class Other : R|kotlin/Any| { + public constructor(): R|test/Other| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } + public final fun checkClass(klass: R|kotlin/reflect/KClass<*>|): R|kotlin/Boolean| { + lval foo: R|kotlin/reflect/KFunction<*>| = R|/klass|.R|kotlin/reflect/full/declaredFunctions|.R|kotlin/collections/first||>( = first@fun (it: R|kotlin/reflect/KFunction<*>|): R|kotlin/Boolean| { + ^ ==(R|/it|.R|SubstitutionOverride|, String(foo)) + } + ) + ^checkClass R|/foo|.R|kotlin/reflect/KAnnotatedElement.annotations|.R|kotlin/collections/any|( = any@fun (it: R|kotlin/Annotation|): R|kotlin/Boolean| { + ^ ==(R|/it|.R|kotlin/jvm/annotationClass|.R|SubstitutionOverride|, String(AnnotationToAdd)) + } + ) + } + public final fun box(): R|kotlin/String| { + when () { + R|test/checkClass|((Q|test/Some|)).R|kotlin/Boolean.not|() -> { + ^box String(Fail: Some) + } + } + + when () { + R|test/checkClass|((Q|test/Other|)).R|kotlin/Boolean.not|() -> { + ^box String(Fail: Other) + } + } + + ^box String(OK) + } diff --git a/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.kt b/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.kt new file mode 100644 index 00000000000..fe3f2a4a23f --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.kt @@ -0,0 +1,39 @@ +// LANGUAGE: +MultiPlatformProjects +// TARGET_BACKEND: JVM_IR +// WITH_REFLECT +// WITH_STDLIB + +// MODULE: common +package test + +import org.jetbrains.kotlin.fir.plugin.AddAnnotations +import kotlin.reflect.KClass + +@AddAnnotations +class Some { + fun foo() {} +} + +// MODULE: platform()()(common) +package test + +import org.jetbrains.kotlin.fir.plugin.AddAnnotations +import kotlin.reflect.KAnnotatedElement +import kotlin.reflect.KClass +import kotlin.reflect.full.declaredFunctions + +@AddAnnotations +class Other { + fun foo() {} +} + +fun checkClass(klass: KClass<*>): Boolean { + val foo = klass.declaredFunctions.first { it.name == "foo" } + return foo.annotations.any { it.annotationClass.simpleName == "AnnotationToAdd" } +} + +fun box(): String { + if (!checkClass(Some::class)) return "Fail: Some" + if (!checkClass(Other::class)) return "Fail: Other" + return "OK" +} diff --git a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java index c1fd8799c27..05e0757bd4c 100644 --- a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java +++ b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java @@ -25,6 +25,12 @@ public class FirLightTreePluginBlackBoxCodegenTestGenerated extends AbstractFirL KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/fir-plugin-prototype/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("annotationsGeneratedInBackend_mpp.kt") + public void testAnnotationsGeneratedInBackend_mpp() throws Exception { + runTest("plugins/fir-plugin-prototype/testData/box/annotationsGeneratedInBackend_mpp.kt"); + } + @Test @TestMetadata("builtins.kt") public void testBuiltins() throws Exception { diff --git a/plugins/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/services/PluginAnnotationsProvider.kt b/plugins/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/services/PluginAnnotationsProvider.kt index 5e31b3df0d3..ed4c5f5610a 100644 --- a/plugins/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/services/PluginAnnotationsProvider.kt +++ b/plugins/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/services/PluginAnnotationsProvider.kt @@ -37,9 +37,11 @@ class PluginAnnotationsProvider(testServices: TestServices) : EnvironmentConfigu class PluginRuntimeAnnotationsProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) { override fun runtimeClassPaths(module: TestModule): List { - if (!module.targetPlatform.isJs()) return emptyList() - val jar = findJsLib() - return listOf(jar) + return when { + module.targetPlatform.isJvm() -> listOf(findJvmLib()) + module.targetPlatform.isJs() -> listOf(findJsLib()) + else -> emptyList() + } } }