Skip to content

Commit

Permalink
#9 Update codegen: implement update method
Browse files Browse the repository at this point in the history
  • Loading branch information
PatilShreyas committed Sep 8, 2022
1 parent c6e2833 commit 570fb30
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ package dev.shreyaspatil.mutekt.codegen.codebuild
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.ksp.toTypeName
import dev.shreyaspatil.mutekt.core.StateFlowable
import dev.shreyaspatil.mutekt.core.AtomicExecutor
import dev.shreyaspatil.mutekt.core.MutektMutableState

object ClassNames {

fun stateFlowableOf(clazz: ClassName) = ClassName(
StateFlowable::class.java.packageName,
StateFlowable::class.simpleName!!
).parameterizedBy(clazz)
fun mutektMutableState(
immutableInterface: ClassName,
mutableInterface: ClassName
) = MutektMutableState::class.asClassName().parameterizedBy(immutableInterface, mutableInterface)

fun stateFlowOf(clazz: ClassName) = ClassName(
"kotlinx.coroutines.flow",
Expand All @@ -47,4 +49,6 @@ object ClassNames {
"kotlinx.coroutines.flow",
"FlowCollector"
).parameterizedBy(clazz)

fun atomicExecutor() = AtomicExecutor::class.asClassName()
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ object MemberNames {
val COROUTINE_SCOPE = MemberName("kotlinx.coroutines", "coroutineScope")
val COMBINE = MemberName("kotlinx.coroutines.flow", "combine")
val STATE_IN = MemberName("kotlinx.coroutines.flow", "stateIn")
val FILTER_NOT_NULL = MemberName("kotlinx.coroutines.flow", "filterNotNull")
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ class MutableInterfaceModelBuilder(

fun build() = TypeSpec.interfaceBuilder(interfaceName)
.addSuperinterface(immutableStateInterface)
.addSuperinterface(ClassNames.stateFlowableOf(immutableStateInterface))
.addSuperinterface(ClassNames.mutektMutableState(immutableStateInterface, thisClass()))
.addKdoc("Mutable state model for [%L]", immutableStateInterface.simpleName)
.addMutableStateModelFields()
.build()

private fun TypeSpec.Builder.addMutableStateModelFields() = apply {
publicProperties.eachToProperty { mutable().addModifiers(KModifier.OVERRIDE) }.forEach { addProperty(it) }
}

private fun thisClass() = ClassName(immutableStateInterface.packageName, interfaceName)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.LambdaTypeName
import com.squareup.kotlinpoet.NOTHING
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.asClassName
import com.squareup.kotlinpoet.buildCodeBlock
import com.squareup.kotlinpoet.ksp.toTypeName
import com.squareup.kotlinpoet.withIndent
Expand All @@ -44,9 +47,11 @@ class MutableClassModelImplBuilder(
.addModifiers(KModifier.PRIVATE)
.addSuperinterface(mutableModelInterfaceName)
.primaryConstructor()
.privateAtomicExecutor()
.addPrivateStateFlowAndGetterSetterFields()
.immutableStateFlowImpl()
.overrideFunAsStateFlow()
.overrideFunUpdate()
.build()

private fun TypeSpec.Builder.primaryConstructor() = apply {
Expand All @@ -58,6 +63,15 @@ class MutableClassModelImplBuilder(
)
}

private fun TypeSpec.Builder.privateAtomicExecutor() = apply {
addProperty(
PropertySpec.builder("_atomicExecutor", ClassNames.atomicExecutor())
.initializer("%T()", ClassNames.atomicExecutor())
.addModifiers(KModifier.PRIVATE)
.build()
)
}

/**
* Creates MutableStateFlow property from [property]
*/
Expand Down Expand Up @@ -120,6 +134,24 @@ class MutableClassModelImplBuilder(
.build()
)
}

private fun TypeSpec.Builder.overrideFunUpdate() = apply {
addFunction(
FunSpec.builder("update")
.addModifiers(KModifier.OVERRIDE)
.addParameter(
ParameterSpec.builder(
name = "mutate",
type = LambdaTypeName.get(
receiver = mutableModelInterfaceName,
returnType = Unit::class.asClassName()
)
).build()
)
.addStatement("_atomicExecutor.execute { mutate() }")
.build()
)
}
}

/**
Expand Down Expand Up @@ -191,27 +223,24 @@ class StateFlowImplBuilder(
beginControlFlow("%M", MemberNames.COROUTINE_SCOPE)
withIndent {
beginControlFlow(
"%M(%L) { params ->",
"%M(_atomicExecutor.executing, %L) { params ->",
MemberNames.COMBINE,
publicProperties.joinToString { "_${it.simpleName.asString()}" }
)

withIndent {
addStatement("Immutable%L(", type.simpleName)
addStatement("val isUpdating = params[0] as Boolean")

withIndent {
publicProperties.forEachIndexed { index, field ->
addStatement(
"%L = params[%L] as %L,",
field.simpleName.asString(),
index,
field.type.toTypeName()
)
}
}
addStatement(")")
beginControlFlow("if (!isUpdating)")
addStatement("value")
endControlFlow()

beginControlFlow("else")
addStatement("null")
endControlFlow()
}
endControlFlow()
addStatement(".%M()", MemberNames.FILTER_NOT_NULL)
addStatement(".%M(this)", MemberNames.STATE_IN)
addStatement(".collect(collector)")
}
Expand Down

0 comments on commit 570fb30

Please sign in to comment.