Update project code to use new script.runtime APIs

This commit is contained in:
Pavel V. Talanov
2017-06-22 23:14:16 +03:00
parent 375b058a28
commit 65dba3615c
14 changed files with 191 additions and 241 deletions
@@ -26,7 +26,7 @@ import java.io.File
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.read import kotlin.concurrent.read
import kotlin.concurrent.write import kotlin.concurrent.write
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
class KotlinScriptExternalImportsProviderImpl( class KotlinScriptExternalImportsProviderImpl(
val project: Project, val project: Project,
@@ -34,13 +34,13 @@ class KotlinScriptExternalImportsProviderImpl(
) : KotlinScriptExternalImportsProviderBase(project) { ) : KotlinScriptExternalImportsProviderBase(project) {
private val cacheLock = ReentrantReadWriteLock() private val cacheLock = ReentrantReadWriteLock()
private val cache = hashMapOf<String, KotlinScriptExternalDependencies?>() private val cache = hashMapOf<String, ScriptDependencies?>()
override fun getScriptDependencies(file: VirtualFile): KotlinScriptExternalDependencies? = cacheLock.read { override fun getScriptDependencies(file: VirtualFile): ScriptDependencies? = cacheLock.read {
calculateExternalDependencies(file) calculateExternalDependencies(file)
} }
private fun calculateExternalDependencies(file: VirtualFile): KotlinScriptExternalDependencies? { private fun calculateExternalDependencies(file: VirtualFile): ScriptDependencies? {
val path = file.path val path = file.path
val cached = cache[path] val cached = cache[path]
return if (cached != null) cached return if (cached != null) cached
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder
import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) { class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) {
@@ -70,5 +70,5 @@ class GenericReplCompilerState(environment: KotlinCoreEnvironment, override val
val analyzerEngine = ReplCodeAnalyzer(environment) val analyzerEngine = ReplCodeAnalyzer(environment)
var lastDependencies: KotlinScriptExternalDependencies? = null var lastDependencies: ScriptDependencies? = null
} }
@@ -17,8 +17,6 @@
package org.jetbrains.kotlin.script package org.jetbrains.kotlin.script
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
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.psi.KtScript import org.jetbrains.kotlin.psi.KtScript
@@ -28,15 +26,13 @@ import kotlin.reflect.KFunction
import kotlin.reflect.KParameter import kotlin.reflect.KParameter
import kotlin.reflect.full.memberFunctions import kotlin.reflect.full.memberFunctions
import kotlin.reflect.full.primaryConstructor import kotlin.reflect.full.primaryConstructor
import kotlin.script.dependencies.BasicScriptDependenciesResolver import kotlin.script.dependencies.DependenciesResolver
import kotlin.script.dependencies.KotlinScriptExternalDependencies
import kotlin.script.dependencies.ScriptContents
import kotlin.script.dependencies.ScriptDependenciesResolver import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.templates.AcceptedAnnotations import kotlin.script.templates.AcceptedAnnotations
open class KotlinScriptDefinitionFromAnnotatedTemplate( open class KotlinScriptDefinitionFromAnnotatedTemplate(
template: KClass<out Any>, template: KClass<out Any>,
providedResolver: ScriptDependenciesResolver? = null, providedResolver: DependenciesResolver? = null,
providedScriptFilePattern: String? = null, providedScriptFilePattern: String? = null,
val environment: Map<String, Any?>? = null val environment: Map<String, Any?>? = null
) : KotlinScriptDefinition(template) { ) : KotlinScriptDefinition(template) {
@@ -48,38 +44,45 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
?: DEFAULT_SCRIPT_FILE_PATTERN ?: DEFAULT_SCRIPT_FILE_PATTERN
} }
override val dependencyResolver: ScriptDependenciesResolver by lazy { override val dependencyResolver: DependenciesResolver by lazy {
computeResolver(template, providedResolver)
}
private fun computeResolver(
template: KClass<out Any>,
providedResolver: DependenciesResolver?
): @Suppress("DEPRECATION") DependenciesResolver {
val defAnn by lazy { takeUnlessError { template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() } } val defAnn by lazy { takeUnlessError { template.annotations.firstIsInstanceOrNull<kotlin.script.templates.ScriptTemplateDefinition>() } }
val legacyDefAnn by lazy { takeUnlessError { template.annotations.firstIsInstanceOrNull<org.jetbrains.kotlin.script.ScriptTemplateDefinition>() } } val legacyDefAnn by lazy { takeUnlessError { template.annotations.firstIsInstanceOrNull<ScriptTemplateDefinition>() } }
when { return when {
providedResolver != null -> providedResolver providedResolver != null -> providedResolver
// TODO: logScriptDefMessage missing or invalid constructor // TODO: logScriptDefMessage missing or invalid constructor
defAnn != null -> defAnn != null ->
try { try {
defAnn.resolver.primaryConstructor?.call() ?: null.apply { defAnn.resolver.primaryConstructor?.call() as? DependenciesResolver ?: null.apply {
log.warn("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}") log.warn("[kts] No default constructor found for ${defAnn.resolver.qualifiedName}")
} }
} }
catch (ex: ClassCastException) { catch (ex: ClassCastException) {
log.warn("[kts] Script def error ${ex.message}") log.warn("[kts] Script def error ${ex.message}")
null null
} }
legacyDefAnn != null -> legacyDefAnn != null ->
try { try {
log.warn("[kts] Deprecated annotations on the script template are used, please update the provider") log.warn("[kts] Deprecated annotations on the script template are used, please update the provider")
legacyDefAnn.resolver.primaryConstructor?.call()?.let { legacyDefAnn.resolver.primaryConstructor?.call()?.let {
LegacyScriptDependenciesResolverWrapper(it) LegacyScriptDependenciesResolverWrapper(it)
} }
?: null.apply { ?: null.apply {
log.warn("[kts] No default constructor found for ${legacyDefAnn.resolver.qualifiedName}") log.warn("[kts] No default constructor found for ${legacyDefAnn.resolver.qualifiedName}")
} }
} }
catch (ex: ClassCastException) { catch (ex: ClassCastException) {
log.warn("[kts] Script def error ${ex.message}") log.warn("[kts] Script def error ${ex.message}")
null null
} }
else -> null else -> null
} ?: BasicScriptDependenciesResolver() } ?: DependenciesResolver.NoDependencies
} }
val samWithReceiverAnnotations: List<String>? by lazy { val samWithReceiverAnnotations: List<String>? by lazy {
@@ -116,8 +119,6 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
// TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern // TODO: implement other strategy - e.g. try to extract something from match with ScriptFilePattern
override fun getScriptName(script: KtScript): Name = NameUtils.getScriptNameForFile(script.containingKtFile.name) override fun getScriptName(script: KtScript): Name = NameUtils.getScriptNameForFile(script.containingKtFile.name)
override fun getDependenciesFor(file: VirtualFile, project: Project, previousDependencies: KotlinScriptExternalDependencies?) = error("Should not be called")
override fun toString(): String = "KotlinScriptDefinitionFromAnnotatedTemplate - ${template.simpleName}" override fun toString(): String = "KotlinScriptDefinitionFromAnnotatedTemplate - ${template.simpleName}"
override val annotationsForSamWithReceivers: List<String> override val annotationsForSamWithReceivers: List<String>
@@ -141,20 +142,3 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate(
internal val log = Logger.getInstance(KotlinScriptDefinitionFromAnnotatedTemplate::class.java) internal val log = Logger.getInstance(KotlinScriptDefinitionFromAnnotatedTemplate::class.java)
} }
} }
internal fun logScriptDefMessage(reportSeverity: ScriptDependenciesResolver.ReportSeverity, s: String, position: ScriptContents.Position?): Unit {
val msg = (position?.run { "[at $line:$col]" } ?: "") + s
when (reportSeverity) {
ScriptDependenciesResolver.ReportSeverity.ERROR -> KotlinScriptDefinitionFromAnnotatedTemplate.log.error(msg)
ScriptDependenciesResolver.ReportSeverity.WARNING -> KotlinScriptDefinitionFromAnnotatedTemplate.log.warn(msg)
ScriptDependenciesResolver.ReportSeverity.INFO -> KotlinScriptDefinitionFromAnnotatedTemplate.log.info(msg)
ScriptDependenciesResolver.ReportSeverity.DEBUG -> KotlinScriptDefinitionFromAnnotatedTemplate.log.debug(msg)
}
}
internal fun sameSignature(left: KFunction<*>, right: KFunction<*>): Boolean =
left.parameters.size == right.parameters.size &&
left.parameters.zip(right.parameters).all {
it.first.kind == KParameter.Kind.INSTANCE ||
it.first.type == it.second.type
}
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.io.File import java.io.File
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.script.dependencies.KotlinScriptExternalDependencies
import kotlin.script.dependencies.ScriptContents import kotlin.script.dependencies.ScriptContents
import kotlin.script.dependencies.ScriptDependencies
abstract class KotlinScriptExternalImportsProviderBase(private val project: Project): KotlinScriptExternalImportsProvider { abstract class KotlinScriptExternalImportsProviderBase(private val project: Project): KotlinScriptExternalImportsProvider {
fun getScriptContents(scriptDefinition: KotlinScriptDefinition, file: VirtualFile) fun getScriptContents(scriptDefinition: KotlinScriptDefinition, file: VirtualFile)
@@ -58,16 +58,13 @@ abstract class KotlinScriptExternalImportsProviderBase(private val project: Proj
fun resolveDependencies( fun resolveDependencies(
scriptDef: KotlinScriptDefinition, scriptDef: KotlinScriptDefinition,
file: VirtualFile, file: VirtualFile
oldDependencies: KotlinScriptExternalDependencies? = null ): ScriptDependencies? {
): KotlinScriptExternalDependencies? {
val scriptContents = getScriptContents(scriptDef, file) val scriptContents = getScriptContents(scriptDef, file)
return scriptDef.dependencyResolver.resolve( return scriptDef.dependencyResolver.resolve(
scriptContents, scriptContents,
(scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment, (scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment ?: emptyMap()
{ _, _, _ -> Unit }, // TODO_R: ).dependencies
oldDependencies
).get()
} }
} }
@@ -20,6 +20,9 @@ import java.io.File
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.script.dependencies.DependenciesResolver.ResolveResult
import kotlin.script.dependencies.ScriptDependencies
import kotlin.script.dependencies.ScriptReport
const val DEFAULT_SCRIPT_FILE_PATTERN = ".*\\.kts" const val DEFAULT_SCRIPT_FILE_PATTERN = ".*\\.kts"
@@ -115,41 +118,42 @@ private fun<T: Comparable<T>> compareIterables(a: Iterable<T>, b: Iterable<T>):
private inline fun Int.chainCompare(compFn: () -> Int ): Int = if (this != 0) this else compFn() private inline fun Int.chainCompare(compFn: () -> Int ): Int = if (this != 0) this else compFn()
class LegacyScriptDependenciesResolverWrapper(val legacyResolver: ScriptDependenciesResolver) : kotlin.script.dependencies.ScriptDependenciesResolver { @Suppress("DEPRECATION")
class LegacyScriptDependenciesResolverWrapper(val legacyResolver: ScriptDependenciesResolver) : kotlin.script.dependencies.DependenciesResolver {
override fun resolve(script: kotlin.script.dependencies.ScriptContents, override fun resolve(
environment: Map<String, Any?>?, scriptContents: kotlin.script.dependencies.ScriptContents,
report: (kotlin.script.dependencies.ScriptDependenciesResolver.ReportSeverity, String, kotlin.script.dependencies.ScriptContents.Position?) -> Unit, environment: Map<String, Any?>
previousDependencies: kotlin.script.dependencies.KotlinScriptExternalDependencies? ): ResolveResult {
): Future<kotlin.script.dependencies.KotlinScriptExternalDependencies?> { val reports = ArrayList<ScriptReport>()
val legacyDeps = legacyResolver.resolve( val legacyDeps = legacyResolver.resolve(
object : ScriptContents { object : ScriptContents {
override val file: File? get() = script.file override val file: File? get() = scriptContents.file
override val annotations: Iterable<Annotation> get() = script.annotations override val annotations: Iterable<Annotation> get() = scriptContents.annotations
override val text: CharSequence? get() = script.text override val text: CharSequence? get() = scriptContents.text
}, },
environment, environment,
{ sev, msg, pos -> report(kotlin.script.dependencies.ScriptDependenciesResolver.ReportSeverity.values()[sev.ordinal], { sev, msg, pos ->
msg, reports.add(ScriptReport(msg, sev.convertSeverity(), pos?.convertPosition()))
pos?.let { kotlin.script.dependencies.ScriptContents.Position(it.line, it.col) }) }, }, null
previousDependencies?.let { ).get() ?: return ResolveResult.Failure()
object : KotlinScriptExternalDependencies {
override val javaHome get() = it.javaHome val dependencies = ScriptDependencies(
override val classpath get() = it.classpath javaHome = legacyDeps.javaHome?.let(::File),
override val imports get() = it.imports classpath = legacyDeps.classpath.toList(),
override val sources get() = it.sources imports = legacyDeps.imports.toList(),
override val scripts get() = it.scripts sources = legacyDeps.sources.toList(),
} scripts = legacyDeps.scripts.toList()
} )
).get() return ResolveResult.Success(dependencies, reports)
return kotlin.script.dependencies.PseudoFuture(legacyDeps?.let {
object : kotlin.script.dependencies.KotlinScriptExternalDependencies {
override val javaHome get() = it.javaHome
override val classpath get() = it.classpath
override val imports get() = it.imports
override val sources get() = it.sources
override val scripts get() = it.scripts
}
})
} }
private fun ScriptDependenciesResolver.ReportSeverity.convertSeverity(): ScriptReport.Severity = when(this) {
ScriptDependenciesResolver.ReportSeverity.ERROR -> ScriptReport.Severity.ERROR
ScriptDependenciesResolver.ReportSeverity.WARNING -> ScriptReport.Severity.WARNING
ScriptDependenciesResolver.ReportSeverity.INFO -> ScriptReport.Severity.INFO
ScriptDependenciesResolver.ReportSeverity.DEBUG -> ScriptReport.Severity.DEBUG
}
private fun ScriptContents.Position.convertPosition(): ScriptReport.Position = ScriptReport.Position(line, col)
} }
@@ -22,7 +22,7 @@ import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import java.io.File import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
import kotlin.script.dependencies.ScriptDependenciesResolver import kotlin.script.dependencies.DependenciesResolver
interface ScriptTemplatesProvider { interface ScriptTemplatesProvider {
@@ -38,7 +38,7 @@ interface ScriptTemplatesProvider {
val templateClassNames: Iterable<String> val templateClassNames: Iterable<String>
val resolver: ScriptDependenciesResolver? get() = null val resolver: DependenciesResolver? get() = null
val filePattern: String? get() = null val filePattern: String? get() = null
@@ -17,16 +17,13 @@
package org.jetbrains.kotlin.script package org.jetbrains.kotlin.script
import com.intellij.openapi.fileTypes.LanguageFileType import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
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.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtScript import org.jetbrains.kotlin.psi.KtScript
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.DependenciesResolver
import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.templates.standard.ScriptTemplateWithArgs import kotlin.script.templates.standard.ScriptTemplateWithArgs
open class KotlinScriptDefinition(val template: KClass<out Any>) { open class KotlinScriptDefinition(val template: KClass<out Any>) {
@@ -45,14 +42,9 @@ open class KotlinScriptDefinition(val template: KClass<out Any>) {
open fun getScriptName(script: KtScript): Name = open fun getScriptName(script: KtScript): Name =
NameUtils.getScriptNameForFile(script.containingKtFile.name) NameUtils.getScriptNameForFile(script.containingKtFile.name)
@Deprecated("Use dependencyResolver instead", level = DeprecationLevel.ERROR) open val dependencyResolver: DependenciesResolver get() = DependenciesResolver.NoDependencies
open fun getDependenciesFor(file: VirtualFile, project: Project, previousDependencies: KotlinScriptExternalDependencies?): KotlinScriptExternalDependencies? = null
open val dependencyResolver: ScriptDependenciesResolver = EmptyDependencyResolver open val acceptedAnnotations: List<KClass<out Annotation>> get() = emptyList()
open val acceptedAnnotations: List<KClass<out Annotation>> = emptyList()
private object EmptyDependencyResolver : ScriptDependenciesResolver
} }
object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class) object StandardScriptDefinition : KotlinScriptDefinition(ScriptTemplateWithArgs::class)
@@ -20,10 +20,10 @@ import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
interface KotlinScriptExternalImportsProvider { interface KotlinScriptExternalImportsProvider {
fun getScriptDependencies(file: VirtualFile): KotlinScriptExternalDependencies? fun getScriptDependencies(file: VirtualFile): ScriptDependencies?
fun getScriptDependencies(file: PsiFile) = getScriptDependencies(file.virtualFile) fun getScriptDependencies(file: PsiFile) = getScriptDependencies(file.virtualFile)
companion object { companion object {
@@ -32,5 +32,5 @@ interface KotlinScriptExternalImportsProvider {
} }
} }
fun getScriptExternalDependencies(file: VirtualFile, project: Project): KotlinScriptExternalDependencies? = fun getScriptExternalDependencies(file: VirtualFile, project: Project): ScriptDependencies? =
KotlinScriptExternalImportsProvider.getInstance(project).getScriptDependencies(file) KotlinScriptExternalImportsProvider.getInstance(project).getScriptDependencies(file)
@@ -35,13 +35,10 @@ import java.net.URLClassLoader
import java.nio.charset.Charset import java.nio.charset.Charset
import java.rmi.server.UnicastRemoteObject import java.rmi.server.UnicastRemoteObject
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread import kotlin.concurrent.thread
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.*
import kotlin.script.dependencies.ScriptContents import kotlin.script.dependencies.DependenciesResolver.ResolveResult
import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.dependencies.asFuture
import kotlin.script.templates.ScriptTemplateDefinition import kotlin.script.templates.ScriptTemplateDefinition
import kotlin.test.fail import kotlin.test.fail
@@ -817,18 +814,13 @@ internal val File.loggerCompatiblePath: String
if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/') if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/')
else absolutePath else absolutePath
open class TestKotlinScriptDummyDependenciesResolver : ScriptDependenciesResolver { open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
override fun resolve(script: ScriptContents, override fun resolve(scriptContents: ScriptContents, environment: Environment): ResolveResult {
environment: Map<String, Any?>?, return ScriptDependencies(
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, classpath = classpathFromClassloader(),
previousDependencies: KotlinScriptExternalDependencies? imports = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo")
): Future<KotlinScriptExternalDependencies?> ).asSuccess()
{
return object : KotlinScriptExternalDependencies {
override val classpath: Iterable<File> = classpathFromClassloader()
override val imports: Iterable<String> = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo")
}.asFuture()
} }
} }
@@ -44,12 +44,9 @@ import java.lang.Exception
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.net.URL import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.Future
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.*
import kotlin.script.dependencies.ScriptContents import kotlin.script.dependencies.DependenciesResolver.ResolveResult
import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.dependencies.asFuture
import kotlin.script.templates.AcceptedAnnotations import kotlin.script.templates.AcceptedAnnotations
import kotlin.script.templates.ScriptTemplateDefinition import kotlin.script.templates.ScriptTemplateDefinition
import kotlin.script.templates.standard.ScriptTemplateWithArgs import kotlin.script.templates.standard.ScriptTemplateWithArgs
@@ -320,19 +317,17 @@ class ScriptTemplateTest {
} }
} }
open class TestKotlinScriptDummyDependenciesResolver : ScriptDependenciesResolver { open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
@AcceptedAnnotations(DependsOn::class, DependsOnTwo::class) @AcceptedAnnotations(DependsOn::class, DependsOnTwo::class)
override fun resolve(script: ScriptContents, override fun resolve(scriptContents: ScriptContents,
environment: Map<String, Any?>?, environment: Environment
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, ): ResolveResult
previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?>
{ {
return object : KotlinScriptExternalDependencies { return ScriptDependencies(
override val classpath: Iterable<File> = classpathFromClassloader() classpath = classpathFromClassloader(),
override val imports: Iterable<String> = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo") imports = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo")
}.asFuture() ).asSuccess()
} }
protected fun classpathFromClassloader(): List<File> = protected fun classpathFromClassloader(): List<File> =
@@ -347,13 +342,11 @@ class TestKotlinScriptDependenciesResolver : TestKotlinScriptDummyDependenciesRe
private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() } private val kotlinPaths by lazy { PathUtil.getKotlinPathsForCompiler() }
@AcceptedAnnotations(DependsOn::class, DependsOnTwo::class) @AcceptedAnnotations(DependsOn::class, DependsOnTwo::class)
override fun resolve(script: ScriptContents, override fun resolve(scriptContents: ScriptContents,
environment: Map<String, Any?>?, environment: Environment
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, ): ResolveResult
previousDependencies: KotlinScriptExternalDependencies?
): Future<KotlinScriptExternalDependencies?>
{ {
val cp = script.annotations.flatMap { val cp = scriptContents.annotations.flatMap {
when (it) { when (it) {
is DependsOn -> if (it.path == "@{runtime}") listOf(kotlinPaths.runtimePath, kotlinPaths.scriptRuntimePath) else listOf(File(it.path)) is DependsOn -> if (it.path == "@{runtime}") listOf(kotlinPaths.runtimePath, kotlinPaths.scriptRuntimePath) else listOf(File(it.path))
is DependsOnTwo -> listOf(it.path1, it.path2).flatMap { is DependsOnTwo -> listOf(it.path1, it.path2).flatMap {
@@ -367,10 +360,10 @@ class TestKotlinScriptDependenciesResolver : TestKotlinScriptDummyDependenciesRe
else -> throw Exception("Unknown annotation ${it::class.java}") else -> throw Exception("Unknown annotation ${it::class.java}")
} }
} }
return object : KotlinScriptExternalDependencies { return ScriptDependencies(
override val classpath: Iterable<File> = classpathFromClassloader() + cp classpath = classpathFromClassloader() + cp,
override val imports: Iterable<String> = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo") imports = listOf("org.jetbrains.kotlin.scripts.DependsOn", "org.jetbrains.kotlin.scripts.DependsOnTwo")
}.asFuture() ).asSuccess()
} }
} }
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.idea.core.script.KotlinScriptConfigurationManager
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
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 kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSearchScope) : DelegatingGlobalSearchScope(baseScope) { class ScriptModuleSearchScope(val scriptFile: VirtualFile, baseScope: GlobalSearchScope) : DelegatingGlobalSearchScope(baseScope) {
override fun equals(other: Any?) = other is ScriptModuleSearchScope && scriptFile == other.scriptFile && super.equals(other) override fun equals(other: Any?) = other is ScriptModuleSearchScope && scriptFile == other.scriptFile && super.equals(other)
@@ -42,7 +42,7 @@ data class ScriptModuleInfo(val project: Project, val scriptFile: VirtualFile,
override val moduleOrigin: ModuleOrigin override val moduleOrigin: ModuleOrigin
get() = ModuleOrigin.OTHER get() = ModuleOrigin.OTHER
val externalDependencies: KotlinScriptExternalDependencies? val externalDependencies: ScriptDependencies?
get() = KotlinScriptConfigurationManager.getInstance(project).getScriptDependencies(scriptFile) get() = KotlinScriptConfigurationManager.getInstance(project).getScriptDependencies(scriptFile)
override val name: Name = Name.special("<script ${scriptFile.name} ${scriptDefinition.name}>") override val name: Name = Name.special("<script ${scriptFile.name} ${scriptDefinition.name}>")
@@ -56,13 +56,13 @@ data class ScriptModuleInfo(val project: Project, val scriptFile: VirtualFile,
} }
} }
private fun sdkDependencies(scriptDependencies: KotlinScriptExternalDependencies?, project: Project): List<SdkInfo> private fun sdkDependencies(scriptDependencies: ScriptDependencies?, project: Project): List<SdkInfo>
= listOfNotNull(findJdk(scriptDependencies, project)?.let { SdkInfo(project, it) }) = listOfNotNull(findJdk(scriptDependencies, project)?.let { SdkInfo(project, it) })
fun findJdk(dependencies: KotlinScriptExternalDependencies?, project: Project): Sdk? { fun findJdk(dependencies: ScriptDependencies?, project: Project): Sdk? {
val allJdks = getAllProjectSdks() val allJdks = getAllProjectSdks()
// workaround for mismatched gradle wrapper and plugin version // workaround for mismatched gradle wrapper and plugin version
val javaHome = try { dependencies?.javaHome } catch (e: Throwable) { null } val javaHome = try { dependencies?.javaHome?.canonicalPath } catch (e: Throwable) { null }
return allJdks.find { javaHome != null && it.homePath == javaHome } ?: return allJdks.find { javaHome != null && it.homePath == javaHome } ?:
ProjectRootManager.getInstance(project).projectSdk ?: ProjectRootManager.getInstance(project).projectSdk ?:
@@ -113,8 +113,8 @@ data class ScriptDependenciesSourceModuleInfo(
} }
private class ScriptBinariesScopeCache(private val project: Project) : SLRUCache<KotlinScriptExternalDependencies, GlobalSearchScope>(6, 6) { private class ScriptBinariesScopeCache(private val project: Project) : SLRUCache<ScriptDependencies, GlobalSearchScope>(6, 6) {
override fun createValue(key: KotlinScriptExternalDependencies?): GlobalSearchScope { override fun createValue(key: ScriptDependencies?): GlobalSearchScope {
val roots = key?.classpath ?: emptyList() val roots = key?.classpath ?: emptyList()
val classpath = KotlinScriptConfigurationManager.toVfsRoots(roots) val classpath = KotlinScriptConfigurationManager.toVfsRoots(roots)
// TODO: this is not very efficient because KotlinSourceFilterScope already checks if the files are in scripts classpath // TODO: this is not very efficient because KotlinSourceFilterScope already checks if the files are in scripts classpath
@@ -34,19 +34,19 @@ import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.NonClasspathDirectoriesScope import com.intellij.psi.search.NonClasspathDirectoriesScope
import com.intellij.util.io.URLUtil import com.intellij.util.io.URLUtil
import kotlinx.coroutines.experimental.asCoroutineDispatcher
import kotlinx.coroutines.experimental.future.future
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.script.* import org.jetbrains.kotlin.script.*
import java.io.File import java.io.File
import java.lang.Math.max
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture.supplyAsync
import java.util.concurrent.Executors.newFixedThreadPool import java.util.concurrent.Executors.newFixedThreadPool
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
import java.util.function.Supplier
import kotlin.concurrent.read import kotlin.concurrent.read
import kotlin.concurrent.write import kotlin.concurrent.write
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
import kotlin.script.dependencies.experimental.AsyncDependenciesResolver
// NOTE: this service exists exclusively because KotlinScriptConfigurationManager // NOTE: this service exists exclusively because KotlinScriptConfigurationManager
@@ -54,7 +54,7 @@ import kotlin.script.dependencies.KotlinScriptExternalDependencies
class IdeScriptExternalImportsProvider( class IdeScriptExternalImportsProvider(
private val scriptConfigurationManager: KotlinScriptConfigurationManager private val scriptConfigurationManager: KotlinScriptConfigurationManager
) : KotlinScriptExternalImportsProvider { ) : KotlinScriptExternalImportsProvider {
override fun getScriptDependencies(file: VirtualFile): KotlinScriptExternalDependencies? { override fun getScriptDependencies(file: VirtualFile): ScriptDependencies? {
return scriptConfigurationManager.getScriptDependencies(file) return scriptConfigurationManager.getScriptDependencies(file)
} }
} }
@@ -64,7 +64,7 @@ class KotlinScriptConfigurationManager(
private val scriptDefinitionProvider: KotlinScriptDefinitionProvider private val scriptDefinitionProvider: KotlinScriptDefinitionProvider
) : KotlinScriptExternalImportsProviderBase(project) { ) : KotlinScriptExternalImportsProviderBase(project) {
private val cacheLock = ReentrantReadWriteLock() private val cacheLock = ReentrantReadWriteLock()
private val threadPool = newFixedThreadPool(max(1, Runtime.getRuntime().availableProcessors() / 2)) private val scriptDependencyUpdatesDispatcher = newFixedThreadPool(1).asCoroutineDispatcher()
init { init {
reloadScriptDefinitions() reloadScriptDefinitions()
@@ -144,17 +144,17 @@ class KotlinScriptConfigurationManager(
scriptDefinitionProvider.setScriptDefinitions(def) scriptDefinitionProvider.setScriptDefinitions(def)
} }
private class TimeStampedRequest(val future: CompletableFuture<Unit>, val timeStamp: TimeStamp) private class TimeStampedRequest(val future: CompletableFuture<*>, val timeStamp: TimeStamp)
private class DataAndRequest( private class DataAndRequest(
val dependencies: KotlinScriptExternalDependencies?, val dependencies: ScriptDependencies?,
val modificationStamp: Long?, val modificationStamp: Long?,
val requestInProgress: TimeStampedRequest? = null val requestInProgress: TimeStampedRequest? = null
) )
private val cache = hashMapOf<String, DataAndRequest?>() private val cache = hashMapOf<String, DataAndRequest?>()
override fun getScriptDependencies(file: VirtualFile): KotlinScriptExternalDependencies = cacheLock.read { override fun getScriptDependencies(file: VirtualFile): ScriptDependencies = cacheLock.read {
val path = file.path val path = file.path
val cached = cache[path] val cached = cache[path]
cached?.dependencies?.let { return it } cached?.dependencies?.let { return it }
@@ -163,7 +163,7 @@ class KotlinScriptConfigurationManager(
updateExternalImportsCache(listOf(file)) updateExternalImportsCache(listOf(file))
return cache[path]?.dependencies ?: NoDependencies return cache[path]?.dependencies ?: ScriptDependencies.Empty
} }
private fun tryLoadingFromDisk(cached: DataAndRequest?, file: VirtualFile, path: String) { private fun tryLoadingFromDisk(cached: DataAndRequest?, file: VirtualFile, path: String) {
@@ -189,14 +189,18 @@ class KotlinScriptConfigurationManager(
return cache.remove(file.path) != null return cache.remove(file.path) != null
} }
// TODO: support apis that allow for async updates for any template val dependencyResolver = scriptDef.dependencyResolver
if (scriptDef is KotlinScriptDefinitionFromAnnotatedTemplate) { if (dependencyResolver is AsyncDependenciesResolver) {
return updateAsync(file, scriptDef) return updateAsync(file, scriptDef, dependencyResolver)
} }
return updateSync(file, scriptDef) return updateSync(file, scriptDef)
} }
private fun updateAsync(file: VirtualFile, scriptDefinition: KotlinScriptDefinitionFromAnnotatedTemplate): Boolean { private fun updateAsync(
file: VirtualFile,
scriptDefinition: KotlinScriptDefinition,
dependencyResolver: AsyncDependenciesResolver
): Boolean {
val path = file.path val path = file.path
val oldDataAndRequest = cache[path] val oldDataAndRequest = cache[path]
@@ -206,7 +210,7 @@ class KotlinScriptConfigurationManager(
oldDataAndRequest?.requestInProgress?.future?.cancel(true) oldDataAndRequest?.requestInProgress?.future?.cancel(true)
val (currentTimeStamp, newFuture) = sendRequest(path, scriptDefinition, file, oldDataAndRequest) val (currentTimeStamp, newFuture) = sendRequest(path, scriptDefinition, dependencyResolver, file, oldDataAndRequest)
cache[path] = DataAndRequest( cache[path] = DataAndRequest(
oldDataAndRequest?.dependencies, oldDataAndRequest?.dependencies,
@@ -218,24 +222,29 @@ class KotlinScriptConfigurationManager(
private fun sendRequest( private fun sendRequest(
path: String, path: String,
scriptDefinition: KotlinScriptDefinitionFromAnnotatedTemplate, scriptDef: KotlinScriptDefinition,
dependenciesResolver: AsyncDependenciesResolver,
file: VirtualFile, file: VirtualFile,
oldDataAndRequest: DataAndRequest? oldDataAndRequest: DataAndRequest?
): Pair<TimeStamp, CompletableFuture<Unit>> { ): Pair<TimeStamp, CompletableFuture<*>> {
val currentTimeStamp = TimeStamps.next() val currentTimeStamp = TimeStamps.next()
val newFuture = supplyAsync(Supplier { val newFuture = future(scriptDependencyUpdatesDispatcher) {
val newDependencies = resolveDependencies(scriptDefinition, file, oldDataAndRequest?.dependencies) ?: EmptyDependencies dependenciesResolver.resolveAsync(
getScriptContents(scriptDef, file),
(scriptDef as? KotlinScriptDefinitionFromAnnotatedTemplate)?.environment.orEmpty()
)
}.thenAccept { result ->
cacheLock.read { cacheLock.read {
val lastTimeStamp = cache[path]?.requestInProgress?.timeStamp val lastTimeStamp = cache[path]?.requestInProgress?.timeStamp
if (lastTimeStamp == currentTimeStamp) { if (lastTimeStamp == currentTimeStamp) {
if (cacheSync(newDependencies, oldDataAndRequest?.dependencies, path, file)) { if (cacheSync(result.dependencies ?: ScriptDependencies.Empty, oldDataAndRequest?.dependencies, path, file)) {
invalidateLocalCaches() invalidateLocalCaches()
notifyRootsChanged() notifyRootsChanged()
} }
} }
} }
}, threadPool) }
return Pair(currentTimeStamp, newFuture) return Pair(currentTimeStamp, newFuture)
} }
@@ -253,13 +262,13 @@ class KotlinScriptConfigurationManager(
private fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean { private fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean {
val path = file.path val path = file.path
val oldDeps = cache[path]?.dependencies val oldDeps = cache[path]?.dependencies
val newDeps = resolveDependencies(scriptDef, file, oldDeps) ?: EmptyDependencies val newDeps = resolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty
return cacheSync(newDeps, oldDeps, path, file) return cacheSync(newDeps, oldDeps, path, file)
} }
private fun cacheSync( private fun cacheSync(
new: KotlinScriptExternalDependencies, new: ScriptDependencies,
old: KotlinScriptExternalDependencies?, old: ScriptDependencies?,
path: String, path: String,
file: VirtualFile file: VirtualFile
): Boolean { ): Boolean {
@@ -277,7 +286,7 @@ class KotlinScriptConfigurationManager(
} }
} }
private fun save(path: String, new: KotlinScriptExternalDependencies?, virtualFile: VirtualFile, persist: Boolean) { private fun save(path: String, new: ScriptDependencies?, virtualFile: VirtualFile, persist: Boolean) {
cacheLock.write { cacheLock.write {
cache.put(path, DataAndRequest(new, virtualFile.modificationStamp)) cache.put(path, DataAndRequest(new, virtualFile.modificationStamp))
} }
@@ -342,8 +351,6 @@ class KotlinScriptConfigurationManager(
} }
} }
} }
private object NoDependencies: KotlinScriptExternalDependencies
} }
private class ClearableLazyValue<out T : Any>(private val lock: ReentrantReadWriteLock, private val compute: () -> T) { private class ClearableLazyValue<out T : Any>(private val lock: ReentrantReadWriteLock, private val compute: () -> T) {
@@ -368,7 +375,7 @@ private class ClearableLazyValue<out T : Any>(private val lock: ReentrantReadWri
} }
// TODO: relying on this to compare dependencies seems wrong, doesn't take javaHome and other stuff into account // TODO: relying on this to compare dependencies seems wrong, doesn't take javaHome and other stuff into account
private fun KotlinScriptExternalDependencies.match(other: KotlinScriptExternalDependencies) private fun ScriptDependencies.match(other: ScriptDependencies)
= classpath.isSamePathListAs(other.classpath) && = classpath.isSamePathListAs(other.classpath) &&
sources.toSet().isSamePathListAs(other.sources.toSet()) // TODO: gradle returns stdlib and reflect sources in unstable order for some reason sources.toSet().isSamePathListAs(other.sources.toSet()) // TODO: gradle returns stdlib and reflect sources in unstable order for some reason
@@ -390,5 +397,3 @@ object TimeStamps {
fun next() = TimeStamp(current++) fun next() = TimeStamp(current++)
} }
private object EmptyDependencies: KotlinScriptExternalDependencies
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.idea.caches.FileAttributeService
import java.io.DataInput import java.io.DataInput
import java.io.DataOutput import java.io.DataOutput
import java.io.File import java.io.File
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.ScriptDependencies
// TODO_R: write nullable, write version // TODO_R: write nullable, write version
object ScriptDependenciesFileAttribute { object ScriptDependenciesFileAttribute {
@@ -40,29 +40,27 @@ object ScriptDependenciesFileAttribute {
fileAttributeService.register(ID, VERSION, false) fileAttributeService.register(ID, VERSION, false)
} }
fun write(virtualFile: VirtualFile, dependencies: KotlinScriptExternalDependencies) { fun write(virtualFile: VirtualFile, dependencies: ScriptDependencies) {
if (virtualFile !is VirtualFileWithId) return if (virtualFile !is VirtualFileWithId) return
fileAttributeService.write(virtualFile, ID, dependencies) { output, dep -> fileAttributeService.write(virtualFile, ID, dependencies) { output, dep ->
with(dep) { with(dep) {
output.writeFileList(classpath) output.writeFileList(classpath)
output.writeStringList(imports) output.writeStringList(imports)
// TODO: actually read/write nullable // TODO: actually read/write nullable
output.writeString(javaHome ?: "") output.writeFile(javaHome ?: File(""))
output.writeFileList(scripts) output.writeFileList(scripts)
output.writeFileList(sources) output.writeFileList(sources)
} }
} }
} }
fun read(virtualFile: VirtualFile): KotlinScriptExternalDependencies? { fun read(virtualFile: VirtualFile): ScriptDependencies? {
if (virtualFile !is VirtualFileWithId) return null if (virtualFile !is VirtualFileWithId) return null
return fileAttributeService.read(virtualFile, ID) { input -> return fileAttributeService.read(virtualFile, ID) { input ->
SerializedScriptDependencies( ScriptDependencies(
classpath = input.readFileList(), classpath = input.readFileList(),
imports = input.readStringList(), imports = input.readStringList(),
javaHome = input.readString(), javaHome = input.readFile(),
scripts = input.readFileList(), scripts = input.readFileList(),
sources = input.readFileList() sources = input.readFileList()
) )
@@ -71,19 +69,11 @@ object ScriptDependenciesFileAttribute {
} }
private fun DataInput.readStringList(): List<String> = readSeq(this) { readString() } private fun DataInput.readStringList(): List<String> = readSeq(this) { readString() }
private fun DataInput.readFileList() = readStringList().map { File(it) } private fun DataInput.readFileList() = readSeq(this) { readFile() }
private fun DataInput.readString() = readUTF(this) private fun DataInput.readString() = readUTF(this)
private fun DataInput.readFile() = readUTF(this).let { File(it) }
private fun DataOutput.writeFileList(iterable: Iterable<File>) = writeSeq(this, iterable.toList()) { writeFile(it) } private fun DataOutput.writeFileList(iterable: Iterable<File>) = writeSeq(this, iterable.toList()) { writeFile(it) }
private fun DataOutput.writeFile(it: File) = writeString(it.canonicalPath) private fun DataOutput.writeFile(it: File) = writeString(it.canonicalPath)
private fun DataOutput.writeString(string: String) = writeUTF(this, string) private fun DataOutput.writeString(string: String) = writeUTF(this, string)
private fun DataOutput.writeStringList(iterable: Iterable<String>) = writeSeq(this, iterable.toList()) { writeString(it) } private fun DataOutput.writeStringList(iterable: Iterable<String>) = writeSeq(this, iterable.toList()) { writeString(it) }
private class SerializedScriptDependencies(
override val classpath: Iterable<File>,
override val imports: Iterable<String>,
override val javaHome: String?,
override val scripts: Iterable<File>,
override val sources: Iterable<File>
) : KotlinScriptExternalDependencies
@@ -24,11 +24,8 @@ import org.jetbrains.kotlin.idea.core.script.dependencies.KotlinScriptResolveSco
import org.jetbrains.kotlin.script.ScriptTemplatesProvider import org.jetbrains.kotlin.script.ScriptTemplatesProvider
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import java.io.File import java.io.File
import java.util.concurrent.Future import kotlin.script.dependencies.*
import kotlin.script.dependencies.KotlinScriptExternalDependencies import kotlin.script.dependencies.DependenciesResolver.ResolveResult
import kotlin.script.dependencies.PseudoFuture
import kotlin.script.dependencies.ScriptContents
import kotlin.script.dependencies.ScriptDependenciesResolver
import kotlin.script.templates.standard.ScriptTemplateWithArgs import kotlin.script.templates.standard.ScriptTemplateWithArgs
class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplatesProvider { class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplatesProvider {
@@ -45,7 +42,7 @@ class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplat
) )
} }
override val resolver: ScriptDependenciesResolver = BundledKotlinScriptDependenciesResolver() override val resolver: DependenciesResolver = BundledKotlinScriptDependenciesResolver()
private fun getScriptSDK(project: Project): String? { private fun getScriptSDK(project: Project): String? {
val jdk = PathUtilEx.getAnyJdk(project) ?: val jdk = PathUtilEx.getAnyJdk(project) ?:
@@ -55,26 +52,22 @@ class StandardKotlinScriptTemplateProvider(val project: Project) : ScriptTemplat
} }
} }
class BundledKotlinScriptDependenciesResolver : ScriptDependenciesResolver { class BundledKotlinScriptDependenciesResolver : DependenciesResolver {
override fun resolve( override fun resolve(
script: ScriptContents, scriptContents: ScriptContents,
environment: Map<String, Any?>?, environment: Environment
report: (ScriptDependenciesResolver.ReportSeverity, String, ScriptContents.Position?) -> Unit, ): ResolveResult {
previousDependencies: KotlinScriptExternalDependencies?): Future<KotlinScriptExternalDependencies?> { val javaHome = environment.get("sdk") as String?
val javaHome = environment?.get("sdk") as String? val dependencies = ScriptDependencies(
val dependencies = KotlinBundledScriptDependencies(javaHome) javaHome = javaHome?.let(::File),
return PseudoFuture(dependencies) classpath = with(PathUtil.getKotlinPathsForIdeaPlugin()) {
} listOf(
} reflectPath,
stdlibPath,
class KotlinBundledScriptDependencies(override val javaHome: String?) : KotlinScriptExternalDependencies { scriptRuntimePath
override val classpath: Iterable<File> get() { )
return with(PathUtil.getKotlinPathsForIdeaPlugin()) { }
listOf( )
reflectPath, return dependencies.asSuccess()
stdlibPath,
scriptRuntimePath
)
}
} }
} }