Rename ScriptingEnvironment to ScriptingHostConfiguration
This commit is contained in:
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.script.experimental.host
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.annotations.KotlinScript
|
||||
import kotlin.script.experimental.annotations.KotlinScriptFileExtension
|
||||
import kotlin.script.experimental.annotations.KotlinScriptProperties
|
||||
import kotlin.script.experimental.api.*
|
||||
|
||||
private const val ERROR_MSG_PREFIX = "Unable to construct script definition: "
|
||||
|
||||
private const val ILLEGAL_CONFIG_ANN_ARG =
|
||||
"Illegal argument compilationConfiguration of the KotlinScript annotation: expecting an object or default-constructed class derived from ScriptCompilationConfiguration"
|
||||
|
||||
fun createScriptCompilationConfigurationFromAnnotatedBaseClass(
|
||||
baseClassType: KotlinType,
|
||||
hostConfiguration: ScriptingHostConfiguration,
|
||||
contextClass: KClass<*> = ScriptCompilationConfiguration::class,
|
||||
body: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
||||
): ScriptCompilationConfiguration {
|
||||
|
||||
val getScriptingClass = hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
|
||||
?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting 'getScriptingClass' parameter in the scripting environment")
|
||||
|
||||
val baseClass: KClass<*> =
|
||||
try {
|
||||
getScriptingClass(baseClassType, contextClass, hostConfiguration)
|
||||
} catch (e: Throwable) {
|
||||
throw IllegalArgumentException("${ERROR_MSG_PREFIX}Unable to load base class $baseClassType", e)
|
||||
}
|
||||
val loadedBaseClassType = if (baseClass == baseClassType.fromClass) baseClassType else KotlinType(baseClass)
|
||||
|
||||
val mainAnnotation = baseClass.findAnnotation<KotlinScript>()
|
||||
?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting KotlinScript annotation on the $baseClass")
|
||||
|
||||
fun scriptingPropsInstance(kclass: KClass<out ScriptCompilationConfiguration>): ScriptCompilationConfiguration = try {
|
||||
kclass.objectInstance ?: kclass.createInstance()
|
||||
} catch (e: Throwable) {
|
||||
throw IllegalArgumentException(ILLEGAL_CONFIG_ANN_ARG, e)
|
||||
}
|
||||
|
||||
return ScriptCompilationConfiguration {
|
||||
baseClass(loadedBaseClassType)
|
||||
fileExtension(baseClass.findAnnotation<KotlinScriptFileExtension>()?.extension ?: mainAnnotation.extension)
|
||||
displayName(mainAnnotation.name)
|
||||
|
||||
include(scriptingPropsInstance(mainAnnotation.compilationConfiguration))
|
||||
|
||||
baseClass.java.annotations.filterIsInstance(KotlinScriptProperties::class.java).forEach { ann ->
|
||||
include(scriptingPropsInstance(ann.compilationConfiguration))
|
||||
}
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : Annotation> KClass<*>.findAnnotation(): T? =
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
this.java.annotations.firstOrNull { it is T } as T?
|
||||
|
||||
private fun <T : Any> KClass<T>.createInstance(): T {
|
||||
// TODO: throw a meaningful exception
|
||||
val noArgsConstructor = java.constructors.singleOrNull { it.parameters.isEmpty() }
|
||||
?: throw IllegalArgumentException("Class should have a single no-arg constructor: $this")
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return noArgsConstructor.newInstance() as T
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.script.experimental.host
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.api.KotlinType
|
||||
import kotlin.script.experimental.api.ScriptDependency
|
||||
import kotlin.script.experimental.util.PropertiesCollection
|
||||
|
||||
interface ScriptingHostConfigurationKeys
|
||||
|
||||
class ScriptingHostConfiguration(baseScriptingEnvironments: Iterable<ScriptingHostConfiguration>, body: Builder.() -> Unit) :
|
||||
PropertiesCollection(Builder(baseScriptingEnvironments).apply(body).data) {
|
||||
|
||||
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
|
||||
constructor(
|
||||
vararg baseConfigurations: ScriptingHostConfiguration, body: Builder.() -> Unit = {}
|
||||
) : this(baseConfigurations.asIterable(), body)
|
||||
|
||||
class Builder internal constructor(baseScriptingEnvironments: Iterable<ScriptingHostConfiguration>) :
|
||||
ScriptingHostConfigurationKeys,
|
||||
PropertiesCollection.Builder(baseScriptingEnvironments)
|
||||
|
||||
companion object : ScriptingHostConfigurationKeys
|
||||
}
|
||||
|
||||
// should contain all dependencies needed for baseClass and compilationConfigurator
|
||||
val ScriptingHostConfigurationKeys.configurationDependencies by PropertiesCollection.key<List<ScriptDependency>>()
|
||||
|
||||
// do not use configurationDependencies as script dependencies, so only the dependencies defined by compilationConfigurator will be used
|
||||
// (NOTE: in this case they should include the dependencies for the base class anyway, since this class is needed for script
|
||||
// compilation and instantiation, but compilationConfigurator could be excluded)
|
||||
val ScriptingHostConfigurationKeys.isolatedDependencies by PropertiesCollection.key<Boolean>(false)
|
||||
|
||||
// a "class loader" for KotlinTypes
|
||||
val ScriptingHostConfigurationKeys.getScriptingClass by PropertiesCollection.key<GetScriptingClass>()
|
||||
|
||||
|
||||
interface GetScriptingClass {
|
||||
operator fun invoke(classType: KotlinType, contextClass: KClass<*>, hostConfiguration: ScriptingHostConfiguration): KClass<*>
|
||||
}
|
||||
|
||||
fun ScriptingHostConfiguration.getScriptingClass(type: KotlinType, contextClass: KClass<*>): KClass<*> {
|
||||
val getClass = get(ScriptingHostConfiguration.getScriptingClass)
|
||||
?: throw IllegalArgumentException("Expecting 'getScriptingClass' property in the scripting environment: unable to load scripting class $type")
|
||||
return getClass(type, contextClass, this)
|
||||
}
|
||||
|
||||
fun ScriptingHostConfiguration.getScriptingClass(type: KotlinType, context: Any): KClass<*> = getScriptingClass(type, context::class)
|
||||
|
||||
Reference in New Issue
Block a user