Implement base jvm scripting infrastructure
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
|
||||
import org.jetbrains.kotlin.gradle.dsl.Coroutines
|
||||
|
||||
apply {
|
||||
plugin("kotlin")
|
||||
}
|
||||
|
||||
jvmTarget = "1.6"
|
||||
|
||||
dependencies {
|
||||
compile(project(":kotlin-script-runtime"))
|
||||
compile(project(":kotlin-stdlib"))
|
||||
compile(project(":kotlin-scripting-common"))
|
||||
compile(project(":kotlin-scripting-jvm"))
|
||||
compileOnly(project(":compiler:cli"))
|
||||
compileOnly(intellijCoreDep())
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
|
||||
kotlin.experimental.coroutines = Coroutines.ENABLE
|
||||
|
||||
standardPublicJars()
|
||||
|
||||
publish()
|
||||
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2000-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.jvmhost.impl
|
||||
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.*
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmSdkRoots
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
|
||||
import org.jetbrains.kotlin.codegen.GeneratedClassLoader
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||
import kotlin.script.experimental.host.getMergedScriptText
|
||||
import kotlin.script.experimental.jvm.JvmDependency
|
||||
import kotlin.script.experimental.jvm.JvmScriptCompileConfigurationParams
|
||||
import kotlin.script.experimental.jvm.JvmScriptEvaluationEnvironmentParams
|
||||
import kotlin.script.experimental.jvm.KJVMCompilerProxy
|
||||
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
|
||||
|
||||
class KJVMCompiledScript<out ScriptBase : Any>(
|
||||
override val configuration: ScriptCompileConfiguration,
|
||||
val generationState: GenerationState,
|
||||
val scriptClassFQName: String
|
||||
) : CompiledScript<ScriptBase> {
|
||||
|
||||
override suspend fun instantiate(scriptEvaluationEnvironment: ScriptEvaluationEnvironment): ResultWithDiagnostics<ScriptBase> = try {
|
||||
val baseClassLoader = scriptEvaluationEnvironment.getOrNull(JvmScriptEvaluationEnvironmentParams.baseClassLoader)
|
||||
val dependencies = configuration.getOrNull(ScriptCompileConfigurationParams.dependencies)
|
||||
?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() }
|
||||
// TODO: previous dependencies and classloaders should be taken into account here
|
||||
val classLoaderWithDeps =
|
||||
if (dependencies == null) baseClassLoader
|
||||
else URLClassLoader(dependencies.toTypedArray(), baseClassLoader)
|
||||
val classLoader = GeneratedClassLoader(generationState.factory, classLoaderWithDeps)
|
||||
|
||||
val clazz = classLoader.loadClass(scriptClassFQName)
|
||||
(clazz as? ScriptBase)?.asSuccess()
|
||||
?: ResultWithDiagnostics.Failure("Compiled class expected to be a subclass of the <ScriptBase>, but got ${clazz.javaClass.name}".asErrorDiagnostics())
|
||||
} catch (e: Throwable) {
|
||||
ResultWithDiagnostics.Failure(ScriptDiagnostic("Unable to instantiate class $scriptClassFQName", exception = e))
|
||||
}
|
||||
}
|
||||
|
||||
class KJVMCompilerImpl : KJVMCompilerProxy {
|
||||
|
||||
override fun compile(
|
||||
scriptCompilerConfiguration: ScriptCompileConfiguration,
|
||||
configurator: ScriptConfigurator?
|
||||
): ResultWithDiagnostics<CompiledScript<*>> {
|
||||
val messageCollector = ScriptDiagnosticsMessageCollector()
|
||||
|
||||
fun failure(vararg diagnostics: ScriptDiagnostic): ResultWithDiagnostics.Failure =
|
||||
ResultWithDiagnostics.Failure(*messageCollector.diagnostics.toTypedArray(), *diagnostics)
|
||||
|
||||
try {
|
||||
var environment: KotlinCoreEnvironment? = null
|
||||
var updatedScriptCompileConfiguration = scriptCompilerConfiguration
|
||||
|
||||
fun updateClasspath(classpath: Iterable<File>) {
|
||||
environment!!.updateClasspath(classpath.map(::JvmClasspathRoot))
|
||||
val updatedDeps = updatedScriptCompileConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)?.plus(
|
||||
JvmDependency(classpath)
|
||||
) ?: listOf(JvmDependency(classpath))
|
||||
updatedScriptCompileConfiguration = updatedScriptCompileConfiguration.cloneWith(
|
||||
ScriptCompileConfigurationParams.dependencies to updatedDeps
|
||||
)
|
||||
}
|
||||
|
||||
val disposable = Disposer.newDisposable()
|
||||
val kotlinCompilerConfiguration = org.jetbrains.kotlin.config.CompilerConfiguration().apply {
|
||||
add(
|
||||
JVMConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||
BridgeScriptDefinition(scriptCompilerConfiguration, configurator, ::updateClasspath)
|
||||
)
|
||||
put<MessageCollector>(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
|
||||
|
||||
scriptCompilerConfiguration.getOrNull(JvmScriptCompileConfigurationParams.javaHomeDir)?.let {
|
||||
put(JVMConfigurationKeys.JDK_HOME, it)
|
||||
}
|
||||
|
||||
scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)?.let {
|
||||
addJvmClasspathRoots(it.flatMap { (it as JvmDependency).classpath })
|
||||
}
|
||||
put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script") // TODO" take meaningful and valid name from somewhere
|
||||
languageVersionSettings = LanguageVersionSettingsImpl(
|
||||
LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, mapOf(AnalysisFlag.skipMetadataVersionCheck to true)
|
||||
)
|
||||
}
|
||||
environment = KotlinCoreEnvironment.createForProduction(
|
||||
disposable,
|
||||
kotlinCompilerConfiguration,
|
||||
EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||
)
|
||||
|
||||
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, environment.configuration.languageVersionSettings)
|
||||
|
||||
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
|
||||
val scriptText = scriptCompilerConfiguration[ScriptCompileConfigurationParams.scriptSourceFragments].getMergedScriptText()
|
||||
val scriptFileName = "script" // TODO: extract from file/url if available
|
||||
val virtualFile = LightVirtualFile(
|
||||
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
|
||||
KotlinLanguage.INSTANCE,
|
||||
StringUtil.convertLineSeparators(scriptText)
|
||||
).apply {
|
||||
charset = CharsetToolkit.UTF8_CHARSET
|
||||
}
|
||||
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||
?: return failure("Unable to make PSI file from script".asErrorDiagnostics())
|
||||
|
||||
val sourceFiles = listOf(psiFile)
|
||||
|
||||
analyzerWithCompilerReport.analyzeAndReport(sourceFiles) {
|
||||
val project = environment.project
|
||||
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||
project,
|
||||
sourceFiles,
|
||||
NoScopeRecordCliBindingTrace(),
|
||||
environment.configuration,
|
||||
environment::createPackagePartProvider
|
||||
)
|
||||
}
|
||||
val analysisResult = analyzerWithCompilerReport.analysisResult
|
||||
|
||||
if (!analysisResult.shouldGenerateCode) return failure("no code to generate".asErrorDiagnostics())
|
||||
if (analysisResult.isError() || messageCollector.hasErrors()) return failure()
|
||||
|
||||
val generationState = GenerationState.Builder(
|
||||
psiFile.project,
|
||||
ClassBuilderFactories.binaries(false),
|
||||
analysisResult.moduleDescriptor,
|
||||
analysisResult.bindingContext,
|
||||
sourceFiles,
|
||||
kotlinCompilerConfiguration
|
||||
).build()
|
||||
generationState.beforeCompile()
|
||||
KotlinCodegenFacade.generatePackage(
|
||||
generationState,
|
||||
psiFile.script!!.containingKtFile.packageFqName,
|
||||
setOf(psiFile.script!!.containingKtFile),
|
||||
org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION
|
||||
)
|
||||
|
||||
val res = KJVMCompiledScript<Any>(updatedScriptCompileConfiguration, generationState, scriptFileName.capitalize())
|
||||
|
||||
return ResultWithDiagnostics.Success(res, messageCollector.diagnostics)
|
||||
} catch (ex: Throwable) {
|
||||
return failure(ex.asDiagnostics())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ScriptDiagnosticsMessageCollector : MessageCollector {
|
||||
|
||||
private val _diagnostics = arrayListOf<ScriptDiagnostic>()
|
||||
|
||||
val diagnostics: List<ScriptDiagnostic> get() = _diagnostics
|
||||
|
||||
override fun clear() {
|
||||
_diagnostics.clear()
|
||||
}
|
||||
|
||||
override fun hasErrors(): Boolean =
|
||||
_diagnostics.any { it.severity == ScriptDiagnostic.Severity.ERROR }
|
||||
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||
val mappedSeverity = when (severity) {
|
||||
CompilerMessageSeverity.EXCEPTION,
|
||||
CompilerMessageSeverity.ERROR -> ScriptDiagnostic.Severity.ERROR
|
||||
CompilerMessageSeverity.STRONG_WARNING,
|
||||
CompilerMessageSeverity.WARNING -> ScriptDiagnostic.Severity.WARNING
|
||||
CompilerMessageSeverity.INFO -> ScriptDiagnostic.Severity.INFO
|
||||
CompilerMessageSeverity.LOGGING -> ScriptDiagnostic.Severity.DEBUG
|
||||
else -> null
|
||||
}
|
||||
if (mappedSeverity != null) {
|
||||
val mappedLocation = location?.let {
|
||||
ScriptSource.Location(ScriptSource.Position(it.line, it.column))
|
||||
}
|
||||
_diagnostics.add(ScriptDiagnostic(message, mappedSeverity, mappedLocation))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A bridge to the current scripting
|
||||
|
||||
internal class BridgeScriptDefinition(
|
||||
scriptCompilerConfiguration: ScriptCompileConfiguration,
|
||||
scriptConfigurator: ScriptConfigurator?,
|
||||
updateClasspath: (List<File>) -> Unit
|
||||
) : KotlinScriptDefinition(scriptCompilerConfiguration[ScriptCompileConfigurationParams.scriptSignature].scriptBase as KClass<out Any>) {
|
||||
override val acceptedAnnotations =
|
||||
scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.updateConfigurationOnAnnotations)?.toList() ?: emptyList()
|
||||
|
||||
override val dependencyResolver: DependenciesResolver =
|
||||
BridgeDependenciesResolver(scriptConfigurator, scriptCompilerConfiguration, updateClasspath)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import org.jetbrains.kotlin.gradle.dsl.Coroutines
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2000-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.jvm.impl
|
||||
|
||||
import kotlinx.coroutines.experimental.runBlocking
|
||||
import java.io.File
|
||||
import kotlin.script.dependencies.Environment
|
||||
import kotlin.script.dependencies.ScriptContents
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
import kotlin.script.experimental.dependencies.ScriptReport
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.JvmDependency
|
||||
import kotlin.script.experimental.jvm.defaultConfiguration
|
||||
import kotlin.script.experimental.jvm.mapToLegacyScriptReportPosition
|
||||
import kotlin.script.experimental.jvm.mapToLegacyScriptReportSeverity
|
||||
|
||||
class BridgeDependenciesResolver(
|
||||
val scriptConfigurator: ScriptConfigurator?,
|
||||
val baseScriptCompilerConfiguration: ScriptCompileConfiguration = scriptConfigurator.defaultConfiguration,
|
||||
val onClasspathUpdated: (List<File>) -> Unit = {}
|
||||
) : AsyncDependenciesResolver {
|
||||
|
||||
override fun resolve(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult =
|
||||
runBlocking {
|
||||
resolveAsync(scriptContents, environment)
|
||||
}
|
||||
|
||||
override suspend fun resolveAsync(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult {
|
||||
return try {
|
||||
|
||||
val diagnostics = arrayListOf<ScriptReport>()
|
||||
val processedScriptData =
|
||||
ProcessedScriptData(ProcessedScriptDataParams.annotations to scriptContents.annotations)
|
||||
|
||||
val scriptCompilerConfiguration = baseScriptCompilerConfiguration.cloneWith(
|
||||
ScriptCompileConfigurationParams.scriptSourceFragments to scriptContents.toScriptSourceFragments()
|
||||
)
|
||||
|
||||
val refinedConfiguration = scriptConfigurator?.let {
|
||||
val res = scriptConfigurator.refineConfiguration(scriptCompilerConfiguration, processedScriptData)
|
||||
when (res) {
|
||||
is ResultWithDiagnostics.Failure ->
|
||||
return@resolveAsync DependenciesResolver.ResolveResult.Failure(res.reports.mapScriptReportsToDiagnostics())
|
||||
is ResultWithDiagnostics.Success -> {
|
||||
diagnostics.addAll(res.reports.mapScriptReportsToDiagnostics())
|
||||
res.value
|
||||
}
|
||||
}
|
||||
} ?: scriptCompilerConfiguration
|
||||
|
||||
val newClasspath = refinedConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)
|
||||
?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
|
||||
if (refinedConfiguration != scriptCompilerConfiguration) {
|
||||
val oldClasspath = scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)
|
||||
?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
|
||||
if (newClasspath != oldClasspath) {
|
||||
onClasspathUpdated(newClasspath)
|
||||
}
|
||||
}
|
||||
DependenciesResolver.ResolveResult.Success(
|
||||
ScriptDependencies(
|
||||
classpath = newClasspath, // TODO: maybe it should return only increment from the initial config
|
||||
imports = refinedConfiguration.getOrNull(ScriptCompileConfigurationParams.importedPackages)?.toList()
|
||||
?: emptyList()
|
||||
),
|
||||
diagnostics
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
DependenciesResolver.ResolveResult.Failure(
|
||||
ScriptReport(
|
||||
e.message ?: "unknown error $e"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<ScriptDiagnostic>.mapScriptReportsToDiagnostics() =
|
||||
map { ScriptReport(it.message, mapToLegacyScriptReportSeverity(it.severity), mapToLegacyScriptReportPosition(it.location)) }
|
||||
|
||||
internal fun ScriptContents.toScriptSourceFragments(): ScriptSourceFragments =
|
||||
ScriptSourceFragments(
|
||||
when {
|
||||
text != null -> text!!.toString().toScriptSource()
|
||||
file != null -> file!!.toScriptSource()
|
||||
else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
|
||||
},
|
||||
null
|
||||
)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2000-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.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package kotlin.script.experimental.jvm
|
||||
|
||||
import kotlin.script.experimental.api.*
|
||||
|
||||
open class JvmScriptCompiler(
|
||||
val compilerProxy: KJVMCompilerProxy,
|
||||
val cache: CompiledJvmScriptsCache
|
||||
) : ScriptCompiler {
|
||||
|
||||
override suspend fun compile(configuration: ScriptCompileConfiguration, configurator: ScriptConfigurator?): ResultWithDiagnostics<CompiledScript<*>> {
|
||||
val refinedConfiguration = configurator?.refineConfiguration(configuration)?.let {
|
||||
when (it) {
|
||||
is ResultWithDiagnostics.Failure -> return it
|
||||
is ResultWithDiagnostics.Success -> it.value
|
||||
?: return ResultWithDiagnostics.Failure("Null script compile configuration received".asErrorDiagnostics())
|
||||
}
|
||||
} ?: configuration
|
||||
val cached = cache[refinedConfiguration[ScriptCompileConfigurationParams.scriptSourceFragments]]
|
||||
|
||||
if (cached != null) return cached.asSuccess()
|
||||
|
||||
return compilerProxy.compile(refinedConfiguration, configurator).also {
|
||||
if (it is ResultWithDiagnostics.Success) {
|
||||
cache.store(it.value as CompiledScript<*>)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface CompiledJvmScriptsCache {
|
||||
operator fun get(script: ScriptSourceFragments): CompiledScript<*>?
|
||||
fun store(compiledScript: CompiledScript<*>)
|
||||
}
|
||||
|
||||
interface KJVMCompilerProxy {
|
||||
fun compile(
|
||||
scriptCompilerConfiguration: ScriptCompileConfiguration,
|
||||
configurator: ScriptConfigurator?
|
||||
): ResultWithDiagnostics<CompiledScript<*>>
|
||||
}
|
||||
|
||||
class DummyCompiledJvmScriptCache : CompiledJvmScriptsCache {
|
||||
override operator fun get(script: ScriptSourceFragments): CompiledScript<*>? = null
|
||||
override fun store(compiledScript: CompiledScript<*>) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2000-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.jvm
|
||||
|
||||
import kotlinx.coroutines.experimental.runBlocking
|
||||
import kotlin.script.experimental.api.*
|
||||
import java.io.File
|
||||
|
||||
fun jvmConfigWithJavaHome(vararg params: Pair<TypedKey<*>, Any?>): ScriptCompileConfiguration =
|
||||
ScriptCompileConfiguration(
|
||||
JvmScriptCompileConfigurationParams.javaHomeDir to File(System.getProperty("java.home")),
|
||||
*params
|
||||
)
|
||||
|
||||
val ScriptConfigurator?.defaultConfiguration: ScriptCompileConfiguration
|
||||
get() = this?.let { runBlocking { baseConfiguration(null) } }?.resultOrNull() ?: ScriptCompileConfiguration()
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-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.jvm
|
||||
|
||||
import java.io.File
|
||||
import kotlin.script.experimental.api.ScriptDependency
|
||||
import kotlin.script.experimental.api.TypedKey
|
||||
|
||||
object JvmScriptCompileConfigurationParams {
|
||||
|
||||
val javaHomeDir = TypedKey<File>("javaHomeDir")
|
||||
}
|
||||
|
||||
class JvmDependency(val classpath: Iterable<File>): ScriptDependency
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2000-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.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package kotlin.script.experimental.jvm
|
||||
|
||||
import kotlin.script.experimental.api.ScriptConfigurator
|
||||
import kotlin.script.experimental.api.ScriptRunner
|
||||
import kotlin.script.experimental.api.typedKey
|
||||
import kotlin.script.experimental.host.BasicScriptingHost
|
||||
|
||||
open class JvmBasicScriptingHost<ScriptBase : Any>(
|
||||
configurationExtractor: ScriptConfigurator,
|
||||
compiler: JvmScriptCompiler,
|
||||
runner: ScriptRunner<ScriptBase>
|
||||
) : BasicScriptingHost<ScriptBase>(configurationExtractor, compiler, runner)
|
||||
|
||||
object JvmScriptEvaluationEnvironmentParams {
|
||||
val baseClassLoader by typedKey<ClassLoader?>()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2000-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.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package kotlin.script.experimental.jvm
|
||||
|
||||
import kotlin.script.experimental.api.ScriptDiagnostic
|
||||
import kotlin.script.experimental.api.ScriptSource
|
||||
import kotlin.script.dependencies.ScriptContents
|
||||
import kotlin.script.dependencies.ScriptDependenciesResolver
|
||||
import kotlin.script.experimental.dependencies.ScriptReport
|
||||
|
||||
fun mapLegacyDiagnosticSeverity(severity: ScriptDependenciesResolver.ReportSeverity): ScriptDiagnostic.Severity = when (severity) {
|
||||
ScriptDependenciesResolver.ReportSeverity.ERROR -> ScriptDiagnostic.Severity.ERROR
|
||||
ScriptDependenciesResolver.ReportSeverity.WARNING -> ScriptDiagnostic.Severity.WARNING
|
||||
ScriptDependenciesResolver.ReportSeverity.INFO -> ScriptDiagnostic.Severity.INFO
|
||||
ScriptDependenciesResolver.ReportSeverity.DEBUG -> ScriptDiagnostic.Severity.DEBUG
|
||||
}
|
||||
|
||||
fun mapToLegacyScriptReportSeverity(severity: ScriptDiagnostic.Severity): ScriptReport.Severity = when (severity) {
|
||||
ScriptDiagnostic.Severity.ERROR -> ScriptReport.Severity.ERROR
|
||||
ScriptDiagnostic.Severity.WARNING -> ScriptReport.Severity.WARNING
|
||||
ScriptDiagnostic.Severity.INFO -> ScriptReport.Severity.INFO
|
||||
ScriptDiagnostic.Severity.DEBUG -> ScriptReport.Severity.DEBUG
|
||||
}
|
||||
|
||||
fun mapLegacyScriptPosition(pos: ScriptContents.Position?): ScriptSource.Location? =
|
||||
pos?.let { ScriptSource.Location(ScriptSource.Position(pos.line, pos.col)) }
|
||||
|
||||
fun mapToLegacyScriptReportPosition(pos: ScriptSource.Location?): ScriptReport.Position? =
|
||||
pos?.let { ScriptReport.Position(pos.start.line, pos.start.col) }
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2000-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.jvm.runners
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.api.*
|
||||
|
||||
open class BasicJvmScriptRunner<ScriptBase : Any>(val baseClass: KClass<ScriptBase>? = null) : ScriptRunner<ScriptBase> {
|
||||
|
||||
override suspend fun run(
|
||||
compiledScript: CompiledScript<ScriptBase>,
|
||||
scriptEvaluationEnvironment: ScriptEvaluationEnvironment
|
||||
): ResultWithDiagnostics<EvaluationResult> =
|
||||
try {
|
||||
val obj = compiledScript.instantiate(scriptEvaluationEnvironment)
|
||||
when (obj) {
|
||||
is ResultWithDiagnostics.Failure -> obj
|
||||
is ResultWithDiagnostics.Success -> {
|
||||
// in the future, when (if) we'll stop to compile everything into constructor
|
||||
// run as SAM
|
||||
// return res
|
||||
val scriptObject = obj.value
|
||||
if (scriptObject !is Class<*>)
|
||||
ResultWithDiagnostics.Failure(ScriptDiagnostic("expecting class in this implementation, got ${scriptObject?.javaClass}"))
|
||||
else {
|
||||
scriptObject.getConstructor().newInstance()
|
||||
|
||||
ResultWithDiagnostics.Success(EvaluationResult(null, scriptEvaluationEnvironment))
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
ResultWithDiagnostics.Failure(e.asDiagnostics())
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,10 @@ include ":kotlin-build-common",
|
||||
":kotlin-annotations-jvm",
|
||||
":kotlin-annotations-android",
|
||||
":kotlin-scripting-common",
|
||||
":kotlin-scripting-jvm",
|
||||
":kotlin-scripting-jvm-host",
|
||||
":examples:scripting-jvm-simple-script",
|
||||
":examples:scripting-jvm-maven-deps",
|
||||
":pill:generate-all-tests",
|
||||
":include:kotlin-compiler",
|
||||
|
||||
@@ -245,6 +249,10 @@ project(':examples:kotlin-jsr223-daemon-local-eval-example').projectDir = "$root
|
||||
project(':kotlin-annotations-jvm').projectDir = "$rootDir/libraries/tools/kotlin-annotations-jvm" as File
|
||||
project(':kotlin-annotations-android').projectDir = "$rootDir/libraries/tools/kotlin-annotations-android" as File
|
||||
project(':kotlin-scripting-common').projectDir = "$rootDir/libraries/scripting/common" as File
|
||||
project(':kotlin-scripting-jvm').projectDir = "$rootDir/libraries/scripting/jvm" as File
|
||||
project(':kotlin-scripting-jvm-host').projectDir = "$rootDir/libraries/scripting/jvm-host" as File
|
||||
project(':examples:scripting-jvm-simple-script').projectDir = "$rootDir/libraries/examples/scripting/jvm-simple-script" as File
|
||||
project(':examples:scripting-jvm-maven-deps').projectDir = "$rootDir/libraries/examples/scripting/jvm-maven-deps" as File
|
||||
project(':pill:generate-all-tests').projectDir = "$rootDir/plugins/pill/generate-all-tests" as File
|
||||
|
||||
// plugin markers:
|
||||
|
||||
Reference in New Issue
Block a user