Add a handler for providing evaluation context for scripts
use it on refinement. also some refactoring on context class and around
This commit is contained in:
@@ -36,7 +36,7 @@ open class ScriptCompilationConfiguration(baseConfigurations: Iterable<ScriptCom
|
|||||||
object Default : ScriptCompilationConfiguration()
|
object Default : ScriptCompilationConfiguration()
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "ScriptCompilationConfiguration($providedProperties)"
|
return "ScriptCompilationConfiguration($properties)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,11 +106,43 @@ interface ScriptEvaluationContextDataKeys
|
|||||||
* The container for script evaluation context data
|
* The container for script evaluation context data
|
||||||
* Used for transferring data to the evaluation refinement callbacks
|
* Used for transferring data to the evaluation refinement callbacks
|
||||||
*/
|
*/
|
||||||
class ScriptEvaluationContextData(properties: Map<PropertiesCollection.Key<*>, Any>) : PropertiesCollection(properties) {
|
class ScriptEvaluationContextData(baseConfigurations: Iterable<ScriptEvaluationContextData>, body: Builder.() -> Unit = {}) :
|
||||||
|
PropertiesCollection(Builder(baseConfigurations).apply(body).data) {
|
||||||
|
|
||||||
|
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
|
||||||
|
constructor(
|
||||||
|
vararg baseConfigurations: ScriptEvaluationContextData, body: Builder.() -> Unit = {}
|
||||||
|
) : this(baseConfigurations.asIterable(), body)
|
||||||
|
|
||||||
|
class Builder internal constructor(baseConfigurations: Iterable<ScriptEvaluationContextData>) :
|
||||||
|
ScriptEvaluationContextDataKeys,
|
||||||
|
PropertiesCollection.Builder(baseConfigurations)
|
||||||
|
|
||||||
companion object : ScriptEvaluationContextDataKeys
|
companion object : ScriptEvaluationContextDataKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optimized alternative to the constructor with multiple base configurations
|
||||||
|
*/
|
||||||
|
fun merge(vararg contexts: ScriptEvaluationContextData?): ScriptEvaluationContextData? {
|
||||||
|
val nonEmpty = ArrayList<ScriptEvaluationContextData>()
|
||||||
|
for (data in contexts) {
|
||||||
|
if (data != null && !data.isEmpty()) {
|
||||||
|
nonEmpty.add(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return when {
|
||||||
|
nonEmpty.isEmpty() -> null
|
||||||
|
nonEmpty.size == 1 -> nonEmpty.first()
|
||||||
|
else -> ScriptEvaluationContextData(nonEmpty.asIterable())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command line arguments of the current process, could be provided by an evaluation host
|
||||||
|
*/
|
||||||
|
val ScriptEvaluationContextDataKeys.commandLineArgs by PropertiesCollection.key<List<String>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The facade to the script data for evaluation configuration refinement callbacks
|
* The facade to the script data for evaluation configuration refinement callbacks
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package kotlin.script.experimental.api
|
|||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.host.getEvaluationContext
|
||||||
import kotlin.script.experimental.util.PropertiesCollection
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
interface ScriptEvaluationConfigurationKeys
|
interface ScriptEvaluationConfigurationKeys
|
||||||
@@ -121,10 +122,14 @@ data class RefineEvaluationConfigurationData(
|
|||||||
fun ScriptEvaluationConfiguration.refineBeforeEvaluation(
|
fun ScriptEvaluationConfiguration.refineBeforeEvaluation(
|
||||||
script: CompiledScript<*>,
|
script: CompiledScript<*>,
|
||||||
contextData: ScriptEvaluationContextData? = null
|
contextData: ScriptEvaluationContextData? = null
|
||||||
): ResultWithDiagnostics<ScriptEvaluationConfiguration> =
|
): ResultWithDiagnostics<ScriptEvaluationConfiguration> {
|
||||||
simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData ->
|
val hostConfiguration = get(ScriptEvaluationConfiguration.hostConfiguration)
|
||||||
refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, contextData))
|
val baseContextData = hostConfiguration?.get(ScriptingHostConfiguration.getEvaluationContext)?.invoke(hostConfiguration)
|
||||||
|
val actualContextData = merge(baseContextData, contextData)
|
||||||
|
return simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData ->
|
||||||
|
refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, actualContextData))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The script evaluation result value
|
* The script evaluation result value
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package kotlin.script.experimental.host
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.experimental.api.KotlinType
|
import kotlin.script.experimental.api.KotlinType
|
||||||
import kotlin.script.experimental.api.ScriptDependency
|
import kotlin.script.experimental.api.ScriptDependency
|
||||||
|
import kotlin.script.experimental.api.ScriptEvaluationContextData
|
||||||
import kotlin.script.experimental.util.PropertiesCollection
|
import kotlin.script.experimental.util.PropertiesCollection
|
||||||
|
|
||||||
interface ScriptingHostConfigurationKeys
|
interface ScriptingHostConfigurationKeys
|
||||||
@@ -52,6 +53,11 @@ val ScriptingHostConfigurationKeys.configurationDependencies by PropertiesCollec
|
|||||||
*/
|
*/
|
||||||
val ScriptingHostConfigurationKeys.getScriptingClass by PropertiesCollection.key<GetScriptingClass>(isTransient = true)
|
val ScriptingHostConfigurationKeys.getScriptingClass by PropertiesCollection.key<GetScriptingClass>(isTransient = true)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluation context getter, allows to provide data to the evaluation configuration refinement functions
|
||||||
|
*/
|
||||||
|
val ScriptingHostConfigurationKeys.getEvaluationContext by PropertiesCollection.key<GetEvaluationContext>(isTransient = true)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface to the generic "class loader" for the types used in the script configurations
|
* The interface to the generic "class loader" for the types used in the script configurations
|
||||||
*/
|
*/
|
||||||
@@ -59,6 +65,18 @@ interface GetScriptingClass {
|
|||||||
operator fun invoke(classType: KotlinType, contextClass: KClass<*>, hostConfiguration: ScriptingHostConfiguration): KClass<*>
|
operator fun invoke(classType: KotlinType, contextClass: KClass<*>, hostConfiguration: ScriptingHostConfiguration): KClass<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper to enable passing lambda directly to the getEvaluationContext "keyword"
|
||||||
|
*/
|
||||||
|
fun ScriptingHostConfiguration.Builder.getEvaluationContext(handler: GetEvaluationContext) {
|
||||||
|
ScriptingHostConfiguration.getEvaluationContext.put(handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface to an evaluation context getter
|
||||||
|
*/
|
||||||
|
typealias GetEvaluationContext = (hostConfiguration: ScriptingHostConfiguration) -> ScriptEvaluationContextData
|
||||||
|
|
||||||
// helper method
|
// helper method
|
||||||
fun ScriptingHostConfiguration.getScriptingClass(type: KotlinType, contextClass: KClass<*>): KClass<*> {
|
fun ScriptingHostConfiguration.getScriptingClass(type: KotlinType, contextClass: KClass<*>): KClass<*> {
|
||||||
val getClass = get(ScriptingHostConfiguration.getScriptingClass)
|
val getClass = get(ScriptingHostConfiguration.getScriptingClass)
|
||||||
|
|||||||
+3
-1
@@ -13,7 +13,7 @@ import kotlin.reflect.KProperty
|
|||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.script.experimental.api.KotlinType
|
import kotlin.script.experimental.api.KotlinType
|
||||||
|
|
||||||
open class PropertiesCollection(private var properties: Map<Key<*>, Any?> = emptyMap()) : Serializable {
|
open class PropertiesCollection(protected var properties: Map<Key<*>, Any?> = emptyMap()) : Serializable {
|
||||||
|
|
||||||
open class Key<T>(
|
open class Key<T>(
|
||||||
val name: String,
|
val name: String,
|
||||||
@@ -64,6 +64,8 @@ open class PropertiesCollection(private var properties: Map<Key<*>, Any?> = empt
|
|||||||
|
|
||||||
val notTransientData: Map<Key<*>, Any?> get() = properties.filterKeys { it !is TransientKey<*>}
|
val notTransientData: Map<Key<*>, Any?> get() = properties.filterKeys { it !is TransientKey<*>}
|
||||||
|
|
||||||
|
fun isEmpty(): Boolean = properties.isEmpty()
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
(other as? PropertiesCollection)?.let { it.properties == properties } == true
|
(other as? PropertiesCollection)?.let { it.properties == properties } == true
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user