Pass script source directly instead of via configuration

This commit is contained in:
Ilya Chernikov
2018-03-27 20:12:44 +02:00
parent 29797ec264
commit 6ea41b425d
7 changed files with 27 additions and 17 deletions
@@ -28,7 +28,7 @@ fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
scriptDefinition.evaluator scriptDefinition.evaluator
) )
return host.eval(myJvmConfig { add(scriptFile.toScriptSource().toConfigEntry()) }, ScriptEvaluationEnvironment()) return host.eval(scriptFile.toScriptSource(), myJvmConfig(), ScriptEvaluationEnvironment())
} }
fun main(vararg args: String) { fun main(vararg args: String) {
@@ -35,7 +35,7 @@ fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
scriptDefinition.evaluator scriptDefinition.evaluator
) )
return host.eval(myJvmConfig { add(scriptFile.toScriptSource().toConfigEntry()) }, ScriptEvaluationEnvironment()) return host.eval(scriptFile.toScriptSource(), myJvmConfig(), ScriptEvaluationEnvironment())
} }
fun main(vararg args: String) { fun main(vararg args: String) {
@@ -8,6 +8,7 @@ package kotlin.script.experimental.api
interface ScriptCompiler { interface ScriptCompiler {
suspend fun compile( suspend fun compile(
script: ScriptSource,
configuration: ScriptCompileConfiguration, configuration: ScriptCompileConfiguration,
configurator: ScriptCompilationConfigurator? = null configurator: ScriptCompilationConfigurator? = null
): ResultWithDiagnostics<CompiledScript<*>> ): ResultWithDiagnostics<CompiledScript<*>>
@@ -29,9 +29,13 @@ abstract class BasicScriptingHost<ScriptBase : Any>(
) { ) {
open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() } open fun <T> runInCoroutineContext(block: suspend CoroutineScope.() -> T): T = runBlocking { block() }
open fun eval(configuration: ScriptCompileConfiguration, environment: ScriptEvaluationEnvironment): ResultWithDiagnostics<EvaluationResult> = open fun eval(
script: ScriptSource,
configuration: ScriptCompileConfiguration,
environment: ScriptEvaluationEnvironment
): ResultWithDiagnostics<EvaluationResult> =
runInCoroutineContext { runInCoroutineContext {
val compiled = compiler.compile(configuration, configurator) val compiled = compiler.compile(script, configuration, configurator)
when (compiled) { when (compiled) {
is ResultWithDiagnostics.Failure -> compiled is ResultWithDiagnostics.Failure -> compiled
is ResultWithDiagnostics.Success -> { is ResultWithDiagnostics.Success -> {
@@ -5,11 +5,9 @@
package kotlin.script.experimental.host package kotlin.script.experimental.host
import kotlin.script.experimental.api.ScriptSource
import kotlin.script.experimental.api.ScriptSourceFragments
import kotlin.script.experimental.api.ScriptSourceNamedFragment
import java.io.File import java.io.File
import java.net.URL import java.net.URL
import kotlin.script.experimental.api.*
fun ScriptSourceFragments.isWholeFile(): Boolean = fragments?.isEmpty() ?: true fun ScriptSourceFragments.isWholeFile(): Boolean = fragments?.isEmpty() ?: true
@@ -20,14 +18,15 @@ fun ScriptSource.getScriptText(): String = when {
else -> throw RuntimeException("unable to get text from null script") else -> throw RuntimeException("unable to get text from null script")
} }
fun ScriptSourceFragments.getMergedScriptText(): String { fun getMergedScriptText(script: ScriptSource, configuration: ScriptCompileConfiguration): String {
val originalScriptText = originalSource.getScriptText() val originalScriptText = script.getScriptText()
return if (isWholeFile()) { val sourceFragments = configuration.getOrNull(ScriptCompileConfigurationParams.scriptSourceFragments)
return if (sourceFragments == null || sourceFragments.isWholeFile()) {
originalScriptText originalScriptText
} else { } else {
val sb = StringBuilder(originalScriptText.length) val sb = StringBuilder(originalScriptText.length)
var prevFragment: ScriptSourceNamedFragment? = null var prevFragment: ScriptSourceNamedFragment? = null
for (fragment in fragments!!) { for (fragment in sourceFragments!!.fragments!!) {
val fragmentStartPos = fragment.range.start.absolutePos val fragmentStartPos = fragment.range.start.absolutePos
val fragmentEndPos = fragment.range.end.absolutePos val fragmentEndPos = fragment.range.end.absolutePos
if (fragmentStartPos == null || fragmentEndPos == null) if (fragmentStartPos == null || fragmentEndPos == null)
@@ -69,6 +69,7 @@ class KJVMCompiledScript<out ScriptBase : Any>(
class KJVMCompilerImpl : KJVMCompilerProxy { class KJVMCompilerImpl : KJVMCompilerProxy {
override fun compile( override fun compile(
script: ScriptSource,
scriptCompilerConfiguration: ScriptCompileConfiguration, scriptCompilerConfiguration: ScriptCompileConfiguration,
configurator: ScriptCompilationConfigurator? configurator: ScriptCompilationConfigurator?
): ResultWithDiagnostics<CompiledScript<*>> { ): ResultWithDiagnostics<CompiledScript<*>> {
@@ -147,7 +148,7 @@ class KJVMCompilerImpl : KJVMCompilerProxy {
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, environment.configuration.languageVersionSettings) val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, environment.configuration.languageVersionSettings)
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
val scriptText = scriptCompilerConfiguration[ScriptCompileConfigurationParams.scriptSourceFragments].getMergedScriptText() val scriptText = getMergedScriptText(script, scriptCompilerConfiguration)
val scriptFileName = "script" // TODO: extract from file/url if available val scriptFileName = "script" // TODO: extract from file/url if available
val virtualFile = LightVirtualFile( val virtualFile = LightVirtualFile(
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}", "$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
@@ -14,7 +14,11 @@ open class JvmScriptCompiler(
val cache: CompiledJvmScriptsCache val cache: CompiledJvmScriptsCache
) : ScriptCompiler { ) : ScriptCompiler {
override suspend fun compile(configuration: ScriptCompileConfiguration, configurator: ScriptCompilationConfigurator?): ResultWithDiagnostics<CompiledScript<*>> { override suspend fun compile(
script: ScriptSource,
configuration: ScriptCompileConfiguration,
configurator: ScriptCompilationConfigurator?
): ResultWithDiagnostics<CompiledScript<*>> {
val refinedConfiguration = configurator?.refineConfiguration(configuration)?.let { val refinedConfiguration = configurator?.refineConfiguration(configuration)?.let {
when (it) { when (it) {
is ResultWithDiagnostics.Failure -> return it is ResultWithDiagnostics.Failure -> return it
@@ -22,11 +26,11 @@ open class JvmScriptCompiler(
?: return ResultWithDiagnostics.Failure("Null script compile configuration received".asErrorDiagnostics()) ?: return ResultWithDiagnostics.Failure("Null script compile configuration received".asErrorDiagnostics())
} }
} ?: configuration } ?: configuration
val cached = cache[refinedConfiguration[ScriptCompileConfigurationParams.scriptSourceFragments]] val cached = cache.get(script, refinedConfiguration)
if (cached != null) return cached.asSuccess() if (cached != null) return cached.asSuccess()
return compilerProxy.compile(refinedConfiguration, configurator).also { return compilerProxy.compile(script, refinedConfiguration, configurator).also {
if (it is ResultWithDiagnostics.Success) { if (it is ResultWithDiagnostics.Success) {
cache.store(it.value as CompiledScript<*>) cache.store(it.value as CompiledScript<*>)
} }
@@ -35,19 +39,20 @@ open class JvmScriptCompiler(
} }
interface CompiledJvmScriptsCache { interface CompiledJvmScriptsCache {
operator fun get(script: ScriptSourceFragments): CompiledScript<*>? fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>?
fun store(compiledScript: CompiledScript<*>) fun store(compiledScript: CompiledScript<*>)
} }
interface KJVMCompilerProxy { interface KJVMCompilerProxy {
fun compile( fun compile(
script: ScriptSource,
scriptCompilerConfiguration: ScriptCompileConfiguration, scriptCompilerConfiguration: ScriptCompileConfiguration,
configurator: ScriptCompilationConfigurator? configurator: ScriptCompilationConfigurator?
): ResultWithDiagnostics<CompiledScript<*>> ): ResultWithDiagnostics<CompiledScript<*>>
} }
class DummyCompiledJvmScriptCache : CompiledJvmScriptsCache { class DummyCompiledJvmScriptCache : CompiledJvmScriptsCache {
override operator fun get(script: ScriptSourceFragments): CompiledScript<*>? = null override fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>? = null
override fun store(compiledScript: CompiledScript<*>) {} override fun store(compiledScript: CompiledScript<*>) {}
} }