[Test] Reproduce crash when plugin generates top-level private suspend

...function.

^KT-61993
This commit is contained in:
Roman Efremov
2024-02-27 10:35:12 +01:00
committed by Space Team
parent bba39dd4fe
commit b2a2d32d70
8 changed files with 115 additions and 0 deletions
@@ -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
@@ -30,6 +30,7 @@ class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() {
// Declaration generators
+::TopLevelDeclarationsGenerator
+::TopLevelPrivateSuspendFunctionGenerator
+::ExternalClassGenerator
+::AdditionalMembersGenerator
+::CompanionGenerator
@@ -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<FirNamedFunctionSymbol>()
.map { it.callableId.packageName }
.toSet()
}
override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List<FirNamedFunctionSymbol> {
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<CallableId> {
return matchedPackageNames.map { CallableId(it, TEST_FUN_NAME) }.toSet()
}
object Key : GeneratedDeclarationKey()
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
register(PREDICATE)
}
}
@@ -17,6 +17,7 @@ class GeneratedDeclarationsIrBodyFiller : IrGenerationExtension {
TransformerForCompanionGenerator(pluginContext),
TransformerForAdditionalMembersGenerator(pluginContext),
TransformerForTopLevelDeclarationsGenerator(pluginContext),
TransformerForTopLevelPrivateSuspendFunctionsGenerator(pluginContext),
AllPropertiesConstructorIrGenerator(pluginContext),
TransformerForAddingAnnotations(pluginContext),
ComposableFunctionsTransformer(pluginContext),
@@ -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")
}
}
@@ -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|
@@ -0,0 +1,5 @@
// This test currently fails!
package foo
@org.jetbrains.kotlin.fir.plugin.TestTopLevelPrivateSuspendFun
fun box(): String = "OK"
@@ -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");
}
}