diff --git a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctChangeCache.kt b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctChangeCache.kt index 28ffa38..d17a181 100644 --- a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctChangeCache.kt +++ b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctChangeCache.kt @@ -4,20 +4,21 @@ import io.github.stslex.compiler_plugin.model.DistinctChangeConfig import io.github.stslex.compiler_plugin.utils.RuntimeLogger import org.jetbrains.kotlin.utils.addToStdlib.runIf -internal class DistinctChangeCache( - private val config: DistinctChangeConfig -) { +internal const val GENERATED_FIELD_NAME = "_generatedField" + +internal class DistinctChangeCache { private val cache = mutableMapOf, Any?>>() - private val logger = runIf(config.logging) { RuntimeLogger.tag("DistinctChangeLogger") } @Suppress("UNCHECKED_CAST") internal operator fun invoke( key: String, args: List, + config: DistinctChangeConfig, body: () -> R, ): R { val entry = cache[key] + val logger = runIf(config.logging) { RuntimeLogger.tag("DistinctChangeLogger") } logger?.i("name: ${config.name} key: $key, config:$config, entry: $entry, args: $args") diff --git a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/transformers/IrFunctionTransformer.kt b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/transformers/IrFunctionTransformer.kt index 83d4b04..8f0af40 100644 --- a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/transformers/IrFunctionTransformer.kt +++ b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/transformers/IrFunctionTransformer.kt @@ -49,7 +49,7 @@ internal class IrFunctionTransformer( val argsListExpr = pluginContext.buildArgsListExpression(declaration) val lambdaExpr = pluginContext.buildLambdaForBody(originalBody, declaration) - val backingField = pluginContext.generateFields(declaration, qualifierArgs, logger) + val backingField = pluginContext.generateFields(declaration, logger) logger.i("backingField = $backingField") val memoizeCall = pluginContext.buildSaveInCacheCall( @@ -58,7 +58,8 @@ internal class IrFunctionTransformer( lambdaExpr = lambdaExpr, function = declaration, backingField = backingField, - logger = logger + logger = logger, + qualifierArgs = qualifierArgs ) declaration.body = pluginContext.irFactory.createExpressionBody(memoizeCall) diff --git a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerExtensions.kt b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerExtensions.kt index 20f1ad5..f87f957 100644 --- a/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerExtensions.kt +++ b/compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerExtensions.kt @@ -1,11 +1,13 @@ package io.github.stslex.compiler_plugin.utils import io.github.stslex.compiler_plugin.DistinctChangeCache +import io.github.stslex.compiler_plugin.GENERATED_FIELD_NAME import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.jvm.ir.fileParentOrNull import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor @@ -116,7 +118,8 @@ internal fun IrPluginContext.buildSaveInCacheCall( lambdaExpr: IrExpression, function: IrSimpleFunction, logger: CompileLogger, - backingField: IrFieldSymbolImpl + backingField: IrFieldSymbolImpl, + qualifierArgs: IrExpression ): IrExpression { logger.i("buildSaveInCacheCall for ${function.name}, args: ${argsListExpr.dump()}") @@ -150,7 +153,7 @@ internal fun IrPluginContext.buildSaveInCacheCall( type = function.returnType, symbol = invokeFunSymbol.symbol, typeArgumentsCount = 1, - valueArgumentsCount = 3, + valueArgumentsCount = 4, origin = null ) .also { it.patchDeclarationParents(function.parent) } @@ -160,14 +163,14 @@ internal fun IrPluginContext.buildSaveInCacheCall( putTypeArgument(0, function.returnType) putValueArgument(0, keyLiteral) putValueArgument(1, argsListExpr) - putValueArgument(2, lambdaExpr) + putValueArgument(2, qualifierArgs) + putValueArgument(3, lambdaExpr) } } -@OptIn(UnsafeDuringIrConstructionAPI::class) +@OptIn(UnsafeDuringIrConstructionAPI::class, ObsoleteDescriptorBasedAPI::class) internal fun IrPluginContext.generateFields( function: IrSimpleFunction, - qualifierArgs: IrExpression, logger: CompileLogger ): IrFieldSymbolImpl { logger.i("generateFields for ${function.name} parent: ${function.file}") @@ -175,6 +178,21 @@ internal fun IrPluginContext.generateFields( val parentClass = function.parentClassOrNull val parentFile = function.fileParentOrNull + // check if parentClass or parentFile already contains _generatedField + val createdField = when { + parentClass != null -> parentClass.declarations.find { + it.descriptor.name.identifierOrNullIfSpecial == GENERATED_FIELD_NAME + } + + parentFile != null -> parentFile.declarations.find { + it.descriptor.name.identifierOrNullIfSpecial == GENERATED_FIELD_NAME + } + + else -> null + }?.symbol as? IrFieldSymbolImpl + + if (createdField != null) return createdField + val errorNotFound = "function ${function.name} in ${function.file} couldn't be used with @DistinctUntilChangeFun" @@ -194,7 +212,7 @@ internal fun IrPluginContext.generateFields( endOffset = endOffset, origin = IrDeclarationOrigin.PROPERTY_BACKING_FIELD, symbol = fieldSymbol, - name = Name.identifier("_distinctCache"), + name = Name.identifier(GENERATED_FIELD_NAME), type = distinctChangeClass.defaultType, visibility = DescriptorVisibilities.PRIVATE, isFinal = true, @@ -213,9 +231,6 @@ internal fun IrPluginContext.generateFields( type = distinctChangeClass.defaultType, constructorSymbol = constructorSymbol.symbol ) - .apply { - putValueArgument(0, qualifierArgs) - } backingField.parent = function.parent backingField.initializer = irFactory.createExpressionBody(callDistInit) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5f507f1..6fa474e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ activity = "1.10.0" constraintLayout = "2.2.0" jetbrainsKotlinJvm = "2.0.20" -stslexCompilerPlugin = "0.0.4" +stslexCompilerPlugin = "0.0.5" [libraries] android-desugarJdkLibs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" }