Skip to content

Commit 3cf2a74

Browse files
committed
add compile time loggers, optional logging for runtime
1 parent 89641dd commit 3cf2a74

File tree

16 files changed

+180
-45
lines changed

16 files changed

+180
-45
lines changed

app/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ android {
2828
}
2929

3030
dependencies {
31+
// todo: for debug
32+
// implementation(project(":compiler-plugin"))
33+
// kotlinCompilerPluginClasspath(project(":compiler-plugin"))
34+
3135
implementation(libs.stslex.compilerPlugin)
3236
kotlinCompilerPluginClasspath(libs.stslex.compilerPlugin)
3337

app/src/main/kotlin/com/stslex/compiler_app/MainActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ class MainActivity : ComponentActivity() {
5353
setSecondName(user.secondName)
5454
}
5555

56-
@DistinctUntilChangeFun
56+
@DistinctUntilChangeFun(false)
5757
private fun setName(name: String) {
5858
logger.log(Level.INFO, "setName: $name")
5959
findViewById<TextView>(R.id.usernameFieldTextView).text = name
6060
}
6161

62-
@DistinctUntilChangeFun
62+
@DistinctUntilChangeFun(true)
6363
private fun setSecondName(name: String) {
6464
logger.log(Level.INFO, "setSecondName: $name")
6565
findViewById<TextView>(R.id.secondNameFieldTextView).text = name

compiler-plugin/build.gradle.kts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
}
99

1010
group = "io.github.stslex"
11-
version = "0.0.1"
11+
version = libs.versions.stslexCompilerPlugin.get()
1212

1313
java {
1414
sourceCompatibility = JavaVersion.VERSION_21
@@ -43,7 +43,7 @@ publishing {
4343

4444
groupId = "io.github.stslex"
4545
artifactId = "compiler-plugin"
46-
version = "0.0.1"
46+
version = libs.versions.stslexCompilerPlugin.get()
4747

4848
artifact(tasks["javadocJar"])
4949
artifact(tasks["sourcesJar"])
@@ -94,7 +94,6 @@ tasks.named("publishToMavenLocal") {
9494

9595
val generateChecksums by tasks.register("generateChecksums") {
9696
mustRunAfter("publishToMavenLocal")
97-
finalizedBy("packageArtifacts")
9897

9998
group = "publishing"
10099
description = "Generate MD5 и SHA1 for all artifacts in local repository"
@@ -127,9 +126,6 @@ val generateChecksums by tasks.register("generateChecksums") {
127126
}
128127

129128
tasks.register<Zip>("packageArtifacts") {
130-
mustRunAfter("generateChecksums")
131-
dependsOn("generateChecksums")
132-
133129
group = "publishing"
134130
description = "Create ZIP-archive with artifacts for Central Publisher Portal"
135131

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctChangeCache.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package io.github.stslex.compiler_plugin
22

3-
import java.util.logging.Level
4-
import java.util.logging.Logger
3+
import io.github.stslex.compiler_plugin.utils.RuntimeLogger
54

65
internal object DistinctChangeCache {
76

8-
private const val TAG = "KotlinCompilerDistinct"
9-
private val logger = Logger.getLogger(TAG)
107
private val cache = mutableMapOf<String, Pair<List<Any?>, Any?>>()
8+
private val logger = RuntimeLogger.tag("DistinctChangeLogger")
119

1210
@JvmStatic
1311
@Suppress("UNCHECKED_CAST")
14-
fun <R> invoke(key: String, args: List<Any?>, body: () -> R): R {
12+
fun <R> invoke(
13+
key: String,
14+
args: List<Any?>,
15+
body: () -> R,
16+
config: DistinctChangeConfig
17+
): R {
1518
val entry = cache[key]
16-
logger.log(Level.INFO, "memorize key: $key, entry: $entry, args: $args")
19+
20+
if (config.logging) {
21+
logger.i("key: $key, config:$config, entry: $entry, args: $args")
22+
}
1723

1824
if (entry != null && entry.first == args) {
1925
return entry.second as R
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.github.stslex.compiler_plugin
2+
3+
internal data class DistinctChangeConfig(
4+
val logging: Boolean
5+
)

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/DistinctUntilChangeFun.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,13 @@ package io.github.stslex.compiler_plugin
22

33
@Target(AnnotationTarget.FUNCTION)
44
@Retention(AnnotationRetention.BINARY)
5-
public annotation class DistinctUntilChangeFun
5+
public annotation class DistinctUntilChangeFun(
6+
val logging: Boolean = LOGGING_DEFAULT
7+
) {
8+
9+
public companion object {
10+
11+
internal const val LOGGING_DEFAULT = false
12+
13+
}
14+
}

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/WorkshopCompilerPlugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ internal class WorkshopCompilerPlugin(
1212
) : CompilerPluginRegistrar() {
1313

1414
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
15-
IrGenerationExtension.registerExtension(DistinctChangeIrGenerationExtension())
15+
IrGenerationExtension.registerExtension(DistinctChangeIrGenerationExtension(configuration))
1616
}
1717
}

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/extensions/DistinctChangeIrGenerationExtension.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,24 @@ package io.github.stslex.compiler_plugin.extensions
33
import io.github.stslex.compiler_plugin.transformers.IrFunctionTransformer
44
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
55
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
6+
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
7+
import org.jetbrains.kotlin.config.CommonConfigurationKeys
8+
import org.jetbrains.kotlin.config.CompilerConfiguration
69
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
710
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
811

9-
internal class DistinctChangeIrGenerationExtension : IrGenerationExtension {
12+
internal class DistinctChangeIrGenerationExtension(
13+
private val configuration: CompilerConfiguration
14+
) : IrGenerationExtension {
1015

1116
override fun generate(
1217
moduleFragment: IrModuleFragment,
13-
pluginContext: IrPluginContext
18+
pluginContext: IrPluginContext,
1419
) {
15-
moduleFragment.transformChildrenVoid(IrFunctionTransformer(pluginContext))
20+
val messageCollector = configuration.get(
21+
CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY,
22+
MessageCollector.NONE
23+
)
24+
moduleFragment.transformChildrenVoid(IrFunctionTransformer(pluginContext, messageCollector))
1625
}
1726
}
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,33 @@
11
package io.github.stslex.compiler_plugin.transformers
22

33
import buildArgsListExpression
4-
import io.github.stslex.compiler_plugin.DistinctUntilChangeFun
4+
import io.github.stslex.compiler_plugin.utils.CompileLogger.Companion.toCompilerLogger
55
import io.github.stslex.compiler_plugin.utils.buildLambdaForBody
66
import io.github.stslex.compiler_plugin.utils.buildSaveInCacheCall
77
import io.github.stslex.compiler_plugin.utils.fullyQualifiedName
8+
import io.github.stslex.compiler_plugin.utils.readQualifier
89
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
910
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
11+
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
1012
import org.jetbrains.kotlin.ir.IrStatement
1113
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
1214
import org.jetbrains.kotlin.ir.declarations.createExpressionBody
1315
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
14-
import org.jetbrains.kotlin.ir.util.hasAnnotation
15-
import org.jetbrains.kotlin.name.FqName
1616

1717
internal class IrFunctionTransformer(
18-
private val pluginContext: IrPluginContext
18+
private val pluginContext: IrPluginContext,
19+
private val messageCollector: MessageCollector
1920
) : IrElementTransformerVoidWithContext() {
2021

21-
private val IrSimpleFunction.isAnnotationValid: Boolean
22-
get() = DistinctUntilChangeFun::class.qualifiedName
23-
?.let { qualifier -> hasAnnotation(FqName(qualifier)) }
24-
?: false
22+
private val logger by lazy { messageCollector.toCompilerLogger() }
2523

2624
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement {
27-
if (declaration.isAnnotationValid.not()) {
28-
return super.visitSimpleFunction(declaration)
29-
}
30-
val originalBody = declaration.body ?: return super.visitSimpleFunction(declaration)
25+
val qualifierArgs = pluginContext.readQualifier(declaration, logger)
26+
?: return super.visitSimpleFunction(declaration)
3127

28+
val originalBody = declaration.body ?: return super.visitSimpleFunction(declaration)
3229

30+
logger.i("fullyQualifiedName: ${declaration.fullyQualifiedName}")
3331
val keyLiteral = IrConstImpl.string(
3432
startOffset = declaration.startOffset,
3533
endOffset = declaration.endOffset,
@@ -44,11 +42,14 @@ internal class IrFunctionTransformer(
4442
argsListExpr = argsListExpr,
4543
lambdaExpr = lambdaExpr,
4644
function = declaration,
45+
qualifierArgs = qualifierArgs,
46+
logger = logger
4747
)
4848

4949
declaration.body = pluginContext.irFactory.createExpressionBody(memoizeCall)
5050

5151
return super.visitSimpleFunction(declaration)
5252
}
53+
5354
}
5455

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.stslex.compiler_plugin.utils
2+
3+
import org.jetbrains.kotlin.backend.common.toLogger
4+
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
5+
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
6+
7+
internal class CompileLogger(
8+
private val messageCollector: MessageCollector
9+
) {
10+
11+
fun i(msg: String) {
12+
messageCollector.toLogger()
13+
messageCollector.report(CompilerMessageSeverity.INFO, msg)
14+
}
15+
16+
companion object {
17+
18+
fun MessageCollector.toCompilerLogger(): CompileLogger = CompileLogger(this)
19+
}
20+
}

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerConsts.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

compiler-plugin/src/main/kotlin/io/github/stslex/compiler_plugin/utils/CompilerExtensions.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package io.github.stslex.compiler_plugin.utils
22

33
import io.github.stslex.compiler_plugin.DistinctChangeCache
44
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
5+
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
56
import org.jetbrains.kotlin.descriptors.Modality
67
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
78
import org.jetbrains.kotlin.ir.declarations.IrClass
9+
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
810
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
911
import org.jetbrains.kotlin.ir.declarations.IrFunction
1012
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
@@ -16,13 +18,26 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
1618
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
1719
import org.jetbrains.kotlin.ir.types.typeWith
1820
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
21+
import org.jetbrains.kotlin.ir.util.dump
1922
import org.jetbrains.kotlin.ir.util.kotlinFqName
2023
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
2124
import org.jetbrains.kotlin.name.CallableId
2225
import org.jetbrains.kotlin.name.ClassId
2326
import org.jetbrains.kotlin.name.FqName
2427
import org.jetbrains.kotlin.name.Name
28+
import kotlin.reflect.KClass
2529

30+
internal fun IrPluginContext.createIrBuilder(
31+
declaration: IrDeclaration
32+
): DeclarationIrBuilder = DeclarationIrBuilder(
33+
generatorContext = this,
34+
symbol = declaration.symbol
35+
)
36+
37+
internal inline fun <reified T : Any> KClass<T>.toClassId(): ClassId = ClassId(
38+
FqName(java.`package`.name),
39+
Name.identifier(java.simpleName)
40+
)
2641

2742
internal fun IrPluginContext.buildLambdaForBody(
2843
originalBody: IrBody,
@@ -78,13 +93,14 @@ internal fun IrPluginContext.buildSaveInCacheCall(
7893
argsListExpr: IrExpression,
7994
lambdaExpr: IrExpression,
8095
function: IrSimpleFunction,
96+
qualifierArgs: IrExpression,
97+
logger: CompileLogger
8198
): IrExpression {
82-
val cacheNameClass = checkNotNull(DistinctChangeCache::class.simpleName) {
83-
"Cannot get simpleName"
84-
}
99+
logger.i("buildSaveInCacheCall for ${function.name}, args: ${argsListExpr.dump()} with config: ${qualifierArgs.dump()}")
100+
85101
val memoizeFunction = referenceFunctions(
86102
CallableId(
87-
classId = ClassId(FqName(CompilerConsts.PATH), Name.identifier(cacheNameClass)),
103+
classId = DistinctChangeCache::class.toClassId(),
88104
callableName = Name.identifier("invoke")
89105
)
90106
)
@@ -97,13 +113,14 @@ internal fun IrPluginContext.buildSaveInCacheCall(
97113
type = function.returnType,
98114
symbol = memoizeFunction,
99115
typeArgumentsCount = 1,
100-
valueArgumentsCount = 3
116+
valueArgumentsCount = 4
101117
)
102118
.also { call -> call.patchDeclarationParents(function) }
103119
.apply {
104120
putTypeArgument(0, function.returnType)
105121
putValueArgument(0, keyLiteral)
106122
putValueArgument(1, argsListExpr)
107123
putValueArgument(2, lambdaExpr)
124+
putValueArgument(3, qualifierArgs)
108125
}
109126
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.github.stslex.compiler_plugin.utils
2+
3+
import io.github.stslex.compiler_plugin.DistinctChangeConfig
4+
import io.github.stslex.compiler_plugin.DistinctUntilChangeFun
5+
import io.github.stslex.compiler_plugin.DistinctUntilChangeFun.Companion.LOGGING_DEFAULT
6+
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
7+
import org.jetbrains.kotlin.ir.builders.irBoolean
8+
import org.jetbrains.kotlin.ir.builders.irCallConstructor
9+
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
10+
import org.jetbrains.kotlin.ir.expressions.IrExpression
11+
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
12+
import org.jetbrains.kotlin.ir.util.constructors
13+
import org.jetbrains.kotlin.ir.util.getAnnotation
14+
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
15+
import org.jetbrains.kotlin.name.FqName
16+
17+
@OptIn(UnsafeDuringIrConstructionAPI::class)
18+
internal fun IrPluginContext.readQualifier(
19+
function: IrSimpleFunction,
20+
logger: CompileLogger
21+
): IrExpression? {
22+
val qualifiedName = DistinctUntilChangeFun::class.qualifiedName ?: return null
23+
val annotation = function.getAnnotation(FqName(qualifiedName)) ?: return null
24+
25+
logger.i("readQualifier: annotation is found for ${function.name}")
26+
27+
val irBuilder = createIrBuilder(function)
28+
29+
val currentValue = annotation.getValueArgument(0)
30+
val logging = currentValue ?: irBuilder.irBoolean(LOGGING_DEFAULT)
31+
32+
val constructorSymbol = referenceClass(DistinctChangeConfig::class.toClassId())
33+
?.constructors
34+
?.firstOrNull()
35+
?: error("CheckChangesConfig not found in IR")
36+
37+
return irBuilder
38+
.irCallConstructor(
39+
callee = constructorSymbol,
40+
typeArguments = emptyList()
41+
)
42+
.also { it.patchDeclarationParents(function) }
43+
.apply {
44+
putValueArgument(0, logging)
45+
}
46+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.github.stslex.compiler_plugin.utils
2+
3+
import java.util.logging.Level
4+
import java.util.logging.Logger
5+
6+
internal class RuntimeLogger private constructor(tag: String) {
7+
8+
private val logger = Logger.getLogger(tag)
9+
10+
fun i(msg: String) {
11+
logger.log(Level.INFO, msg)
12+
}
13+
14+
companion object {
15+
16+
private const val TAG = "KotlinCompilerLogger"
17+
18+
fun i(msg: String) {
19+
RuntimeLogger(TAG).i(msg)
20+
}
21+
22+
fun tag(tag: String): RuntimeLogger = RuntimeLogger(tag)
23+
}
24+
25+
}

0 commit comments

Comments
 (0)