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 5afa326d737..f7e48def319 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 @@ -11,6 +11,9 @@ annotation class AllOpen annotation class AllOpen2 annotation class DummyFunction + +@Target(AnnotationTarget.FUNCTION) +annotation class TestTopLevelPrivateSuspendFun annotation class ExternalClassWithNested annotation class NestedClassAndMaterializeMember annotation class MyInterfaceSupertype diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt index 924ada8c344..fc0fa2f4916 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt @@ -30,6 +30,7 @@ class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() { // Declaration generators +::TopLevelDeclarationsGenerator + +::TopLevelPrivateSuspendFunctionGenerator +::ExternalClassGenerator +::AdditionalMembersGenerator +::CompanionGenerator diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/TopLevelPrivateSuspendFunctionGenerator.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/TopLevelPrivateSuspendFunctionGenerator.kt new file mode 100644 index 00000000000..621515a3062 --- /dev/null +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/TopLevelPrivateSuspendFunctionGenerator.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.plugin.generators + +import org.jetbrains.kotlin.GeneratedDeclarationKey +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension +import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar +import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext +import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate +import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider +import org.jetbrains.kotlin.fir.plugin.createTopLevelFunction +import org.jetbrains.kotlin.fir.plugin.fqn +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.Name + +/* + * Generates `private suspend fun testFun_generated() {}` function + * for each package containing function annotated with `org.jetbrains.kotlin.fir.plugin.TestTopLevelPrivateSuspendFun`. + */ +internal class TopLevelPrivateSuspendFunctionGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { + private companion object { + private val PREDICATE = LookupPredicate.create { annotated("TestTopLevelPrivateSuspendFun".fqn()) } + private val TEST_FUN_NAME = Name.identifier("testFun_generated") + } + + private val predicateBasedProvider = session.predicateBasedProvider + private val matchedPackageNames by lazy { + // This could be done more elegantly if TestTopLevelPrivateSuspendFun was file-level annotation, + // but it's currently not possible to find all annotated files using FirPredicateBasedProvider (see KT-66151). + predicateBasedProvider.getSymbolsByPredicate(PREDICATE) + .filterIsInstance() + .map { it.callableId.packageName } + .toSet() + } + + override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List { + if (context != null) return emptyList() + if (callableId.callableName != TEST_FUN_NAME) return emptyList() + val function = createTopLevelFunction(Key, callableId, session.builtinTypes.unitType.type) { + visibility = Visibilities.Private + status { isSuspend = true } + } + return listOf(function.symbol) + } + + override fun getTopLevelCallableIds(): Set { + return matchedPackageNames.map { CallableId(it, TEST_FUN_NAME) }.toSet() + } + + object Key : GeneratedDeclarationKey() + + override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(PREDICATE) + } +} diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt index aa7c413f4bb..8342d915a5e 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt @@ -17,6 +17,7 @@ class GeneratedDeclarationsIrBodyFiller : IrGenerationExtension { TransformerForCompanionGenerator(pluginContext), TransformerForAdditionalMembersGenerator(pluginContext), TransformerForTopLevelDeclarationsGenerator(pluginContext), + TransformerForTopLevelPrivateSuspendFunctionsGenerator(pluginContext), AllPropertiesConstructorIrGenerator(pluginContext), TransformerForAddingAnnotations(pluginContext), ComposableFunctionsTransformer(pluginContext), diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/TransformerForTopLevelPrivateSuspendFunctionsGenerator.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/TransformerForTopLevelPrivateSuspendFunctionsGenerator.kt new file mode 100644 index 00000000000..8cdbe739847 --- /dev/null +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/TransformerForTopLevelPrivateSuspendFunctionsGenerator.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.plugin + +import org.jetbrains.kotlin.GeneratedDeclarationKey +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.fir.plugin.generators.TopLevelPrivateSuspendFunctionGenerator +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrBody + +internal class TransformerForTopLevelPrivateSuspendFunctionsGenerator(context: IrPluginContext) : AbstractTransformerForGenerator(context, visitBodies = false) { + override fun interestedIn(key: GeneratedDeclarationKey?): Boolean { + return key == TopLevelPrivateSuspendFunctionGenerator.Key + } + + override fun generateBodyForFunction(function: IrSimpleFunction, key: GeneratedDeclarationKey?): IrBody { + return irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) + } + + override fun generateBodyForConstructor(constructor: IrConstructor, key: GeneratedDeclarationKey?): IrBody? { + error("Should not be called") + } +} diff --git a/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.fir.txt b/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.fir.txt new file mode 100644 index 00000000000..b28bd92fdac --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.fir.txt @@ -0,0 +1,10 @@ +FILE: topLevelPrivateSuspendFun.kt + package foo + + @R|org/jetbrains/kotlin/fir/plugin/TestTopLevelPrivateSuspendFun|() public final fun box(): R|kotlin/String| { + ^box String(OK) + } +FILE: __GENERATED DECLARATIONS__.kt + package foo + + private final suspend fun testFun_generated(): R|kotlin/Unit| diff --git a/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.kt b/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.kt new file mode 100644 index 00000000000..8499e361b47 --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.kt @@ -0,0 +1,5 @@ +// This test currently fails! +package foo + +@org.jetbrains.kotlin.fir.plugin.TestTopLevelPrivateSuspendFun +fun box(): String = "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 5bca50ac7fe..598b9e67729 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 @@ -143,4 +143,10 @@ public class FirLightTreePluginBlackBoxCodegenTestGenerated extends AbstractFirL public void testTopLevelCallables() { runTest("plugins/fir-plugin-prototype/testData/box/topLevelCallables.kt"); } + + @Test + @TestMetadata("topLevelPrivateSuspendFun.kt") + public void testTopLevelPrivateSuspendFun() { + runTest("plugins/fir-plugin-prototype/testData/box/topLevelPrivateSuspendFun.kt"); + } }