fix(build): explicitly use ktfmt Google style

This commit is contained in:
Harsh Shandilya 2023-08-19 02:03:59 +05:30
parent bdc5960a56
commit 7b3172e99d
No known key found for this signature in database
13 changed files with 156 additions and 143 deletions

View File

@ -1,14 +1,12 @@
plugins {
alias(libs.plugins.spotless)
}
plugins { alias(libs.plugins.spotless) }
spotless {
kotlin {
target("**/*.kt")
ktfmt()
ktfmt().googleStyle()
}
kotlinGradle {
target("**/*.kts")
ktfmt()
ktfmt().googleStyle()
}
}

View File

@ -1,5 +1,3 @@
plugins { `kotlin-dsl` }
dependencies {
implementation(libs.kotlin.gradle.plugin)
}
dependencies { implementation(libs.kotlin.gradle.plugin) }

View File

@ -9,11 +9,7 @@ pluginManagement {
dependencyResolutionManagement {
repositories { mavenCentral() }
versionCatalogs {
maybeCreate("libs").apply {
from(files("../gradle/libs.versions.toml"))
}
}
versionCatalogs { maybeCreate("libs").apply { from(files("../gradle/libs.versions.toml")) } }
}
rootProject.name = "buildSrc"

View File

@ -4,6 +4,7 @@ plugins {
}
group = "dev.msfjarvis.tracelog"
version = "1.0.0-SNAPSHOT"
kotlin {

View File

@ -37,32 +37,37 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
public class DebugLogTransformer(
private val pluginContext: IrPluginContext,
private val annotationClass: IrClassSymbol,
private val logFunction: IrSimpleFunctionSymbol,
private val pluginContext: IrPluginContext,
private val annotationClass: IrClassSymbol,
private val logFunction: IrSimpleFunctionSymbol,
) : IrElementTransformerVoidWithContext() {
private val typeUnit = pluginContext.irBuiltIns.unitType
private val typeThrowable = pluginContext.irBuiltIns.throwableType
private val classMonotonic =
pluginContext.referenceClass(
ClassId(KOTLIN_TIME_FQNAME, Name.identifier("TimeSource.Monotonic")))!!
pluginContext.referenceClass(
ClassId(KOTLIN_TIME_FQNAME, Name.identifier("TimeSource.Monotonic"))
)!!
private val funMarkNow =
pluginContext
.referenceFunctions(
CallableId(
KOTLIN_TIME_FQNAME.child(Name.identifier("TimeSource")),
Name.identifier("markNow")))
.single()
pluginContext
.referenceFunctions(
CallableId(
KOTLIN_TIME_FQNAME.child(Name.identifier("TimeSource")),
Name.identifier("markNow")
)
)
.single()
private val funElapsedNow =
pluginContext
.referenceFunctions(
CallableId(
KOTLIN_TIME_FQNAME.child(Name.identifier("TimeMark")),
Name.identifier("elapsedNow")))
.single()
pluginContext
.referenceFunctions(
CallableId(
KOTLIN_TIME_FQNAME.child(Name.identifier("TimeMark")),
Name.identifier("elapsedNow")
)
)
.single()
override fun visitFunctionNew(declaration: IrFunction): IrStatement {
val body = declaration.body
@ -86,14 +91,15 @@ public class DebugLogTransformer(
}
private fun IrBuilderWithScope.irDebugExit(
function: IrFunction,
startTime: IrValueDeclaration,
result: IrExpression? = null
function: IrFunction,
startTime: IrValueDeclaration,
result: IrExpression? = null
): IrCall {
val concat = irConcat()
concat.addArgument(irString("${function.name} ["))
concat.addArgument(
irCall(funElapsedNow).also { call -> call.dispatchReceiver = irGet(startTime) })
irCall(funElapsedNow).also { call -> call.dispatchReceiver = irGet(startTime) }
)
if (result != null) {
concat.addArgument(irString("] = "))
concat.addArgument(result)
@ -109,43 +115,44 @@ public class DebugLogTransformer(
+irDebugEnter(function)
val startTime =
irTemporary(
irCall(funMarkNow).also { call ->
call.dispatchReceiver = irGetObject(classMonotonic)
})
irTemporary(
irCall(funMarkNow).also { call -> call.dispatchReceiver = irGetObject(classMonotonic) }
)
val tryBlock =
irBlock(resultType = function.returnType) {
for (statement in body.statements) +statement
if (function.returnType == typeUnit) +irDebugExit(function, startTime)
}
.transform(DebugLogReturnTransformer(function, startTime), null)
irBlock(resultType = function.returnType) {
for (statement in body.statements) +statement
if (function.returnType == typeUnit) +irDebugExit(function, startTime)
}
.transform(DebugLogReturnTransformer(function, startTime), null)
val throwable =
buildVariable(
scope.getLocalDeclarationParent(),
startOffset,
endOffset,
IrDeclarationOrigin.CATCH_PARAMETER,
Name.identifier("t"),
typeThrowable)
buildVariable(
scope.getLocalDeclarationParent(),
startOffset,
endOffset,
IrDeclarationOrigin.CATCH_PARAMETER,
Name.identifier("t"),
typeThrowable
)
+IrTryImpl(startOffset, endOffset, tryBlock.type).also { irTry ->
irTry.tryResult = tryBlock
irTry.catches +=
irCatch(
throwable,
irBlock {
+irDebugExit(function, startTime, irGet(throwable))
+irThrow(irGet(throwable))
})
irCatch(
throwable,
irBlock {
+irDebugExit(function, startTime, irGet(throwable))
+irThrow(irGet(throwable))
}
)
}
}
}
private inner class DebugLogReturnTransformer(
private val function: IrFunction,
private val startTime: IrVariable
private val function: IrFunction,
private val startTime: IrVariable
) : IrElementTransformerVoidWithContext() {
override fun visitReturn(expression: IrReturn): IrExpression {
if (expression.returnTargetSymbol != function.symbol) return super.visitReturn(expression)

View File

@ -9,8 +9,9 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
internal val LOGGER_FUNCTION =
CompilerConfigurationKey<String>(
"Logger function invoked to dump function metadata. Must have a single parameter of type `Any?`")
CompilerConfigurationKey<String>(
"Logger function invoked to dump function metadata. Must have a single parameter of type `Any?`"
)
@OptIn(ExperimentalCompilerApi::class)
@AutoService(CommandLineProcessor::class)
@ -18,21 +19,22 @@ public class TracingCommandLineProcessor : CommandLineProcessor {
internal companion object {
val OPTION_LOGGER_FUNCTION =
CliOption(
optionName = "loggerFunction",
valueDescription = "kotlin.io.println",
description = LOGGER_FUNCTION.toString(),
required = false,
allowMultipleOccurrences = false)
CliOption(
optionName = "loggerFunction",
valueDescription = "kotlin.io.println",
description = LOGGER_FUNCTION.toString(),
required = false,
allowMultipleOccurrences = false
)
}
override val pluginId: String = "dev.msfjarvis.tracelog"
override val pluginOptions: Collection<AbstractCliOption> = listOf(OPTION_LOGGER_FUNCTION)
override fun processOption(
option: AbstractCliOption,
value: String,
configuration: CompilerConfiguration
option: AbstractCliOption,
value: String,
configuration: CompilerConfiguration
) {
when (option.optionName) {
"loggerFunction" -> configuration.put(LOGGER_FUNCTION, value)

View File

@ -16,10 +16,11 @@ public class TracingCompilerPluginRegistrar : CompilerPluginRegistrar() {
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
val messageCollector =
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
val loggerFunction = configuration[LOGGER_FUNCTION] ?: "kotlin.io.println"
IrGenerationExtension.registerExtension(
TracingIrGenerationExtension(messageCollector, loggerFunction))
TracingIrGenerationExtension(messageCollector, loggerFunction)
)
}
}

View File

@ -12,44 +12,49 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
public class TracingIrGenerationExtension(
private val messageCollector: MessageCollector,
private val loggerFunction: String
private val messageCollector: MessageCollector,
private val loggerFunction: String
) : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
val debugLogAnnotation =
pluginContext.referenceClass(
ClassId(
FqName("${BuildConfig.KOTLIN_PLUGIN_GROUP}.runtime.annotations"),
Name.identifier("DebugLog"),
))
pluginContext.referenceClass(
ClassId(
FqName("${BuildConfig.KOTLIN_PLUGIN_GROUP}.runtime.annotations"),
Name.identifier("DebugLog"),
)
)
if (debugLogAnnotation == null) {
messageCollector.report(CompilerMessageSeverity.ERROR, "Failed to find 'DebugLog' annotation")
return
}
val loggerFun =
pluginContext.referenceFunctions(loggerFunction.toCallableId()).firstOrNull {
val parameters = it.owner.valueParameters
parameters.size == 1 && parameters[0].type.isNullableAny()
}
pluginContext.referenceFunctions(loggerFunction.toCallableId()).firstOrNull {
val parameters = it.owner.valueParameters
parameters.size == 1 && parameters[0].type.isNullableAny()
}
if (loggerFun == null) {
messageCollector.report(
CompilerMessageSeverity.ERROR, "Failed to resolve logger method '$loggerFunction'")
CompilerMessageSeverity.ERROR,
"Failed to resolve logger method '$loggerFunction'"
)
return
}
moduleFragment.transform(
DebugLogTransformer(pluginContext, debugLogAnnotation, loggerFun), null)
DebugLogTransformer(pluginContext, debugLogAnnotation, loggerFun),
null
)
}
private fun String.toCallableId(): CallableId {
val parts = split(".")
val methodName = parts.last()
val fqName =
if (parts.size == 1) {
FqName("")
} else {
FqName((parts - methodName).joinToString("."))
}
if (parts.size == 1) {
FqName("")
} else {
FqName((parts - methodName).joinToString("."))
}
return CallableId(fqName, Name.identifier(methodName))
}
}

View File

@ -17,9 +17,9 @@ class DebugLogTransformerTest {
@Test
fun `compiler plugin successfully transforms code`() {
val srcFile =
kotlin(
"SourceFile.kt",
"""
kotlin(
"SourceFile.kt",
"""
import ${BuildConfig.KOTLIN_PLUGIN_GROUP}.runtime.annotations.DebugLog
public val messages = mutableListOf<String>()
fun recordMessage(message: Any?) {
@ -52,31 +52,32 @@ class DebugLogTransformerTest {
}
}
"""
.trimIndent())
.trimIndent()
)
val result =
KotlinCompilation()
.apply {
val processor = TracingCommandLineProcessor()
pluginOptions = buildList {
add(
processor.option(
TracingCommandLineProcessor.OPTION_LOGGER_FUNCTION, "recordMessage"))
}
sources = listOf(srcFile)
compilerPluginRegistrars = listOf(TracingCompilerPluginRegistrar())
commandLineProcessors = listOf(processor)
noOptimize = true
KotlinCompilation()
.apply {
val processor = TracingCommandLineProcessor()
pluginOptions = buildList {
add(
processor.option(TracingCommandLineProcessor.OPTION_LOGGER_FUNCTION, "recordMessage")
)
}
sources = listOf(srcFile)
compilerPluginRegistrars = listOf(TracingCompilerPluginRegistrar())
commandLineProcessors = listOf(processor)
noOptimize = true
inheritClassPath = true
messageOutputStream = System.out
}
.compile()
inheritClassPath = true
messageOutputStream = System.out
}
.compile()
assertEquals(ExitCode.OK, result.exitCode)
val kClazz = result.classLoader.loadClass("SourceFileKt")
val transformableWithReturnValue =
kClazz.declaredMethods.first { it.name == "transformableWithReturnValue" }
kClazz.declaredMethods.first { it.name == "transformableWithReturnValue" }
val retVal = transformableWithReturnValue.invoke(null)
assertThat(retVal).isInstanceOf(String::class.java)
assertThat(retVal).isEqualTo("Return value!")
@ -86,9 +87,9 @@ class DebugLogTransformerTest {
assertThat(messages).isNotNull()
assertThat(messages).contains("⇢ transformableWithReturnValue()")
assertThat((messages?.last() as? String)?.replace("\\[.*]".toRegex(), "[]"))
.isEqualTo(
"⇠ transformableWithReturnValue [] = Return value!",
)
.isEqualTo(
"⇠ transformableWithReturnValue [] = Return value!",
)
}
private fun CommandLineProcessor.option(key: CliOption, value: Any?): PluginOption {

View File

@ -12,7 +12,7 @@ import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
public class TraceLogGradlePlugin : KotlinCompilerPluginSupportPlugin {
override fun applyToCompilation(
kotlinCompilation: KotlinCompilation<*>
kotlinCompilation: KotlinCompilation<*>
): Provider<List<SubpluginOption>> {
return kotlinCompilation.target.project.provider {
buildList { add(SubpluginOption(key = "loggerFunction", value = "kotlin.io.println")) }
@ -22,11 +22,11 @@ public class TraceLogGradlePlugin : KotlinCompilerPluginSupportPlugin {
override fun getCompilerPluginId(): String = BuildConfig.KOTLIN_PLUGIN_GROUP
override fun getPluginArtifact(): SubpluginArtifact =
SubpluginArtifact(
groupId = BuildConfig.KOTLIN_PLUGIN_GROUP,
artifactId = BuildConfig.KOTLIN_PLUGIN_NAME,
version = BuildConfig.KOTLIN_PLUGIN_VERSION,
)
SubpluginArtifact(
groupId = BuildConfig.KOTLIN_PLUGIN_GROUP,
artifactId = BuildConfig.KOTLIN_PLUGIN_NAME,
version = BuildConfig.KOTLIN_PLUGIN_VERSION,
)
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = true
}

View File

@ -1,3 +1 @@
plugins {
`tracelog-kotlin-library`
}
plugins { `tracelog-kotlin-library` }

View File

@ -5,9 +5,7 @@ plugins {
application
}
application {
mainClass.set("dev.msfjarvis.tracelog.sample.MainKt")
}
application { mainClass.set("dev.msfjarvis.tracelog.sample.MainKt") }
tasks.withType<KotlinCompile>().configureEach {
compilerOptions.freeCompilerArgs.addAll(

View File

@ -12,8 +12,11 @@ private const val MATCH_PARAMS = "params"
private const val MATCH_TIME = "time"
private const val MATCH_RETURN = "retval"
private val ENTER_REGEX = "(?<$MATCH_ARROW>⇢) (?<$MATCH_IDENTIFIER>[a-zA-Z].*)\\((?<$MATCH_PARAMS>.*)\\)".toRegex()
private val EXIT_REGEX = "(?<$MATCH_ARROW>⇠) (?<$MATCH_IDENTIFIER>[a-zA-Z].*) \\[(?<$MATCH_TIME>.*)] = (?<$MATCH_RETURN>.*)".toRegex()
private val ENTER_REGEX =
"(?<$MATCH_ARROW>⇢) (?<$MATCH_IDENTIFIER>[a-zA-Z].*)\\((?<$MATCH_PARAMS>.*)\\)".toRegex()
private val EXIT_REGEX =
"(?<$MATCH_ARROW>⇠) (?<$MATCH_IDENTIFIER>[a-zA-Z].*) \\[(?<$MATCH_TIME>.*)] = (?<$MATCH_RETURN>.*)"
.toRegex()
private fun MatchResult.getMatch(groupName: String): String {
return groups[groupName]!!.value
@ -25,38 +28,43 @@ fun main() {
messages.forEach { msg ->
var matches = ENTER_REGEX.find(msg)
if (matches != null) {
val params = matches.getMatch(MATCH_PARAMS).split(", ").map {
val split = it.split("=")
(split[0] to split[1])
}.joinToString(", ") { (name, value) ->
"${brightYellow(name)}=${brightBlue(value)}"
}
t.println("""
val params =
matches
.getMatch(MATCH_PARAMS)
.split(", ")
.map {
val split = it.split("=")
(split[0] to split[1])
}
.joinToString(", ") { (name, value) -> "${brightYellow(name)}=${brightBlue(value)}" }
t.println(
"""
${red(matches.getMatch(MATCH_ARROW))} ${green(matches.getMatch(MATCH_IDENTIFIER))}($params)
""".trimIndent())
"""
.trimIndent()
)
} else {
matches = EXIT_REGEX.matchEntire(msg)
if (matches != null) {
t.println("""
t.println(
"""
${red(matches.getMatch(MATCH_ARROW))} ${green(matches.getMatch(MATCH_IDENTIFIER))} [${blue(matches.getMatch(
MATCH_TIME))}] = ${brightWhite(matches.getMatch(MATCH_RETURN))}
""".trimIndent())
"""
.trimIndent()
)
}
}
}
}
/**
* Custom implementation of a logger function for use by the compiler plugin.
*/
/** Custom implementation of a logger function for use by the compiler plugin. */
@Suppress("Unused") // Used by the generated bytecode
fun recordMessage(message: Any?) {
messages += message.toString()
}
/**
* An example of an annotated method which will be transformed by the compiler plugin.
*/
/** An example of an annotated method which will be transformed by the compiler plugin. */
@DebugLog
fun debuggableFunction(p0: String, p1: String = "Bar"): String {
return "Debugging is cool!"