Make script launcher aware of custom scripts, minor correction is core env
This commit is contained in:
@@ -89,6 +89,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFact
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||||
import org.jetbrains.kotlin.script.*
|
import org.jetbrains.kotlin.script.*
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -136,22 +137,14 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
|
|
||||||
KotlinScriptDefinitionProvider.getInstance(project).let { scriptDefinitionProvider ->
|
KotlinScriptDefinitionProvider.getInstance(project).let { scriptDefinitionProvider ->
|
||||||
scriptDefinitionProvider.scriptDefinitions =
|
scriptDefinitionProvider.scriptDefinitions =
|
||||||
configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS).let {
|
configuration.getList(JVMConfigurationKeys.SCRIPT_DEFINITIONS)
|
||||||
if (it.isNotEmpty()) it
|
.ifEmpty { listOf(StandardScriptDefinition) }
|
||||||
else {
|
|
||||||
val kotlinEnvVars = generateKotlinScriptClasspathEnvVarsForCompiler(project)
|
configuration.addJvmClasspathRoots(
|
||||||
loadScriptConfigsFromProjectRoot(File(project.basePath ?: ".")).map {
|
sourceFiles
|
||||||
KotlinConfigurableScriptDefinition(it, kotlinEnvVars)
|
.mapNotNull { src -> src.virtualFile?.let { scriptDefinitionProvider.findScriptDefinition(it) } }
|
||||||
} + StandardScriptDefinition
|
.flatMap { it.getScriptDependenciesClasspath().map { File(it).canonicalFile } }
|
||||||
}
|
.distinct())
|
||||||
}
|
|
||||||
KotlinScriptExtraImportsProvider.getInstance(project).let { scriptExtraImportsProvider ->
|
|
||||||
configuration.addJvmClasspathRoots(
|
|
||||||
sourceFiles
|
|
||||||
.filter { it.originalFile.virtualFile != null && scriptDefinitionProvider.isScript(it.originalFile.virtualFile) }
|
|
||||||
.flatMap { scriptExtraImportsProvider.getExtraImports(it.originalFile.virtualFile).flatMap { it.classpath.map { File(it).canonicalFile } } }
|
|
||||||
.distinct())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fillClasspath(configuration)
|
fillClasspath(configuration)
|
||||||
|
|||||||
+68
-4
@@ -17,10 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||||
|
|
||||||
import com.intellij.openapi.util.io.JarUtil
|
import com.intellij.openapi.util.io.JarUtil
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
|
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
||||||
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
|
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.messages.*
|
import org.jetbrains.kotlin.cli.common.messages.*
|
||||||
@@ -49,6 +51,7 @@ import org.jetbrains.kotlin.name.isSubpackageOf
|
|||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||||
|
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
@@ -59,6 +62,12 @@ import java.lang.reflect.InvocationTargetException
|
|||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.jar.Attributes
|
import java.util.jar.Attributes
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KParameter
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.defaultType
|
||||||
|
import kotlin.reflect.jvm.javaMethod
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
|
||||||
object KotlinToJVMBytecodeCompiler {
|
object KotlinToJVMBytecodeCompiler {
|
||||||
|
|
||||||
@@ -213,11 +222,11 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
scriptArgs: List<String>): ExitCode
|
scriptArgs: List<String>): ExitCode
|
||||||
{
|
{
|
||||||
val scriptClass = compileScript(environment, paths) ?: return ExitCode.COMPILATION_ERROR
|
val scriptClass = compileScript(environment, paths) ?: return ExitCode.COMPILATION_ERROR
|
||||||
val scriptConstructor = getScriptConstructor(scriptClass)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
scriptConstructor.newInstance(*arrayOf<Any>(scriptArgs.toTypedArray()))
|
tryConstructClass(scriptClass.kotlin, scriptArgs)
|
||||||
|
?: throw RuntimeException("unable to find appropriate constructor for class ${scriptClass.name} accepting arguments $scriptArgs")
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
// NB: these lines are required (see KT-9546) but aren't covered by tests
|
// NB: these lines are required (see KT-9546) but aren't covered by tests
|
||||||
@@ -249,8 +258,63 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getScriptConstructor(scriptClass: Class<*>): Constructor<*> =
|
@TestOnly
|
||||||
scriptClass.getConstructor(Array<String>::class.java)
|
fun tryConstructClassPub(scriptClass: KClass<out Any>, scriptArgs: List<String>): Any? = tryConstructClass(scriptClass, scriptArgs)
|
||||||
|
|
||||||
|
private fun tryConstructClass(scriptClass: KClass<out Any>, scriptArgs: List<String>): Any? {
|
||||||
|
|
||||||
|
fun convertPrimitive(type: KType?, arg: String): Any? =
|
||||||
|
when (type) {
|
||||||
|
String::class.defaultType -> arg
|
||||||
|
Int::class.defaultType -> arg.toInt()
|
||||||
|
Long::class.defaultType -> arg.toLong()
|
||||||
|
Short::class.defaultType -> arg.toShort()
|
||||||
|
Byte::class.defaultType -> arg.toByte()
|
||||||
|
Char::class.defaultType -> arg[0]
|
||||||
|
Float::class.defaultType -> arg.toFloat()
|
||||||
|
Double::class.defaultType -> arg.toDouble()
|
||||||
|
Boolean::class.defaultType -> arg.toBoolean()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun convertArray(type: KType?, args: List<String>): Any? =
|
||||||
|
when (type) {
|
||||||
|
String::class.defaultType -> args.toTypedArray()
|
||||||
|
Int::class.defaultType -> args.map { it.toInt() }.toTypedArray()
|
||||||
|
Long::class.defaultType -> args.map { it.toLong() }.toTypedArray()
|
||||||
|
Short::class.defaultType -> args.map { it.toShort() }.toTypedArray()
|
||||||
|
Byte::class.defaultType -> args.map { it.toByte() }.toTypedArray()
|
||||||
|
Char::class.defaultType -> args.map { it[0] }.toTypedArray()
|
||||||
|
Float::class.defaultType -> args.map { it.toFloat() }.toTypedArray()
|
||||||
|
Double::class.defaultType -> args.map { it.toDouble() }.toTypedArray()
|
||||||
|
Boolean::class.defaultType -> args.map { it.toBoolean() }.toTypedArray()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foldingFunc(state: Pair<List<Any>, List<String>>, par: KParameter): Pair<List<Any>, List<String>> {
|
||||||
|
if (state.second.isNotEmpty()) {
|
||||||
|
try {
|
||||||
|
val primArgCandidate = convertPrimitive(par.type, state.second.first())
|
||||||
|
if (primArgCandidate != null)
|
||||||
|
return Pair(state.first + primArgCandidate, state.second.drop(1))
|
||||||
|
|
||||||
|
val arrayArgCandidate = convertArray((par.type.javaType as? Class<*>)?.componentType?.kotlin?.defaultType, state.second)
|
||||||
|
if (arrayArgCandidate != null)
|
||||||
|
return Pair(state.first + arrayArgCandidate, emptyList<String>())
|
||||||
|
}
|
||||||
|
catch (e: NumberFormatException) {
|
||||||
|
} // just skips to return below
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ctor in scriptClass.constructors) {
|
||||||
|
val (ctorArgs, scriptArgsLeft) = ctor.parameters.fold(Pair(emptyList<Any>(), scriptArgs), ::foldingFunc)
|
||||||
|
if (ctorArgs.size == ctor.parameters.size && scriptArgsLeft.isEmpty())
|
||||||
|
return ctor.call(*ctorArgs.toTypedArray())
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
fun compileScript(environment: KotlinCoreEnvironment, paths: KotlinPaths): Class<*>? =
|
fun compileScript(environment: KotlinCoreEnvironment, paths: KotlinPaths): Class<*>? =
|
||||||
compileScript(environment,
|
compileScript(environment,
|
||||||
|
|||||||
+8
-24
@@ -49,43 +49,27 @@ class KotlinConfigurableScriptDefinition(val config: KotlinScriptConfig, val env
|
|||||||
|
|
||||||
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
override fun getScriptName(script: KtScript): Name = ScriptNameUtil.fileNameWithExtensionStripped(script, KotlinParserDefinition.STD_SCRIPT_EXT)
|
||||||
|
|
||||||
protected val evaluatedClasspath by lazy { config.classpath.evalDistinctWith(environmentVars) }
|
private val evaluatedClasspath by lazy { config.classpath.evalWithVars(environmentVars).distinct() }
|
||||||
|
|
||||||
override fun getScriptDependenciesClasspath(): List<String> = evaluatedClasspath
|
override fun getScriptDependenciesClasspath(): List<String> = evaluatedClasspath
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinDelegatingScriptDefinitionWithExtraImports internal constructor (
|
|
||||||
val delegate: KotlinScriptDefinition,
|
|
||||||
val extraImports: List<KotlinScriptExtraImport>
|
|
||||||
) : KotlinScriptDefinition {
|
|
||||||
override val name: String get() = delegate.name
|
|
||||||
override fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> = delegate.getScriptParameters(scriptDescriptor)
|
|
||||||
override fun getScriptSupertypes(scriptDescriptor: ScriptDescriptor): List<KotlinType> = delegate.getScriptSupertypes(scriptDescriptor)
|
|
||||||
override fun getScriptParametersToPassToSuperclass(scriptDescriptor: ScriptDescriptor): List<Name> =
|
|
||||||
delegate.getScriptParametersToPassToSuperclass(scriptDescriptor)
|
|
||||||
override fun isScript(file: VirtualFile): Boolean = delegate.isScript(file)
|
|
||||||
override fun getScriptName(script: KtScript): Name = delegate.getScriptName(script)
|
|
||||||
|
|
||||||
protected val evaluatedExtraClasspath by lazy {
|
|
||||||
(delegate.getScriptDependenciesClasspath() + extraImports.flatMap { it.classpath }).distinct()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getScriptDependenciesClasspath(): List<String> = evaluatedExtraClasspath
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return all combination of replacements of vars in the strings
|
// return all combination of replacements of vars in the strings
|
||||||
// if corresponding list of replacements is empty, all strings containing the reference to the var are removed
|
// if corresponding list of replacements is empty, all strings containing the reference to the var are removed
|
||||||
// TODO: fix and tests
|
// TODO: fix and tests
|
||||||
// TODO: move to some utils
|
// TODO: move to some utils
|
||||||
internal fun List<String>.evalDistinctWith(varsMap: Map<String, List<String>>?): List<String> =
|
internal fun List<String>.evalWithVars(varsMap: Map<String, List<String>>?): List<String> =
|
||||||
if (varsMap == null || varsMap.isEmpty()) this
|
if (varsMap == null || varsMap.isEmpty()) this
|
||||||
else this.flatMap { cpentry ->
|
else this.flatMap { cpentry ->
|
||||||
varsMap.entries.fold(listOf(cpentry)) { p, v ->
|
varsMap.entries.fold(listOf(cpentry)) { p, v ->
|
||||||
if (v.value.isEmpty() && cpentry.contains("\${${v.key}}")) emptyList()
|
if (cpentry.contains("\${${v.key}}")) {
|
||||||
else v.value.flatMap { valListElement ->
|
if (v.value.isEmpty()) emptyList()
|
||||||
p.map { it.replace("\${${v.key}}", valListElement) }
|
else v.value.flatMap { valListElement ->
|
||||||
|
p.map { it.replace("\${${v.key}}", valListElement) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -31,12 +31,14 @@ class KotlinScriptExtraImportsProvider(val project: Project) {
|
|||||||
fun isExtraImportsConfig(file: VirtualFile): Boolean = file.name.endsWith(IMPORTSFILEEXTENSION)
|
fun isExtraImportsConfig(file: VirtualFile): Boolean = file.name.endsWith(IMPORTSFILEEXTENSION)
|
||||||
|
|
||||||
fun getExtraImports(file: VirtualFile): List<KotlinScriptExtraImport> = lock.read {
|
fun getExtraImports(file: VirtualFile): List<KotlinScriptExtraImport> = lock.read {
|
||||||
cache.getOrPut(file) {
|
if (file.isInLocalFileSystem)
|
||||||
file.parent.findFileByRelativePath(file.name + IMPORTSFILEEXTENSION)?.let {
|
cache.getOrPut(file) {
|
||||||
loadScriptExtraImportConfigs(it.inputStream).map { KotlinScriptExtraImportFromConfig(it, envVars) }
|
file.parent.findFileByRelativePath(file.name + IMPORTSFILEEXTENSION)?.let {
|
||||||
|
loadScriptExtraImportConfigs(it.inputStream).map { KotlinScriptExtraImportFromConfig(it, envVars) }
|
||||||
|
}
|
||||||
|
?: emptyList()
|
||||||
}
|
}
|
||||||
?: listOf()
|
else emptyList()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun invalidateExtraImports(importsFile: VirtualFile) {
|
fun invalidateExtraImports(importsFile: VirtualFile) {
|
||||||
@@ -49,7 +51,7 @@ class KotlinScriptExtraImportsProvider(val project: Project) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(project: Project): KotlinScriptExtraImportsProvider =
|
fun getInstance(project: Project): KotlinScriptExtraImportsProvider? =
|
||||||
ServiceManager.getService(project, KotlinScriptExtraImportsProvider::class.java)
|
ServiceManager.getService(project, KotlinScriptExtraImportsProvider::class.java)
|
||||||
|
|
||||||
val IMPORTSFILEEXTENSION = ".ktsimports.xml"
|
val IMPORTSFILEEXTENSION = ".ktsimports.xml"
|
||||||
|
|||||||
@@ -21,19 +21,15 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
|
||||||
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
fun getScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefinition? =
|
||||||
KotlinScriptDefinitionProvider.getInstance(project).findScriptDefinition(file)?.let { kindDef ->
|
KotlinScriptDefinitionProvider.getInstance(project).findScriptDefinition(file)
|
||||||
val extraImports = KotlinScriptExtraImportsProvider.getInstance(project).getExtraImports(file)
|
|
||||||
if (extraImports.isEmpty()) kindDef
|
|
||||||
else KotlinDelegatingScriptDefinitionWithExtraImports(kindDef, extraImports)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
fun getScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? =
|
||||||
KotlinScriptDefinitionProvider.getInstance(psiFile.project).findScriptDefinition(psiFile.originalFile.virtualFile)?.let { kindDef ->
|
KotlinScriptDefinitionProvider.getInstance(psiFile.project).findScriptDefinition(psiFile.originalFile.virtualFile)
|
||||||
(psiFile.originalFile.virtualFile ?: psiFile.virtualFile)?.let { file ->
|
|
||||||
val extraImports = KotlinScriptExtraImportsProvider.getInstance(psiFile.project).getExtraImports(file)
|
|
||||||
if (extraImports.isEmpty()) kindDef
|
|
||||||
else KotlinDelegatingScriptDefinitionWithExtraImports(kindDef, extraImports)
|
|
||||||
}
|
|
||||||
?: kindDef
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fun getScriptExtraImports(file: VirtualFile, project: Project): List<KotlinScriptExtraImport> =
|
||||||
|
KotlinScriptExtraImportsProvider.getInstance(project)?.getExtraImports(file) ?: emptyList()
|
||||||
|
|
||||||
|
fun getScriptExtraImports(psiFile: PsiFile): List<KotlinScriptExtraImport> =
|
||||||
|
psiFile.virtualFile?.let { file ->
|
||||||
|
KotlinScriptExtraImportsProvider.getInstance(psiFile.project)?.getExtraImports(file)
|
||||||
|
} ?: emptyList()
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ fun loadScriptExtraImportConfigs(configStream: InputStream): List<KotlinScriptEx
|
|||||||
}
|
}
|
||||||
|
|
||||||
class KotlinScriptExtraImportFromConfig(val config : KotlinScriptExtraImportConfig, val envVars: Map<String, List<String>>) : KotlinScriptExtraImport {
|
class KotlinScriptExtraImportFromConfig(val config : KotlinScriptExtraImportConfig, val envVars: Map<String, List<String>>) : KotlinScriptExtraImport {
|
||||||
override val classpath: List<String> by lazy { config.classpath.evalDistinctWith(envVars) }
|
override val classpath: List<String> by lazy { config.classpath.evalWithVars(envVars).distinct() }
|
||||||
override val names: List<String>
|
override val names: List<String>
|
||||||
get() = config.names
|
get() = config.names
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// Expecting two string parameters
|
||||||
|
|
||||||
|
fun fib(n: Int): Int {
|
||||||
|
val v = if(n < 2) 1 else fib(n-1) + fib(n-2)
|
||||||
|
System.out.println("fib($n)=$v")
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("num: ${args[0]} (${args[1]})")
|
||||||
|
val result = fib(java.lang.Integer.parseInt(args[0]))
|
||||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.config.addKotlinSourceRoot
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.kotlin.script.ScriptParameter
|
import org.jetbrains.kotlin.script.ScriptParameter
|
||||||
|
import org.jetbrains.kotlin.script.StandardScriptDefinition
|
||||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
@@ -38,16 +39,35 @@ import org.jetbrains.kotlin.utils.PathUtil
|
|||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.reflect.defaultType
|
||||||
|
|
||||||
class ScriptTest {
|
class ScriptTest {
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testScript() {
|
fun testScriptWithParam() {
|
||||||
val aClass = compileScript("fib.kts", SimpleParamsTestScriptDefinition(".kts", numIntParam()))
|
val aClass = compileScript("fib.kts", SimpleParamsTestScriptDefinition(".kts", numIntParam()))
|
||||||
Assert.assertNotNull(aClass)
|
Assert.assertNotNull(aClass)
|
||||||
aClass!!.getConstructor(Integer.TYPE).newInstance(4)
|
aClass!!.getConstructor(Integer.TYPE).newInstance(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun testStandardScript() {
|
||||||
|
val aClass = compileScript("fib_std.kts", StandardScriptDefinition)
|
||||||
|
Assert.assertNotNull(aClass)
|
||||||
|
val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, listOf("4", "comment"))
|
||||||
|
Assert.assertNotNull(anObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun testScriptWithParamConversion() {
|
||||||
|
val aClass = compileScript("fib.kts", SimpleParamsTestScriptDefinition(".kts", numIntParam()))
|
||||||
|
Assert.assertNotNull(aClass)
|
||||||
|
val anObj = KotlinToJVMBytecodeCompiler.tryConstructClassPub(aClass!!.kotlin, listOf("4"))
|
||||||
|
Assert.assertNotNull(anObj)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testScriptWithPackage() {
|
fun testScriptWithPackage() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.KotlinScriptExtraImport
|
||||||
import org.jetbrains.kotlin.utils.alwaysNull
|
import org.jetbrains.kotlin.utils.alwaysNull
|
||||||
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -289,7 +290,8 @@ internal object NotUnderContentRootModuleInfo : IdeaModuleInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal data class CustomizedScriptModuleInfo(val project: Project, val module: Module?, val virtualFile: VirtualFile,
|
internal data class CustomizedScriptModuleInfo(val project: Project, val module: Module?, val virtualFile: VirtualFile,
|
||||||
val scriptDefinition: KotlinScriptDefinition) : IdeaModuleInfo {
|
val scriptDefinition: KotlinScriptDefinition,
|
||||||
|
val scriptExtraImports: List<KotlinScriptExtraImport>) : IdeaModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.OTHER
|
get() = ModuleOrigin.OTHER
|
||||||
|
|
||||||
@@ -301,7 +303,7 @@ internal data class CustomizedScriptModuleInfo(val project: Project, val module:
|
|||||||
// TODO: find out whether it should be cashed (some changes listener should be implemented for the cached roots)
|
// TODO: find out whether it should be cashed (some changes listener should be implemented for the cached roots)
|
||||||
val virtualFileManager = VirtualFileManager.getInstance()
|
val virtualFileManager = VirtualFileManager.getInstance()
|
||||||
val jarfs = StandardFileSystems.jar()
|
val jarfs = StandardFileSystems.jar()
|
||||||
return (scriptDefinition.getScriptDependenciesClasspath())
|
return (scriptDefinition.getScriptDependenciesClasspath() + scriptExtraImports.flatMap { it.classpath })
|
||||||
.map { File(it).canonicalFile }
|
.map { File(it).canonicalFile }
|
||||||
.distinct()
|
.distinct()
|
||||||
.map {
|
.map {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
|
||||||
import org.jetbrains.kotlin.script.getScriptDefinition
|
import org.jetbrains.kotlin.script.getScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.script.getScriptExtraImports
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
|
|
||||||
fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.getModuleInfo { reason ->
|
fun PsiElement.getModuleInfo(): IdeaModuleInfo = this.getModuleInfo { reason ->
|
||||||
@@ -125,7 +126,7 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
|||||||
|
|
||||||
val scriptDefinition = getScriptDefinition(virtualFile, project)
|
val scriptDefinition = getScriptDefinition(virtualFile, project)
|
||||||
if (scriptDefinition != null)
|
if (scriptDefinition != null)
|
||||||
return CustomizedScriptModuleInfo(project, module, virtualFile, scriptDefinition)
|
return CustomizedScriptModuleInfo(project, module, virtualFile, scriptDefinition, getScriptExtraImports(virtualFile, project))
|
||||||
|
|
||||||
return NotUnderContentRootModuleInfo
|
return NotUnderContentRootModuleInfo
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.io.File
|
|||||||
@Suppress("unused") // project component
|
@Suppress("unused") // project component
|
||||||
class KotlinScriptConfigurationManager(project: Project,
|
class KotlinScriptConfigurationManager(project: Project,
|
||||||
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider,
|
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider,
|
||||||
private val scriptExtraImportsProvider: KotlinScriptExtraImportsProvider
|
scriptExtraImportsProvider: KotlinScriptExtraImportsProvider?
|
||||||
) : AbstractProjectComponent(project) {
|
) : AbstractProjectComponent(project) {
|
||||||
|
|
||||||
private val kotlinEnvVars: Map<String, List<String>> by lazy { generateKotlinScriptClasspathEnvVarsForIdea(myProject) }
|
private val kotlinEnvVars: Map<String, List<String>> by lazy { generateKotlinScriptClasspathEnvVarsForIdea(myProject) }
|
||||||
@@ -43,8 +43,10 @@ class KotlinScriptConfigurationManager(project: Project,
|
|||||||
if (!anyScriptDefinitionChanged && isScriptDefinitionConfigFile(it)) {
|
if (!anyScriptDefinitionChanged && isScriptDefinitionConfigFile(it)) {
|
||||||
anyScriptDefinitionChanged = true
|
anyScriptDefinitionChanged = true
|
||||||
}
|
}
|
||||||
if (scriptExtraImportsProvider.isExtraImportsConfig(it)) {
|
scriptExtraImportsProvider?.run {
|
||||||
scriptExtraImportsProvider.invalidateExtraImports(it)
|
if (isExtraImportsConfig(it)) {
|
||||||
|
invalidateExtraImports(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user