```class MyCompilerPluginRegistrar: CompilerPlugin...
# compiler
m
Copy code
class MyCompilerPluginRegistrar: CompilerPluginRegistrar() {
    override val pluginId = BuildConfig.KOTLIN_PLUGIN_ID
    override val supportsK2 = true
    override fun ExtensionStorage.registerExtensions(
        configuration: CompilerConfiguration,
    ) {
        FirExtensionRegistrarAdapter.registerExtension(MyFirExtensionRegistrar())
        IrGenerationExtension.registerExtension(MyIrGenerationExtension())
    }
}
I’m working on my first plugin. I’ve implemented the FIR layer to generate a companion method in every annotated class. I’ve been told to give it a body in the IR layer.
Copy code
class MyIrGenerationExtension: IrGenerationExtension {
    override fun generate(
        moduleFragment: IrModuleFragment,
        pluginContext: IrPluginContext,
    ) {
        moduleFragment.transformChildrenVoid(
            MyIrElementTransformerVoid(pluginContext)
        )
    }
}

private class MyIrElementTransformerVoid(
    private val pluginContext: IrPluginContext,
): IrElementTransformerVoid() {
    override fun visitSimpleFunction(
        declaration: IrSimpleFunction,
    ): IrStatement {
        val annotatedConstructor = declaration.takeIf(IrSimpleFunction::isGeneratedCompanionMethod)
            ?.parentAsClass // `companion object`
            ?.parentAsClass // `class`
            ?.primaryConstructor
            ?: return declaration
        declaration.body = DeclarationIrBuilder(pluginContext, declaration.symbol)
        return declaration
    }
}

private fun IrSimpleFunction.isGeneratedCompanionMethod(): Boolean {
    return this.origin == KEY.origin
        && this.name == COMPANION_METHOD_TO_GENERATE
}
The
declaration
, if it’s a generated companion method, should have the same signature as the
annotatedConstructor
. I want it to relay every argument to and the return value from the constructor.
Copy code
val annotatedConstructor = declaration.takeIf(IrSimpleFunction::isGeneratedCompanionMethod)
            .coalesce { return declaration } // `?: return declaration`
            .parentAsClass // `companion object`
            .parentAsClass // `class`
            .primaryConstructor!!
Can I assert the above in the IR, since my FIR would have reported an error diagnostic if it was missing? Also can somebody please point me to a worked example of constructing the
declaration.body
?
y
Feel free to throw errors and such in IR. One of the easiest things you can do is write out the method body in actual Kotlin code, then mimic the IR it turns to
❤️ 1
m
@Youssef Shoaib [MOD] How can I see the IR for a function?
y
If you have the internal testing framework set up, then you can get IR dumps pretty easily. Otherwise, you can add it to some code you're compiling, and then debug your plugin and inspect that method in the debugger (probably a bit more accurate since it shows you the exact structure that your plugin receives and thus the structure it's meant to generate)
m
I don’t think I have it set up, but I’ll go try to figure out how to do both on my own! I’m new to Kotlin and to plugin development, so I have no idea about anything. I needed somebody to point me in the right direction, so I appreciate your advice a lot.
y
If you've used the compiler plugin template, then you already have the dumps set up. If not, then worst case scenario you can just
error(someIr.dump())
(
dump
is an extension function I believe, so your IDE should offer to import it once you type that in)
❤️ 1
m
Yes I cloned the template, and I have an IR dump now. Thank you!