diff --git a/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt b/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt index 3e909c2cd55..aa20aba1163 100644 --- a/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt +++ b/libraries/examples/scripting/jvm-maven-deps/script/src/org/jetbrains/kotlin/script/examples/jvm/resolve/maven/scriptDef.kt @@ -32,7 +32,8 @@ object MyConfiguration : ScriptingProperties() { init { include(jvmJavaHomeScriptingProperties) ScriptDefinitionProperties { - defaultImports(DependsOn::class.qualifiedName!!, Repository::class.qualifiedName!!) + defaultImports() + defaultImports() dependencies( JvmDependency( scriptCompilationClasspathFromContext( diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/propertiesDsl.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/propertiesDsl.kt index 0282957fa9b..7b70a98f868 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/api/propertiesDsl.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/api/propertiesDsl.kt @@ -10,7 +10,7 @@ import kotlin.reflect.KType import kotlin.script.experimental.util.ChainedPropertyBag import kotlin.script.experimental.util.TypedKey -interface PropertiesGroup +interface PropertiesGroup open class ScriptingProperties(body: ScriptingProperties.() -> Unit = {}) { @@ -25,10 +25,17 @@ open class ScriptingProperties(body: ScriptingProperties.() -> Unit = {}) { internal fun makePropertyBag(): ChainedPropertyBag = ChainedPropertyBag.createOptimized(parentPropertiesBag ?: parentPropertiesBuilder?.makePropertyBag(), data) - // generic invoke for properties groups + // -------------------------- + // DSL: + + // generic invoke for properties groups, allowing to use syntax: + // PropertiesGroup { + // ... + // } + inline operator fun T.invoke(body: T.() -> Unit) = body() - // chaining + // chaining: private fun chain(propsBag: ChainedPropertyBag?, propsBuilder: ScriptingProperties?, replaceParent: Boolean) { assert(propsBag == null || propsBuilder == null) @@ -46,7 +53,7 @@ open class ScriptingProperties(body: ScriptingProperties.() -> Unit = {}) { chain(props, null, replaceParent) } - // inclusion + // inclusion: fun include(props: ScriptingProperties) { data.putAll(props.data) @@ -56,12 +63,19 @@ open class ScriptingProperties(body: ScriptingProperties.() -> Unit = {}) { data.putAll(props.data) } - // builders for known property types: + // builders for known property types, allowing to use syntax + // propertyKey(value...) + // or + // propertyKey() + + // generic: inline operator fun TypedKey.invoke(v: T) { data[this] = v } + // for KotlinType: + inline operator fun TypedKey.invoke() { data[this] = KotlinType(K::class) } @@ -78,38 +92,93 @@ open class ScriptingProperties(body: ScriptingProperties.() -> Unit = {}) { data[this] = KotlinType(fqname) } + // for list of KotlinTypes + + @JvmName("invoke_kotlintype_list_from_generic") + inline operator fun TypedKey>.invoke() { + data.addToListProperty(this, KotlinType(K::class)) + } + operator fun TypedKey>.invoke(vararg classes: KClass<*>) { - data[this] = classes.map { KotlinType(it) } + data.addToListProperty(this, classes.map { KotlinType(it) }) } operator fun TypedKey>.invoke(vararg types: KType) { - data[this] = types.map { KotlinType(it) } + data.addToListProperty(this, types.map { KotlinType(it) }) } operator fun TypedKey>.invoke(vararg fqnames: String) { - data[this] = fqnames.map { KotlinType(it) } + data.addToListProperty(this, fqnames.map { KotlinType(it) }) } + // generic for list + inline operator fun TypedKey>.invoke(vararg vs: E) { - data[this] = vs.toList() + data.addToListProperty(this, vs.toList()) } + // for map of generic keys to KotlinTypes: + @JvmName("invoke_kotlintype_map_from_kclass") inline operator fun TypedKey>.invoke(vararg classes: Pair>) { - data[this] = HashMap().also { it.putAll(classes.asSequence().map { (k, v) -> k to KotlinType(v) }) } + data.addToMapProperty(this, classes.map { (k, v) -> k to KotlinType(v) }) } @JvmName("invoke_kotlintype_map_from_ktype") inline operator fun TypedKey>.invoke(vararg types: Pair) { - data[this] = HashMap().also { it.putAll(types.asSequence().map { (k, v) -> k to KotlinType(v) }) } + data.addToMapProperty(this, types.map { (k, v) -> k to KotlinType(v) }) } @JvmName("invoke_kotlintype_map_from_fqname") inline operator fun TypedKey>.invoke(vararg fqnames: Pair) { - data[this] = HashMap().also { it.putAll(fqnames.asSequence().map { (k, v) -> k to KotlinType(v) }) } + data.addToMapProperty(this, fqnames.map { (k, v) -> k to KotlinType(v) }) } + // generic for maps: + inline operator fun TypedKey>.invoke(vararg vs: Pair) { - data[this] = hashMapOf(*vs) + data.addToMapProperty(this, vs.asIterable()) + } + + // for strings and list of strings that could be converted from other types + + @JvmName("invoke_string_fqn_from_generic") + inline operator fun TypedKey.invoke() { + data[this] = K::class.qualifiedName!! + } + + @JvmName("invoke_string_fqn_from_reflected_class") + operator fun TypedKey.invoke(kclass: KClass<*>) { + data[this] = kclass.qualifiedName!! + } + + @JvmName("invoke_string_list_fqn_from_generic") + inline operator fun TypedKey>.invoke() { + data.addToListProperty(this, K::class.qualifiedName!!) + } + + @JvmName("invoke_string_list_fqn_from_reflected_class") + operator fun TypedKey>.invoke(vararg kclasses: KClass<*>) { + data.addToListProperty(this, kclasses.map { it.qualifiedName!! }) } } + +fun HashMap, Any?>.addToListProperty(key: TypedKey>, values: Iterable) { + val newValues = get(key)?.let { (it as List) + values } ?: values.toList() + put(key, newValues) +} + +fun HashMap, Any?>.addToListProperty(key: TypedKey>, vararg values: V) { + val newValues = get(key)?.let { (it as List) + values } ?: values.toList() + put(key, newValues) +} + +fun HashMap, Any?>.addToMapProperty(key: TypedKey>, values: Map) { + val newValues = get(key)?.let { (it as Map) + values } ?: values + put(key, newValues) +} + +fun HashMap, Any?>.addToMapProperty(key: TypedKey>, values: Iterable>) { + val newValues = get(key)?.let { (it as Map) + values } ?: values + put(key, newValues) +}