diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java index 1f068b6f49f..eb577094bba 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java @@ -152,10 +152,7 @@ public class ScriptCodegen extends MemberCodegen { iv.invokespecial("java/lang/Object", "", "()V", false); } else { - // TODO: check if it is correct way to find a primary constructor - Collection ctorDescriptors = superclass.getConstructors(); - assert ctorDescriptors.size() == 1; - ConstructorDescriptor ctorDesc = ctorDescriptors.iterator().next(); + ConstructorDescriptor ctorDesc = superclass.getUnsubstitutedPrimaryConstructor(); assert ctorDesc != null; iv.load(0, classType); diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/CompilerMessageLocation.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/CompilerMessageLocation.kt index 3ae51828be5..013eb183c49 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/CompilerMessageLocation.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/CompilerMessageLocation.kt @@ -38,6 +38,6 @@ data class CompilerMessageLocation private constructor( ): CompilerMessageLocation = if (path == null) NO_LOCATION else CompilerMessageLocation(path, line, column, lineContent) - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/reflectionUtil.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/reflectionUtil.kt index 1d650157b72..4403f619899 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/reflectionUtil.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/reflectionUtil.kt @@ -73,13 +73,13 @@ fun tryConstructScriptClass(scriptClass: Class<*>, scriptArgs: List): An } try { - return scriptClass.getConstructor(Array::class.java).newInstance(*arrayOf(scriptArgs.toTypedArray())) + return scriptClass.getConstructor(Array::class.java).newInstance(scriptArgs.toTypedArray()) } - catch (e: java.lang.NoSuchMethodException) { + catch (e: NoSuchMethodException) { for (ctor in scriptClass.kotlin.constructors) { val (ctorArgs, scriptArgsLeft) = ctor.parameters.fold(Pair(emptyList(), scriptArgs), ::foldingFunc) if (ctorArgs.size <= ctor.parameters.size && (scriptArgsLeft == null || scriptArgsLeft.isEmpty())) { - val argsMap = ctorArgs.zip(ctor.parameters) { a, p -> Pair(p, a) }.toMap() + val argsMap = ctor.parameters.zip(ctorArgs).toMap() try { return ctor.callBy(argsMap) } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt index c72ac1eb521..dfe95831f18 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt @@ -25,8 +25,7 @@ import kotlin.concurrent.write open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClassloader: ClassLoader?, val scriptArgs: Array? = null, val scriptArgsTypes: Array>? = null) : ReplCompiledEvaluator { - private var classLoader: org.jetbrains.kotlin.cli.common.repl.ReplClassLoader = - org.jetbrains.kotlin.cli.common.repl.ReplClassLoader(URLClassLoader(baseClasspath.map { it.toURI().toURL() }.toTypedArray(), baseClassloader)) + private var classLoader: org.jetbrains.kotlin.cli.common.repl.ReplClassLoader = makeReplClassLoader(baseClassloader, baseClasspath) private val classLoaderLock = ReentrantReadWriteLock() private class ClassWithInstance(val klass: Class<*>, val instance: Any) @@ -42,7 +41,7 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass classLoaderLock.read { if (newClasspath.isNotEmpty()) { classLoaderLock.write { - classLoader = org.jetbrains.kotlin.cli.common.repl.ReplClassLoader(URLClassLoader(newClasspath.map { it.toURI().toURL() }.toTypedArray(), classLoader)) + classLoader = makeReplClassLoader(classLoader, newClasspath) } } compiledClasses.filter { it.path.endsWith(".class") } @@ -55,14 +54,9 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass val constructorParams: Array> = (compiledLoadedClassesHistory.map { it.second.klass } + - (scriptArgs?.asIterable() - ?.mapIndexed { i, it -> - if (i < (scriptArgsTypes?.size ?: 0)) scriptArgsTypes!![i] else it?.javaClass ?: Any::class.java - } - ?: emptyList() - ) + (scriptArgs?.mapIndexed { i, it -> scriptArgsTypes?.getOrNull(i) ?: it?.javaClass ?: Any::class.java } ?: emptyList()) ).toTypedArray() - val constructorArgs: Array = (compiledLoadedClassesHistory.map { it.second.instance } + (scriptArgs?.asIterable() ?: emptyList())).toTypedArray() + val constructorArgs: Array = (compiledLoadedClassesHistory.map { it.second.instance } + scriptArgs.orEmpty()).toTypedArray() val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams) val scriptInstance = @@ -85,4 +79,7 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass companion object { private val SCRIPT_RESULT_FIELD_NAME = "\$\$result" } -} \ No newline at end of file +} + +private fun makeReplClassLoader(baseClassloader: ClassLoader?, baseClasspath: Iterable) = + ReplClassLoader(URLClassLoader(baseClasspath.map { it.toURI().toURL() }.toTypedArray(), baseClassloader)) \ No newline at end of file diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/Repl.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/Repl.kt index 34bb845d988..d0897c9edd4 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/Repl.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/Repl.kt @@ -23,7 +23,7 @@ import java.util.* data class ReplCodeLine(val no: Int, val code: String) : Serializable { companion object { - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } @@ -31,7 +31,7 @@ data class CompiledClassData(val path: String, val bytes: ByteArray) : Serializa override fun equals(other: Any?): Boolean = (other as? CompiledClassData)?.let { path == it.path && Arrays.equals(bytes, it.bytes) } ?: false override fun hashCode(): Int = path.hashCode() + Arrays.hashCode(bytes) companion object { - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } @@ -42,7 +42,7 @@ sealed class ReplCheckResult : Serializable { override fun toString(): String = "Error(message = \"$message\"" } companion object { - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } @@ -54,7 +54,7 @@ sealed class ReplCompileResult : Serializable { override fun toString(): String = "Error(message = \"$message\"" } companion object { - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } @@ -68,10 +68,10 @@ sealed class ReplEvalResult : Serializable { sealed class Error(val message: String) : ReplEvalResult() { class Runtime(message: String) : Error(message) class CompileTime(message: String, val location: CompilerMessageLocation = CompilerMessageLocation.NO_LOCATION) : Error(message) - override fun toString(): String = "${this.javaClass.kotlin.simpleName}Error(message = \"$message\"" + override fun toString(): String = "${this::class.simpleName}Error(message = \"$message\"" } companion object { - private val serialVersionUID: Long = 8228357578L // just a random number, should be changed when serialized data is changed + private val serialVersionUID: Long = 8228357578L } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt index bfd8c480e52..feebcd840b8 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.script.KotlinScriptDefinition @@ -74,28 +73,27 @@ open class GenericReplChecker( fun createDiagnosticHolder() = ReplTerminalDiagnosticMessageHolder() + @Synchronized override fun check(codeLine: ReplCodeLine, history: Iterable): ReplCheckResult { - synchronized(this) { - val virtualFile = - LightVirtualFile("line${codeLine.no}${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, codeLine.code).apply { - charset = CharsetToolkit.UTF8_CHARSET - } - val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile? - ?: error("Script file not analyzed at line ${codeLine.no}: ${codeLine.code}") + val virtualFile = + LightVirtualFile("line${codeLine.no}${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, codeLine.code).apply { + charset = CharsetToolkit.UTF8_CHARSET + } + val psiFile: KtFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile? + ?: error("Script file not analyzed at line ${codeLine.no}: ${codeLine.code}") - val errorHolder = createDiagnosticHolder() + val errorHolder = createDiagnosticHolder() - val syntaxErrorReport = AnalyzerWithCompilerReport.Companion.reportSyntaxErrors(psiFile, errorHolder) + val syntaxErrorReport = AnalyzerWithCompilerReport.Companion.reportSyntaxErrors(psiFile, errorHolder) - if (!syntaxErrorReport.isHasErrors) { - lineState = LineState(codeLine, psiFile, errorHolder) - } + if (!syntaxErrorReport.isHasErrors) { + lineState = LineState(codeLine, psiFile, errorHolder) + } - return when { - syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof -> ReplCheckResult.Incomplete - syntaxErrorReport.isHasErrors -> ReplCheckResult.Error(errorHolder.renderedDiagnostics) - else -> ReplCheckResult.Ok - } + return when { + syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof -> ReplCheckResult.Incomplete + syntaxErrorReport.isHasErrors -> ReplCheckResult.Error(errorHolder.renderedDiagnostics) + else -> ReplCheckResult.Ok } } } @@ -113,61 +111,59 @@ open class GenericReplCompiler( private val descriptorsHistory = arrayListOf>() + @Synchronized override fun compile(codeLine: ReplCodeLine, history: Iterable): ReplCompileResult { - synchronized(this) { - - checkAndUpdateReplHistoryCollection(descriptorsHistory, history)?.let { - return@compile ReplCompileResult.HistoryMismatch(it) - } - - val (psiFile, errorHolder) = run { - if (lineState == null || lineState!!.codeLine != codeLine) { - val res = check(codeLine, history) - when (res) { - ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete - is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(res.message, res.location) - ReplCheckResult.Ok -> {} // continue - } - } - Pair(lineState!!.psiFile, lineState!!.errorHolder) - } - - val newDependencies = scriptDefinition.getDependenciesFor(psiFile, environment.project, lastDependencies) - if (lastDependencies != newDependencies) { - lastDependencies = newDependencies - } - - val analysisResult = analyzerEngine.analyzeReplLine(psiFile, codeLine.no) - AnalyzerWithCompilerReport.Companion.reportDiagnostics(analysisResult.diagnostics, errorHolder, false) - val scriptDescriptor = when (analysisResult) { - is CliReplAnalyzerEngine.ReplLineAnalysisResult.WithErrors -> return ReplCompileResult.Error(errorHolder.renderedDiagnostics) - is CliReplAnalyzerEngine.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor - else -> error("Unexpected result ${analysisResult.javaClass}") - } - - val state = GenerationState( - psiFile.project, - ClassBuilderFactories.binaries(false), - analyzerEngine.module, - analyzerEngine.trace.bindingContext, - listOf(psiFile), - compilerConfiguration - ) - state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME - state.replSpecific.earlierScriptsForReplInterpreter = descriptorsHistory.map { it.second } - state.beforeCompile() - KotlinCodegenFacade.generatePackage( - state, - psiFile.script!!.getContainingKtFile().packageFqName, - setOf(psiFile.script!!.getContainingKtFile()), - org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION) - - descriptorsHistory.add(codeLine to scriptDescriptor) - - return ReplCompileResult.CompiledClasses(state.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) }, - state.replSpecific.hasResult, - newDependencies?.let { environment.updateClasspath(it.classpath.map(::JvmClasspathRoot)) } ?: emptyList()) + checkAndUpdateReplHistoryCollection(descriptorsHistory, history)?.let { + return@compile ReplCompileResult.HistoryMismatch(it) } + + val (psiFile, errorHolder) = run { + if (lineState == null || lineState!!.codeLine != codeLine) { + val res = check(codeLine, history) + when (res) { + ReplCheckResult.Incomplete -> return@compile ReplCompileResult.Incomplete + is ReplCheckResult.Error -> return@compile ReplCompileResult.Error(res.message, res.location) + ReplCheckResult.Ok -> {} // continue + } + } + Pair(lineState!!.psiFile, lineState!!.errorHolder) + } + + val newDependencies = scriptDefinition.getDependenciesFor(psiFile, environment.project, lastDependencies) + if (lastDependencies != newDependencies) { + lastDependencies = newDependencies + } + + val analysisResult = analyzerEngine.analyzeReplLine(psiFile, codeLine.no) + AnalyzerWithCompilerReport.Companion.reportDiagnostics(analysisResult.diagnostics, errorHolder, false) + val scriptDescriptor = when (analysisResult) { + is CliReplAnalyzerEngine.ReplLineAnalysisResult.WithErrors -> return ReplCompileResult.Error(errorHolder.renderedDiagnostics) + is CliReplAnalyzerEngine.ReplLineAnalysisResult.Successful -> analysisResult.scriptDescriptor + else -> error("Unexpected result ${analysisResult.javaClass}") + } + + val state = GenerationState( + psiFile.project, + ClassBuilderFactories.binaries(false), + analyzerEngine.module, + analyzerEngine.trace.bindingContext, + listOf(psiFile), + compilerConfiguration + ) + state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME + state.replSpecific.earlierScriptsForReplInterpreter = descriptorsHistory.map { it.second } + state.beforeCompile() + KotlinCodegenFacade.generatePackage( + state, + psiFile.script!!.getContainingKtFile().packageFqName, + setOf(psiFile.script!!.getContainingKtFile()), + org.jetbrains.kotlin.codegen.CompilationErrorHandler.THROW_EXCEPTION) + + descriptorsHistory.add(codeLine to scriptDescriptor) + + return ReplCompileResult.CompiledClasses(state.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) }, + state.replSpecific.hasResult, + newDependencies?.let { environment.updateClasspath(it.classpath.map(::JvmClasspathRoot)) } ?: emptyList()) } companion object { @@ -188,9 +184,9 @@ open class GenericRepl( private val compiledEvaluator = GenericReplCompiledEvaluator(compilerConfiguration.jvmClasspathRoots, baseClassloader, scriptArgs, scriptArgsTypes) - override fun eval(codeLine: ReplCodeLine, history: Iterable): ReplEvalResult = synchronized(this) { - return compileAndEval(this, compiledEvaluator, codeLine, history) - } + @Synchronized + override fun eval(codeLine: ReplCodeLine, history: Iterable): ReplEvalResult = + compileAndEval(this, compiledEvaluator, codeLine, history) } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index d3cb4c6c6d9..32f033c2099 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -390,9 +390,10 @@ class CompileServiceImpl( synchronized(state.sessions) { // 2. check if any session hanged - clean - state.sessions.filterValues { !it.isAlive }.apply { anyDead = true }.forEach { + state.sessions.filterValues { !it.isAlive }.forEach { it.value.dispose() state.sessions.remove(it.key) + anyDead = true } } @@ -403,13 +404,14 @@ class CompileServiceImpl( } // 4. clean dead clients, then check if any left - conditional shutdown (with small delay) - synchronized(state.clientProxies) { - state.clientProxies.removeAll( - state.clientProxies.filter { !it.isAlive }.apply { anyDead = true }.map { - it.dispose() - it - }) - } + synchronized(state.clientProxies) { + state.clientProxies.removeAll( + state.clientProxies.filter { !it.isAlive }.map { + it.dispose() + anyDead = true + it + }) + } if (state.clientProxies.isEmpty() && compilationsCounter.get() > 0 && !state.delayedShutdownQueued.get()) { log.info("No more clients left, delayed shutdown in ${daemonOptions.shutdownDelayMilliseconds}ms") shutdownWithDelay() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt index a5294c44643..4d3f69032bd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt @@ -52,11 +52,11 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate( defAnn != null -> try { defAnn.resolver.primaryConstructor?.call() ?: null.apply { - log.error("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}") + log.warn("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}") } } catch (ex: ClassCastException) { - log.error("[kts] Script def error ${ex.message}") + log.warn("[kts] Script def error ${ex.message}") null } else -> BasicScriptDependenciesResolver() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt index 0a22a9536b8..1f3a56fdb7d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/scriptTypeUtil.kt @@ -37,7 +37,7 @@ fun KotlinScriptDefinition.getScriptParameters(scriptDescriptor: ScriptDescripto fun getKotlinType(scriptDescriptor: ScriptDescriptor, kClass: KClass): KotlinType = getKotlinTypeByFqName(scriptDescriptor, - kClass.qualifiedName ?: throw java.lang.RuntimeException("Cannot get FQN from $kClass")) + kClass.qualifiedName ?: throw RuntimeException("Cannot get FQN from $kClass")) fun getKotlinTypeByFqName(scriptDescriptor: ScriptDescriptor, fqName: String): KotlinType = scriptDescriptor.module.findNonGenericClassAcrossDependencies( diff --git a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt index 2013e6976cf..2946bd87459 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt @@ -22,14 +22,14 @@ import junit.framework.TestCase import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.common.repl.* -import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.integration.KotlinIntegrationTestBase import org.jetbrains.kotlin.script.KotlinScriptDefinition import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate -import org.jetbrains.kotlin.utils.PathUtil +import org.jetbrains.kotlin.test.ConfigurationKind +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TestJdkKind import org.junit.Test import java.io.File import java.net.URLClassLoader @@ -48,7 +48,7 @@ class GenericReplTest : TestCase() { val res1 = repl.replCompiler?.check(ReplCodeLine(0, "val x ="), emptyList()) TestCase.assertTrue("Unexpected check results: $res1", res1 is ReplCheckResult.Incomplete) - val codeLine0 = ReplCodeLine(0, "1 + 2") + val codeLine0 = ReplCodeLine(0, "val l1 = listOf(1 + 2)\nl1.first()") val res2 = repl.replCompiler?.compile(codeLine0, emptyList()) val res2c = res2 as? ReplCompileResult.CompiledClasses TestCase.assertNotNull("Unexpected compile result: $res2", res2c) @@ -89,12 +89,10 @@ internal class TestRepl( templateClasspath: List, templateClassName: String ) { - private val configuration = CompilerConfiguration().apply { - addJvmClasspathRoots(PathUtil.getJdkClassesRoots()) - addJvmClasspathRoots(PathUtil.getKotlinPathsForCompiler().let { listOf(it.runtimePath, it.reflectPath) }) - addJvmClasspathRoots(templateClasspath) + private val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, *templateClasspath.toTypedArray()).apply { put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script") } + private fun makeScriptDefinition(templateClasspath: List, templateClassName: String): KotlinScriptDefinition { val classloader = URLClassLoader(templateClasspath.map { it.toURI().toURL() }.toTypedArray(), this.javaClass.classLoader) val cls = classloader.loadClass(templateClassName) diff --git a/compiler/tests/org/jetbrains/kotlin/daemon/CompilerDaemonTest.kt b/compiler/tests/org/jetbrains/kotlin/daemon/CompilerDaemonTest.kt index 56fd768903c..ffbe7c2aba1 100644 --- a/compiler/tests/org/jetbrains/kotlin/daemon/CompilerDaemonTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/daemon/CompilerDaemonTest.kt @@ -510,7 +510,7 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() { val res0 = repl.check(ReplCodeLine(0, "val x ="), emptyList()) TestCase.assertTrue("Unexpected check results: $res0", res0 is ReplCheckResult.Incomplete) - val codeLine1 = ReplCodeLine(1, "val x = 5") + val codeLine1 = ReplCodeLine(1, "val lst = listOf(1)\nval x = 5") val res1 = repl.compile(codeLine1, emptyList()) val res1c = res1 as? ReplCompileResult.CompiledClasses TestCase.assertNotNull("Unexpected compile result: $res1", res1c) diff --git a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt index b13fe2b31f2..05bb0bfaa56 100644 --- a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTemplateTest.kt @@ -181,29 +181,45 @@ class ScriptTemplateTest { fun testScriptWithStandardTemplate() { val aClass = compileScript("fib_std.kts", StandardScriptTemplate::class, runIsolated = false) Assert.assertNotNull(aClass) - aClass!!.getConstructor(Array::class.java).newInstance(arrayOf("4", "other")) + captureOut { + aClass!!.getConstructor(Array::class.java).newInstance(arrayOf("4", "other")) + }.let { + assertEqualsTrimmed(NUM_4_LINE + " (other)" + FIB_SCRIPT_OUTPUT_TAIL, it) + } } @Test fun testScriptWithPackage() { val aClass = compileScript("fib.pkg.kts", ScriptWithIntParam::class) Assert.assertNotNull(aClass) - aClass!!.getConstructor(Integer.TYPE).newInstance(4) + captureOut { + aClass!!.getConstructor(Integer.TYPE).newInstance(4) + }.let { + assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, it) + } } @Test fun testScriptWithScriptDefinition() { val aClass = compileScript("fib.kts", ScriptWithIntParam::class) Assert.assertNotNull(aClass) - aClass!!.getConstructor(Integer.TYPE).newInstance(4) + captureOut { + aClass!!.getConstructor(Integer.TYPE).newInstance(4) + }.let { + assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, it) + } } @Test fun testScriptWithParamConversion() { val aClass = compileScript("fib.kts", ScriptWithIntParam::class) Assert.assertNotNull(aClass) - val anObj = tryConstructScriptClass(aClass!!, listOf("4")) - Assert.assertNotNull(anObj) + captureOut { + val anObj = tryConstructScriptClass(aClass!!, listOf("4")) + Assert.assertNotNull(anObj) + }.let { + assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, it) + } } @Test @@ -275,8 +291,6 @@ class ScriptTemplateTest { open class TestKotlinScriptDummyDependenciesResolver : ScriptDependenciesResolver { - private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() } - @AcceptedAnnotations(DependsOn::class, DependsOnTwo::class) override fun resolve(script: ScriptContents, environment: Map?, diff --git a/compiler/tests/org/jetbrains/kotlin/scripts/scriptTestsUtil.kt b/compiler/tests/org/jetbrains/kotlin/scripts/scriptTestsUtil.kt index fb6ed6d9e9d..ad38373e77d 100644 --- a/compiler/tests/org/jetbrains/kotlin/scripts/scriptTestsUtil.kt +++ b/compiler/tests/org/jetbrains/kotlin/scripts/scriptTestsUtil.kt @@ -39,9 +39,13 @@ internal fun captureOut(body: () -> Unit): String { val outStream = ByteArrayOutputStream() val prevOut = System.out System.setOut(PrintStream(outStream)) - body() - System.out.flush() - System.setOut(prevOut) + try { + body() + } + finally { + System.out.flush() + System.setOut(prevOut) + } return outStream.toString() } diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223JvmScriptEngine4Idea.kt b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223JvmScriptEngine4Idea.kt index c620e9d6b3c..2633533256a 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223JvmScriptEngine4Idea.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223JvmScriptEngine4Idea.kt @@ -69,8 +69,9 @@ class KotlinJsr223JvmScriptEngine4Idea( override fun eval(codeLine: ReplCodeLine, history: Iterable): ReplEvalResult { - fun ReplCompileResult.Error.locationString() = if (location == CompilerMessageLocation.NO_LOCATION) "" - else " at ${location.line}:${location.column}:" + fun ReplCompileResult.Error.locationString() = + if (location == CompilerMessageLocation.NO_LOCATION) "" + else " at ${location.line}:${location.column}" val compileResult = replCompiler.compile(codeLine, history) val compiled = when (compileResult) { diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223StandardScriptEngineFactory4Idea.kt b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223StandardScriptEngineFactory4Idea.kt index 5370e4b78ee..9fc7c21845f 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223StandardScriptEngineFactory4Idea.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJsr223StandardScriptEngineFactory4Idea.kt @@ -36,6 +36,6 @@ class KotlinJsr223StandardScriptEngineFactory4Idea : KotlinJsr223JvmScriptEngine arrayOf( (bindings[ScriptEngine.ARGV] as? Array<*>) ?: emptyArray(), bindings) }, - arrayOf(Array::class.java, java.util.Map::class.java) + arrayOf(Array::class.java, Map::class.java) ) } diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt deleted file mode 100644 index a1f5fb45fca..00000000000 --- a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.jsr223 - -import com.intellij.openapi.Disposable -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.repl.GenericReplCompiledEvaluator -import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine -import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult -import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult -import org.jetbrains.kotlin.daemon.client.DaemonReportMessage -import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets -import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient -import org.jetbrains.kotlin.daemon.client.KotlinRemoteReplCompiler -import org.jetbrains.kotlin.daemon.common.* -import org.jetbrains.kotlin.utils.PathUtil -import java.io.File -import java.io.Reader -import javax.script.* - -class KotlinJvmJsr223ScriptEngine4Idea( - disposable: Disposable, - private val factory: ScriptEngineFactory, - templateClasspath: List, - templateClassName: String, - getScriptArgs: (ScriptContext) -> Array?, - scriptArgsTypes: Array>? -) : AbstractScriptEngine(), ScriptEngine { - - private val daemon by lazy { - val path = PathUtil.getKotlinPathsForIdeaPlugin().compilerPath - assert(path.exists()) - val compilerId = CompilerId.makeCompilerId(path) - val daemonOptions = configureDaemonOptions() - val daemonJVMOptions = DaemonJVMOptions() - - val daemonReportMessages = arrayListOf() - - KotlinCompilerClient.connectToCompileService(compilerId, daemonJVMOptions, daemonOptions, DaemonReportingTargets(null, daemonReportMessages), true, true) - ?: throw ScriptException("Unable to connect to repl server:" + daemonReportMessages.joinToString("\n ", prefix = "\n ") { "${it.category.name} ${it.message}" }) - } - - private val replCompiler by lazy { - daemon.let { - KotlinRemoteReplCompiler(disposable, - it, - makeAutodeletingFlagFile("idea-jsr223-repl-session"), - CompileService.TargetPlatform.JVM, - templateClasspath, - templateClassName, - System.out) - } - } - - // TODO: bindings passing works only once on the first eval, subsequent setContext/setBindings call have no effect. Consider making it dynamic, but take history into account - val localEvaluator by lazy { GenericReplCompiledEvaluator(templateClasspath, Thread.currentThread().contextClassLoader, getScriptArgs(getContext()), scriptArgsTypes) } - - private var lineCount = 0 - - private val history = arrayListOf() - - override fun eval(script: String, context: ScriptContext?): Any? { - - fun ReplCompileResult.Error.locationString() = if (location == CompilerMessageLocation.NO_LOCATION) "" - else " at ${location.line}:${location.column}:" - - lineCount += 1 - // TODO bind to context - val codeLine = ReplCodeLine(lineCount, script) - val compileResult = replCompiler?.compile(codeLine, history) - val compiled = when (compileResult) { - is ReplCompileResult.Error -> throw ScriptException("Error${compileResult.locationString()}: ${compileResult.message}") - is ReplCompileResult.Incomplete -> throw ScriptException("error: incomplete code") - is ReplCompileResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${compileResult.lineNo}") - is ReplCompileResult.CompiledClasses -> compileResult - } - - val evalResult = localEvaluator.eval(codeLine, history, compiled.classes, compiled.hasResult, compiled.newClasspath) - val ret = when (evalResult) { - is ReplEvalResult.ValueResult -> evalResult.value - is ReplEvalResult.UnitResult -> null - is ReplEvalResult.Error -> throw ScriptException(evalResult.message) - is ReplEvalResult.Incomplete -> throw ScriptException("error: incomplete code") - is ReplEvalResult.HistoryMismatch -> throw ScriptException("Repl history mismatch at line: ${evalResult.lineNo}") - } - history.add(codeLine) - // TODO update context - return ret - } - - override fun eval(script: Reader, context: ScriptContext?): Any? = eval(script.readText(), context) - - override fun createBindings(): Bindings = SimpleBindings() - - override fun getFactory(): ScriptEngineFactory = factory -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt b/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt index c495eb9b073..46f2cb2ab28 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt @@ -37,10 +37,10 @@ class IdeaJsr223Test : PlatformTestCase() { val res0 = assertFails { engine.eval("val x =") } assertTrue("Unexpected check results: $res0", (res0 as? ScriptException)?.message?.contains("incomplete code") ?: false) - val res1 = engine.eval("val x = 5") + val res1 = engine.eval("val x = 5\nval y = listOf(x)") assertNull("Unexpected eval result: $res1", res1) - val res2 = engine.eval("x + 2") + val res2 = engine.eval("y.first() + 2") assertEquals(7, res2) } diff --git a/libraries/examples/kotlin-jsr223-daemon-local-eval-example/pom.xml b/libraries/examples/kotlin-jsr223-daemon-local-eval-example/pom.xml index 32fc14bd9e0..ee281276b24 100644 --- a/libraries/examples/kotlin-jsr223-daemon-local-eval-example/pom.xml +++ b/libraries/examples/kotlin-jsr223-daemon-local-eval-example/pom.xml @@ -86,8 +86,8 @@ 2.6 - ${org.jetbrains.kotlin:kotlin-compiler:jar} - ${org.jetbrains.kotlin:kotlin-runtime:jar} + ${org.jetbrains.kotlin:kotlin-compiler:jar} + ${org.jetbrains.kotlin:kotlin-runtime:jar} diff --git a/libraries/examples/kotlin-jsr223-daemon-remote-eval-example/pom.xml b/libraries/examples/kotlin-jsr223-daemon-remote-eval-example/pom.xml index 6c11742f0a1..44062fea97e 100644 --- a/libraries/examples/kotlin-jsr223-daemon-remote-eval-example/pom.xml +++ b/libraries/examples/kotlin-jsr223-daemon-remote-eval-example/pom.xml @@ -86,8 +86,8 @@ 2.6 - ${org.jetbrains.kotlin:kotlin-compiler:jar} - ${org.jetbrains.kotlin:kotlin-runtime:jar} + ${org.jetbrains.kotlin:kotlin-compiler:jar} + ${org.jetbrains.kotlin:kotlin-runtime:jar} diff --git a/libraries/examples/kotlin-jsr223-local-example/pom.xml b/libraries/examples/kotlin-jsr223-local-example/pom.xml index 241eda41e85..153a4b81920 100644 --- a/libraries/examples/kotlin-jsr223-local-example/pom.xml +++ b/libraries/examples/kotlin-jsr223-local-example/pom.xml @@ -86,8 +86,8 @@ 2.6 - ${org.jetbrains.kotlin:kotlin-compiler:jar} - ${org.jetbrains.kotlin:kotlin-runtime:jar} + ${org.jetbrains.kotlin:kotlin-compiler:jar} + ${org.jetbrains.kotlin:kotlin-runtime:jar} diff --git a/libraries/examples/kotlin-jsr223-local-example/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/libraries/examples/kotlin-jsr223-local-example/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory index 8a5ab31ff5e..b60d0efbd69 100644 --- a/libraries/examples/kotlin-jsr223-local-example/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory +++ b/libraries/examples/kotlin-jsr223-local-example/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -1 +1,2 @@ -org.jetbrains.kotlin.script.jsr223.KotlinJsr232JvmLocalScriptEngineFactory +org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory + diff --git a/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt b/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt index b79d0d094bf..0bd7611b438 100644 --- a/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt +++ b/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt @@ -51,7 +51,7 @@ class KotlinJsr223ScriptEngineIT { val factory = ScriptEngineManager().getEngineByExtension("kts").factory Assert.assertNotNull(factory) val engine = factory!!.scriptEngine - Assert.assertNotNull(engine as? KotlinJsr232JvmLocalScriptEngine) + Assert.assertNotNull(engine as? KotlinJsr223JvmLocalScriptEngine) Assert.assertSame(factory, engine!!.factory) val bindings = engine.createBindings() Assert.assertTrue(bindings is SimpleBindings) diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptWithTemplate/script.kts b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptWithTemplate/script.kts index a43c85f2173..41c0ca6bf44 100644 --- a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptWithTemplate/script.kts +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptWithTemplate/script.kts @@ -1,5 +1,9 @@ +import java.lang.Exception if (!args.isEmpty()) println("some args passed") +if (this !is org.jetbrains.kotlin.script.util.StandardScript) + throw Exception("Unexpected script base class") + println("Hello from Kotlin script file!") \ No newline at end of file diff --git a/libraries/tools/kotlin-script-util/pom.xml b/libraries/tools/kotlin-script-util/pom.xml index e3bf2acd0d3..0bde17084b9 100644 --- a/libraries/tools/kotlin-script-util/pom.xml +++ b/libraries/tools/kotlin-script-util/pom.xml @@ -103,7 +103,7 @@ ${env.JDK_17}/bin/java - ${org.jetbrains.kotlin:kotlin-stdlib:jar} + ${org.jetbrains.kotlin:kotlin-stdlib:jar} diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232JvmLocalScriptEngine.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223JvmLocalScriptEngine.kt similarity index 92% rename from libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232JvmLocalScriptEngine.kt rename to libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223JvmLocalScriptEngine.kt index 2aa96bb006a..62124ede3d6 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232JvmLocalScriptEngine.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223JvmLocalScriptEngine.kt @@ -37,7 +37,7 @@ import javax.script.ScriptContext import javax.script.ScriptEngineFactory import javax.script.ScriptException -class KotlinJsr232JvmLocalScriptEngine( +class KotlinJsr223JvmLocalScriptEngine( disposable: Disposable, factory: ScriptEngineFactory, val templateClasspath: List, @@ -68,12 +68,11 @@ class KotlinJsr232JvmLocalScriptEngine( fun resetAndThrowOnErrors() { try { if (hasErrors) { - val msg = reports.joinToString("\n") { messageRenderer.render(it.severity, it.message, it.location) } val firstErr = reports.firstOrNull { it.severity.isError } if (firstErr != null) - throw ScriptException(msg, firstErr.location.path, firstErr.location.line, firstErr.location.column) + throw ScriptException(messageRenderer.render(firstErr.severity, firstErr.message, firstErr.location), firstErr.location.path, firstErr.location.line, firstErr.location.column) else - throw ScriptException(msg) + throw ScriptException(reports.joinToString("\n") { messageRenderer.render(it.severity, it.message, it.location) }) } } finally { diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232ScriptEngineFactoryExamples.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineFactoryExamples.kt similarity index 90% rename from libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232ScriptEngineFactoryExamples.kt rename to libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineFactoryExamples.kt index 0db2122bb21..c28801343d3 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr232ScriptEngineFactoryExamples.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineFactoryExamples.kt @@ -27,10 +27,10 @@ import javax.script.ScriptContext import javax.script.ScriptEngine import kotlin.script.StandardScriptTemplate -class KotlinJsr232JvmLocalScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() { +class KotlinJsr223JvmLocalScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() { override fun getScriptEngine(): ScriptEngine = - KotlinJsr232JvmLocalScriptEngine( + KotlinJsr223JvmLocalScriptEngine( Disposer.newDisposable(), this, listOf(kotlinRuntimeJar), @@ -88,11 +88,11 @@ private fun makeSerializableArgumentsForTemplateWithArgsAndBindings(ctx: ScriptC private fun File.existsOrNull(): File? = existsAndCheckOrNull { true } private inline fun File.existsAndCheckOrNull(check: (File.() -> Boolean)): File? = if (exists() && check()) this else null -private val kotlinCompilerJar = System.getProperty("KOTLIN_COMPILER_JAR")?.let(::File)?.existsOrNull() +private val kotlinCompilerJar = System.getProperty("kotlin.compiler.jar")?.let(::File)?.existsOrNull() ?: getPathUtilJar().existsAndCheckOrNull { name == KOTLIN_COMPILER_JAR } - ?: throw FileNotFoundException("Cannot find kotlin compiler jar, set KOTLIN_COMPILER_JAR property to proper location") + ?: throw FileNotFoundException("Cannot find kotlin compiler jar, set kotlin.compiler.jar property to proper location") -private val kotlinRuntimeJar = System.getProperty("KOTLIN_JAVA_RUNTIME_JAR")?.let(::File)?.existsOrNull() +private val kotlinRuntimeJar = System.getProperty("kotlin.java.runtime.jar")?.let(::File)?.existsOrNull() ?: kotlinCompilerJar.let { File(it.parentFile, KOTLIN_JAVA_RUNTIME_JAR) }.existsOrNull() ?: getResourcePathForClass(StandardScriptTemplate::class.java).existsOrNull() - ?: throw FileNotFoundException("Cannot find kotlin runtime jar, set KOTLIN_JAVA_RUNTIME_JAR property to proper location") + ?: throw FileNotFoundException("Cannot find kotlin runtime jar, set kotlin.java.runtime.jar property to proper location") diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/annotations.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/annotations.kt index 23544b7c71b..7783c7e4ba9 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/annotations.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/annotations.kt @@ -16,10 +16,14 @@ package org.jetbrains.kotlin.script.util +// in case of flat or direct resolvers the value should be a direct path or file name of a jar respectively +// in case of maven resolver the maven coordinates string is accepted (resolved with com.jcabi.aether library) @Target(AnnotationTarget.FILE, AnnotationTarget.EXPRESSION, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) @Retention(AnnotationRetention.RUNTIME) annotation class DependsOn(val value: String) +// only flat directory repositories are supported now, so value should be a path to a directory with jars +// TODO: support other types of repos @Target(AnnotationTarget.FILE, AnnotationTarget.EXPRESSION, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) @Retention(AnnotationRetention.RUNTIME) annotation class Repository(val value: String) diff --git a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolve.kt b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolve.kt index ec102702a50..a2041c3366a 100644 --- a/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolve.kt +++ b/libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/resolve.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.script.util.resolvers.DirectResolver import org.jetbrains.kotlin.script.util.resolvers.FlatLibDirectoryResolver import org.jetbrains.kotlin.script.util.resolvers.MavenResolver import org.jetbrains.kotlin.script.util.resolvers.Resolver +import org.jetbrains.kotlin.utils.addToStdlib.check import java.io.File import java.lang.Exception import java.lang.IllegalArgumentException @@ -34,29 +35,28 @@ open class KotlinAnnotatedScriptDependenciesResolver(val baseClassPath: List = resolvers.toMutableList() + inner class ResolvedDependencies(previousDependencies: KotlinScriptExternalDependencies?, depsFromAnnotations: List ) : KotlinScriptExternalDependencies { + override val classpath = if (resolvers.isEmpty()) baseClassPath else baseClassPath + depsFromAnnotations + override val imports = if (previousDependencies != null) emptyList() else listOf(DependsOn::class.java.`package`.name + ".*") + } + @AcceptedAnnotations(DependsOn::class, Repository::class) override fun resolve(script: ScriptContents, environment: Map?, report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, previousDependencies: KotlinScriptExternalDependencies? - ): Future - = (if (previousDependencies != null && resolveFromAnnotations(script).isEmpty()) previousDependencies - else - object : KotlinScriptExternalDependencies { - override val classpath: Iterable = if (resolvers.isEmpty()) baseClassPath else baseClassPath + resolveFromAnnotations(script) - override val imports: Iterable = - previousDependencies?.let { emptyList() } ?: listOf(DependsOn::class.java.`package`.name + ".*") - } - ).asFuture() + ): Future { + val depsFromAnnotations: List = resolveFromAnnotations(script) + return (if (previousDependencies != null && depsFromAnnotations.isEmpty()) previousDependencies + else ResolvedDependencies(previousDependencies, depsFromAnnotations) + ).asFuture() + } private fun resolveFromAnnotations(script: ScriptContents): List { script.annotations.forEach { when (it) { - is Repository -> - when { - File(it.value).run { exists() && isDirectory } -> resolvers.add(FlatLibDirectoryResolver(File(it.value))) - else -> throw IllegalArgumentException("Illegal argument for Repository annotation: ${it.value}") - } + is Repository -> File(it.value).check { it.exists() && it.isDirectory }?.let { resolvers.add(FlatLibDirectoryResolver(it)) } + ?: throw IllegalArgumentException("Illegal argument for Repository annotation: ${it.value}") is DependsOn -> {} is InvalidScriptResolverAnnotation -> throw Exception("Invalid annotation ${it.name}", it.error) else -> throw Exception("Unknown annotation ${it.javaClass}") @@ -83,7 +83,7 @@ private fun classpathFromClassloader(classLoader: ClassLoader): List? = private fun classpathFromClasspathProperty(): List? = System.getProperty("java.class.path")?.let { - it.split(String.format("\\%s", File.pathSeparatorChar).toRegex()).dropLastWhile(String::isEmpty).toTypedArray() + it.split(String.format("\\%s", File.pathSeparatorChar).toRegex()).dropLastWhile(String::isEmpty) .map(::File) } diff --git a/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt b/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt index 8d2d7c42f34..bb304975d31 100644 --- a/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt +++ b/libraries/tools/kotlin-script-util/src/test/kotlin/org/jetbrains/kotlin/script/util/ScriptUtilIT.kt @@ -104,14 +104,12 @@ done scriptFileName: String, scriptTemplate: KClass, environment: Map? = null, - runIsolated: Boolean = true, suppressOutput: Boolean = false): Class<*>? = - compileScriptImpl("src/test/resources/scripts/" + scriptFileName, KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, null, null, environment), runIsolated, suppressOutput) + compileScriptImpl("src/test/resources/scripts/" + scriptFileName, KotlinScriptDefinitionFromAnnotatedTemplate(scriptTemplate, null, null, environment), suppressOutput) private fun compileScriptImpl( scriptPath: String, scriptDefinition: KotlinScriptDefinition, - runIsolated: Boolean, suppressOutput: Boolean): Class<*>? { val paths = PathUtil.getKotlinPathsForDistDirectory() @@ -123,7 +121,7 @@ done try { val configuration = CompilerConfiguration().apply { addJvmClasspathRoots(PathUtil.getJdkClassesRoots()) - val rtJar = System.getProperty("KOTLIN_JAVA_RUNTIME_JAR") + val rtJar = System.getProperty("kotlin.java.runtime.jar") Assert.assertNotNull(rtJar) addJvmClasspathRoot(File(rtJar)) put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) @@ -141,14 +139,12 @@ done put(CommonConfigurationKeys.MODULE_NAME, "kotlin-script-util-test") add(JVMConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinition) put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true) - put(JVMConfigurationKeys.INCLUDE_RUNTIME, true) } val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) try { - return if (runIsolated) KotlinToJVMBytecodeCompiler.compileScript(environment, paths) - else KotlinToJVMBytecodeCompiler.compileScript(environment, this.javaClass.classLoader) + return KotlinToJVMBytecodeCompiler.compileScript(environment, paths) } catch (e: CompilationException) { messageCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), @@ -183,9 +179,13 @@ done val outStream = ByteArrayOutputStream() val prevOut = System.out System.setOut(PrintStream(outStream)) - body() - System.out.flush() - System.setOut(prevOut) + try { + body() + } + finally { + System.out.flush() + System.setOut(prevOut) + } return outStream.toString() } } diff --git a/libraries/tools/kotlin-script-util/src/test/resources/scripts/bnd-hello-world.kts b/libraries/tools/kotlin-script-util/src/test/resources/scripts/bnd-hello-world.kts deleted file mode 100644 index b0e051318a5..00000000000 --- a/libraries/tools/kotlin-script-util/src/test/resources/scripts/bnd-hello-world.kts +++ /dev/null @@ -1,8 +0,0 @@ - -println("Hello, world!") - -if (bindings.isNotEmpty()) { - println(bindings.joinToString { "${it.key} = ${it.value}" }) -} - -println("done") diff --git a/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-hello-world.kts b/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-hello-world.kts deleted file mode 100644 index 2d332bd05aa..00000000000 --- a/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-hello-world.kts +++ /dev/null @@ -1,8 +0,0 @@ - -println("Hello, world!") - -if (args.isNotEmpty()) { - println(args.joinToString()) -} - -println("done") diff --git a/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-junit-hello-world.kts b/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-junit-hello-world.kts deleted file mode 100644 index 2d332bd05aa..00000000000 --- a/libraries/tools/kotlin-script-util/src/test/resources/scripts/std-junit-hello-world.kts +++ /dev/null @@ -1,8 +0,0 @@ - -println("Hello, world!") - -if (args.isNotEmpty()) { - println(args.joinToString()) -} - -println("done")