Skip to content

Commit

Permalink
Merge pull request #119 from kitakkun/feature/move_value_containers_i…
Browse files Browse the repository at this point in the history
…nside_compiler

Remove Gradle DSL for ValueContainer and embed it directly into the compiler
  • Loading branch information
kitakkun authored Jul 11, 2024
2 parents 6a91830 + 7d40135 commit 4d489e5
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 328 deletions.
14 changes: 0 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,6 @@ dependencies {

backInTime {
enabled = true // default is true
// [NOTE] we might remove this feature soon, and will introduce easier way to configure value containers in other modules by using annotations.
valueContainers {
androidValueContainers() // support for MutableLiveData, MutableStateFlow, MutableState
composeMutableStates() // support for MutableState, MutableIntState, MutableLongState, etc...
collections() // support for MutableList, MutableMap, MutableSet

// You can also add your own value container
container {
className = "com.example.MyValueContainer"
captures = listOf("<set-value>", "updateValue")
getter = "<get-value>"
setter = "<set-value>"
}
}
}
```

Expand Down
6 changes: 1 addition & 5 deletions backintime-demo/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,5 @@ dependencies {
}

backInTime {
valueContainers {
androidValueContainers()
composeMutableStates()
collections()
}
enabled = true
}
5 changes: 0 additions & 5 deletions backintime-plugin/common/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
plugins {
alias(libs.plugins.kotlinJvm)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.backintimeLint)
`maven-publish`
}

dependencies {
implementation(libs.kotlinx.serialization.json)
}

publishing {
publications {
create<MavenPublication>("mavenJava") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ package io.github.kitakkun.backintime.plugin

object BackInTimeCompilerOptionKey {
const val ENABLED = "enabled"
const val VALUE_CONTAINER: String = "valueContainers"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import com.google.auto.service.AutoService
import io.github.kitakkun.backintime.compiler.configuration.BackInTimeCompilerConfigurationKey
import io.github.kitakkun.backintime.plugin.BackInTimeCompilerOptionKey
import io.github.kitakkun.backintime.plugin.BackInTimePluginConsts
import io.github.kitakkun.backintime.plugin.extension.ValueContainerConfig
import kotlinx.serialization.json.Json
import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption
import org.jetbrains.kotlin.compiler.plugin.CliOption
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import java.util.Base64

@Suppress("UNUSED")
@OptIn(ExperimentalCompilerApi::class)
Expand All @@ -25,23 +22,10 @@ class BackInTimeCommandLineProcessor : CommandLineProcessor {
description = "Whether BackInTime plugin is enabled or not.",
required = false,
),
CliOption(
optionName = BackInTimeCompilerOptionKey.VALUE_CONTAINER,
valueDescription = "configurable via container dsl",
description = "predefined debuggable value-container class",
allowMultipleOccurrences = true,
required = false,
),
)

override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) = when (option.optionName) {
BackInTimeCompilerOptionKey.ENABLED -> configuration.put(BackInTimeCompilerConfigurationKey.ENABLED, value.toBoolean())
BackInTimeCompilerOptionKey.VALUE_CONTAINER -> {
val decodedValue = String(Base64.getDecoder().decode(value), Charsets.UTF_8)
val config = Json.decodeFromString<ValueContainerConfig>(decodedValue)
configuration.appendList(BackInTimeCompilerConfigurationKey.VALUE_CONTAINER, config)
}

else -> error("Unexpected config option ${option.optionName}")
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package io.github.kitakkun.backintime.compiler.configuration

import io.github.kitakkun.backintime.plugin.BackInTimeCompilerOptionKey
import io.github.kitakkun.backintime.plugin.extension.ValueContainerConfig
import org.jetbrains.kotlin.config.CompilerConfigurationKey

object BackInTimeCompilerConfigurationKey {
val ENABLED = CompilerConfigurationKey.create<Boolean>(BackInTimeCompilerOptionKey.ENABLED)
val VALUE_CONTAINER = CompilerConfigurationKey.create<List<ValueContainerConfig>>(BackInTimeCompilerOptionKey.VALUE_CONTAINER)
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
package io.github.kitakkun.backintime.compiler.configuration

import io.github.kitakkun.backintime.compiler.backend.ValueContainerClassInfo
import io.github.kitakkun.backintime.compiler.valuecontainer.ValueContainerBuiltIns
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name

class BackInTimeCompilerConfigurationProcessor {
fun process(configuration: CompilerConfiguration) = BackInTimeCompilerConfiguration(
enabled = configuration[BackInTimeCompilerConfigurationKey.ENABLED] ?: false,
valueContainers = configuration[BackInTimeCompilerConfigurationKey.VALUE_CONTAINER].orEmpty()
.map { config ->
val classId = ClassId.fromString(config.className)

ValueContainerClassInfo(
classId = classId,
capturedFunctionNames = config.captures.map { Name.guessByFirstCharacter(it) },
getterFunctionName = Name.guessByFirstCharacter(config.getter),
preSetterFunctionNames = config.preSetters.map { Name.guessByFirstCharacter(it) },
setterFunctionName = Name.guessByFirstCharacter(config.setter),
serializeItSelf = config.serializeItself,
serializeAs = config.serializeAs?.let { ClassId.fromString(it) },
)
},
valueContainers = ValueContainerBuiltIns,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package io.github.kitakkun.backintime.compiler.valuecontainer

import io.github.kitakkun.backintime.compiler.backend.ValueContainerClassInfo
import org.jetbrains.kotlin.javac.resolve.classId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames

val ValueContainerBuiltIns = listOf(
ValueContainerClassInfo(
classId = classId("androidx.lifecycle", "MutableLiveData"),
capturedFunctionNames = listOf(
Name.identifier("postValue"),
Name.identifier("setValue"),
),
getterFunctionName = Name.identifier("getValue"),
setterFunctionName = Name.identifier("postValue"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime", "MutableState"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("kotlinx.coroutines.flow", "MutableStateFlow"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
Name.identifier("update"),
Name.identifier("updateAndGet"),
Name.identifier("getAndUpdate"),
Name.identifier("emit"),
Name.identifier("tryEmit"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("kotlin.collections", "MutableList"),
capturedFunctionNames = listOf(
Name.identifier("add"),
Name.identifier("addAll"),
Name.identifier("clear"),
Name.identifier("remove"),
Name.identifier("removeAll"),
Name.identifier("removeAt"),
Name.identifier("set"),
Name.identifier("replaceAll"),
),
getterFunctionName = SpecialNames.THIS,
setterFunctionName = Name.identifier("addAll"),
preSetterFunctionNames = listOf(Name.identifier("clear")),
serializeItSelf = true,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("kotlin.collections", "MutableSet"),
capturedFunctionNames = listOf(
Name.identifier("add"),
Name.identifier("addAll"),
Name.identifier("clear"),
Name.identifier("remove"),
Name.identifier("removeAll"),
),
getterFunctionName = SpecialNames.THIS,
setterFunctionName = Name.identifier("addAll"),
preSetterFunctionNames = listOf(Name.identifier("clear")),
serializeItSelf = true,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("kotlin.collections", "MutableMap"),
capturedFunctionNames = listOf(
Name.identifier("clear"),
Name.identifier("put"),
Name.identifier("putAll"),
Name.identifier("remove"),
Name.identifier("set"),
Name.identifier("replace"),
Name.identifier("replaceAll"),
),
getterFunctionName = SpecialNames.THIS,
setterFunctionName = Name.identifier("putAll"),
preSetterFunctionNames = listOf(Name.identifier("clear")),
serializeItSelf = true,
serializeAs = null,
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime", "MutableIntState"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
Name.guessByFirstCharacter("<set-intValue>"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = classId("kotlin", "Int"),
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime", "MutableLongState"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
Name.guessByFirstCharacter("<set-longValue>"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = classId("kotlin", "Long"),
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime", "MutableFloatState"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
Name.guessByFirstCharacter("<set-floatValue>"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = classId("kotlin", "Float"),
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime", "MutableDoubleState"),
capturedFunctionNames = listOf(
Name.guessByFirstCharacter("<set-value>"),
Name.guessByFirstCharacter("<set-doubleValue>"),
),
getterFunctionName = Name.guessByFirstCharacter("<get-value>"),
setterFunctionName = Name.guessByFirstCharacter("<set-value>"),
preSetterFunctionNames = emptyList(),
serializeItSelf = false,
serializeAs = classId("kotlin", "Double"),
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime.snapshots", "SnapshotStateList"),
capturedFunctionNames = listOf(
Name.identifier("add"),
Name.identifier("addAll"),
Name.identifier("clear"),
Name.identifier("remove"),
Name.identifier("removeAll"),
Name.identifier("removeAt"),
Name.identifier("set"),
Name.identifier("replaceAll"),
),
getterFunctionName = SpecialNames.THIS,
setterFunctionName = Name.identifier("addAll"),
preSetterFunctionNames = listOf(Name.identifier("clear")),
serializeItSelf = true,
serializeAs = classId("kotlin.collections", "List"),
),
ValueContainerClassInfo(
classId = classId("androidx.compose.runtime.snapshots", "SnapshotStateMap"),
capturedFunctionNames = listOf(
Name.identifier("clear"),
Name.identifier("put"),
Name.identifier("putAll"),
Name.identifier("remove"),
Name.identifier("set"),
),
getterFunctionName = SpecialNames.THIS,
setterFunctionName = Name.identifier("putAll"),
preSetterFunctionNames = listOf(Name.identifier("clear")),
serializeItSelf = true,
serializeAs = classId("kotlin.collections", "Map"),
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package io.github.kitakkun.backintime
import io.github.kitakkun.backintime.extension.BackInTimeExtension
import io.github.kitakkun.backintime.plugin.BackInTimeCompilerOptionKey
import io.github.kitakkun.backintime.plugin.BackInTimePluginConsts
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
Expand All @@ -14,7 +12,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin
import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
import java.util.Base64

class BackInTimePlugin : KotlinCompilerPluginSupportPlugin {
override fun apply(target: Project) {
Expand Down Expand Up @@ -60,16 +57,7 @@ class BackInTimePlugin : KotlinCompilerPluginSupportPlugin {
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> {
val extension = kotlinCompilation.project.extensions.findByType(BackInTimeExtension::class.java) ?: BackInTimeExtension()
return kotlinCompilation.target.project.provider {
listOf(
SubpluginOption(key = BackInTimeCompilerOptionKey.ENABLED, value = extension.enabled.toString()),
).plus(
extension.valueContainers
.map { Json.encodeToString(it) }
.map { Base64.getEncoder().encodeToString(it.toByteArray(Charsets.UTF_8)) }
.map {
SubpluginOption(key = BackInTimeCompilerOptionKey.VALUE_CONTAINER, value = it)
},
)
listOf(SubpluginOption(key = BackInTimeCompilerOptionKey.ENABLED, value = extension.enabled.toString()))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
package io.github.kitakkun.backintime.extension

import groovy.lang.Closure
import io.github.kitakkun.backintime.plugin.extension.ValueContainerConfig
import kotlinx.serialization.Serializable

@Serializable
open class BackInTimeExtension(
var enabled: Boolean = true,
val valueContainers: MutableList<ValueContainerConfig> = mutableListOf(),
) {
// KTS用
fun valueContainers(configuration: ValueContainersScope.() -> Unit) {
val scope = ValueContainersScope().apply(configuration)
valueContainers.addAll(scope.containers)
}

// Groovy用
fun valueContainers(closure: Closure<ValueContainersScope>) {
val scope = ValueContainersScope()
closure.delegate = scope
closure.call()
valueContainers.addAll(scope.containers)
}
}
)
Loading

0 comments on commit 4d489e5

Please sign in to comment.