ScriptConfigurationManager: rebuild cache synchronously from default loader
This commit is contained in:
+10
-5
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.idea.core.script.configuration
|
||||
|
||||
import com.intellij.ProjectTopics
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootEvent
|
||||
@@ -111,13 +113,16 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
|
||||
* Loads script configuration if classpath roots don't contain [file] yet
|
||||
*/
|
||||
private fun getActualClasspathRoots(file: VirtualFile): ScriptClassRootsCache {
|
||||
val classpathRoots = classpathRoots
|
||||
if (classpathRoots.contains(file)) {
|
||||
return classpathRoots
|
||||
try {
|
||||
// we should run default loader if this [file] is not cached in [classpathRoots]
|
||||
// and it is not supported by any of [plugins]
|
||||
// getOrLoadConfiguration will do this
|
||||
// (despite that it's result becomes unused, it still may populate [classpathRoots])
|
||||
getOrLoadConfiguration(file, null)
|
||||
} catch (cancelled: ProcessCanceledException) {
|
||||
// read actions may be cancelled if we are called by impatient reader
|
||||
}
|
||||
|
||||
getOrLoadConfiguration(file)
|
||||
|
||||
return this.classpathRoots
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -223,7 +223,7 @@ class DefaultScriptingSupport(manager: CompositeScriptConfigurationManager) : De
|
||||
file.removeScriptDependenciesNotificationPanel(project)
|
||||
}
|
||||
saveReports(file, newResult.reports)
|
||||
setAppliedConfiguration(file, newResult)
|
||||
setAppliedConfiguration(file, newResult, syncUpdate = true)
|
||||
} else {
|
||||
debug(file) {
|
||||
"configuration changed, notification is shown: old = $oldConfiguration, new = $newConfiguration"
|
||||
@@ -377,15 +377,21 @@ abstract class DefaultScriptingSupportBase(val manager: CompositeScriptConfigura
|
||||
|
||||
protected open fun setAppliedConfiguration(
|
||||
file: VirtualFile,
|
||||
newConfigurationSnapshot: ScriptConfigurationSnapshot?
|
||||
newConfigurationSnapshot: ScriptConfigurationSnapshot?,
|
||||
syncUpdate: Boolean = false
|
||||
) {
|
||||
manager.updater.checkInTransaction()
|
||||
val newConfiguration = newConfigurationSnapshot?.configuration
|
||||
debug(file) { "configuration changed = $newConfiguration" }
|
||||
|
||||
if (newConfiguration != null) {
|
||||
manager.updater.invalidate(file)
|
||||
cache.setApplied(file, newConfigurationSnapshot)
|
||||
|
||||
if (syncUpdate) {
|
||||
manager.updater.updateSynchronously()
|
||||
} else {
|
||||
manager.updater.invalidate(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -15,6 +15,7 @@ import com.intellij.util.containers.HashSetQueue
|
||||
import org.jetbrains.kotlin.idea.core.script.debug
|
||||
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
|
||||
import java.util.*
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
/**
|
||||
* Sequentially loads script configuration in background.
|
||||
@@ -227,9 +228,12 @@ internal class DefaultBackgroundExecutor(
|
||||
override fun start() {
|
||||
super.start()
|
||||
|
||||
BackgroundTaskUtil.executeOnPooledThread(project, Runnable {
|
||||
run()
|
||||
})
|
||||
// executeOnPooledThread requires read lock, and we may fail to acquire it
|
||||
SwingUtilities.invokeLater {
|
||||
BackgroundTaskUtil.executeOnPooledThread(project, {
|
||||
run()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
|
||||
+39
-19
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.idea.core.script.configuration.ScriptingSupportHelpe
|
||||
import org.jetbrains.kotlin.idea.core.script.debug
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
/**
|
||||
* Utility for postponing indexing of new roots to the end of some bulk operation.
|
||||
@@ -78,6 +80,7 @@ class ScriptClassRootsUpdater(
|
||||
ensureUpdateScheduled()
|
||||
}
|
||||
|
||||
private val syncLock = ReentrantLock()
|
||||
private var scheduledUpdate: ProgressIndicator? = null
|
||||
|
||||
@Synchronized
|
||||
@@ -88,31 +91,48 @@ class ScriptClassRootsUpdater(
|
||||
}
|
||||
}
|
||||
|
||||
fun doUpdate() {
|
||||
val updates = manager.collectRootsAndCheckNew()
|
||||
|
||||
if (!updates.changed) return
|
||||
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (updates.hasNewRoots) {
|
||||
notifyRootsChanged()
|
||||
/**
|
||||
* Used from legacy FS cache only, don't use
|
||||
*/
|
||||
@Synchronized
|
||||
fun updateSynchronously() {
|
||||
syncLock.withLock {
|
||||
scheduledUpdate?.cancel()
|
||||
doUpdate(false)
|
||||
}
|
||||
}
|
||||
|
||||
PsiElementFinder.EP.findExtensionOrFail(KotlinScriptDependenciesClassFinder::class.java, project)
|
||||
.clearCache()
|
||||
fun doUpdate(underProgressManager: Boolean = true) {
|
||||
syncLock.withLock {
|
||||
val updates = manager.collectRootsAndCheckNew()
|
||||
|
||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||
if (!updates.changed) return
|
||||
|
||||
if (updates.updatedScripts.isNotEmpty()) {
|
||||
ScriptingSupportHelper.updateHighlighting(project) {
|
||||
it.path in updates.updatedScripts
|
||||
try {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (updates.hasNewRoots) {
|
||||
notifyRootsChanged()
|
||||
}
|
||||
|
||||
PsiElementFinder.EP.findExtensionOrFail(KotlinScriptDependenciesClassFinder::class.java, project)
|
||||
.clearCache()
|
||||
|
||||
ScriptDependenciesModificationTracker.getInstance(project).incModificationCount()
|
||||
|
||||
if (updates.updatedScripts.isNotEmpty()) {
|
||||
ScriptingSupportHelper.updateHighlighting(project) {
|
||||
it.path in updates.updatedScripts
|
||||
}
|
||||
}
|
||||
} catch (cancel: ProcessCanceledException) {
|
||||
if (underProgressManager) throw cancel
|
||||
} finally {
|
||||
synchronized(this) {
|
||||
scheduledUpdate = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
scheduledUpdate = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyRootsChanged() {
|
||||
|
||||
+8
-3
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.scripting.gradle
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
|
||||
@@ -25,10 +26,14 @@ data class GradleKotlinScriptConfigurationInputs(
|
||||
val inputsTS: Long
|
||||
) : CachedConfigurationInputs {
|
||||
override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean {
|
||||
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile) ?: return false
|
||||
try {
|
||||
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile) ?: return false
|
||||
|
||||
if (actualStamp.sections != this.sections) return false
|
||||
if (actualStamp.sections != this.sections) return false
|
||||
|
||||
return project.service<GradleScriptInputsWatcher>().areRelatedFilesUpToDate(file, inputsTS)
|
||||
return project.service<GradleScriptInputsWatcher>().areRelatedFilesUpToDate(file, inputsTS)
|
||||
} catch (cancel: ProcessCanceledException) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user