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-jvm",
|
||||||
":kotlin-annotations-android",
|
":kotlin-annotations-android",
|
||||||
":kotlin-scripting-common",
|
":kotlin-scripting-common",
|
||||||
|
":kotlin-scripting-jvm",
|
||||||
|
":kotlin-scripting-jvm-host",
|
||||||
|
":examples:scripting-jvm-simple-script",
|
||||||
|
":examples:scripting-jvm-maven-deps",
|
||||||
":pill:generate-all-tests",
|
":pill:generate-all-tests",
|
||||||
":include:kotlin-compiler",
|
":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-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-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-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
|
project(':pill:generate-all-tests').projectDir = "$rootDir/plugins/pill/generate-all-tests" as File
|
||||||
|
|
||||||
// plugin markers:
|
// plugin markers:
|
||||||
|
|||||||
Reference in New Issue
Block a user