Implement composable refinement handlers...
for compilation and evaluation configurations. Add utilities to apply refinements uniformly. Also fix one invoke for list values - it was not consistent with other builders
This commit is contained in:
@@ -130,17 +130,17 @@ val ScriptCompilationConfigurationKeys.compilerOptions by PropertiesCollection.k
|
||||
/**
|
||||
* The callback that will be called on the script compilation before parsing the script
|
||||
*/
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationBeforeParsing by PropertiesCollection.key<RefineConfigurationUnconditionallyData>()
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationBeforeParsing by PropertiesCollection.key<List<RefineConfigurationUnconditionallyData>>()
|
||||
|
||||
/**
|
||||
* The callback that will be called on the script compilation after parsing script file annotations
|
||||
*/
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationOnAnnotations by PropertiesCollection.key<RefineConfigurationOnAnnotationsData>()
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationOnAnnotations by PropertiesCollection.key<List<RefineConfigurationOnAnnotationsData>>()
|
||||
|
||||
/**
|
||||
* The callback that will be called on the script compilation immediately before starting the compilation
|
||||
*/
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationBeforeCompiling by PropertiesCollection.key<RefineConfigurationUnconditionallyData>()
|
||||
val ScriptCompilationConfigurationKeys.refineConfigurationBeforeCompiling by PropertiesCollection.key<List<RefineConfigurationUnconditionallyData>>()
|
||||
|
||||
/**
|
||||
* The list of script fragments that should be compiled intead of the whole text
|
||||
@@ -166,7 +166,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() {
|
||||
* @param handler the callback that will be called
|
||||
*/
|
||||
fun beforeParsing(handler: RefineScriptCompilationConfigurationHandler) {
|
||||
set(ScriptCompilationConfiguration.refineConfigurationBeforeParsing, RefineConfigurationUnconditionallyData(handler))
|
||||
ScriptCompilationConfiguration.refineConfigurationBeforeParsing.append(RefineConfigurationUnconditionallyData(handler))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +176,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() {
|
||||
*/
|
||||
fun onAnnotations(annotations: List<KotlinType>, handler: RefineScriptCompilationConfigurationHandler) {
|
||||
// TODO: implement handlers composition
|
||||
set(ScriptCompilationConfiguration.refineConfigurationOnAnnotations, RefineConfigurationOnAnnotationsData(annotations, handler))
|
||||
ScriptCompilationConfiguration.refineConfigurationOnAnnotations.append(RefineConfigurationOnAnnotationsData(annotations, handler))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() {
|
||||
* @param handler the callback that will be called
|
||||
*/
|
||||
fun beforeCompiling(handler: RefineScriptCompilationConfigurationHandler) {
|
||||
set(ScriptCompilationConfiguration.refineConfigurationBeforeCompiling, RefineConfigurationUnconditionallyData(handler))
|
||||
ScriptCompilationConfiguration.refineConfigurationBeforeCompiling.append(RefineConfigurationUnconditionallyData(handler))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,20 +230,72 @@ class RefineConfigurationBuilder : PropertiesCollection.Builder() {
|
||||
typealias RefineScriptCompilationConfigurationHandler =
|
||||
(ScriptConfigurationRefinementContext) -> ResultWithDiagnostics<ScriptCompilationConfiguration>
|
||||
|
||||
/**
|
||||
* The refinement callback function signature for simple handlers (without diagnostics or errors)
|
||||
*/
|
||||
typealias SimpleRefineScriptCompilationConfigurationHandler =
|
||||
(ScriptConfigurationRefinementContext) -> ScriptCompilationConfiguration
|
||||
|
||||
data class RefineConfigurationUnconditionallyData(
|
||||
val handler: RefineScriptCompilationConfigurationHandler
|
||||
) : Serializable {
|
||||
companion object { private const val serialVersionUID: Long = 1L }
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
}
|
||||
|
||||
data class RefineConfigurationOnAnnotationsData(
|
||||
val annotations: List<KotlinType>,
|
||||
val handler: RefineScriptCompilationConfigurationHandler
|
||||
) : Serializable {
|
||||
companion object { private const val serialVersionUID: Long = 1L }
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun ScriptCompilationConfiguration.refineBeforeParsing(
|
||||
script: SourceCode,
|
||||
collectedData: ScriptCollectedData? = null
|
||||
): ResultWithDiagnostics<ScriptCompilationConfiguration> =
|
||||
simpleRefineImpl(ScriptCompilationConfiguration.refineConfigurationBeforeParsing) { config, refineData ->
|
||||
refineData.handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData))
|
||||
}
|
||||
|
||||
fun ScriptCompilationConfiguration.refineOnAnnotations(
|
||||
script: SourceCode,
|
||||
collectedData: ScriptCollectedData
|
||||
): ResultWithDiagnostics<ScriptCompilationConfiguration> {
|
||||
val foundAnnotationNames = collectedData[ScriptCollectedData.foundAnnotations]?.mapTo(HashSet()) { it.annotationClass.java.name }
|
||||
if (foundAnnotationNames.isNullOrEmpty()) return this.asSuccess()
|
||||
|
||||
val refinedConfig = this[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]
|
||||
?.fold(this) { config, (annotations, handler) ->
|
||||
// checking that the collected data contains expected annotations
|
||||
if (annotations.none { foundAnnotationNames.contains(it.typeName) }) config
|
||||
else handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData)).valueOr { return it }
|
||||
}
|
||||
return (refinedConfig ?: this).asSuccess()
|
||||
}
|
||||
|
||||
fun ScriptCompilationConfiguration.refineBeforeCompiling(
|
||||
script: SourceCode,
|
||||
collectedData: ScriptCollectedData? = null
|
||||
): ResultWithDiagnostics<ScriptCompilationConfiguration> =
|
||||
simpleRefineImpl(ScriptCompilationConfiguration.refineConfigurationBeforeCompiling) { config, refineData ->
|
||||
refineData.handler.invoke(ScriptConfigurationRefinementContext(script, config, collectedData))
|
||||
}
|
||||
|
||||
internal inline fun <Configuration: PropertiesCollection, RefineData> Configuration.simpleRefineImpl(
|
||||
key: PropertiesCollection.Key<List<RefineData>>,
|
||||
refineFn: (Configuration, RefineData) -> ResultWithDiagnostics<Configuration>
|
||||
): ResultWithDiagnostics<Configuration> = (
|
||||
this[key]
|
||||
?.fold(this) { config, refineData ->
|
||||
refineFn(config, refineData).valueOr { return it }
|
||||
} ?: this
|
||||
).asSuccess()
|
||||
|
||||
/**
|
||||
* The functional interface to the script compiler
|
||||
*/
|
||||
|
||||
@@ -94,7 +94,7 @@ val ScriptCollectedDataKeys.foundAnnotations by PropertiesCollection.key<List<An
|
||||
/**
|
||||
* The facade to the script data for compilation configuration refinement callbacks
|
||||
*/
|
||||
class ScriptConfigurationRefinementContext(
|
||||
data class ScriptConfigurationRefinementContext(
|
||||
val script: SourceCode,
|
||||
val compilationConfiguration: ScriptCompilationConfiguration,
|
||||
val collectedData: ScriptCollectedData? = null
|
||||
@@ -114,7 +114,7 @@ class ScriptEvaluationContextData(properties: Map<PropertiesCollection.Key<*>, A
|
||||
/**
|
||||
* The facade to the script data for evaluation configuration refinement callbacks
|
||||
*/
|
||||
class ScriptEvaluationConfigurationRefinementContext(
|
||||
data class ScriptEvaluationConfigurationRefinementContext(
|
||||
val compiledScript: CompiledScript<*>,
|
||||
val evaluationConfiguration: ScriptEvaluationConfiguration,
|
||||
val contextData: ScriptEvaluationContextData? = null
|
||||
|
||||
@@ -88,7 +88,7 @@ val ScriptEvaluationConfigurationKeys.hostConfiguration by PropertiesCollection.
|
||||
/**
|
||||
* The callback that will be called on the script compilation immediately before starting the compilation
|
||||
*/
|
||||
val ScriptEvaluationConfigurationKeys.refineConfigurationBeforeEvaluate by PropertiesCollection.key<RefineEvaluationConfigurationData>()
|
||||
val ScriptEvaluationConfigurationKeys.refineConfigurationBeforeEvaluate by PropertiesCollection.key<List<RefineEvaluationConfigurationData>>()
|
||||
|
||||
/**
|
||||
* A helper to enable scriptsInstancesSharingMap with default implementation
|
||||
@@ -103,7 +103,7 @@ fun ScriptEvaluationConfiguration.Builder.enableScriptsInstancesSharing() {
|
||||
* A helper to enable passing lambda directly to the refinement "keyword"
|
||||
*/
|
||||
fun ScriptEvaluationConfiguration.Builder.refineConfigurationBeforeEvaluate(handler: RefineScriptEvaluationConfigurationHandler) {
|
||||
set(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate, RefineEvaluationConfigurationData(handler))
|
||||
ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate.append(RefineEvaluationConfigurationData(handler))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,6 +118,14 @@ data class RefineEvaluationConfigurationData(
|
||||
companion object { private const val serialVersionUID: Long = 1L }
|
||||
}
|
||||
|
||||
fun ScriptEvaluationConfiguration.refineBeforeEvaluation(
|
||||
script: CompiledScript<*>,
|
||||
contextData: ScriptEvaluationContextData? = null
|
||||
): ResultWithDiagnostics<ScriptEvaluationConfiguration> =
|
||||
simpleRefineImpl(ScriptEvaluationConfiguration.refineConfigurationBeforeEvaluate) { config, refineData ->
|
||||
refineData.handler.invoke(ScriptEvaluationConfigurationRefinementContext(script, config, contextData))
|
||||
}
|
||||
|
||||
/**
|
||||
* The script evaluation result value
|
||||
*/
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ open class PropertiesCollection(private val properties: Map<Key<*>, Any?> = empt
|
||||
// generic for lists
|
||||
|
||||
operator fun <T> PropertiesCollection.Key<in List<T>>.invoke(vararg vals: T) {
|
||||
data[this] = vals.toList()
|
||||
append(vals.asIterable())
|
||||
}
|
||||
|
||||
// generic for maps:
|
||||
|
||||
Reference in New Issue
Block a user