All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.jensklingenberg.ktorfit.CreateFuncTransformer.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-2.1.0
Show newest version
package de.jensklingenberg.ktorfit

import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name

/**
 * Transform exampleKtorfit.create() to exampleKtorfit.create(_TestApiImpl())
 */
class CreateFuncTransformer(
    private val pluginContext: IrPluginContext,
    private val debugLogger: DebugLogger
) :
    IrElementTransformerVoidWithContext() {

    override fun visitExpression(expression: IrExpression): IrExpression {

        //Find exampleKtorfit.create()
        (expression as? IrCall)?.let { irCall ->
            if (irCall.typeArgumentsCount > 0) {
                if (expression.symbol.owner.name.asString() != "create") {
                    return expression
                }

                if (!expression.symbol.owner.symbol.toString().contains("de.jensklingenberg.ktorfit.Ktorfit")) {
                    return expression
                }

                //Get T from create()
                val argumentType = irCall.getTypeArgument(0) ?: return expression

                if(argumentType.toIrBasedKotlinType().toString() == "T"){
                    return expression
                }

                val packaage = argumentType.classFqName?.asString()?.substringBeforeLast(".") ?: return expression
                val className = argumentType.classFqName?.asString()?.substringAfterLast(".") ?: ""

                //Find the class _TestApiImpl
                val implClassSymbol = pluginContext.referenceClass(
                    ClassId(
                        FqName(packaage),
                        Name.identifier("_$className" + "Impl")
                    )
                ) ?: throw NullPointerException("_$className" + "Impl not found, did you apply the Ksp Ktorfit plugin?")

                val newConstructor = implClassSymbol.constructors.first()

                //Create the constructor call for _ExampleApiImpl()
                val newCall = IrConstructorCallImpl(
                    0,
                    0,
                    type = implClassSymbol.defaultType,
                    symbol = newConstructor,
                    0,
                    0,
                    0,
                    null
                )

                //Set _ExampleApiImpl() as argument for create()
                irCall.putValueArgument(0, newCall)
                debugLogger.log("Transformed "+argumentType.toIrBasedKotlinType().toString()+" to _$className" + "Impl" )
                return super.visitExpression(irCall)
            }
        }
        return super.visitExpression(expression)
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy