Introduce script names and location ids, use them in diagnostics and...
for virtual file names. Also fix compiled script serialization.
This commit is contained in:
@@ -68,6 +68,7 @@ import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PRO
|
|||||||
import org.jetbrains.kotlin.cli.common.config.ContentRoot
|
import org.jetbrains.kotlin.cli.common.config.ContentRoot
|
||||||
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
||||||
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
|
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
|
||||||
@@ -429,7 +430,7 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
internal fun report(severity: CompilerMessageSeverity, message: String) = report(configuration, severity, message)
|
internal fun report(severity: CompilerMessageSeverity, message: String) = report(configuration, severity, message)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
|
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
|
||||||
|
|
||||||
private val APPLICATION_LOCK = Object()
|
private val APPLICATION_LOCK = Object()
|
||||||
private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null
|
private var ourApplicationEnvironment: JavaCoreApplicationEnvironment? = null
|
||||||
@@ -479,14 +480,20 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
// used in the daemon for jar cache cleanup
|
// used in the daemon for jar cache cleanup
|
||||||
val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
|
val applicationEnvironment: JavaCoreApplicationEnvironment? get() = ourApplicationEnvironment
|
||||||
|
|
||||||
internal fun report(configuration: CompilerConfiguration, severity: CompilerMessageSeverity, message: String) {
|
internal fun report(
|
||||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message)
|
configuration: CompilerConfiguration,
|
||||||
|
severity: CompilerMessageSeverity,
|
||||||
|
message: String,
|
||||||
|
location: CompilerMessageLocation? = null
|
||||||
|
) {
|
||||||
|
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(severity, message, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createSourceFilesFromSourceRoots(
|
internal fun createSourceFilesFromSourceRoots(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
project: Project,
|
project: Project,
|
||||||
sourceRoots: List<KotlinSourceRoot>
|
sourceRoots: List<KotlinSourceRoot>,
|
||||||
|
reportLocation: CompilerMessageLocation? = null
|
||||||
): MutableList<KtFile> {
|
): MutableList<KtFile> {
|
||||||
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
@@ -506,12 +513,12 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
KotlinCoreEnvironment.LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
|
KotlinCoreEnvironment.LOG.warn("$message\n\nbuild file path: $buildFilePath\ncontent:\n${buildFilePath.readText()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
report(configuration, ERROR, message)
|
report(configuration, ERROR, message, reportLocation)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
|
if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) {
|
||||||
report(configuration, ERROR, "Source entry is not a Kotlin file: $sourceRootPath")
|
report(configuration, ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||||
@@ -46,7 +47,11 @@ fun collectScriptsCompilationDependencies(
|
|||||||
KotlinSourceRoot(it.path, false)
|
KotlinSourceRoot(it.path, false)
|
||||||
}
|
}
|
||||||
val sourceDependencies =
|
val sourceDependencies =
|
||||||
KotlinCoreEnvironment.createSourceFilesFromSourceRoots(configuration, project, sourceDependenciesRoots)
|
KotlinCoreEnvironment.createSourceFilesFromSourceRoots(
|
||||||
|
configuration, project, sourceDependenciesRoots,
|
||||||
|
// TODO: consider receiving and using precise location from the resolver in the future
|
||||||
|
source.virtualFile?.path?.let { CompilerMessageLocation.create(it) }
|
||||||
|
)
|
||||||
if (sourceDependencies.isNotEmpty()) {
|
if (sourceDependencies.isNotEmpty()) {
|
||||||
collectedSourceDependencies.add(ScriptsCompilationDependencies.SourceDependencies(source, sourceDependencies))
|
collectedSourceDependencies.add(ScriptsCompilationDependencies.SourceDependencies(source, sourceDependencies))
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -52,7 +52,14 @@ fun configureMavenDepsOnAnnotations(context: ScriptConfigurationRefinementContex
|
|||||||
}
|
}
|
||||||
val diagnostics = arrayListOf<ScriptDiagnostic>()
|
val diagnostics = arrayListOf<ScriptDiagnostic>()
|
||||||
fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {
|
fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {
|
||||||
diagnostics.add(ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), mapLegacyScriptPosition(position)))
|
diagnostics.add(
|
||||||
|
ScriptDiagnostic(
|
||||||
|
message,
|
||||||
|
mapLegacyDiagnosticSeverity(severity),
|
||||||
|
context.script.locationId,
|
||||||
|
mapLegacyScriptPosition(position)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return try {
|
return try {
|
||||||
val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get()
|
val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get()
|
||||||
@@ -63,7 +70,7 @@ fun configureMavenDepsOnAnnotations(context: ScriptConfigurationRefinementContex
|
|||||||
dependencies.append(JvmDependency(resolvedClasspath))
|
dependencies.append(JvmDependency(resolvedClasspath))
|
||||||
}.asSuccess(diagnostics)
|
}.asSuccess(diagnostics)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics())
|
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics(path = context.script.locationId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package kotlin.script.experimental.api
|
|||||||
data class ScriptDiagnostic(
|
data class ScriptDiagnostic(
|
||||||
val message: String,
|
val message: String,
|
||||||
val severity: Severity = Severity.ERROR,
|
val severity: Severity = Severity.ERROR,
|
||||||
|
val sourcePath: String? = null,
|
||||||
val location: SourceCode.Location? = null,
|
val location: SourceCode.Location? = null,
|
||||||
val exception: Throwable? = null
|
val exception: Throwable? = null
|
||||||
) {
|
) {
|
||||||
@@ -92,21 +93,25 @@ fun <R> R.asSuccess(reports: List<ScriptDiagnostic> = listOf()): ResultWithDiagn
|
|||||||
ResultWithDiagnostics.Success(this, reports)
|
ResultWithDiagnostics.Success(this, reports)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the receiver Throwable to the Failure results wrapper with optional [message] and [location]
|
* Converts the receiver Throwable to the Failure results wrapper with optional [customMessage], [path] and [location]
|
||||||
*/
|
*/
|
||||||
fun Throwable.asDiagnostics(customMessage: String? = null, location: SourceCode.Location? = null): ScriptDiagnostic =
|
fun Throwable.asDiagnostics(
|
||||||
ScriptDiagnostic(customMessage ?: message ?: "$this", ScriptDiagnostic.Severity.ERROR, location, this)
|
customMessage: String? = null,
|
||||||
|
path: String? = null,
|
||||||
|
location: SourceCode.Location? = null
|
||||||
|
): ScriptDiagnostic =
|
||||||
|
ScriptDiagnostic(customMessage ?: message ?: "$this", ScriptDiagnostic.Severity.ERROR, path, location, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the receiver String to error diagnostic report with optional [location]
|
* Converts the receiver String to error diagnostic report with optional [path] and [location]
|
||||||
*/
|
*/
|
||||||
fun String.asErrorDiagnostics(location: SourceCode.Location? = null): ScriptDiagnostic =
|
fun String.asErrorDiagnostics(path: String? = null, location: SourceCode.Location? = null): ScriptDiagnostic =
|
||||||
ScriptDiagnostic(this, ScriptDiagnostic.Severity.ERROR, location)
|
ScriptDiagnostic(this, ScriptDiagnostic.Severity.ERROR, path, location)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the result value from the receiver wrapper or null if receiver represents a Failure
|
* Extracts the result value from the receiver wrapper or null if receiver represents a Failure
|
||||||
*/
|
*/
|
||||||
fun<R> ResultWithDiagnostics<R>.resultOrNull(): R? = when (this) {
|
fun <R> ResultWithDiagnostics<R>.resultOrNull(): R? = when (this) {
|
||||||
is ResultWithDiagnostics.Success<R> -> value
|
is ResultWithDiagnostics.Success<R> -> value
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,12 @@ interface ScriptCompiler {
|
|||||||
*/
|
*/
|
||||||
interface CompiledScript<out ScriptBase : Any> {
|
interface CompiledScript<out ScriptBase : Any> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location identifier for the script source, taken from SourceCode.locationId
|
||||||
|
*/
|
||||||
|
val sourceLocationId: String?
|
||||||
|
get() = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The compilation configuration used for script compilation
|
* The compilation configuration used for script compilation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,6 +20,16 @@ interface SourceCode {
|
|||||||
*/
|
*/
|
||||||
val text: String
|
val text: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The script file or display name
|
||||||
|
*/
|
||||||
|
val name: String?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path or other script location identifier
|
||||||
|
*/
|
||||||
|
val locationId: String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The source code position
|
* The source code position
|
||||||
* @param line source code position line
|
* @param line source code position line
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ fun getMergedScriptText(script: SourceCode, configuration: ScriptCompilationConf
|
|||||||
open class FileScriptSource(val file: File, private val preloadedText: String? = null) : ExternalSourceCode {
|
open class FileScriptSource(val file: File, private val preloadedText: String? = null) : ExternalSourceCode {
|
||||||
override val externalLocation: URL get() = file.toURI().toURL()
|
override val externalLocation: URL get() = file.toURI().toURL()
|
||||||
override val text: String by lazy { preloadedText ?: file.readText() }
|
override val text: String by lazy { preloadedText ?: file.readText() }
|
||||||
|
override val name: String? get() = file.name
|
||||||
|
override val locationId: String? get() = file.path
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,6 +54,8 @@ open class FileScriptSource(val file: File, private val preloadedText: String? =
|
|||||||
*/
|
*/
|
||||||
open class UrlScriptSource(override val externalLocation: URL) : ExternalSourceCode {
|
open class UrlScriptSource(override val externalLocation: URL) : ExternalSourceCode {
|
||||||
override val text: String by lazy { externalLocation.readText() }
|
override val text: String by lazy { externalLocation.readText() }
|
||||||
|
override val name: String? get() = externalLocation.file
|
||||||
|
override val locationId: String? get() = externalLocation.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +67,11 @@ fun File.toScriptSource(): SourceCode = FileScriptSource(this)
|
|||||||
* The implementation of the ScriptSource for a script in a String
|
* The implementation of the ScriptSource for a script in a String
|
||||||
*/
|
*/
|
||||||
open class StringScriptSource(val source: String) : SourceCode {
|
open class StringScriptSource(val source: String) : SourceCode {
|
||||||
|
|
||||||
override val text: String get() = source
|
override val text: String get() = source
|
||||||
|
|
||||||
|
override val name: String? = null
|
||||||
|
override val locationId: String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+20
-3
@@ -31,22 +31,33 @@ class KJvmCompiledModule(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class KJvmCompiledScript<out ScriptBase : Any>(
|
class KJvmCompiledScript<out ScriptBase : Any>(
|
||||||
|
sourceLocationId: String?,
|
||||||
compilationConfiguration: ScriptCompilationConfiguration,
|
compilationConfiguration: ScriptCompilationConfiguration,
|
||||||
private var scriptClassFQName: String,
|
private var scriptClassFQName: String,
|
||||||
override val otherScripts: List<CompiledScript<*>> = emptyList(),
|
otherScripts: List<CompiledScript<*>> = emptyList(),
|
||||||
private var compiledModule: KJvmCompiledModule? = null
|
private var compiledModule: KJvmCompiledModule? = null
|
||||||
) : CompiledScript<ScriptBase>, Serializable {
|
) : CompiledScript<ScriptBase>, Serializable {
|
||||||
|
|
||||||
|
private var _sourceLocationId: String? = sourceLocationId
|
||||||
|
|
||||||
|
override val sourceLocationId: String?
|
||||||
|
get() = _sourceLocationId
|
||||||
|
|
||||||
private var _compilationConfiguration: ScriptCompilationConfiguration? = compilationConfiguration
|
private var _compilationConfiguration: ScriptCompilationConfiguration? = compilationConfiguration
|
||||||
|
|
||||||
override val compilationConfiguration: ScriptCompilationConfiguration
|
override val compilationConfiguration: ScriptCompilationConfiguration
|
||||||
get() = _compilationConfiguration!!
|
get() = _compilationConfiguration!!
|
||||||
|
|
||||||
|
private var _otherScripts: List<CompiledScript<*>> = otherScripts
|
||||||
|
|
||||||
|
override val otherScripts: List<CompiledScript<*>>
|
||||||
|
get() = _otherScripts
|
||||||
|
|
||||||
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> = try {
|
override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics<KClass<*>> = try {
|
||||||
val classLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationConfiguration.actualClassLoader)
|
val classLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationConfiguration.actualClassLoader)
|
||||||
?: run {
|
?: run {
|
||||||
if (compiledModule == null)
|
if (compiledModule == null)
|
||||||
return ResultWithDiagnostics.Failure("Unable to load class $scriptClassFQName: no compiled module is provided".asErrorDiagnostics())
|
return ResultWithDiagnostics.Failure("Unable to load class $scriptClassFQName: no compiled module is provided".asErrorDiagnostics(path = sourceLocationId))
|
||||||
val baseClassLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationConfiguration.baseClassLoader)
|
val baseClassLoader = scriptEvaluationConfiguration?.get(JvmScriptEvaluationConfiguration.baseClassLoader)
|
||||||
?: Thread.currentThread().contextClassLoader
|
?: Thread.currentThread().contextClassLoader
|
||||||
val dependencies = compilationConfiguration[ScriptCompilationConfiguration.dependencies]
|
val dependencies = compilationConfiguration[ScriptCompilationConfiguration.dependencies]
|
||||||
@@ -64,6 +75,7 @@ class KJvmCompiledScript<out ScriptBase : Any>(
|
|||||||
ResultWithDiagnostics.Failure(
|
ResultWithDiagnostics.Failure(
|
||||||
ScriptDiagnostic(
|
ScriptDiagnostic(
|
||||||
"Unable to instantiate class $scriptClassFQName",
|
"Unable to instantiate class $scriptClassFQName",
|
||||||
|
sourcePath = sourceLocationId,
|
||||||
exception = e
|
exception = e
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -77,18 +89,23 @@ class KJvmCompiledScript<out ScriptBase : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun writeObject(outputStream: ObjectOutputStream) {
|
private fun writeObject(outputStream: ObjectOutputStream) {
|
||||||
|
outputStream.writeObject(sourceLocationId)
|
||||||
|
outputStream.writeObject(otherScripts)
|
||||||
outputStream.writeObject(compiledModule)
|
outputStream.writeObject(compiledModule)
|
||||||
outputStream.writeObject(scriptClassFQName)
|
outputStream.writeObject(scriptClassFQName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun readObject(inputStream: ObjectInputStream) {
|
private fun readObject(inputStream: ObjectInputStream) {
|
||||||
_compilationConfiguration = null
|
_compilationConfiguration = null
|
||||||
|
_sourceLocationId = inputStream.readObject() as String?
|
||||||
|
_otherScripts = inputStream.readObject() as List<CompiledScript<*>>
|
||||||
compiledModule = inputStream.readObject() as KJvmCompiledModule
|
compiledModule = inputStream.readObject() as KJvmCompiledModule
|
||||||
scriptClassFQName = inputStream.readObject() as String
|
scriptClassFQName = inputStream.readObject() as String
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private val serialVersionUID = 0L
|
private val serialVersionUID = 1L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+19
-10
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.idea.KotlinFileType
|
|||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
@@ -65,6 +64,12 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
fun failure(vararg diagnostics: ScriptDiagnostic): ResultWithDiagnostics.Failure =
|
fun failure(vararg diagnostics: ScriptDiagnostic): ResultWithDiagnostics.Failure =
|
||||||
ResultWithDiagnostics.Failure(*messageCollector.diagnostics.toTypedArray(), *diagnostics)
|
ResultWithDiagnostics.Failure(*messageCollector.diagnostics.toTypedArray(), *diagnostics)
|
||||||
|
|
||||||
|
fun failure(message: String): ResultWithDiagnostics.Failure =
|
||||||
|
ResultWithDiagnostics.Failure(
|
||||||
|
*messageCollector.diagnostics.toTypedArray(),
|
||||||
|
message.asErrorDiagnostics(path = script.locationId)
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIdeaIoUseFallback()
|
setIdeaIoUseFallback()
|
||||||
|
|
||||||
@@ -130,19 +135,19 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
|
|
||||||
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
|
val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
|
||||||
val scriptText = getMergedScriptText(script, updatedConfiguration)
|
val scriptText = getMergedScriptText(script, updatedConfiguration)
|
||||||
val scriptFileName = "script" // TODO: extract from file/url if available
|
val scriptFileName = script.name ?: "script.${updatedConfiguration[ScriptCompilationConfiguration.fileExtension]}"
|
||||||
val virtualFile = LightVirtualFile(
|
val virtualFile = LightVirtualFile(
|
||||||
"$scriptFileName${KotlinParserDefinition.STD_SCRIPT_EXT}",
|
scriptFileName,
|
||||||
KotlinLanguage.INSTANCE,
|
KotlinLanguage.INSTANCE,
|
||||||
StringUtil.convertLineSeparators(scriptText)
|
StringUtil.convertLineSeparators(scriptText)
|
||||||
).apply {
|
).apply {
|
||||||
charset = CharsetToolkit.UTF8_CHARSET
|
charset = CharsetToolkit.UTF8_CHARSET
|
||||||
}
|
}
|
||||||
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
|
||||||
?: return failure("Unable to make PSI file from script".asErrorDiagnostics())
|
?: return failure("Unable to make PSI file from script")
|
||||||
|
|
||||||
val ktScript = psiFile.declarations.firstIsInstanceOrNull<KtScript>()
|
val ktScript = psiFile.declarations.firstIsInstanceOrNull<KtScript>()
|
||||||
?: return failure("Not a script file".asErrorDiagnostics())
|
?: return failure("Not a script file")
|
||||||
|
|
||||||
val sourceFiles = arrayListOf(psiFile)
|
val sourceFiles = arrayListOf(psiFile)
|
||||||
val (classpath, newSources, sourceDependencies) =
|
val (classpath, newSources, sourceDependencies) =
|
||||||
@@ -162,7 +167,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
}
|
}
|
||||||
val analysisResult = analyzerWithCompilerReport.analysisResult
|
val analysisResult = analyzerWithCompilerReport.analysisResult
|
||||||
|
|
||||||
if (!analysisResult.shouldGenerateCode) return failure("no code to generate".asErrorDiagnostics())
|
if (!analysisResult.shouldGenerateCode) return failure("no code to generate")
|
||||||
if (analysisResult.isError() || messageCollector.hasErrors()) return failure()
|
if (analysisResult.isError() || messageCollector.hasErrors()) return failure()
|
||||||
|
|
||||||
val generationState = GenerationState.Builder(
|
val generationState = GenerationState.Builder(
|
||||||
@@ -189,7 +194,9 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
val otherScripts: List<KJvmCompiledScript<*>> =
|
val otherScripts: List<KJvmCompiledScript<*>> =
|
||||||
sourceDependencies.find { it.scriptFile == containingKtFile }?.sourceDependencies?.mapNotNull { sourceFile ->
|
sourceDependencies.find { it.scriptFile == containingKtFile }?.sourceDependencies?.mapNotNull { sourceFile ->
|
||||||
sourceFile.declarations.firstIsInstanceOrNull<KtScript>()?.let {
|
sourceFile.declarations.firstIsInstanceOrNull<KtScript>()?.let {
|
||||||
KJvmCompiledScript<Any>(updatedConfiguration, it.fqName.asString(), makeOtherScripts(it))
|
KJvmCompiledScript<Any>(
|
||||||
|
containingKtFile.virtualFile?.path, updatedConfiguration, it.fqName.asString(), makeOtherScripts(it)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
@@ -198,6 +205,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
}
|
}
|
||||||
|
|
||||||
val compiledScript = KJvmCompiledScript<Any>(
|
val compiledScript = KJvmCompiledScript<Any>(
|
||||||
|
script.locationId,
|
||||||
updatedConfiguration,
|
updatedConfiguration,
|
||||||
ktScript.fqName.asString(),
|
ktScript.fqName.asString(),
|
||||||
makeOtherScripts(ktScript),
|
makeOtherScripts(ktScript),
|
||||||
@@ -206,7 +214,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
|
|||||||
|
|
||||||
return ResultWithDiagnostics.Success(compiledScript, messageCollector.diagnostics)
|
return ResultWithDiagnostics.Success(compiledScript, messageCollector.diagnostics)
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
return failure(ex.asDiagnostics())
|
return failure(ex.asDiagnostics(path = script.locationId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,9 +245,10 @@ internal class ScriptDiagnosticsMessageCollector : MessageCollector {
|
|||||||
}
|
}
|
||||||
if (mappedSeverity != null) {
|
if (mappedSeverity != null) {
|
||||||
val mappedLocation = location?.let {
|
val mappedLocation = location?.let {
|
||||||
SourceCode.Location(SourceCode.Position(it.line, it.column))
|
if (it.line < 0 && it.column < 0) null // special location created by CompilerMessageLocation.create
|
||||||
|
else SourceCode.Location(SourceCode.Position(it.line, it.column))
|
||||||
}
|
}
|
||||||
_diagnostics.add(ScriptDiagnostic(message, mappedSeverity, mappedLocation))
|
_diagnostics.add(ScriptDiagnostic(message, mappedSeverity, location?.path, mappedLocation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -92,6 +92,6 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script"))
|
ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script", path = compiledScript.sourceLocationId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
@@ -75,6 +75,25 @@ class ScriptingHostTest : TestCase() {
|
|||||||
Assert.assertEquals(greeting, output)
|
Assert.assertEquals(greeting, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testImportError() {
|
||||||
|
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||||
|
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||||
|
refineConfiguration {
|
||||||
|
beforeCompiling { ctx ->
|
||||||
|
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||||
|
importScripts(File(TEST_DATA_DIR, "missing_script.kts").toScriptSource())
|
||||||
|
}.asSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val res = BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration, null)
|
||||||
|
assertTrue(res is ResultWithDiagnostics.Failure)
|
||||||
|
val report = res.reports.find { it.message.startsWith("Source file or directory not found") }
|
||||||
|
assertNotNull(report)
|
||||||
|
assertEquals("/script.kts", report?.sourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMemoryCache() {
|
fun testMemoryCache() {
|
||||||
|
|||||||
@@ -72,6 +72,6 @@ public class KotlinVersion(val major: Int, val minor: Int, val patch: Int) : Com
|
|||||||
* Returns the current version of the Kotlin standard library.
|
* Returns the current version of the Kotlin standard library.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmField
|
@kotlin.jvm.JvmField
|
||||||
public val CURRENT: KotlinVersion = KotlinVersion(1, 3, 0) // value is written here automatically during build
|
public val CURRENT: KotlinVersion = KotlinVersion(1, 3, 115) // value is written here automatically during build
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,14 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler {
|
|||||||
}
|
}
|
||||||
val diagnostics = arrayListOf<ScriptDiagnostic>()
|
val diagnostics = arrayListOf<ScriptDiagnostic>()
|
||||||
fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {
|
fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {
|
||||||
diagnostics.add(ScriptDiagnostic(message, mapLegacyDiagnosticSeverity(severity), mapLegacyScriptPosition(position)))
|
diagnostics.add(
|
||||||
|
ScriptDiagnostic(
|
||||||
|
message,
|
||||||
|
mapLegacyDiagnosticSeverity(severity),
|
||||||
|
context.script.locationId,
|
||||||
|
mapLegacyScriptPosition(position)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return try {
|
return try {
|
||||||
val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get()
|
val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get()
|
||||||
@@ -62,7 +69,7 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler {
|
|||||||
dependencies.append(JvmDependency(resolvedClasspath))
|
dependencies.append(JvmDependency(resolvedClasspath))
|
||||||
}.asSuccess(diagnostics)
|
}.asSuccess(diagnostics)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics())
|
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics(path = context.script.locationId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user