From 799bcebfb2bc87d2e6b156a21df1a174b2557561 Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Fri, 13 Sep 2024 16:44:49 +0200 Subject: [PATCH] Use delegates instead of recursive computes when generating args --- odoo/build.gradle.kts | 1 - odoo/src/CliGenerator.kt | 105 +++++++++++++ odoo/src/ContextGenerator.kt | 137 +++-------------- odoo/src/Odoo.kt | 227 ++++++++++++++--------------- odoo/src/actions/ActionProvider.kt | 10 +- odoo/src/actions/LaunchAction.kt | 12 +- odoo/src/commands/LaunchCommand.kt | 42 +----- odoo/src/commands/Widgets.kt | 8 +- 8 files changed, 256 insertions(+), 286 deletions(-) create mode 100644 odoo/src/CliGenerator.kt diff --git a/odoo/build.gradle.kts b/odoo/build.gradle.kts index 9840ddc..17a5dc2 100644 --- a/odoo/build.gradle.kts +++ b/odoo/build.gradle.kts @@ -16,7 +16,6 @@ dependencies { implementation(libs.process) implementation(libs.xmlbuilder) implementation(libs.kodein.di) - implementation(libs.kotlin.reflect) implementation(libs.serialization.json) testImplementation(testFixtures(project(":workspace"))) diff --git a/odoo/src/CliGenerator.kt b/odoo/src/CliGenerator.kt new file mode 100644 index 0000000..57824cc --- /dev/null +++ b/odoo/src/CliGenerator.kt @@ -0,0 +1,105 @@ +package com.github.hubvd.odootools.odoo + +import kotlin.properties.PropertyDelegateProvider +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +class OptionCompute( + val name: String, + initialValue: String?, + private val block: (() -> String?)? = null, +) : ReadOnlyProperty { + private var value = initialValue + private var hasBeenCalled = false + + fun get(): String? { + if (value == null && !hasBeenCalled && block != null) { + value = block() + hasBeenCalled = true + } + return value + } + + override fun getValue(thisRef: CliGenerator, property: KProperty<*>) = get() +} + +class EnvCompute( + val name: String, + private val block: (() -> String?)? = null, +) : ReadOnlyProperty { + private var value: String? = null + private var hasBeenCalled = false + + fun get(): String? { + if (!hasBeenCalled && block != null) { + value = block() + hasBeenCalled = true + } + return value + } + + override fun getValue(thisRef: CliGenerator, property: KProperty<*>) = get() +} + +class FlagCompute( + val name: String, + initialValue: Boolean, + private val block: (() -> Boolean)? = null, +) : ReadOnlyProperty { + private var value = initialValue + private var hasBeenCalled = false + + fun get(): Boolean { + if (!value && !hasBeenCalled && block != null) { + value = block() + hasBeenCalled = true + } + return value + } + + override fun getValue(thisRef: CliGenerator, property: KProperty<*>) = get() +} + +abstract class CliGenerator( + options: Map, + flags: Set, +) { + + private val options: MutableMap = options.toMap(HashMap()) + private val flags = flags.toHashSet() + private val camelCaseRe = Regex("([a-z0-9])([A-Z])") + + val registeredOptions = ArrayList() + val registeredFlags = ArrayList() + val registeredEnv = ArrayList() + val registeredEffects = ArrayList<() -> Unit>() + + fun effect(block: () -> Unit) { + registeredEffects += block + } + + fun option( + block: (() -> String?)? = null, + ): PropertyDelegateProvider> = + PropertyDelegateProvider { thisRef, property -> + val name = camelCaseRe.replace(property.name, "\$1-\$2").lowercase() + OptionCompute(name, options[name], block).also { registeredOptions += it } + } + + fun flag( + block: (() -> Boolean)? = null, + ): PropertyDelegateProvider> = + PropertyDelegateProvider { thisRef, property -> + val name = camelCaseRe.replace(property.name, "\$1-\$2").lowercase() + FlagCompute(name, flags.contains(name), block).also { registeredFlags += it } + } + + fun env( + name: String? = null, + block: () -> String?, + ): PropertyDelegateProvider> = + PropertyDelegateProvider { thisRef, property -> + val name = name ?: camelCaseRe.replace(property.name, "\$1_\$2").uppercase() + EnvCompute(name, block).also { registeredEnv += it } + } +} diff --git a/odoo/src/ContextGenerator.kt b/odoo/src/ContextGenerator.kt index 1208547..c067fa1 100644 --- a/odoo/src/ContextGenerator.kt +++ b/odoo/src/ContextGenerator.kt @@ -5,11 +5,7 @@ import com.github.ajalt.clikt.parameters.options.OptionWithValues import com.github.hubvd.odootools.odoo.commands.* import com.github.hubvd.odootools.workspace.Workspace import com.github.hubvd.odootools.workspace.WorkspaceConfig -import java.lang.reflect.Proxy import java.nio.file.Path -import kotlin.reflect.full.declaredMemberProperties -import kotlin.reflect.jvm.javaGetter -import kotlin.reflect.typeOf private typealias StringOption = OptionWithValues private typealias Flag = OptionWithValues @@ -18,15 +14,10 @@ data class RunConfiguration( val args: List, val env: Map, val cwd: Path, - val context: DslContext, - val effects: List<(DslContext) -> Unit>, + val odoo: Odoo, + val effects: List<() -> Unit>, ) -@DslMarker -annotation class CmdComputeDsl - -typealias Effect = (DslContext) -> Unit - class ContextGenerator( private val options: List