Remove ScriptCompileConfiguration as separate entity, refactor pieces accordingly

This commit is contained in:
Ilya Chernikov
2018-08-17 17:51:48 +02:00
parent bda8089004
commit acb0f6c6a9
18 changed files with 88 additions and 148 deletions
@@ -10,12 +10,14 @@ import java.io.File
import kotlin.script.experimental.api.EvaluationResult
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvmhost.makeBasicHostFromAnnotatedScriptBaseClass
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
import kotlin.script.experimental.jvmhost.createBasicScriptDefinitionFromAnnotatedBaseClass
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val host = makeBasicHostFromAnnotatedScriptBaseClass<MyScriptWithMavenDeps>()
return host.eval(scriptFile.toScriptSource(), null, null)
val scriptDefinition = createBasicScriptDefinitionFromAnnotatedBaseClass<MyScriptWithMavenDeps>()
return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), scriptDefinition, null)
}
fun main(vararg args: String) {
@@ -49,9 +49,9 @@ object MyScriptDefinition : ScriptDefinition(
private val resolver = FilesAndMavenResolver()
fun myConfigureOnAnnotations(script: ScriptDataFacade): ResultWithDiagnostics<ScriptCompileConfiguration?> {
fun myConfigureOnAnnotations(script: ScriptDataFacade): ResultWithDiagnostics<ScriptDefinition?> {
val annotations = script.collectedData?.get(ScriptCollectedData.foundAnnotations)?.takeIf { it.isNotEmpty() }
?: return script.configuration.asSuccess()
?: return null.asSuccess()
val scriptContents = object : ScriptContents {
override val annotations: Iterable<Annotation> = annotations
override val file: File? = null
@@ -63,11 +63,11 @@ fun myConfigureOnAnnotations(script: ScriptDataFacade): ResultWithDiagnostics<Sc
}
return try {
val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get()
?: return script.configuration.asSuccess(diagnostics)
?: return null.asSuccess(diagnostics)
val resolvedClasspath = newDepsFromResolver.classpath.toList().takeIf { it.isNotEmpty() }
?: return script.configuration.asSuccess(diagnostics)
ScriptCompileConfiguration {
dependencies(JvmDependency(resolvedClasspath))
?: return null.asSuccess(diagnostics)
ScriptDefinition(script.definition) {
dependencies.append(JvmDependency(resolvedClasspath))
}.asSuccess(diagnostics)
} catch (e: Throwable) {
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics())
@@ -9,15 +9,14 @@ import org.jetbrains.kotlin.script.examples.jvm.simple.MyScript
import java.io.File
import kotlin.script.experimental.api.EvaluationResult
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.api.ScriptCompileConfiguration
import kotlin.script.experimental.api.ScriptEvaluationEnvironment
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvmhost.makeBasicHostFromAnnotatedScriptBaseClass
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
import kotlin.script.experimental.jvmhost.createBasicScriptDefinitionFromAnnotatedBaseClass
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val additionalCompilationProperties = ScriptCompileConfiguration {
val scriptDefinition = createBasicScriptDefinitionFromAnnotatedBaseClass<MyScript> {
jvm {
dependenciesFromCurrentContext(
"scripting-jvm-simple-script" /* script library jar name */
@@ -25,9 +24,7 @@ fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
}
}
val host = makeBasicHostFromAnnotatedScriptBaseClass<MyScript>()
return host.eval(scriptFile.toScriptSource(), additionalCompilationProperties, null)
return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), scriptDefinition, null)
}
fun main(vararg args: String) {
@@ -9,8 +9,7 @@ interface ScriptCompiler {
suspend operator fun invoke(
script: ScriptSource,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration? = null // overrides properties from definition and configurator.defaultConfiguration
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<CompiledScript<*>>
}
@@ -18,7 +17,6 @@ interface ScriptCompiler {
interface CompiledScript<out ScriptBase : Any> {
val definition: ScriptDefinition
val additionalConfiguration: ScriptCompileConfiguration?
suspend fun instantiate(scriptEvaluationEnvironment: ScriptEvaluationEnvironment?): ResultWithDiagnostics<ScriptBase>
}
@@ -9,37 +9,6 @@ package kotlin.script.experimental.api
import kotlin.script.experimental.util.PropertiesCollection
interface ScriptCompileConfigurationKeys
class ScriptCompileConfiguration(baseConfigurations: Iterable<ScriptCompileConfiguration>, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseConfigurations).apply(body).data) {
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
constructor(
vararg baseConfigurations: ScriptCompileConfiguration, body: Builder.() -> Unit = {}
) : this(baseConfigurations.asIterable(), body)
class Builder internal constructor(baseConfigurations: Iterable<ScriptCompileConfiguration>) :
ScriptCompileConfigurationKeys,
PropertiesCollection.Builder(baseConfigurations)
companion object : ScriptCompileConfigurationKeys
}
val ScriptCompileConfigurationKeys.sourceFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
val ScriptCompileConfigurationKeys.scriptBodyTarget by PropertiesCollection.keyCopy(ScriptDefinition.scriptBodyTarget)
val ScriptCompileConfigurationKeys.scriptImplicitReceivers by PropertiesCollection.keyCopy(ScriptDefinition.implicitReceivers)
val ScriptCompileConfigurationKeys.providedProperties by PropertiesCollection.keyCopy(ScriptDefinition.providedProperties)
val ScriptCompileConfigurationKeys.defaultImports by PropertiesCollection.keyCopy(ScriptDefinition.defaultImports)
val ScriptCompileConfigurationKeys.dependencies by PropertiesCollection.keyCopy(ScriptDefinition.dependencies)
val ScriptCompileConfigurationKeys.compilerOptions by PropertiesCollection.keyCopy(ScriptDefinition.compilerOptions)
interface ScriptCollectedDataKeys
@@ -55,11 +24,15 @@ val ScriptCollectedDataKeys.foundFragments by PropertiesCollection.key<List<Scri
class ScriptDataFacade(
val source: ScriptSource,
val definition: ScriptDefinition,
val configuration: ScriptCompileConfiguration?,
val collectedData: ScriptCollectedData? = null
)
typealias RefineScriptCompilationConfigurationHandler = (ScriptDataFacade) -> ResultWithDiagnostics<ScriptCompileConfiguration?>
typealias RefineScriptCompilationConfigurationHandler = (ScriptDataFacade) -> ResultWithDiagnostics<ScriptDefinition?>
// to make it "hasheable" for cashing
class RefineConfigurationBeforeParsingData(
val handler: RefineScriptCompilationConfigurationHandler
)
class RefineConfigurationOnAnnotationsData(
val annotations: List<KotlinType>,
@@ -45,18 +45,18 @@ val ScriptDefinitionKeys.defaultImports by PropertiesCollection.key<List<String>
val ScriptDefinitionKeys.dependencies by PropertiesCollection.key<List<ScriptDependency>>()
val ScriptDefinitionKeys.generatedClassAnnotations by PropertiesCollection.key<List<Annotation>>()
val ScriptDefinitionKeys.copyAnnotationsFrom by PropertiesCollection.key<List<KotlinType>>()
val ScriptDefinitionKeys.compilerOptions by PropertiesCollection.key<List<String>>() // Q: CommonCompilerOptions instead?
val ScriptDefinitionKeys.refineConfigurationBeforeParsing by PropertiesCollection.key<RefineScriptCompilationConfigurationHandler>() // default: false
val ScriptDefinitionKeys.refineConfigurationBeforeParsing by PropertiesCollection.key<RefineConfigurationBeforeParsingData>()
val ScriptDefinitionKeys.refineConfigurationOnAnnotations by PropertiesCollection.key<RefineConfigurationOnAnnotationsData>()
val ScriptDefinitionKeys.refineConfigurationOnSections by PropertiesCollection.key<RefineConfigurationOnSectionsData>()
val ScriptDefinitionKeys.sourceFragments by PropertiesCollection.key<List<ScriptSourceNamedFragment>>()
// DSL:
val ScriptDefinition.Builder.refineConfiguration get() = RefineConfigurationBuilder()
@@ -65,7 +65,7 @@ val ScriptDefinition.Builder.refineConfiguration get() = RefineConfigurationBuil
class RefineConfigurationBuilder : PropertiesCollection.Builder() {
fun beforeParsing(handler: RefineScriptCompilationConfigurationHandler) {
set(ScriptDefinition.refineConfigurationBeforeParsing, handler)
set(ScriptDefinition.refineConfigurationBeforeParsing, RefineConfigurationBeforeParsingData(handler))
}
fun onAnnotations(annotations: List<KotlinType>, handler: RefineScriptCompilationConfigurationHandler) {
@@ -19,7 +19,8 @@ private const val ILLEGAL_CONFIG_ANN_ARG =
fun createScriptDefinitionFromAnnotatedBaseClass(
baseClassType: KotlinType,
environment: ScriptingEnvironment,
contextClass: KClass<*> = ScriptDefinition::class
contextClass: KClass<*> = ScriptDefinition::class,
body: ScriptDefinition.Builder.() -> Unit = {}
): ScriptDefinition {
val getScriptingClass = environment[ScriptingEnvironment.getScriptingClass]
@@ -51,6 +52,7 @@ fun createScriptDefinitionFromAnnotatedBaseClass(
baseClass.java.annotations.filterIsInstance(KotlinScriptProperties::class.java).forEach { ann ->
include(scriptingPropsInstance(ann.definition))
}
body()
}
}
@@ -23,7 +23,6 @@ import kotlinx.coroutines.experimental.runBlocking
import kotlin.script.experimental.api.*
abstract class BasicScriptingHost(
val scriptDefinition: ScriptDefinition,
val compiler: ScriptCompiler,
val evaluator: ScriptEvaluator
) {
@@ -31,11 +30,11 @@ abstract class BasicScriptingHost(
open fun eval(
script: ScriptSource,
compileConfiguration: ScriptCompileConfiguration?,
scriptDefinition: ScriptDefinition,
environment: ScriptEvaluationEnvironment?
): ResultWithDiagnostics<EvaluationResult> =
runInCoroutineContext {
compiler(script, scriptDefinition, compileConfiguration).onSuccess {
compiler(script, scriptDefinition).onSuccess {
evaluator(it, environment)
}
}
@@ -7,10 +7,7 @@ package kotlin.script.experimental.host
import java.io.File
import java.net.URL
import kotlin.script.experimental.api.ScriptCompileConfiguration
import kotlin.script.experimental.api.ScriptSource
import kotlin.script.experimental.api.ScriptSourceNamedFragment
import kotlin.script.experimental.api.sourceFragments
import kotlin.script.experimental.api.*
fun ScriptSource.getScriptText(): String = when {
text != null -> text!!
@@ -19,9 +16,9 @@ fun ScriptSource.getScriptText(): String = when {
else -> throw RuntimeException("unable to get text from null script")
}
fun getMergedScriptText(script: ScriptSource, configuration: ScriptCompileConfiguration?): String {
fun getMergedScriptText(script: ScriptSource, configuration: ScriptDefinition?): String {
val originalScriptText = script.getScriptText()
val sourceFragments = configuration?.get(ScriptCompileConfiguration.sourceFragments)
val sourceFragments = configuration?.get(ScriptDefinition.sourceFragments)
return if (sourceFragments == null || sourceFragments.isEmpty()) {
originalScriptText
} else {
@@ -12,8 +12,7 @@ interface ReplSnippetChecker {
suspend operator fun invoke(
snippet: ReplSnippetSource,
state: ReplStageState<*>,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration? = null // overrides properties from definition
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<Unit>
}
@@ -22,8 +21,7 @@ interface ReplSnippetCompiler {
suspend operator fun invoke(
snippet: ReplSnippetSource,
state: ReplStageState<*>,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration? = null // overrides properties from definition
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<CompiledReplSnippet<*>>
}
@@ -9,7 +9,6 @@ import kotlinx.coroutines.experimental.CoroutineScope
import kotlinx.coroutines.experimental.runBlocking
import kotlin.script.experimental.api.EvaluationResult
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.api.ScriptCompileConfiguration
import kotlin.script.experimental.api.ScriptDefinition
import kotlin.script.experimental.util.PropertiesCollection
@@ -53,7 +52,6 @@ abstract class ReplHost(
snippet: ReplSnippetSource,
state: ReplStageState<*>,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration? = null, // overrides properties from definition
replEvaluationEnvironment: ReplEvaluationEnvironment
): ResultWithDiagnostics<EvaluationResult>
}
@@ -14,17 +14,13 @@ import kotlin.script.experimental.host.BasicScriptingHost
import kotlin.script.experimental.jvm.defaultJvmScriptingEnvironment
open class BasicJvmScriptingHost(
scriptDefinition: ScriptDefinition,
hostEnvironment: ScriptingEnvironment = defaultJvmScriptingEnvironment,
compiler: JvmScriptCompiler = JvmScriptCompiler(hostEnvironment),
evaluator: ScriptEvaluator = BasicJvmScriptEvaluator()
) : BasicScriptingHost(scriptDefinition, compiler, evaluator)
) : BasicScriptingHost(compiler, evaluator)
inline fun <reified T : Any> makeBasicHostFromAnnotatedScriptBaseClass(
hostEnvironment: ScriptingEnvironment = defaultJvmScriptingEnvironment
) =
BasicJvmScriptingHost(
createScriptDefinitionFromAnnotatedBaseClass(KotlinType(T::class), hostEnvironment),
hostEnvironment
)
inline fun <reified T : Any> createBasicScriptDefinitionFromAnnotatedBaseClass(
hostEnvironment: ScriptingEnvironment = defaultJvmScriptingEnvironment,
noinline body: ScriptDefinition.Builder.() -> Unit = {}
): ScriptDefinition = createScriptDefinitionFromAnnotatedBaseClass(KotlinType(T::class), hostEnvironment, ScriptDefinition::class, body)
@@ -47,12 +47,10 @@ import kotlin.script.experimental.jvmhost.JvmScriptEvaluationEnvironment
import kotlin.script.experimental.jvmhost.KJvmCompilerProxy
import kotlin.script.experimental.jvmhost.baseClassLoader
import kotlin.script.experimental.util.getFirstFromChainOrNull
import kotlin.script.experimental.util.getMergedFromChainOrNull
import kotlin.script.experimental.util.getOrError
class KJvmCompiledScript<out ScriptBase : Any>(
override val definition: ScriptDefinition,
override val additionalConfiguration: ScriptCompileConfiguration?,
private val generationState: GenerationState,
private val scriptClassFQName: String
) : CompiledScript<ScriptBase> {
@@ -60,7 +58,7 @@ class KJvmCompiledScript<out ScriptBase : Any>(
override suspend fun instantiate(scriptEvaluationEnvironment: ScriptEvaluationEnvironment?): ResultWithDiagnostics<ScriptBase> = try {
val baseClassLoader = scriptEvaluationEnvironment?.get(JvmScriptEvaluationEnvironment.baseClassLoader)
?: Thread.currentThread().contextClassLoader
val dependencies = additionalConfiguration?.get(ScriptDefinition.dependencies)
val dependencies = definition[ScriptDefinition.dependencies]
?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() }
// TODO: previous dependencies and classloaders should be taken into account here
val classLoaderWithDeps =
@@ -80,8 +78,7 @@ class KJvmCompilerImpl(val hostEnvironment: ScriptingEnvironment) : KJvmCompiler
override fun compile(
script: ScriptSource,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration?
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<CompiledScript<*>> {
val messageCollector = ScriptDiagnosticsMessageCollector()
@@ -92,13 +89,12 @@ class KJvmCompilerImpl(val hostEnvironment: ScriptingEnvironment) : KJvmCompiler
setIdeaIoUseFallback()
var environment: KotlinCoreEnvironment? = null
var updatedScriptCompileConfiguration = additionalConfiguration
var updatedDefinition = scriptDefinition
fun updateClasspath(classpath: List<File>) {
environment!!.updateClasspath(classpath.map(::JvmClasspathRoot))
if (classpath.isNotEmpty()) {
updatedScriptCompileConfiguration = ScriptCompileConfiguration {
include(updatedScriptCompileConfiguration)
updatedDefinition = ScriptDefinition(updatedDefinition) {
dependencies.append(JvmDependency(classpath))
}
}
@@ -108,20 +104,20 @@ class KJvmCompilerImpl(val hostEnvironment: ScriptingEnvironment) : KJvmCompiler
val kotlinCompilerConfiguration = org.jetbrains.kotlin.config.CompilerConfiguration().apply {
add(
JVMConfigurationKeys.SCRIPT_DEFINITIONS,
BridgeScriptDefinition(scriptDefinition, additionalConfiguration, hostEnvironment, ::updateClasspath)
BridgeScriptDefinition(scriptDefinition, hostEnvironment, ::updateClasspath)
)
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
var isModularJava = false
getFirstFromChainOrNull(ScriptCompileConfiguration.jvm.javaHome, updatedScriptCompileConfiguration, hostEnvironment)?.let {
getFirstFromChainOrNull(ScriptDefinition.jvm.javaHome, updatedDefinition, hostEnvironment)?.let {
put(JVMConfigurationKeys.JDK_HOME, it)
isModularJava = CoreJrtFileSystem.isModularJdk(it)
}
getMergedFromChainOrNull(ScriptDefinition.dependencies, scriptDefinition, updatedScriptCompileConfiguration)?.let {
updatedDefinition[ScriptDefinition.dependencies]?.let { dependencies ->
addJvmClasspathRoots(
it.flatMap {
dependencies.flatMap {
(it as JvmDependency).classpath
}
)
@@ -151,7 +147,7 @@ class KJvmCompilerImpl(val hostEnvironment: ScriptingEnvironment) : KJvmCompiler
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, environment.configuration.languageVersionSettings)
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
val scriptText = getMergedScriptText(script, updatedScriptCompileConfiguration)
val scriptText = getMergedScriptText(script, updatedDefinition)
val scriptFileName = "script" // TODO: extract from file/url if available
val virtualFile = LightVirtualFile(
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
@@ -196,7 +192,7 @@ class KJvmCompilerImpl(val hostEnvironment: ScriptingEnvironment) : KJvmCompiler
org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION
)
val res = KJvmCompiledScript<Any>(scriptDefinition, updatedScriptCompileConfiguration, generationState, scriptFileName.capitalize())
val res = KJvmCompiledScript<Any>(updatedDefinition, generationState, scriptFileName.capitalize())
return ResultWithDiagnostics.Success(res, messageCollector.diagnostics)
} catch (ex: Throwable) {
@@ -242,7 +238,6 @@ class ScriptDiagnosticsMessageCollector : MessageCollector {
internal class BridgeScriptDefinition(
scriptDefinition: ScriptDefinition,
additionalCompilationConfiguration: ScriptCompileConfiguration?,
hostEnvironment: ScriptingEnvironment,
updateClasspath: (List<File>) -> Unit
) : KotlinScriptDefinition(
@@ -253,12 +248,11 @@ internal class BridgeScriptDefinition(
) {
override val acceptedAnnotations = run {
val cl = this::class.java.classLoader
getFirstFromChainOrNull(ScriptDefinition.refineConfigurationOnAnnotations, scriptDefinition, additionalCompilationConfiguration)
?.annotations
scriptDefinition[ScriptDefinition.refineConfigurationOnAnnotations]?.annotations
?.map { (cl.loadClass(it.typeName) as Class<out Annotation>).kotlin }
?: emptyList()
}
override val dependencyResolver: DependenciesResolver =
BridgeDependenciesResolver(scriptDefinition, additionalCompilationConfiguration, updateClasspath)
BridgeDependenciesResolver(scriptDefinition, updateClasspath)
}
@@ -5,23 +5,9 @@
package kotlin.script.experimental.jvmhost.impl
import kotlin.script.experimental.api.ScriptCompileConfiguration
import kotlin.script.experimental.api.ScriptingEnvironment
import kotlin.script.experimental.jvm.defaultJvmScriptingEnvironment
internal fun mergeConfigurations(vararg configurations: ScriptCompileConfiguration?): ScriptCompileConfiguration? {
val nonEmptyConfigurations = configurations.filter { it != null && it.properties.isNotEmpty() }
return when {
nonEmptyConfigurations.isEmpty() -> null
nonEmptyConfigurations.size == 1 -> nonEmptyConfigurations.first()!!
else -> ScriptCompileConfiguration {
for (configuration in nonEmptyConfigurations) {
include(configuration!!)
}
}
}
}
fun ScriptingEnvironment.withDefaults(): ScriptingEnvironment =
if (this == defaultJvmScriptingEnvironment || defaultJvmScriptingEnvironment.properties.all {
this.properties.containsKey(it.key)
@@ -10,20 +10,19 @@ package kotlin.script.experimental.jvmhost
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.defaultJvmScriptingEnvironment
import kotlin.script.experimental.jvmhost.impl.KJvmCompilerImpl
import kotlin.script.experimental.jvmhost.impl.mergeConfigurations
import kotlin.script.experimental.jvmhost.impl.withDefaults
interface CompiledJvmScriptsCache {
fun get(script: ScriptSource, scriptDefinition: ScriptDefinition, configuration: ScriptCompileConfiguration?): CompiledScript<*>?
fun store(compiledScript: CompiledScript<*>, scriptDefinition: ScriptDefinition, configuration: ScriptCompileConfiguration?)
fun get(script: ScriptSource, scriptDefinition: ScriptDefinition): CompiledScript<*>?
fun store(compiledScript: CompiledScript<*>, scriptDefinition: ScriptDefinition)
object NoCache : CompiledJvmScriptsCache {
override fun get(
script: ScriptSource, scriptDefinition: ScriptDefinition, configuration: ScriptCompileConfiguration?
script: ScriptSource, scriptDefinition: ScriptDefinition
): CompiledScript<*>? = null
override fun store(
compiledScript: CompiledScript<*>, scriptDefinition: ScriptDefinition, configuration: ScriptCompileConfiguration?
compiledScript: CompiledScript<*>, scriptDefinition: ScriptDefinition
) {
}
}
@@ -37,25 +36,23 @@ open class JvmScriptCompiler(
override suspend operator fun invoke(
script: ScriptSource,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration?
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<CompiledScript<*>> {
val refineConfigurationFn = scriptDefinition[ScriptDefinition.refineConfigurationBeforeParsing]
val refinedConfiguration =
refineConfigurationFn?.invoke(ScriptDataFacade(script, scriptDefinition, additionalConfiguration))?.let {
refineConfigurationFn?.handler?.invoke(ScriptDataFacade(script, scriptDefinition))?.let {
when (it) {
is ResultWithDiagnostics.Failure -> return it
is ResultWithDiagnostics.Success -> it.value
}
}
val actualConfiguration = mergeConfigurations(additionalConfiguration, refinedConfiguration)
val cached = cache.get(script, scriptDefinition, actualConfiguration)
} ?: scriptDefinition
val cached = cache.get(script, refinedConfiguration)
if (cached != null) return cached.asSuccess()
return compilerProxy.compile(script, scriptDefinition, actualConfiguration).also {
return compilerProxy.compile(script, refinedConfiguration).also {
if (it is ResultWithDiagnostics.Success) {
cache.store(it.value, scriptDefinition, actualConfiguration)
cache.store(it.value, refinedConfiguration)
}
}
}
@@ -64,8 +61,7 @@ open class JvmScriptCompiler(
interface KJvmCompilerProxy {
fun compile(
script: ScriptSource,
scriptDefinition: ScriptDefinition,
additionalConfiguration: ScriptCompileConfiguration?
scriptDefinition: ScriptDefinition
): ResultWithDiagnostics<CompiledScript<*>>
}
@@ -18,11 +18,9 @@ import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.compat.mapToLegacyScriptReportPosition
import kotlin.script.experimental.jvm.compat.mapToLegacyScriptReportSeverity
import kotlin.script.experimental.util.getFirstFromChainOrNull
class BridgeDependenciesResolver(
val scriptDefinition: ScriptDefinition,
private val additionalConfiguration: ScriptCompileConfiguration?,
val onClasspathUpdated: (List<File>) -> Unit = {}
) : AsyncDependenciesResolver {
@@ -46,7 +44,7 @@ class BridgeDependenciesResolver(
if (refineFn == null) null
else {
val res = refineFn(
ScriptDataFacade(scriptContents.toScriptSource(), scriptDefinition, additionalConfiguration, processedScriptData)
ScriptDataFacade(scriptContents.toScriptSource(), scriptDefinition, processedScriptData)
)
when (res) {
is ResultWithDiagnostics.Failure ->
@@ -62,7 +60,7 @@ class BridgeDependenciesResolver(
?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
if (newClasspath.isNotEmpty()) {
val oldClasspath =
getFirstFromChainOrNull(ScriptDefinition.dependencies, additionalConfiguration, scriptDefinition)
scriptDefinition[ScriptDefinition.dependencies]
?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
if (newClasspath != oldClasspath) {
onClasspathUpdated(newClasspath)
@@ -71,9 +69,7 @@ class BridgeDependenciesResolver(
DependenciesResolver.ResolveResult.Success(
ScriptDependencies(
classpath = newClasspath, // TODO: maybe it should return only increment from the initial config
imports = getFirstFromChainOrNull(
ScriptDefinition.defaultImports, refinedConfiguration, additionalConfiguration, scriptDefinition
)?.toList() ?: emptyList()
imports = scriptDefinition[ScriptDefinition.defaultImports]?.toList() ?: emptyList()
),
diagnostics
)
@@ -7,26 +7,27 @@ package kotlin.script.experimental.jvm
import org.jetbrains.kotlin.script.util.scriptCompilationClasspathFromContext
import java.io.File
import kotlin.script.experimental.api.ScriptDefinition
import kotlin.script.experimental.api.ScriptDefinitionKeys
import kotlin.script.experimental.api.ScriptDependency
import kotlin.script.experimental.api.dependencies
import kotlin.script.experimental.api.*
import kotlin.script.experimental.util.PropertiesCollection
open class JvmScriptDefinition : PropertiesCollection.Builder()
val ScriptDefinitionKeys.jvm get() = JvmScriptDefinition()
class JvmDependency(val classpath: List<File>) : ScriptDependency {
data class JvmDependency(val classpath: List<File>) : ScriptDependency {
@Suppress("unused")
constructor(vararg classpathEntries: File) : this(classpathEntries.asList())
}
fun JvmScriptDefinition.dependenciesFromCurrentContext(vararg libraries: String, wholeClasspath: Boolean = false) {
interface JvmScriptDefinitionKeys
open class JvmScriptDefinitionBuilder : PropertiesCollection.Builder(), JvmScriptDefinitionKeys {
companion object : PropertiesCollection.Builder.BuilderExtension<JvmScriptDefinitionBuilder>, JvmScriptDefinitionKeys {
override fun get() = JvmScriptDefinitionBuilder()
}
}
fun JvmScriptDefinitionBuilder.dependenciesFromCurrentContext(vararg libraries: String, wholeClasspath: Boolean = false) {
dependenciesFromClassloader(*libraries, wholeClasspath = wholeClasspath)
}
fun JvmScriptDefinition.dependenciesFromClassloader(
fun JvmScriptDefinitionBuilder.dependenciesFromClassloader(
vararg libraries: String,
classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
wholeClasspath: Boolean = false
@@ -35,3 +36,10 @@ fun JvmScriptDefinition.dependenciesFromClassloader(
JvmDependency(scriptCompilationClasspathFromContext(*libraries, classLoader = classLoader, wholeClasspath = wholeClasspath))
)
}
val JvmScriptDefinitionKeys.javaHome by PropertiesCollection.keyCopy(ScriptingEnvironment.jvm.javaHome)
@Suppress("unused")
val ScriptDefinitionKeys.jvm
get() = JvmScriptDefinitionBuilder
@@ -52,7 +52,7 @@ abstract class KotlinScriptDefinitionAdapterFromNewAPIBase : KotlinScriptDefinit
get() = emptyList()
override val dependencyResolver: DependenciesResolver by lazy(LazyThreadSafetyMode.PUBLICATION) {
BridgeDependenciesResolver(scriptDefinition, null)
BridgeDependenciesResolver(scriptDefinition)
}
override val acceptedAnnotations: List<KClass<out Annotation>> by lazy(LazyThreadSafetyMode.PUBLICATION) {