Rename heterogeneous map to PropertyBag, make it chainable

the commit is needed to implement single chained script configuration bags
This commit is contained in:
Ilya Chernikov
2018-03-27 16:56:23 +02:00
parent 15fcee474c
commit 495c75c48e
19 changed files with 59 additions and 77 deletions
@@ -40,8 +40,8 @@ import kotlin.concurrent.read
import kotlin.concurrent.write
import kotlin.script.dependencies.Environment
import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.api.ScriptingEnvironment
import kotlin.script.experimental.api.ScriptingEnvironmentParams
import kotlin.script.experimental.api.ChainedPropertyBag
import kotlin.script.experimental.api.ScriptingEnvironmentProperties
import kotlin.script.experimental.definitions.ScriptDefinitionFromAnnotatedBaseClass
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
@@ -165,7 +165,7 @@ fun loadDefinitionsFromTemplates(
}
template.annotations.firstIsInstanceOrNull<kotlin.script.experimental.annotations.KotlinScript>() != null -> {
KotlinScriptDefinitionAdapterFromNewAPI(
ScriptDefinitionFromAnnotatedBaseClass(ScriptingEnvironment(ScriptingEnvironmentParams.baseClass to template))
ScriptDefinitionFromAnnotatedBaseClass(ChainedPropertyBag(ScriptingEnvironmentProperties.baseClass to template))
)
}
else -> {
@@ -19,7 +19,7 @@ import kotlin.script.experimental.jvmhost.impl.KJVMCompilerImpl
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val scriptCompiler = JvmScriptCompiler(KJVMCompilerImpl(), DummyCompiledJvmScriptCache())
val scriptDefinition = ScriptDefinitionFromAnnotatedBaseClass(
ScriptingEnvironment(ScriptingEnvironmentParams.baseClass to MyScriptWithMavenDeps::class)
ChainedPropertyBag(ScriptingEnvironmentProperties.baseClass to MyScriptWithMavenDeps::class)
)
val host = JvmBasicScriptingHost(
@@ -27,7 +27,7 @@ abstract class MyScriptWithMavenDeps {
}
inline fun myJvmConfig(
from: HeterogeneousMap = HeterogeneousMap(),
from: ChainedPropertyBag = ChainedPropertyBag(),
crossinline body: JvmScriptCompileConfigurationParams.Builder.() -> Unit = {}
) = jvmConfigWithJavaHome(from) {
signature<MyScriptWithMavenDeps>()
@@ -42,12 +42,12 @@ inline fun myJvmConfig(
body()
}
class MyConfigurator(val environment: ScriptingEnvironment) : ScriptCompilationConfigurator {
class MyConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationConfigurator {
private val resolver = FilesAndMavenResolver()
override val defaultConfiguration = myJvmConfig {
add(ScriptCompileConfigurationParams.baseClass to environment[ScriptingEnvironmentParams.baseClass])
add(ScriptCompileConfigurationParams.baseClass to environment[ScriptingEnvironmentProperties.baseClass])
}
override suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration> =
@@ -15,7 +15,7 @@ import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvmhost.impl.KJVMCompilerImpl
inline fun myJvmConfig(
from: HeterogeneousMap = HeterogeneousMap(),
from: ChainedPropertyBag = ChainedPropertyBag(),
crossinline body: JvmScriptCompileConfigurationParams.Builder.() -> Unit = {}
) = jvmConfigWithJavaHome(from) {
signature<MyScript>()
@@ -26,7 +26,7 @@ inline fun myJvmConfig(
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val scriptCompiler = JvmScriptCompiler(KJVMCompilerImpl(), DummyCompiledJvmScriptCache())
val scriptDefinition = ScriptDefinitionFromAnnotatedBaseClass(
ScriptingEnvironment(ScriptingEnvironmentParams.baseClass to MyScript::class)
ChainedPropertyBag(ScriptingEnvironmentProperties.baseClass to MyScript::class)
)
val host = JvmBasicScriptingHost(
@@ -8,14 +8,14 @@
package kotlin.script.experimental.api
typealias ScriptCompileConfiguration = HeterogeneousMap
typealias ScriptCompileConfiguration = ChainedPropertyBag
typealias ProcessedScriptData = HeterogeneousMap
typealias ProcessedScriptData = ChainedPropertyBag
interface ScriptCompilationConfigurator {
// constructor(environment: ScriptingEnvironment) // the constructor is expected from implementations
// constructor(environment: ChainedPropertyBag) // the constructor is expected from implementations
val defaultConfiguration: ScriptCompileConfiguration
@@ -31,21 +31,10 @@ object ScriptCompileConfigurationParams {
val updateConfigurationOnSections by typedKey<Iterable<String>>()
open class Builder : HeterogeneousMapBuilder() {
open class Builder(parentBuilder: PropertyBagBuilder? = null) : PropertyBagBuilder(parentBuilder) {
inline fun <reified T> signature(providedDeclarations: ProvidedDeclarations = ProvidedDeclarations.Empty) {
add(scriptSignature to ScriptSignature(T::class, providedDeclarations))
}
}
}
// DSL
inline fun scriptConfiguration(from: HeterogeneousMap = HeterogeneousMap(), body: ScriptCompileConfigurationParams.Builder.() -> Unit) =
ScriptCompileConfigurationParams.Builder().build(from, body)
fun ScriptSource.toScriptCompileConfiguration(vararg pairs: Pair<TypedKey<*>, Any?>) =
ScriptCompileConfiguration(ScriptCompileConfigurationParams.scriptSourceFragments to ScriptSourceFragments(this, null), *pairs)
fun ScriptSource?.toConfigEntry(): Pair<TypedKey<*>, Any?> =
ScriptCompileConfigurationParams.scriptSourceFragments to this?.let { ScriptSourceFragments(this, null) }
@@ -10,9 +10,9 @@ package kotlin.script.experimental.api
interface ScriptDefinition {
// constructor(environment: ScriptingEnvironment) // the constructor is expected from implementations
// constructor(environment: ChainedPropertyBag) // the constructor is expected from implementations
val properties: ScriptDefinitionPropertiesBag
val properties: ChainedPropertyBag
val compilationConfigurator: ScriptCompilationConfigurator
@@ -7,22 +7,12 @@
package kotlin.script.experimental.api
typealias ScriptDefinitionPropertiesBag = HeterogeneousMap
object ScriptDefinitionProperties {
object ScriptDefinitionProperties : PropertiesBase<ScriptDefinitionProperties>() {
val name by typedKey<String>()
val fileExtension by typedKey<String>()
val makeTitle by typedKey<(String) -> String>()
open class Builder : HeterogeneousMapBuilder() {
inline fun <reified T> makeTitle(noinline fn: (String) -> String) {
add(makeTitle to fn)
}
}
open class Builder(parentBuilder: PropertyBagBuilder? = null) : PropertyBagBuilder(parentBuilder)
}
@@ -7,7 +7,7 @@
package kotlin.script.experimental.api
open class ScriptEvaluationEnvironmentParams : HeterogeneousMapBuilder() {
open class ScriptEvaluationEnvironmentParams : PropertyBagBuilder() {
companion object {
val implicitReceivers by typedKey<List<Any>>()
@@ -19,17 +19,17 @@ open class ScriptEvaluationEnvironmentParams : HeterogeneousMapBuilder() {
}
}
inline fun scriptEvaluationEnvironment(from: HeterogeneousMap = HeterogeneousMap(), body: ScriptEvaluationEnvironmentParams.() -> Unit) =
inline fun scriptEvaluationEnvironment(from: ChainedPropertyBag = ChainedPropertyBag(), body: ScriptEvaluationEnvironmentParams.() -> Unit) =
ScriptEvaluationEnvironmentParams().build(from, body)
typealias ScriptEvaluationEnvironment = HeterogeneousMap
typealias ScriptEvaluationEnvironment = ChainedPropertyBag
data class EvaluationResult(val returnValue: Any?, val environment: ScriptEvaluationEnvironment)
// NOTE: name inconsistency: run vs evaluate
interface ScriptEvaluator<in ScriptBase : Any> {
// constructor(environment: ScriptingEnvironment) // the constructor is expected from implementations
// constructor(environment: ChainedPropertyBag) // the constructor is expected from implementations
suspend fun eval(
compiledScript: CompiledScript<ScriptBase>,
@@ -5,7 +5,7 @@
package kotlin.script.experimental.api
class ProcessedScriptDataParams : HeterogeneousMapBuilder() {
class ProcessedScriptDataParams : PropertyBagBuilder() {
companion object {
val annotations by typedKey<Iterable<Annotation>>()
@@ -13,5 +13,5 @@ class ProcessedScriptDataParams : HeterogeneousMapBuilder() {
}
}
inline fun processedScriptData(from: HeterogeneousMap = HeterogeneousMap(), body: ProcessedScriptDataParams.() -> Unit) =
inline fun processedScriptData(from: ChainedPropertyBag = ChainedPropertyBag(), body: ProcessedScriptDataParams.() -> Unit) =
ProcessedScriptDataParams().build(from, body)
@@ -6,8 +6,7 @@
package kotlin.script.experimental.api
import kotlin.reflect.KProperty
// copy placed into package org.jetbrains.kotlin.utils.addToStdlib as well
import kotlin.reflect.full.primaryConstructor
data class TypedKey<T>(val name: String)
@@ -17,23 +16,27 @@ class TypedKeyDelegate<T> {
fun <T> typedKey() = TypedKeyDelegate<T>()
class HeterogeneousMap(private val data: Map<TypedKey<*>, Any?> = hashMapOf()) {
constructor(vararg pairs: Pair<TypedKey<*>, Any?>) : this(hashMapOf(*pairs))
constructor(from: HeterogeneousMap, vararg pairs: Pair<TypedKey<*>, Any?>) : this(HashMap(from.data).apply { putAll(pairs) })
constructor(from: HeterogeneousMap, pairs: Iterable<Pair<TypedKey<*>, Any?>>) : this(HashMap(from.data).apply { putAll(pairs) })
class ChainedPropertyBag(private val parent: ChainedPropertyBag? = null, private val data: Map<TypedKey<*>, Any?> = hashMapOf()) {
constructor(data: Map<TypedKey<*>, Any?>) : this(null, data)
constructor(parent: ChainedPropertyBag?, pairs: Iterable<Pair<TypedKey<*>, Any?>>) : this(
parent,
HashMap<TypedKey<*>, Any?>().also {
it.putAll(pairs)
})
constructor(parent: ChainedPropertyBag?, vararg pairs: Pair<TypedKey<*>, Any?>) : this(parent, hashMapOf(*pairs))
operator fun <T> get(key: TypedKey<T>): T =
if (data.containsKey(key)) data[key] as T
else throw IllegalArgumentException("Unknown key $key")
when {
data.containsKey(key) -> data[key] as T
parent != null -> parent[key]
else -> throw IllegalArgumentException("Unknown key $key")
}
fun <T> getOrNull(key: TypedKey<T>): T? = data[key] as T?
fun <T> getOrNull(key: TypedKey<T>): T? = data[key] as T? ?: parent?.getOrNull(key)
}
fun HeterogeneousMap.cloneWith(vararg pairs: Pair<TypedKey<*>, Any?>) = HeterogeneousMap(this, *pairs)
fun HeterogeneousMap.cloneWith(pairs: Iterable<Pair<TypedKey<*>, Any?>>) = HeterogeneousMap(this, pairs)
open class HeterogeneousMapBuilder {
open class PropertyBagBuilder(private val parentBuilder: PropertyBagBuilder? = null) {
val pairs: MutableList<Pair<TypedKey<*>, Any?>> = arrayListOf()
open operator fun <T> TypedKey<T>.invoke(v: T) {
@@ -43,9 +46,11 @@ open class HeterogeneousMapBuilder {
fun add(pair: Pair<TypedKey<*>, Any?>) {
pairs.add(pair)
}
fun getAllPairs() = if (parentBuilder == null) pairs else parentBuilder.pairs + pairs
}
inline fun <T : HeterogeneousMapBuilder> T.build(from: HeterogeneousMap = HeterogeneousMap(), body: T.() -> Unit): HeterogeneousMap {
inline fun <T : PropertyBagBuilder> T.build(parent: ChainedPropertyBag? = null, body: T.() -> Unit): ChainedPropertyBag {
body()
return HeterogeneousMap(from, pairs)
return ChainedPropertyBag(parent, getAllPairs())
}
@@ -7,13 +7,11 @@ package kotlin.script.experimental.api
import kotlin.reflect.KClass
typealias ScriptingEnvironment = HeterogeneousMap
object ScriptingEnvironmentParams {
object ScriptingEnvironmentProperties {
// required by definitions that extract data from script base class annotations
val baseClass by typedKey<KClass<*>>()
open class Builder : HeterogeneousMapBuilder()
open class Builder(parentBuilder: PropertyBagBuilder? = null) : PropertyBagBuilder(parentBuilder)
}
@@ -8,10 +8,10 @@ package kotlin.script.experimental.basic
import kotlin.script.experimental.api.*
class PassThroughCompilationConfigurator(val environment: ScriptingEnvironment) : ScriptCompilationConfigurator {
class PassThroughCompilationConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationConfigurator {
override val defaultConfiguration = ScriptCompileConfiguration(
ScriptCompileConfigurationParams.baseClass to environment[ScriptingEnvironmentParams.baseClass]
ScriptCompileConfigurationParams.baseClass to environment[ScriptingEnvironmentProperties.baseClass]
)
override suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration> =
@@ -24,7 +24,7 @@ class PassThroughCompilationConfigurator(val environment: ScriptingEnvironment)
configuration.asSuccess()
}
class DummyEvaluator<ScriptBase : Any>(val environment: ScriptingEnvironment) : ScriptEvaluator<ScriptBase> {
class DummyEvaluator<ScriptBase : Any>(val environment: ChainedPropertyBag) : ScriptEvaluator<ScriptBase> {
override suspend fun eval(
compiledScript: CompiledScript<ScriptBase>,
scriptEvaluationEnvironment: ScriptEvaluationEnvironment
@@ -18,9 +18,9 @@ import kotlin.script.experimental.basic.PassThroughCompilationConfigurator
private const val ERROR_MSG_PREFIX = "Unable to construct script definition: "
open class ScriptDefinitionFromAnnotatedBaseClass(val environment: ScriptingEnvironment) : ScriptDefinition {
open class ScriptDefinitionFromAnnotatedBaseClass(val environment: ChainedPropertyBag) : ScriptDefinition {
private val baseClass: KClass<*> = environment.getOrNull(ScriptingEnvironmentParams.baseClass)
private val baseClass: KClass<*> = environment.getOrNull(ScriptingEnvironmentProperties.baseClass)
?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting baseClass parameter in the scripting environment")
private val mainAnnotation = baseClass.findAnnotation<KotlinScript>()
@@ -29,7 +29,7 @@ open class ScriptDefinitionFromAnnotatedBaseClass(val environment: ScriptingEnvi
private val explicitDefinition: ScriptDefinition? =
mainAnnotation.definition.takeIf { it != this::class }?.let { it.instantiateScriptHandler() }
override val properties = (explicitDefinition?.properties ?: ScriptDefinitionPropertiesBag()).also { properties ->
override val properties = (explicitDefinition?.properties ?: ChainedPropertyBag()).also { properties ->
val toAdd = arrayListOf<Pair<TypedKey<*>, Any>>()
baseClass.findAnnotation<KotlinScriptFileExtension>()?.let { toAdd += ScriptDefinitionProperties.fileExtension to it }
if (properties.getOrNull(ScriptDefinitionProperties.name) == null) {
@@ -11,7 +11,7 @@ import java.io.File
import kotlin.script.experimental.jvm.JvmScriptCompileConfigurationParams.javaHomeDir
inline fun jvmConfigWithJavaHome(
from: HeterogeneousMap = HeterogeneousMap(),
from: ChainedPropertyBag = ChainedPropertyBag(),
crossinline body: JvmScriptCompileConfigurationParams.Builder.() -> Unit = {}
) =
jvmScriptConfiguration(from) {
@@ -17,7 +17,7 @@ object JvmScriptCompileConfigurationParams {
}
}
inline fun jvmScriptConfiguration(from: HeterogeneousMap = HeterogeneousMap(), body: JvmScriptCompileConfigurationParams.Builder.() -> Unit) =
inline fun jvmScriptConfiguration(from: ChainedPropertyBag = ChainedPropertyBag(), body: JvmScriptCompileConfigurationParams.Builder.() -> Unit) =
JvmScriptCompileConfigurationParams.Builder().build(from, body)
class JvmDependency(val classpath: Iterable<File>) : ScriptDependency
@@ -22,5 +22,5 @@ class JvmScriptEvaluationEnvironmentParams : ScriptEvaluationEnvironmentParams()
}
}
inline fun jvmScriptEvaluationEnvironment(from: HeterogeneousMap = HeterogeneousMap(), body: JvmScriptEvaluationEnvironmentParams.() -> Unit) =
inline fun jvmScriptEvaluationEnvironment(from: ChainedPropertyBag = ChainedPropertyBag(), body: JvmScriptEvaluationEnvironmentParams.() -> Unit) =
JvmScriptEvaluationEnvironmentParams().build(from, body)
@@ -7,7 +7,7 @@ package kotlin.script.experimental.jvm.runners
import kotlin.script.experimental.api.*
open class BasicJvmScriptEvaluator<ScriptBase : Any>(val environment: ScriptingEnvironment) : ScriptEvaluator<ScriptBase> {
open class BasicJvmScriptEvaluator<ScriptBase : Any>(val environment: ChainedPropertyBag) : ScriptEvaluator<ScriptBase> {
override suspend fun eval(
compiledScript: CompiledScript<ScriptBase>,
@@ -20,8 +20,8 @@ import java.io.File
import java.io.IOException
import java.net.URLClassLoader
import java.util.jar.JarFile
import kotlin.script.experimental.api.ScriptingEnvironment
import kotlin.script.experimental.api.ScriptingEnvironmentParams
import kotlin.script.experimental.api.ChainedPropertyBag
import kotlin.script.experimental.api.ScriptingEnvironmentProperties
import kotlin.script.experimental.definitions.ScriptDefinitionFromAnnotatedBaseClass
class ScriptingCompilerConfigurationExtension(val project: MockProject) : CompilerConfigurationExtension {
@@ -127,7 +127,7 @@ fun configureScriptDefinitions(
val def =
if (cls.annotations.firstIsInstanceOrNull<kotlin.script.experimental.annotations.KotlinScript>() != null) {
KotlinScriptDefinitionAdapterFromNewAPI(
ScriptDefinitionFromAnnotatedBaseClass(ScriptingEnvironment(ScriptingEnvironmentParams.baseClass to cls.kotlin))
ScriptDefinitionFromAnnotatedBaseClass(ChainedPropertyBag(ScriptingEnvironmentProperties.baseClass to cls.kotlin))
)
} else {
KotlinScriptDefinitionFromAnnotatedTemplate(cls.kotlin, scriptResolverEnv)