Scripting unified cache: update sdks synchronously on changes
This commit is contained in:
+1
-1
@@ -137,7 +137,7 @@ interface ScriptConfigurationManager {
|
|||||||
@TestOnly
|
@TestOnly
|
||||||
fun clearCaches(project: Project) {
|
fun clearCaches(project: Project) {
|
||||||
(getInstance(project) as CompositeScriptConfigurationManager).default
|
(getInstance(project) as CompositeScriptConfigurationManager).default
|
||||||
.updateScriptDefinitions()
|
.updateScriptDefinitionsReferences()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearManualConfigurationLoadingIfNeeded(file: VirtualFile) {
|
fun clearManualConfigurationLoadingIfNeeded(file: VirtualFile) {
|
||||||
|
|||||||
+20
-26
@@ -7,9 +7,10 @@ package org.jetbrains.kotlin.idea.core.script.configuration
|
|||||||
|
|
||||||
import com.intellij.ProjectTopics
|
import com.intellij.ProjectTopics
|
||||||
import com.intellij.codeInsight.daemon.OutsidersPsiFileSupport
|
import com.intellij.codeInsight.daemon.OutsidersPsiFileSupport
|
||||||
import com.intellij.openapi.diagnostic.logger
|
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||||
|
import com.intellij.openapi.projectRoots.ProjectJdkTable.JDK_TABLE_TOPIC
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.roots.ModuleRootEvent
|
import com.intellij.openapi.roots.ModuleRootEvent
|
||||||
import com.intellij.openapi.roots.ModuleRootListener
|
import com.intellij.openapi.roots.ModuleRootListener
|
||||||
@@ -18,9 +19,9 @@ import com.intellij.psi.search.GlobalSearchScope
|
|||||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
|
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangesNotifier
|
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangesNotifier
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsUpdater
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsCache
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsUpdater
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
@@ -44,12 +45,18 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private val notifier = ScriptChangesNotifier(project)
|
private val notifier = ScriptChangesNotifier(project)
|
||||||
|
|
||||||
val updater = ScriptClassRootsUpdater(project, this)
|
private val classpathRoots: ScriptClassRootsCache
|
||||||
|
get() = updater.classpathRoots
|
||||||
|
|
||||||
private val plugins = ScriptingSupport.EPN.getPoint(project).extensionList
|
private val plugins = ScriptingSupport.EPN.getPoint(project).extensionList
|
||||||
|
|
||||||
val default = DefaultScriptingSupport(this)
|
val default = DefaultScriptingSupport(this)
|
||||||
|
|
||||||
|
val updater = ScriptClassRootsUpdater(project, this) { builder ->
|
||||||
|
default.collectConfigurations(builder)
|
||||||
|
plugins.forEach { it.collectConfigurations(builder) }
|
||||||
|
}
|
||||||
|
|
||||||
fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? {
|
fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? {
|
||||||
return classpathRoots.getLightScriptInfo(locationId)?.definition
|
return classpathRoots.getLightScriptInfo(locationId)?.definition
|
||||||
}
|
}
|
||||||
@@ -80,30 +87,13 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
|
|||||||
plugins.firstOrNull { it.isApplicable(file.originalFile.virtualFile) }?.isConfigurationLoadingInProgress(file)
|
plugins.firstOrNull { it.isApplicable(file.originalFile.virtualFile) }?.isConfigurationLoadingInProgress(file)
|
||||||
?: default.isConfigurationLoadingInProgress(file)
|
?: default.isConfigurationLoadingInProgress(file)
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var classpathRoots: ScriptClassRootsCache = recreateRootsCache()
|
|
||||||
|
|
||||||
fun getLightScriptInfo(file: String): ScriptClassRootsCache.LightScriptInfo? =
|
fun getLightScriptInfo(file: String): ScriptClassRootsCache.LightScriptInfo? =
|
||||||
classpathRoots.getLightScriptInfo(file)
|
classpathRoots.getLightScriptInfo(file)
|
||||||
|
|
||||||
private fun recreateRootsCache(): ScriptClassRootsCache {
|
|
||||||
val builder = ScriptClassRootsCache.Builder(project)
|
|
||||||
default.collectConfigurations(builder)
|
|
||||||
plugins.forEach { it.collectConfigurations(builder) }
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun collectRootsAndCheckNew(): ScriptClassRootsCache.Updates {
|
|
||||||
val old = classpathRoots
|
|
||||||
val new = recreateRootsCache()
|
|
||||||
classpathRoots = new
|
|
||||||
return new.diff(old)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateScriptDefinitionReferences() {
|
override fun updateScriptDefinitionReferences() {
|
||||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||||
|
|
||||||
default.updateScriptDefinitions()
|
default.updateScriptDefinitionsReferences()
|
||||||
|
|
||||||
if (classpathRoots.customDefinitionsUsed) {
|
if (classpathRoots.customDefinitionsUsed) {
|
||||||
updater.ensureUpdateScheduled()
|
updater.ensureUpdateScheduled()
|
||||||
@@ -112,15 +102,19 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val connection = project.messageBus.connect(project)
|
val connection = project.messageBus.connect(project)
|
||||||
|
|
||||||
connection.subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
|
connection.subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
|
||||||
override fun rootsChanged(event: ModuleRootEvent) {
|
override fun rootsChanged(event: ModuleRootEvent) {
|
||||||
if (event.isCausedByFileTypesChange) return
|
if (event.isCausedByFileTypesChange) return
|
||||||
|
updater.checkInvalidSdks()
|
||||||
if (classpathRoots.hasInvalidSdk(project)) {
|
|
||||||
updater.ensureUpdateScheduled()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
connection.subscribe(JDK_TABLE_TOPIC, object : ProjectJdkTable.Listener {
|
||||||
|
override fun jdkAdded(jdk: Sdk) = updater.checkInvalidSdks()
|
||||||
|
override fun jdkNameChanged(jdk: Sdk, previousName: String) = updater.checkInvalidSdks()
|
||||||
|
override fun jdkRemoved(jdk: Sdk) = updater.checkInvalidSdks(remove = jdk)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+9
-9
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.idea.core.script.configuration.loader.DefaultScriptC
|
|||||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoader
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext
|
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptOutsiderFileConfigurationLoader
|
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptOutsiderFileConfigurationLoader
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsBuilder
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.*
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.*
|
||||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
@@ -91,8 +93,8 @@ import kotlin.script.experimental.api.ScriptDiagnostic
|
|||||||
class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : DefaultScriptingSupportBase(manager) {
|
class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : DefaultScriptingSupportBase(manager) {
|
||||||
// TODO public for tests
|
// TODO public for tests
|
||||||
val backgroundExecutor: BackgroundExecutor =
|
val backgroundExecutor: BackgroundExecutor =
|
||||||
if (ApplicationManager.getApplication().isUnitTestMode) TestingBackgroundExecutor(manager.updater)
|
if (ApplicationManager.getApplication().isUnitTestMode) TestingBackgroundExecutor(manager)
|
||||||
else DefaultBackgroundExecutor(project, manager.updater)
|
else DefaultBackgroundExecutor(project, manager)
|
||||||
|
|
||||||
private val outsiderLoader = ScriptOutsiderFileConfigurationLoader(project)
|
private val outsiderLoader = ScriptOutsiderFileConfigurationLoader(project)
|
||||||
private val fileAttributeCache = ScriptConfigurationFileAttributeCache(project)
|
private val fileAttributeCache = ScriptConfigurationFileAttributeCache(project)
|
||||||
@@ -121,7 +123,7 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
|
|||||||
*
|
*
|
||||||
* Each files may be in on of the states described below:
|
* Each files may be in on of the states described below:
|
||||||
* - scriptDefinition is not ready. `ScriptDefinitionsManager.getInstance(project).isReady() == false`.
|
* - scriptDefinition is not ready. `ScriptDefinitionsManager.getInstance(project).isReady() == false`.
|
||||||
* [updateScriptDefinitions] will be called when [ScriptDefinitionsManager] will be ready
|
* [updateScriptDefinitionsReferences] will be called when [ScriptDefinitionsManager] will be ready
|
||||||
* which will call [reloadOutOfDateConfiguration] for opened editors.
|
* which will call [reloadOutOfDateConfiguration] for opened editors.
|
||||||
* - unknown. When [isFirstLoad] true (`cache[file] == null`).
|
* - unknown. When [isFirstLoad] true (`cache[file] == null`).
|
||||||
* - up-to-date. `cache[file]?.upToDate == true`.
|
* - up-to-date. `cache[file]?.upToDate == true`.
|
||||||
@@ -509,22 +511,20 @@ abstract class DefaultScriptingSupportBase(val manager: CompositeScriptConfigura
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateScriptDefinitions() {
|
fun updateScriptDefinitionsReferences() {
|
||||||
cache.clear()
|
cache.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun collectConfigurations(builder: ScriptClassRootsCache.Builder) {
|
fun collectConfigurations(builder: ScriptClassRootsBuilder) {
|
||||||
// todo: drop the hell below
|
// todo: drop the hell below
|
||||||
// keep this one only:
|
// keep this one only:
|
||||||
// cache.allApplied().forEach { (vFile, configuration) -> builder.add(vFile, configuration) }
|
// cache.allApplied().forEach { (vFile, configuration) -> builder.add(vFile, configuration) }
|
||||||
|
|
||||||
// own builder for saving to storage
|
// own builder for saving to storage
|
||||||
val ownBuilder = ScriptClassRootsCache.Builder(project)
|
|
||||||
val rootsStorage = ScriptClassRootsStorage.getInstance(project)
|
val rootsStorage = ScriptClassRootsStorage.getInstance(project)
|
||||||
|
val ownBuilder = ScriptClassRootsBuilder.fromStorage(rootsStorage)
|
||||||
rootsStorage.load(ownBuilder)
|
|
||||||
cache.allApplied().forEach { (vFile, configuration) -> ownBuilder.add(vFile, configuration) }
|
cache.allApplied().forEach { (vFile, configuration) -> ownBuilder.add(vFile, configuration) }
|
||||||
rootsStorage.save(ownBuilder)
|
ownBuilder.toStorage(rootsStorage)
|
||||||
|
|
||||||
builder.add(ownBuilder)
|
builder.add(ownBuilder)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -7,8 +7,9 @@ package org.jetbrains.kotlin.idea.core.script.configuration
|
|||||||
|
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
import com.intellij.openapi.extensions.ExtensionPointName
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsCache
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener
|
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptChangeListener
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsBuilder
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,7 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
abstract class ScriptingSupport {
|
abstract class ScriptingSupport {
|
||||||
abstract fun isApplicable(file: VirtualFile): Boolean
|
abstract fun isApplicable(file: VirtualFile): Boolean
|
||||||
abstract fun isConfigurationLoadingInProgress(file: KtFile): Boolean
|
abstract fun isConfigurationLoadingInProgress(file: KtFile): Boolean
|
||||||
abstract fun collectConfigurations(builder: ScriptClassRootsCache.Builder)
|
abstract fun collectConfigurations(builder: ScriptClassRootsBuilder)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EPN: ExtensionPointName<ScriptingSupport> =
|
val EPN: ExtensionPointName<ScriptingSupport> =
|
||||||
|
|||||||
+3
-1
@@ -12,6 +12,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.util.Alarm
|
import com.intellij.util.Alarm
|
||||||
import com.intellij.util.containers.HashSetQueue
|
import com.intellij.util.containers.HashSetQueue
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.debug
|
import org.jetbrains.kotlin.idea.core.script.debug
|
||||||
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
|
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -33,13 +34,14 @@ import javax.swing.SwingUtilities
|
|||||||
*/
|
*/
|
||||||
internal class DefaultBackgroundExecutor(
|
internal class DefaultBackgroundExecutor(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val rootsManager: ScriptClassRootsUpdater
|
val manager: CompositeScriptConfigurationManager
|
||||||
) : BackgroundExecutor {
|
) : BackgroundExecutor {
|
||||||
companion object {
|
companion object {
|
||||||
const val PROGRESS_INDICATOR_DELAY = 1000
|
const val PROGRESS_INDICATOR_DELAY = 1000
|
||||||
const val PROGRESS_INDICATOR_MIN_QUEUE = 3
|
const val PROGRESS_INDICATOR_MIN_QUEUE = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val rootsManager get() = manager.updater
|
||||||
private val work = Any()
|
private val work = Any()
|
||||||
private val queue: Queue<LoadTask> = HashSetQueue()
|
private val queue: Queue<LoadTask> = HashSetQueue()
|
||||||
|
|
||||||
|
|||||||
-257
@@ -1,257 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.core.script.configuration.utils
|
|
||||||
|
|
||||||
import com.intellij.openapi.module.ModuleManager
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.projectRoots.JavaSdkType
|
|
||||||
import com.intellij.openapi.projectRoots.Sdk
|
|
||||||
import com.intellij.openapi.roots.ModuleRootManager
|
|
||||||
import com.intellij.openapi.roots.OrderRootType
|
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
|
||||||
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
|
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
import com.intellij.psi.search.NonClasspathDirectoriesScope.compose
|
|
||||||
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.LOG
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.classpathEntryToVfs
|
|
||||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
|
|
||||||
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
|
||||||
import java.io.File
|
|
||||||
import java.lang.ref.Reference
|
|
||||||
import java.lang.ref.SoftReference
|
|
||||||
|
|
||||||
class ScriptClassRootsCache(
|
|
||||||
val scripts: Map<String, LightScriptInfo>,
|
|
||||||
val classes: Set<String>,
|
|
||||||
val sources: Set<String>,
|
|
||||||
val sdks: Map<String?, Sdk?>,
|
|
||||||
private val nonModulesSdks: Collection<Sdk>,
|
|
||||||
val customDefinitionsUsed: Boolean
|
|
||||||
) {
|
|
||||||
abstract class LightScriptInfo(val definition: ScriptDefinition?) {
|
|
||||||
@Volatile
|
|
||||||
var heavyCache: Reference<HeavyScriptInfo>? = null
|
|
||||||
|
|
||||||
abstract fun buildConfiguration(): ScriptCompilationConfigurationWrapper?
|
|
||||||
}
|
|
||||||
|
|
||||||
class DirectScriptInfo(val result: ScriptCompilationConfigurationWrapper) : LightScriptInfo(null) {
|
|
||||||
override fun buildConfiguration(): ScriptCompilationConfigurationWrapper = result
|
|
||||||
}
|
|
||||||
|
|
||||||
class HeavyScriptInfo(
|
|
||||||
val scriptConfiguration: ScriptCompilationConfigurationWrapper,
|
|
||||||
val classFilesScope: GlobalSearchScope,
|
|
||||||
val sdk: Sdk?
|
|
||||||
)
|
|
||||||
|
|
||||||
class Builder(val project: Project) {
|
|
||||||
val scripts = mutableMapOf<String, LightScriptInfo>()
|
|
||||||
|
|
||||||
private val defaultSdk = getScriptDefaultSdk()
|
|
||||||
val sdks = mutableMapOf<String?, Sdk?>(null to defaultSdk)
|
|
||||||
|
|
||||||
val classes = mutableSetOf<String>()
|
|
||||||
val sources = mutableSetOf<String>()
|
|
||||||
private var customDefinitionsUsed: Boolean = false
|
|
||||||
|
|
||||||
fun build(): ScriptClassRootsCache {
|
|
||||||
val nonIndexedSdks = collectNonIndexedSdks()
|
|
||||||
return ScriptClassRootsCache(scripts, classes, sources, sdks, nonIndexedSdks, customDefinitionsUsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun collectNonIndexedSdks(): MutableSet<Sdk> {
|
|
||||||
val nonIndexedSdks = sdks.values.filterNotNullTo(mutableSetOf())
|
|
||||||
ModuleManager.getInstance(project).modules.map {
|
|
||||||
nonIndexedSdks.remove(ModuleRootManager.getInstance(it).sdk)
|
|
||||||
}
|
|
||||||
return nonIndexedSdks
|
|
||||||
}
|
|
||||||
|
|
||||||
fun useCustomScriptDefinition() {
|
|
||||||
customDefinitionsUsed = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(
|
|
||||||
vFile: VirtualFile,
|
|
||||||
configuration: ScriptCompilationConfigurationWrapper
|
|
||||||
) {
|
|
||||||
addSdk(configuration.javaHome)
|
|
||||||
|
|
||||||
configuration.dependenciesClassPath.forEach { classes.add(it.absolutePath) }
|
|
||||||
configuration.dependenciesSources.forEach { sources.add(it.absolutePath) }
|
|
||||||
|
|
||||||
scripts[vFile.path] = DirectScriptInfo(configuration)
|
|
||||||
|
|
||||||
useCustomScriptDefinition()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(other: Builder) {
|
|
||||||
classes.addAll(other.classes)
|
|
||||||
sources.addAll(other.sources)
|
|
||||||
sdks.putAll(other.sdks)
|
|
||||||
scripts.putAll(other.scripts)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addSdk(javaHome: File?): Sdk? {
|
|
||||||
if (javaHome == null) return defaultSdk
|
|
||||||
val canonicalPath = toSystemIndependentName(javaHome.canonicalPath)
|
|
||||||
return sdks.getOrPut(canonicalPath) {
|
|
||||||
getScriptSdkByJavaHome(javaHome) ?: defaultSdk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getScriptSdkByJavaHome(javaHome: File): Sdk? {
|
|
||||||
// workaround for mismatched gradle wrapper and plugin version
|
|
||||||
val javaHomeVF = try {
|
|
||||||
VfsUtil.findFileByIoFile(javaHome, true)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
null
|
|
||||||
} ?: return null
|
|
||||||
|
|
||||||
return getProjectJdkTableSafe().allJdks.find { it.homeDirectory == javaHomeVF }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addSdkByName(sdkName: String) {
|
|
||||||
val sdk = getProjectJdkTableSafe().allJdks.find { it.name == sdkName } ?: defaultSdk ?: return
|
|
||||||
val homePath = sdk.homePath ?: return
|
|
||||||
sdks[homePath] = sdk
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getScriptDefaultSdk(): Sdk? {
|
|
||||||
val projectSdk = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
|
||||||
if (projectSdk != null) return projectSdk
|
|
||||||
|
|
||||||
val anyJavaSdk = getAllProjectSdks().find { it.canBeUsedForScript() }
|
|
||||||
if (anyJavaSdk != null) {
|
|
||||||
return anyJavaSdk
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.warn(
|
|
||||||
"Default Script SDK is null: " +
|
|
||||||
"projectSdk = ${ProjectRootManager.getInstance(project).projectSdk}, " +
|
|
||||||
"all sdks = ${getAllProjectSdks().joinToString("\n")}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Sdk.canBeUsedForScript() = sdkType is JavaSdkType
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLightScriptInfo(file: String) = scripts[file]
|
|
||||||
|
|
||||||
fun contains(file: VirtualFile): Boolean = file.path in scripts
|
|
||||||
|
|
||||||
private fun getHeavyScriptInfo(file: String): HeavyScriptInfo? {
|
|
||||||
val lightScriptInfo = getLightScriptInfo(file) ?: return null
|
|
||||||
val heavy0 = lightScriptInfo.heavyCache?.get()
|
|
||||||
if (heavy0 != null) return heavy0
|
|
||||||
synchronized(lightScriptInfo) {
|
|
||||||
val heavy1 = lightScriptInfo.heavyCache?.get()
|
|
||||||
if (heavy1 != null) return heavy1
|
|
||||||
val heavy2 = computeHeavy(lightScriptInfo)
|
|
||||||
lightScriptInfo.heavyCache = SoftReference(heavy2)
|
|
||||||
return heavy2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun computeHeavy(lightScriptInfo: LightScriptInfo): HeavyScriptInfo? {
|
|
||||||
val configuration = lightScriptInfo.buildConfiguration() ?: return null
|
|
||||||
|
|
||||||
val roots = configuration.dependenciesClassPath
|
|
||||||
val sdk = sdks[configuration.javaHome?.canonicalPath]
|
|
||||||
|
|
||||||
return if (sdk == null) {
|
|
||||||
HeavyScriptInfo(configuration, compose(toVfsRoots(roots)), null)
|
|
||||||
} else {
|
|
||||||
val sdkClasses = sdk.rootProvider.getFiles(OrderRootType.CLASSES).toList()
|
|
||||||
HeavyScriptInfo(configuration, compose(sdkClasses + toVfsRoots(roots)), sdk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val firstScriptSdk: Sdk? = sdks.values.firstOrNull()
|
|
||||||
|
|
||||||
val allDependenciesClassFiles: List<VirtualFile>
|
|
||||||
|
|
||||||
val allDependenciesSources: List<VirtualFile>
|
|
||||||
|
|
||||||
init {
|
|
||||||
allDependenciesClassFiles = mutableSetOf<VirtualFile>().also { result ->
|
|
||||||
nonModulesSdks.forEach { result.addAll(it.rootProvider.getFiles(OrderRootType.CLASSES)) }
|
|
||||||
classes.mapNotNullTo(result) { classpathEntryToVfs(File(it)) }
|
|
||||||
}.toList()
|
|
||||||
|
|
||||||
allDependenciesSources = mutableSetOf<VirtualFile>().also { result ->
|
|
||||||
nonModulesSdks.forEach { result.addAll(it.rootProvider.getFiles(OrderRootType.SOURCES)) }
|
|
||||||
sources.mapNotNullTo(result) { classpathEntryToVfs(File(it)) }
|
|
||||||
}.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val allDependenciesClassFilesScope = compose(allDependenciesClassFiles)
|
|
||||||
|
|
||||||
val allDependenciesSourcesScope = compose(allDependenciesSources)
|
|
||||||
|
|
||||||
fun getScriptConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? =
|
|
||||||
getHeavyScriptInfo(file.path)?.scriptConfiguration
|
|
||||||
|
|
||||||
fun getScriptSdk(file: VirtualFile): Sdk? =
|
|
||||||
getHeavyScriptInfo(file.path)?.sdk
|
|
||||||
|
|
||||||
fun getScriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope =
|
|
||||||
getHeavyScriptInfo(file.path)?.classFilesScope ?: GlobalSearchScope.EMPTY_SCOPE
|
|
||||||
|
|
||||||
fun hasInvalidSdk(project: Project): Boolean {
|
|
||||||
val builder = Builder(project)
|
|
||||||
if (sdks.any { (home, sdk) -> builder.addSdk(home?.let(::File)) != sdk }) return true
|
|
||||||
if (builder.collectNonIndexedSdks() != nonModulesSdks) return true
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun diff(old: ScriptClassRootsCache): Updates =
|
|
||||||
Updates(
|
|
||||||
hasNewRoots(old),
|
|
||||||
getChangedScripts(old)
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun hasNewRoots(old: ScriptClassRootsCache): Boolean {
|
|
||||||
return classes.any { it !in old.classes }
|
|
||||||
|| sources.any { it !in old.sources }
|
|
||||||
|| sdks.any { it.key !in old.sdks }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getChangedScripts(old: ScriptClassRootsCache): Set<String> {
|
|
||||||
val changed = mutableSetOf<String>()
|
|
||||||
|
|
||||||
scripts.forEach {
|
|
||||||
if (old.scripts[it.key] != it.value) {
|
|
||||||
changed.add(it.key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
old.scripts.forEach {
|
|
||||||
if (it.key !in scripts) {
|
|
||||||
changed.add(it.key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed
|
|
||||||
}
|
|
||||||
|
|
||||||
class Updates(
|
|
||||||
val hasNewRoots: Boolean,
|
|
||||||
val updatedScripts: Set<String>
|
|
||||||
) {
|
|
||||||
val changed: Boolean
|
|
||||||
get() = hasNewRoots || updatedScripts.isNotEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+4
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ import com.intellij.util.xmlb.XmlSerializerUtil
|
|||||||
storages = [Storage(StoragePathMacros.CACHE_FILE)]
|
storages = [Storage(StoragePathMacros.CACHE_FILE)]
|
||||||
)
|
)
|
||||||
class ScriptClassRootsStorage(val project: Project) : PersistentStateComponent<ScriptClassRootsStorage> {
|
class ScriptClassRootsStorage(val project: Project) : PersistentStateComponent<ScriptClassRootsStorage> {
|
||||||
private var classpath: Set<String> = hashSetOf()
|
var classpath: Set<String> = hashSetOf()
|
||||||
private var sources: Set<String> = hashSetOf()
|
var sources: Set<String> = hashSetOf()
|
||||||
private var sdks: Set<String> = hashSetOf()
|
var sdks: Set<String> = hashSetOf()
|
||||||
|
|
||||||
override fun getState(): ScriptClassRootsStorage? {
|
override fun getState(): ScriptClassRootsStorage? {
|
||||||
return this
|
return this
|
||||||
@@ -31,18 +31,6 @@ class ScriptClassRootsStorage(val project: Project) : PersistentStateComponent<S
|
|||||||
XmlSerializerUtil.copyBean(state, this)
|
XmlSerializerUtil.copyBean(state, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(roots: ScriptClassRootsCache.Builder) {
|
|
||||||
classpath = roots.classes
|
|
||||||
sources = roots.sources
|
|
||||||
sdks = roots.sdks.values.mapNotNullTo(mutableSetOf()) { it?.name }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun load(builder: ScriptClassRootsCache.Builder) {
|
|
||||||
builder.sources.addAll(sources)
|
|
||||||
builder.classes.addAll(classpath)
|
|
||||||
sdks.forEach(builder::addSdkByName)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): ScriptClassRootsStorage =
|
fun getInstance(project: Project): ScriptClassRootsStorage =
|
||||||
ServiceManager.getService(project, ScriptClassRootsStorage::class.java)
|
ServiceManager.getService(project, ScriptClassRootsStorage::class.java)
|
||||||
|
|||||||
+3
-1
@@ -8,10 +8,12 @@ package org.jetbrains.kotlin.idea.core.script.configuration.utils
|
|||||||
import com.intellij.openapi.application.impl.LaterInvocator
|
import com.intellij.openapi.application.impl.LaterInvocator
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.util.containers.HashSetQueue
|
import com.intellij.util.containers.HashSetQueue
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
||||||
|
|
||||||
class TestingBackgroundExecutor internal constructor(
|
class TestingBackgroundExecutor internal constructor(
|
||||||
private val rootsManager: ScriptClassRootsUpdater
|
private val manager: CompositeScriptConfigurationManager
|
||||||
) : BackgroundExecutor {
|
) : BackgroundExecutor {
|
||||||
|
val rootsManager get() = manager.updater
|
||||||
val backgroundQueue = HashSetQueue<BackgroundTask>()
|
val backgroundQueue = HashSetQueue<BackgroundTask>()
|
||||||
|
|
||||||
class BackgroundTask(val file: VirtualFile, val actions: () -> Unit) {
|
class BackgroundTask(val file: VirtualFile, val actions: () -> Unit) {
|
||||||
|
|||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.core.script.uсache
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
|
||||||
|
class ScriptClassRootsBuilder(
|
||||||
|
val project: Project,
|
||||||
|
private val classes: MutableSet<String> = mutableSetOf(),
|
||||||
|
private val sources: MutableSet<String> = mutableSetOf(),
|
||||||
|
private val scripts: MutableMap<String, ScriptClassRootsCache.LightScriptInfo> = mutableMapOf()
|
||||||
|
) {
|
||||||
|
val sdks = ScriptSdksBuilder(project)
|
||||||
|
|
||||||
|
private var customDefinitionsUsed: Boolean = false
|
||||||
|
|
||||||
|
fun build(): ScriptClassRootsCache =
|
||||||
|
ScriptClassRootsCache(
|
||||||
|
project, scripts, classes, sources,
|
||||||
|
customDefinitionsUsed, sdks.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun useCustomScriptDefinition() {
|
||||||
|
customDefinitionsUsed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(
|
||||||
|
vFile: VirtualFile,
|
||||||
|
configuration: ScriptCompilationConfigurationWrapper
|
||||||
|
) {
|
||||||
|
sdks.addSdk(configuration.javaHome)
|
||||||
|
|
||||||
|
configuration.dependenciesClassPath.forEach { classes.add(it.absolutePath) }
|
||||||
|
configuration.dependenciesSources.forEach { sources.add(it.absolutePath) }
|
||||||
|
|
||||||
|
scripts[vFile.path] = ScriptClassRootsCache.DirectScriptInfo(configuration)
|
||||||
|
|
||||||
|
useCustomScriptDefinition()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addCustom(
|
||||||
|
path: String,
|
||||||
|
scriptClassesRoots: Collection<String>,
|
||||||
|
sourceSourcesRoots: Collection<String>,
|
||||||
|
info: ScriptClassRootsCache.LightScriptInfo
|
||||||
|
) {
|
||||||
|
classes.addAll(scriptClassesRoots)
|
||||||
|
sources.addAll(sourceSourcesRoots)
|
||||||
|
scripts[path] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addTemplateClassesRoots(classesRoots: Collection<String>) {
|
||||||
|
classes.addAll(classesRoots)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(other: ScriptClassRootsBuilder) {
|
||||||
|
classes.addAll(other.classes)
|
||||||
|
sources.addAll(other.sources)
|
||||||
|
sdks.addAll(other.sdks)
|
||||||
|
scripts.putAll(other.scripts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toStorage(storage: ScriptClassRootsStorage) {
|
||||||
|
storage.classpath = classes
|
||||||
|
storage.sources = sources
|
||||||
|
sdks.toStorage(storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromStorage(storage: ScriptClassRootsStorage) = ScriptClassRootsBuilder(
|
||||||
|
storage.project,
|
||||||
|
storage.classpath.toMutableSet(),
|
||||||
|
storage.sources.toMutableSet(),
|
||||||
|
).also { roots ->
|
||||||
|
storage.sdks.forEach {
|
||||||
|
roots.sdks.addSdkByName(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+180
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.core.script.uсache
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.search.NonClasspathDirectoriesScope.compose
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.classpathEntryToVfs
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
import java.io.File
|
||||||
|
import java.lang.ref.Reference
|
||||||
|
import java.lang.ref.SoftReference
|
||||||
|
|
||||||
|
class ScriptClassRootsCache(
|
||||||
|
val project: Project,
|
||||||
|
private val scripts: Map<String, LightScriptInfo>,
|
||||||
|
private val classes: Set<String>,
|
||||||
|
private val sources: Set<String>,
|
||||||
|
val customDefinitionsUsed: Boolean,
|
||||||
|
val sdks: ScriptSdks
|
||||||
|
) {
|
||||||
|
fun withUpdatedSdks(newSdks: ScriptSdks) =
|
||||||
|
ScriptClassRootsCache(project, scripts, classes, sources, customDefinitionsUsed, newSdks)
|
||||||
|
|
||||||
|
abstract class LightScriptInfo(val definition: ScriptDefinition?) {
|
||||||
|
@Volatile
|
||||||
|
var heavyCache: Reference<HeavyScriptInfo>? = null
|
||||||
|
|
||||||
|
abstract fun buildConfiguration(): ScriptCompilationConfigurationWrapper?
|
||||||
|
}
|
||||||
|
|
||||||
|
class DirectScriptInfo(val result: ScriptCompilationConfigurationWrapper) : LightScriptInfo(null) {
|
||||||
|
override fun buildConfiguration(): ScriptCompilationConfigurationWrapper = result
|
||||||
|
}
|
||||||
|
|
||||||
|
class HeavyScriptInfo(
|
||||||
|
val scriptConfiguration: ScriptCompilationConfigurationWrapper,
|
||||||
|
val classFilesScope: GlobalSearchScope,
|
||||||
|
val sdk: Sdk?
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getLightScriptInfo(file: String) = scripts[file]
|
||||||
|
|
||||||
|
fun contains(file: VirtualFile): Boolean = file.path in scripts
|
||||||
|
|
||||||
|
private fun getHeavyScriptInfo(file: String): HeavyScriptInfo? {
|
||||||
|
val lightScriptInfo = getLightScriptInfo(file) ?: return null
|
||||||
|
val heavy0 = lightScriptInfo.heavyCache?.get()
|
||||||
|
if (heavy0 != null) return heavy0
|
||||||
|
synchronized(lightScriptInfo) {
|
||||||
|
val heavy1 = lightScriptInfo.heavyCache?.get()
|
||||||
|
if (heavy1 != null) return heavy1
|
||||||
|
val heavy2 = computeHeavy(lightScriptInfo)
|
||||||
|
lightScriptInfo.heavyCache = SoftReference(heavy2)
|
||||||
|
return heavy2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeHeavy(lightScriptInfo: LightScriptInfo): HeavyScriptInfo? {
|
||||||
|
val configuration = lightScriptInfo.buildConfiguration() ?: return null
|
||||||
|
|
||||||
|
val roots = configuration.dependenciesClassPath
|
||||||
|
val sdk = sdks[configuration.javaHome?.canonicalPath]
|
||||||
|
|
||||||
|
return if (sdk == null) {
|
||||||
|
HeavyScriptInfo(configuration, compose(toVfsRoots(roots)), null)
|
||||||
|
} else {
|
||||||
|
val sdkClasses = sdk.rootProvider.getFiles(OrderRootType.CLASSES).toList()
|
||||||
|
HeavyScriptInfo(configuration, compose(sdkClasses + toVfsRoots(roots)), sdk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val firstScriptSdk: Sdk?
|
||||||
|
get() = sdks.first
|
||||||
|
|
||||||
|
val allDependenciesClassFiles: List<VirtualFile>
|
||||||
|
|
||||||
|
val allDependenciesSources: List<VirtualFile>
|
||||||
|
|
||||||
|
init {
|
||||||
|
allDependenciesClassFiles = mutableSetOf<VirtualFile>().also { result ->
|
||||||
|
result.addAll(sdks.nonIndexedClassRoots)
|
||||||
|
classes.mapNotNullTo(result) { classpathEntryToVfs(File(it)) }
|
||||||
|
}.toList()
|
||||||
|
|
||||||
|
allDependenciesSources = mutableSetOf<VirtualFile>().also { result ->
|
||||||
|
result.addAll(sdks.nonIndexedSourceRoots)
|
||||||
|
sources.mapNotNullTo(result) { classpathEntryToVfs(File(it)) }
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val allDependenciesClassFilesScope = compose(allDependenciesClassFiles)
|
||||||
|
|
||||||
|
val allDependenciesSourcesScope = compose(allDependenciesSources)
|
||||||
|
|
||||||
|
fun getScriptConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? =
|
||||||
|
getHeavyScriptInfo(file.path)?.scriptConfiguration
|
||||||
|
|
||||||
|
fun getScriptSdk(file: VirtualFile): Sdk? =
|
||||||
|
getHeavyScriptInfo(file.path)?.sdk
|
||||||
|
|
||||||
|
fun getScriptDependenciesClassFilesScope(file: VirtualFile): GlobalSearchScope =
|
||||||
|
getHeavyScriptInfo(file.path)?.classFilesScope ?: GlobalSearchScope.EMPTY_SCOPE
|
||||||
|
|
||||||
|
fun diff(old: ScriptClassRootsCache?): Updates =
|
||||||
|
when (old) {
|
||||||
|
null -> FullUpdate(this)
|
||||||
|
this -> NotChanged(this)
|
||||||
|
else -> IncrementalUpdates(this, hasNewRoots(old), getChangedScripts(old))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasNewRoots(old: ScriptClassRootsCache): Boolean {
|
||||||
|
val oldClassRoots = old.allDependenciesClassFiles.toSet()
|
||||||
|
val oldSourceRoots = old.allDependenciesSources.toSet()
|
||||||
|
|
||||||
|
return allDependenciesClassFiles.any { it !in oldClassRoots }
|
||||||
|
|| allDependenciesSources.any { it !in oldSourceRoots }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getChangedScripts(old: ScriptClassRootsCache): Set<String> {
|
||||||
|
val changed = mutableSetOf<String>()
|
||||||
|
|
||||||
|
scripts.forEach {
|
||||||
|
if (old.scripts[it.key] != it.value) {
|
||||||
|
changed.add(it.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
old.scripts.forEach {
|
||||||
|
if (it.key !in scripts) {
|
||||||
|
changed.add(it.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Updates {
|
||||||
|
val cache: ScriptClassRootsCache
|
||||||
|
val changed: Boolean
|
||||||
|
val hasNewRoots: Boolean
|
||||||
|
val hasUpdatedScripts: Boolean
|
||||||
|
fun isScriptChanged(scriptPath: String): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class IncrementalUpdates(
|
||||||
|
override val cache: ScriptClassRootsCache,
|
||||||
|
override val hasNewRoots: Boolean,
|
||||||
|
private val updatedScripts: Set<String>
|
||||||
|
) : Updates {
|
||||||
|
override val hasUpdatedScripts: Boolean get() = updatedScripts.isNotEmpty()
|
||||||
|
override fun isScriptChanged(scriptPath: String) = scriptPath in updatedScripts
|
||||||
|
|
||||||
|
override val changed: Boolean
|
||||||
|
get() = hasNewRoots || updatedScripts.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FullUpdate(override val cache: ScriptClassRootsCache) : Updates {
|
||||||
|
override val changed: Boolean get() = true
|
||||||
|
override val hasNewRoots: Boolean get() = true
|
||||||
|
override val hasUpdatedScripts: Boolean get() = true
|
||||||
|
override fun isScriptChanged(scriptPath: String): Boolean = true
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotChanged(override val cache: ScriptClassRootsCache) : Updates {
|
||||||
|
override val changed: Boolean get() = false
|
||||||
|
override val hasNewRoots: Boolean get() = false
|
||||||
|
override val hasUpdatedScripts: Boolean get() = false
|
||||||
|
override fun isScriptChanged(scriptPath: String): Boolean = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+49
-12
@@ -1,20 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.core.script.configuration.utils
|
package org.jetbrains.kotlin.idea.core.script.uсache
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.application.TransactionGuard
|
import com.intellij.openapi.application.TransactionGuard
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
|
||||||
import com.intellij.openapi.progress.ProgressIndicator
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
import com.intellij.openapi.progress.util.BackgroundTaskUtil
|
import com.intellij.openapi.progress.util.BackgroundTaskUtil
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
|
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
|
||||||
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.openapi.util.EmptyRunnable
|
import com.intellij.openapi.util.EmptyRunnable
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElementFinder
|
import com.intellij.psi.PsiElementFinder
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTrack
|
|||||||
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.debug
|
import org.jetbrains.kotlin.idea.core.script.debug
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
@@ -36,12 +38,23 @@ import kotlin.concurrent.withLock
|
|||||||
*/
|
*/
|
||||||
class ScriptClassRootsUpdater(
|
class ScriptClassRootsUpdater(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val manager: CompositeScriptConfigurationManager
|
val manager: CompositeScriptConfigurationManager,
|
||||||
|
private val buildNewRoots: (ScriptClassRootsBuilder) -> Unit
|
||||||
) {
|
) {
|
||||||
|
private var lastSeen: ScriptClassRootsCache? = null
|
||||||
private var invalidated: Boolean = false
|
private var invalidated: Boolean = false
|
||||||
private var syncUpdateRequired: Boolean = false
|
private var syncUpdateRequired: Boolean = false
|
||||||
private val concurrentUpdates = AtomicInteger()
|
private val concurrentUpdates = AtomicInteger()
|
||||||
|
|
||||||
|
private fun recreateRootsCache(): ScriptClassRootsCache {
|
||||||
|
val builder = ScriptClassRootsBuilder(project)
|
||||||
|
buildNewRoots(builder)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
var classpathRoots: ScriptClassRootsCache = recreateRootsCache()
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param synchronous Used from legacy FS cache only, don't use
|
* @param synchronous Used from legacy FS cache only, don't use
|
||||||
*/
|
*/
|
||||||
@@ -108,8 +121,12 @@ class ScriptClassRootsUpdater(
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
fun ensureUpdateScheduled() {
|
fun ensureUpdateScheduled() {
|
||||||
scheduledUpdate?.cancel()
|
scheduledUpdate?.cancel()
|
||||||
scheduledUpdate = BackgroundTaskUtil.executeOnPooledThread(project) {
|
runReadAction {
|
||||||
doUpdate()
|
if (project.isDisposed && !Disposer.isDisposing(project)) {
|
||||||
|
scheduledUpdate = BackgroundTaskUtil.executeOnPooledThread(project) {
|
||||||
|
doUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,10 +136,22 @@ class ScriptClassRootsUpdater(
|
|||||||
doUpdate(false)
|
doUpdate(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun checkInvalidSdks(remove: Sdk? = null) {
|
||||||
|
// sdks should be updated synchronously to avoid disposed roots usage
|
||||||
|
syncLock.withLock {
|
||||||
|
val current = classpathRoots
|
||||||
|
val actualSdks = current.sdks.rebuild(remove = remove)
|
||||||
|
if (actualSdks != current.sdks) {
|
||||||
|
classpathRoots = current.withUpdatedSdks(actualSdks)
|
||||||
|
ensureUpdateScheduled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun doUpdate(underProgressManager: Boolean = true) {
|
private fun doUpdate(underProgressManager: Boolean = true) {
|
||||||
syncLock.withLock {
|
syncLock.withLock {
|
||||||
try {
|
try {
|
||||||
val updates = manager.collectRootsAndCheckNew()
|
val updates = recreateRootsCacheAndDiff()
|
||||||
|
|
||||||
if (!updates.changed) return
|
if (!updates.changed) return
|
||||||
|
|
||||||
@@ -130,6 +159,8 @@ class ScriptClassRootsUpdater(
|
|||||||
ProgressManager.checkCanceled()
|
ProgressManager.checkCanceled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (project.isDisposed) return
|
||||||
|
|
||||||
if (updates.hasNewRoots) {
|
if (updates.hasNewRoots) {
|
||||||
notifyRootsChanged()
|
notifyRootsChanged()
|
||||||
}
|
}
|
||||||
@@ -139,13 +170,13 @@ class ScriptClassRootsUpdater(
|
|||||||
|
|
||||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||||
|
|
||||||
if (updates.updatedScripts.isNotEmpty()) {
|
if (updates.hasUpdatedScripts) {
|
||||||
updateHighlighting(project) {
|
updateHighlighting(project) {
|
||||||
it.path in updates.updatedScripts
|
updates.isScriptChanged(it.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (cancel: ProcessCanceledException) {
|
|
||||||
if (underProgressManager) throw cancel
|
lastSeen = updates.cache
|
||||||
} finally {
|
} finally {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
scheduledUpdate = null
|
scheduledUpdate = null
|
||||||
@@ -154,6 +185,12 @@ class ScriptClassRootsUpdater(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun recreateRootsCacheAndDiff(): ScriptClassRootsCache.Updates {
|
||||||
|
val new = recreateRootsCache()
|
||||||
|
classpathRoots = new
|
||||||
|
return new.diff(lastSeen)
|
||||||
|
}
|
||||||
|
|
||||||
private fun notifyRootsChanged() {
|
private fun notifyRootsChanged() {
|
||||||
val doNotifyRootsChanged = Runnable {
|
val doNotifyRootsChanged = Runnable {
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
@@ -173,7 +210,7 @@ class ScriptClassRootsUpdater(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateHighlighting(project: Project, filter: (VirtualFile) -> Boolean) {
|
private fun updateHighlighting(project: Project, filter: (VirtualFile) -> Boolean) {
|
||||||
if (!project.isOpen) return
|
if (!project.isOpen) return
|
||||||
|
|
||||||
val openFiles = FileEditorManager.getInstance(project).openFiles
|
val openFiles = FileEditorManager.getInstance(project).openFiles
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.core.script.uсache
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.ModuleManager
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ScriptSdks(val project: Project, private val sdks: Map<String?, Sdk?>) {
|
||||||
|
fun rebuild(remove: Sdk?): ScriptSdks {
|
||||||
|
val builder = ScriptSdksBuilder(project, remove = remove)
|
||||||
|
sdks.keys.forEach { home ->
|
||||||
|
if (home != null) {
|
||||||
|
builder.addSdk(File(home))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
val nonIndexedClassRoots = mutableSetOf<VirtualFile>()
|
||||||
|
val nonIndexedSourceRoots = mutableSetOf<VirtualFile>()
|
||||||
|
|
||||||
|
val first: Sdk? = sdks.values.firstOrNull()
|
||||||
|
operator fun get(sdkHome: String?) = sdks[sdkHome]
|
||||||
|
|
||||||
|
init {
|
||||||
|
val nonIndexedSdks = sdks.values.filterNotNullTo(mutableSetOf())
|
||||||
|
|
||||||
|
runReadAction {
|
||||||
|
ModuleManager.getInstance(project).modules.map {
|
||||||
|
nonIndexedSdks.remove(ModuleRootManager.getInstance(it).sdk)
|
||||||
|
}
|
||||||
|
|
||||||
|
nonIndexedSdks.forEach {
|
||||||
|
nonIndexedClassRoots.addAll(it.rootProvider.getFiles(OrderRootType.CLASSES))
|
||||||
|
nonIndexedSourceRoots.addAll(it.rootProvider.getFiles(OrderRootType.SOURCES))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as ScriptSdks
|
||||||
|
|
||||||
|
if (nonIndexedClassRoots != other.nonIndexedClassRoots) return false
|
||||||
|
if (nonIndexedSourceRoots != other.nonIndexedSourceRoots) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = nonIndexedClassRoots.hashCode()
|
||||||
|
result = 31 * result + nonIndexedSourceRoots.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.core.script.uсache
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.JavaSdkType
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk
|
||||||
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.LOG
|
||||||
|
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
|
||||||
|
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ScriptSdksBuilder(
|
||||||
|
val project: Project,
|
||||||
|
private val sdks: MutableMap<String?, Sdk?> = mutableMapOf(),
|
||||||
|
private val remove: Sdk? = null
|
||||||
|
) {
|
||||||
|
private val defaultSdk = getScriptDefaultSdk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
sdks[null] = defaultSdk
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() = ScriptSdks(project, sdks)
|
||||||
|
|
||||||
|
fun addAll(other: ScriptSdksBuilder) {
|
||||||
|
sdks.putAll(other.sdks)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSdk(javaHome: File?): Sdk? {
|
||||||
|
if (javaHome == null) return defaultSdk
|
||||||
|
val canonicalPath = FileUtil.toSystemIndependentName(javaHome.canonicalPath)
|
||||||
|
return sdks.getOrPut(canonicalPath) {
|
||||||
|
getScriptSdkByJavaHome(javaHome) ?: defaultSdk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getScriptSdkByJavaHome(javaHome: File): Sdk? {
|
||||||
|
// workaround for mismatched gradle wrapper and plugin version
|
||||||
|
val javaHomeVF = try {
|
||||||
|
VfsUtil.findFileByIoFile(javaHome, true)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
null
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
return getProjectJdkTableSafe().allJdks.find { it.homeDirectory == javaHomeVF }
|
||||||
|
?.takeIf { it.canBeUsedForScript() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSdkByName(sdkName: String) {
|
||||||
|
val sdk = getProjectJdkTableSafe().allJdks
|
||||||
|
.find { it.name == sdkName }
|
||||||
|
?.takeIf { it.canBeUsedForScript() }
|
||||||
|
?: defaultSdk ?: return
|
||||||
|
val homePath = sdk.homePath ?: return
|
||||||
|
sdks[homePath] = sdk
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getScriptDefaultSdk(): Sdk? {
|
||||||
|
val projectSdk = ProjectRootManager.getInstance(project).projectSdk?.takeIf { it.canBeUsedForScript() }
|
||||||
|
if (projectSdk != null) return projectSdk
|
||||||
|
|
||||||
|
val anyJavaSdk = getAllProjectSdks().find { it.canBeUsedForScript() }
|
||||||
|
if (anyJavaSdk != null) {
|
||||||
|
return anyJavaSdk
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.warn(
|
||||||
|
"Default Script SDK is null: " +
|
||||||
|
"projectSdk = ${ProjectRootManager.getInstance(project).projectSdk}, " +
|
||||||
|
"all sdks = ${getAllProjectSdks().joinToString("\n")}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Sdk.canBeUsedForScript() = this != remove && sdkType is JavaSdkType
|
||||||
|
|
||||||
|
fun toStorage(storage: ScriptClassRootsStorage) {
|
||||||
|
storage.sdks = sdks.values.mapNotNullTo(mutableSetOf()) { it?.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-8
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.scripting.gradle.roots
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.LocalFileSystem
|
import com.intellij.openapi.vfs.LocalFileSystem
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsBuilder
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor
|
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.LastModifiedFiles
|
import org.jetbrains.kotlin.idea.scripting.gradle.LastModifiedFiles
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||||
@@ -121,21 +121,24 @@ sealed class GradleBuildRoot {
|
|||||||
loadLastModifiedFiles()
|
loadLastModifiedFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun collectConfigurations(builder: ScriptClassRootsCache.Builder) {
|
fun collectConfigurations(builder: ScriptClassRootsBuilder) {
|
||||||
if (javaHome != null) {
|
if (javaHome != null) {
|
||||||
builder.addSdk(javaHome)
|
builder.sdks.addSdk(javaHome)
|
||||||
}
|
}
|
||||||
|
|
||||||
val definitions = GradleScriptDefinitionsContributor.getDefinitions(project)
|
val definitions = GradleScriptDefinitionsContributor.getDefinitions(project)
|
||||||
|
|
||||||
builder.classes.addAll(data.templateClasspath)
|
builder.addTemplateClassesRoots(data.templateClasspath)
|
||||||
|
|
||||||
data.models.forEach { script ->
|
data.models.forEach { script ->
|
||||||
val definition = selectScriptDefinition(script, definitions)
|
val definition = selectScriptDefinition(script, definitions)
|
||||||
|
|
||||||
builder.scripts[script.file] = GradleScriptInfo(this, definition, script)
|
builder.addCustom(
|
||||||
|
script.file,
|
||||||
builder.classes.addAll(script.classPath)
|
script.classPath,
|
||||||
builder.sources.addAll(script.sourcePath)
|
script.sourcePath,
|
||||||
|
GradleScriptInfo(this, definition, script)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -20,7 +20,7 @@ import kotlinx.coroutines.launch
|
|||||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport
|
import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupport
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsBuilder
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.*
|
import org.jetbrains.kotlin.idea.scripting.gradle.*
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslGradleBuildSync
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslGradleBuildSync
|
||||||
@@ -88,7 +88,7 @@ class GradleBuildRootsManager(val project: Project) : ScriptingSupport() {
|
|||||||
return !script.model.inputs.isUpToDate(project, file)
|
return !script.model.inputs.isUpToDate(project, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun collectConfigurations(builder: ScriptClassRootsCache.Builder) {
|
override fun collectConfigurations(builder: ScriptClassRootsBuilder) {
|
||||||
roots.list.forEach { root ->
|
roots.list.forEach { root ->
|
||||||
if (root is GradleBuildRoot.Imported) {
|
if (root is GradleBuildRoot.Imported) {
|
||||||
root.collectConfigurations(builder)
|
root.collectConfigurations(builder)
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.idea.scripting.gradle.roots
|
package org.jetbrains.kotlin.idea.scripting.gradle.roots
|
||||||
|
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
import org.jetbrains.kotlin.idea.core.script.uсache.ScriptClassRootsCache
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
|
||||||
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
|
||||||
|
|||||||
@@ -226,7 +226,10 @@ abstract class AbstractScriptConfigurationTest : KotlinCompletionTestCase() {
|
|||||||
}
|
}
|
||||||
runWriteAction {
|
runWriteAction {
|
||||||
val jdk = PluginTestCaseBase.jdk(jdkKind)
|
val jdk = PluginTestCaseBase.jdk(jdkKind)
|
||||||
getProjectJdkTableSafe().addJdk(jdk, testRootDisposable)
|
val projectJdkTable = getProjectJdkTableSafe()
|
||||||
|
if (jdk !in projectJdkTable.allJdks) {
|
||||||
|
projectJdkTable.addJdk(jdk, testRootDisposable)
|
||||||
|
}
|
||||||
env["javaHome"] = File(jdk.homePath)
|
env["javaHome"] = File(jdk.homePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user