Split script configuration state into applied and loaded to make markUpToDate more clear
This commit is contained in:
committed by
Natalia Selezneva
parent
fde1d3fdf7
commit
fbb2b260dd
+18
-15
@@ -20,9 +20,9 @@ import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.idea.core.script.*
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationCache
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationState
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsIndexer
|
||||
@@ -40,7 +40,7 @@ import kotlin.concurrent.withLock
|
||||
* Among this two methods concrete implementation should provide script changes listening (by calling [updater] on some event).
|
||||
*
|
||||
* Basically all requests routed to [cache]. If there is no entry in [cache] or it is considered out-of-date,
|
||||
* then [reloadOutOfDateConfiguration] will be called, which, in turn, should call [saveChangedConfiguration]
|
||||
* then [reloadOutOfDateConfiguration] will be called, which, in turn, should call [setAppliedConfiguration]
|
||||
* immediately or in some future (e.g. after user will click "apply context" or/and configuration will
|
||||
* be calculated by some background thread).
|
||||
*
|
||||
@@ -61,7 +61,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
|
||||
/**
|
||||
* Will be called on [cache] miss or when [file] is changed.
|
||||
* Implementation should initiate loading of [file]'s script configuration and call [saveChangedConfiguration]
|
||||
* Implementation should initiate loading of [file]'s script configuration and call [setAppliedConfiguration]
|
||||
* immediately or in some future
|
||||
* (e.g. after user will click "apply context" or/and configuration will be calculated by some background thread).
|
||||
*
|
||||
@@ -73,7 +73,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
*/
|
||||
protected abstract fun reloadOutOfDateConfiguration(
|
||||
file: KtFile,
|
||||
isFirstLoad: Boolean = getCachedConfiguration(file.originalFile.virtualFile) == null,
|
||||
isFirstLoad: Boolean = getAppliedConfiguration(file.originalFile.virtualFile) == null,
|
||||
loadEvenWillNotBeApplied: Boolean = false,
|
||||
forceSync: Boolean = false
|
||||
)
|
||||
@@ -87,13 +87,16 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
override fun getScriptClasspath(file: KtFile): List<VirtualFile> =
|
||||
toVfsRoots(getConfiguration(file)?.dependenciesClassPath.orEmpty())
|
||||
|
||||
fun getCachedConfiguration(file: VirtualFile?): ScriptConfigurationSnapshot? {
|
||||
fun getCachedConfigurationState(file: VirtualFile?): ScriptConfigurationState? {
|
||||
if (file == null) return null
|
||||
return cache[file]
|
||||
}
|
||||
|
||||
fun getAppliedConfiguration(file: VirtualFile?): ScriptConfigurationSnapshot? =
|
||||
getCachedConfigurationState(file)?.applied
|
||||
|
||||
override fun hasConfiguration(file: KtFile): Boolean {
|
||||
return getCachedConfiguration(file.originalFile.virtualFile) != null
|
||||
return getAppliedConfiguration(file.originalFile.virtualFile) != null
|
||||
}
|
||||
|
||||
override fun getConfiguration(file: KtFile): ScriptCompilationConfigurationWrapper? {
|
||||
@@ -104,7 +107,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
virtualFile: VirtualFile,
|
||||
preloadedKtFile: KtFile? = null
|
||||
): ScriptCompilationConfigurationWrapper? {
|
||||
val cached = getCachedConfiguration(virtualFile)
|
||||
val cached = getAppliedConfiguration(virtualFile)
|
||||
if (cached != null) return cached.configuration
|
||||
|
||||
val ktFile = project.getKtFile(virtualFile, preloadedKtFile) ?: return null
|
||||
@@ -112,7 +115,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
reloadOutOfDateConfiguration(ktFile, isFirstLoad = true)
|
||||
}
|
||||
|
||||
return getCachedConfiguration(virtualFile)?.configuration
|
||||
return getAppliedConfiguration(virtualFile)?.configuration
|
||||
}
|
||||
|
||||
override val updater: ScriptConfigurationUpdater = object : ScriptConfigurationUpdater {
|
||||
@@ -143,7 +146,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
val virtualFile = file.originalFile.virtualFile
|
||||
if (virtualFile != null) {
|
||||
val state = cache[virtualFile]
|
||||
if (state == null || !state.inputs.isUpToDate(project, virtualFile, file)) {
|
||||
if (state == null || !state.isUpToDate(project, virtualFile, file)) {
|
||||
upToDate = false
|
||||
reloadOutOfDateConfiguration(
|
||||
file,
|
||||
@@ -165,14 +168,14 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
file as? KtFile ?: error("PsiFile $file should be a KtFile, otherwise script dependencies cannot be loaded")
|
||||
|
||||
val virtualFile = file.virtualFile
|
||||
if (cache[virtualFile]?.inputs?.isUpToDate(project, virtualFile, file) == true) return
|
||||
if (cache[virtualFile]?.isUpToDate(project, virtualFile, file) == true) return
|
||||
|
||||
rootsIndexer.transaction {
|
||||
reloadOutOfDateConfiguration(file, isFirstLoad = true, forceSync = true)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun saveChangedConfiguration(
|
||||
protected open fun setAppliedConfiguration(
|
||||
file: VirtualFile,
|
||||
newConfigurationSnapshot: ScriptConfigurationSnapshot?
|
||||
) {
|
||||
@@ -185,7 +188,7 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
rootsIndexer.markNewRoot(file, newConfiguration)
|
||||
}
|
||||
|
||||
cache[file] = newConfigurationSnapshot
|
||||
cache.setApplied(file, newConfigurationSnapshot)
|
||||
|
||||
clearClassRootsCaches()
|
||||
}
|
||||
@@ -193,11 +196,11 @@ internal abstract class AbstractScriptConfigurationManager(
|
||||
updateHighlighting(listOf(file))
|
||||
}
|
||||
|
||||
protected fun markUpToDate(
|
||||
protected fun setLoadedConfiguration(
|
||||
file: VirtualFile,
|
||||
inputs: CachedConfigurationInputs
|
||||
configurationSnapshot: ScriptConfigurationSnapshot
|
||||
) {
|
||||
cache.markUpToDate(file, inputs)
|
||||
cache.setLoaded(file, configurationSnapshot)
|
||||
}
|
||||
|
||||
private fun hasNotCachedRoots(configuration: ScriptCompilationConfigurationWrapper): Boolean {
|
||||
|
||||
+8
-8
@@ -141,7 +141,7 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
* and file will be up-to-date checked again. This will happen after current loading,
|
||||
* because only `backgroundExecutor` execute tasks in one thread.
|
||||
* - `invalid, waiting for apply`:
|
||||
* Loading will not be queued, since we are marking file is up to date with
|
||||
* Loading will not be queued, since we are marking file as up-to-date with
|
||||
* not yet applied configuration.
|
||||
*
|
||||
* Sync:
|
||||
@@ -177,8 +177,8 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
backgroundExecutor.ensureScheduled(virtualFile) {
|
||||
// don't start loading if nothing was changed
|
||||
// (in case we checking for up-to-date and loading concurrently)
|
||||
val cached = getCachedConfiguration(virtualFile)
|
||||
if (cached == null || !cached.inputs.isUpToDate(project, virtualFile)) {
|
||||
val cached = getCachedConfigurationState(virtualFile)
|
||||
if (cached == null || !cached.isUpToDate(project, virtualFile)) {
|
||||
val actualIsFirstLoad = cached == null
|
||||
async.first { it.loadDependencies(actualIsFirstLoad, virtualFile, scriptDefinition, loadingContext) }
|
||||
}
|
||||
@@ -202,7 +202,7 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
|
||||
private val loadingContext = object : ScriptConfigurationLoadingContext {
|
||||
override fun getCachedConfiguration(file: VirtualFile): ScriptConfigurationSnapshot? =
|
||||
this@DefaultScriptConfigurationManager.getCachedConfiguration(file)
|
||||
this@DefaultScriptConfigurationManager.getAppliedConfiguration(file)
|
||||
|
||||
override fun suggestNewConfiguration(file: VirtualFile, newResult: ScriptConfigurationSnapshot) {
|
||||
suggestOrSaveConfiguration(file, newResult, false)
|
||||
@@ -221,13 +221,13 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
saveLock.withLock {
|
||||
debug(file) { "configuration received = $newResult" }
|
||||
|
||||
markUpToDate(file, newResult.inputs)
|
||||
setLoadedConfiguration(file, newResult)
|
||||
|
||||
val newConfiguration = newResult.configuration
|
||||
if (newConfiguration == null) {
|
||||
saveReports(file, newResult.reports)
|
||||
} else {
|
||||
val oldConfiguration = getCachedConfiguration(file)?.configuration
|
||||
val oldConfiguration = getAppliedConfiguration(file)?.configuration
|
||||
if (oldConfiguration == newConfiguration) {
|
||||
saveReports(file, newResult.reports)
|
||||
file.removeScriptDependenciesNotificationPanel(project)
|
||||
@@ -242,7 +242,7 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
file.removeScriptDependenciesNotificationPanel(project)
|
||||
}
|
||||
saveReports(file, newResult.reports)
|
||||
saveChangedConfiguration(file, newResult)
|
||||
setAppliedConfiguration(file, newResult)
|
||||
} else {
|
||||
debug(file) {
|
||||
"configuration changed, notification is shown: old = $oldConfiguration, new = $newConfiguration"
|
||||
@@ -253,7 +253,7 @@ internal class DefaultScriptConfigurationManager(project: Project) :
|
||||
saveReports(file, newResult.reports)
|
||||
file.removeScriptDependenciesNotificationPanel(project)
|
||||
rootsIndexer.transaction {
|
||||
saveChangedConfiguration(file, newResult)
|
||||
setAppliedConfiguration(file, newResult)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
+13
-5
@@ -30,6 +30,14 @@ data class ScriptConfigurationSnapshot(
|
||||
val configuration: ScriptCompilationConfigurationWrapper?
|
||||
)
|
||||
|
||||
data class ScriptConfigurationState(
|
||||
val applied: ScriptConfigurationSnapshot? = null,
|
||||
val loaded: ScriptConfigurationSnapshot? = null
|
||||
) {
|
||||
fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile? = null): Boolean =
|
||||
(loaded ?: applied)?.inputs?.isUpToDate(project, file, ktFile) ?: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached configurations for file's specific snapshot state.
|
||||
*
|
||||
@@ -37,11 +45,11 @@ data class ScriptConfigurationSnapshot(
|
||||
* Reader may do up-to-date check for existed entry.
|
||||
*/
|
||||
interface ScriptConfigurationCache {
|
||||
operator fun get(file: VirtualFile): ScriptConfigurationSnapshot?
|
||||
operator fun set(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot)
|
||||
operator fun get(file: VirtualFile): ScriptConfigurationState?
|
||||
|
||||
fun markUpToDate(file: VirtualFile, inputs: CachedConfigurationInputs)
|
||||
fun markOutOfDate(file: VirtualFile) = markUpToDate(file, CachedConfigurationInputs.OutOfDate)
|
||||
fun setApplied(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot)
|
||||
fun setLoaded(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot)
|
||||
fun markOutOfDate(file: VirtualFile)
|
||||
|
||||
fun all(): Collection<Pair<VirtualFile, ScriptCompilationConfigurationWrapper>>
|
||||
fun allApplied(): Collection<Pair<VirtualFile, ScriptCompilationConfigurationWrapper>>
|
||||
}
|
||||
+24
-17
@@ -17,34 +17,41 @@ class ScriptConfigurationMemoryCache(
|
||||
const val MAX_SCRIPTS_CACHED = 50
|
||||
}
|
||||
|
||||
private val memoryCache = SLRUMap<VirtualFile, ScriptConfigurationSnapshot>(MAX_SCRIPTS_CACHED, MAX_SCRIPTS_CACHED)
|
||||
private val memoryCache = SLRUMap<VirtualFile, ScriptConfigurationState>(MAX_SCRIPTS_CACHED, MAX_SCRIPTS_CACHED)
|
||||
|
||||
@Synchronized
|
||||
override operator fun get(file: VirtualFile): ScriptConfigurationSnapshot? {
|
||||
override operator fun get(file: VirtualFile): ScriptConfigurationState? {
|
||||
return memoryCache.get(file)
|
||||
}
|
||||
|
||||
|
||||
@Synchronized
|
||||
override operator fun set(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot) {
|
||||
memoryCache.put(
|
||||
file,
|
||||
configurationSnapshot
|
||||
)
|
||||
override fun setApplied(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot) {
|
||||
val old = memoryCache[file] ?: ScriptConfigurationState()
|
||||
memoryCache.put(file, old.copy(applied = configurationSnapshot))
|
||||
}
|
||||
|
||||
override fun markUpToDate(file: VirtualFile, inputs: CachedConfigurationInputs) {
|
||||
val old = memoryCache[file]
|
||||
if (old != null) {
|
||||
memoryCache.put(file, old.copy(inputs = inputs))
|
||||
}
|
||||
@Synchronized
|
||||
override fun setLoaded(file: VirtualFile, configurationSnapshot: ScriptConfigurationSnapshot) {
|
||||
val old = memoryCache[file] ?: ScriptConfigurationState()
|
||||
memoryCache.put(file, old.copy(loaded = configurationSnapshot))
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun markOutOfDate(file: VirtualFile) {
|
||||
val old = memoryCache[file] ?: ScriptConfigurationState()
|
||||
memoryCache.put(
|
||||
file, old.copy(
|
||||
applied = old.applied?.copy(inputs = CachedConfigurationInputs.OutOfDate),
|
||||
loaded = old.loaded?.copy(inputs = CachedConfigurationInputs.OutOfDate)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun all() =
|
||||
memoryCache.entrySet().map {
|
||||
if (it.value.configuration == null) null
|
||||
else it.key to it.value.configuration
|
||||
override fun allApplied() =
|
||||
memoryCache.entrySet().mapNotNull {
|
||||
if (it.value.applied?.configuration == null) null
|
||||
else it.key to it.value.applied?.configuration
|
||||
} as Collection<Pair<VirtualFile, ScriptCompilationConfigurationWrapper>>
|
||||
}
|
||||
+2
-2
@@ -25,8 +25,8 @@ internal class ScriptClassRootsCache(
|
||||
private val project: Project,
|
||||
private val cache: ScriptConfigurationCache
|
||||
) {
|
||||
private val all: Collection<Pair<VirtualFile, ScriptCompilationConfigurationWrapper>> get() = cache.all()
|
||||
private fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? = cache[file]?.configuration
|
||||
private val all: Collection<Pair<VirtualFile, ScriptCompilationConfigurationWrapper>> get() = cache.allApplied()
|
||||
private fun getConfiguration(file: VirtualFile): ScriptCompilationConfigurationWrapper? = cache[file]?.applied?.configuration
|
||||
|
||||
private fun getScriptSdk(compilationConfiguration: ScriptCompilationConfigurationWrapper?): Sdk? {
|
||||
// workaround for mismatched gradle wrapper and plugin version
|
||||
|
||||
Reference in New Issue
Block a user