Coverage Summary for Class: KClassCreatorUtil (com.kotlinorm.compiler.plugin.utils)
Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
KClassCreatorUtil |
100%
(1/1)
|
100%
(8/8)
|
50%
(3/6)
|
100%
(56/56)
|
98.8%
(327/331)
|
/**
* Copyright 2022-2025 kronos-orm
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kotlinorm.compiler.plugin.utils
import com.kotlinorm.compiler.helpers.instantiate
import com.kotlinorm.compiler.helpers.invoke
import com.kotlinorm.compiler.helpers.kFunctionN
import com.kotlinorm.compiler.helpers.nType
import com.kotlinorm.compiler.helpers.toKClass
import com.kotlinorm.compiler.helpers.valueParameters
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.declarations.IrValueParameterBuilder
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irBranch
import org.jetbrains.kotlin.ir.builders.irElseBranch
import org.jetbrains.kotlin.ir.builders.irEquals
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irNull
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.builders.irWhen
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrParameterKind
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.allParameters
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.statements
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
object KClassCreatorUtil {
val kPojoClasses = mutableSetOf<IrClass>()
val initFunctions = mutableSetOf<Triple<IrPluginContext, IrBuilderWithScope, IrFunction>>()
fun resetKClassCreator() {
kPojoClasses.clear()
initFunctions.clear()
}
context(context: IrPluginContext)
private val kClassCreatorSymbol
get() = context.referenceProperties(
CallableId(
packageName = FqName("com.kotlinorm.utils"),
callableName = Name.identifier("kClassCreator")
)
).first()
@OptIn(UnsafeDuringIrConstructionAPI::class)
context(_: IrPluginContext)
private val kClassCreatorSetterSymbol
get() = kClassCreatorSymbol.owner.setter!!.symbol
context(_: IrPluginContext)
private fun lambdaArgument(
lambda: IrSimpleFunction,
type: IrType = kFunctionN(lambda.allParameters.size).typeWith(lambda.allParameters.map { it.type } + lambda.returnType),
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET
): IrFunctionExpression = IrFunctionExpressionImpl(
startOffset,
endOffset,
type,
lambda,
IrStatementOrigin.LAMBDA
)
context(_: IrPluginContext, builder: IrBuilderWithScope)
fun buildKClassMapper(declaration: IrFunction) {
declaration.body = builder.irBlockBody {
val lambda = context.irFactory.buildFun {
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
name = SpecialNames.ANONYMOUS
visibility = DescriptorVisibilities.LOCAL
returnType = KPojoSymbol.nType
modality = Modality.FINAL
}.apply {
parent = declaration
parameters = parameters + context.irFactory.buildValueParameter(IrValueParameterBuilder().apply {
name = Name.identifier("kClass")
type = KPojoSymbol.toKClass().type // KClass<KPojo>
kind = IrParameterKind.Regular
}, this)
body = context.irBuiltIns.createIrBuilder(symbol).run {
irBlockBody {
+irReturn(
irWhen(
KPojoSymbol.nType,
kPojoClasses.distinctBy { it.fqNameWhenAvailable }.mapNotNull {
it.symbol.instantiate()?.let { new ->
irBranch(
irEquals(
irGet(parameters.valueParameters.first()),
it.symbol.toKClass()
),
new
)
}
} + irElseBranch(
irNull()
)
)
)
}
}
}
+kClassCreatorSetterSymbol(
lambdaArgument(lambda),
operator = IrStatementOrigin.EQ
)
declaration.body?.statements?.forEach { +it }
}
}
}