diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesCache.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesCache.kt index a45352117a9..c13b4762276 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesCache.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesCache.kt @@ -16,11 +16,16 @@ package org.jetbrains.kotlin.idea.core.script +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElementFinder +import com.intellij.psi.PsiManager import com.intellij.psi.search.NonClasspathDirectoriesScope +import kotlinx.coroutines.experimental.launch +import org.jetbrains.kotlin.idea.core.util.EDT import java.util.concurrent.locks.ReentrantReadWriteLock import kotlin.concurrent.read import kotlin.concurrent.write @@ -49,7 +54,7 @@ internal class ScriptDependenciesCache(private val project: Project) { NonClasspathDirectoriesScope(allLibrarySourcesCache.get()) } - fun onChange() { + private fun onChange(file: VirtualFile?) { allScriptsClasspathCache.clear() allScriptsClasspathScope.clear() allLibrarySourcesCache.clear() @@ -61,11 +66,33 @@ internal class ScriptDependenciesCache(private val project: Project) { .single() kotlinScriptDependenciesClassFinder.clearCache() + updateHighlighting(file) + } + + private fun updateHighlighting(file: VirtualFile?) { + ScriptDependenciesModificationTracker.getInstance(project).incModificationCount() + + launch(EDT) { + if (file != null) { + file.let { PsiManager.getInstance(project).findFile(it) }?.let { psiFile -> + DaemonCodeAnalyzer.getInstance(project).restart(psiFile) + } + } + else { + assert(ApplicationManager.getApplication().isUnitTestMode) + DaemonCodeAnalyzer.getInstance(project).restart() + } + } + } + + fun hasNotCachedRoots(scriptDependencies: ScriptDependencies): Boolean { + return !allScriptsClasspathCache.get().containsAll(ScriptDependenciesManager.toVfsRoots(scriptDependencies.classpath)) || + !allLibrarySourcesCache.get().containsAll(ScriptDependenciesManager.toVfsRoots(scriptDependencies.sources)) } fun clear() { cacheLock.write(cache::clear) - onChange() + onChange(null) } fun save(virtualFile: VirtualFile, new: ScriptDependencies): Boolean { @@ -75,11 +102,22 @@ internal class ScriptDependenciesCache(private val project: Project) { cache[path] = new old } - return new != old + val changed = new != old + if (changed) { + onChange(virtualFile) + } + + return changed } - fun delete(virtualFile: VirtualFile): Boolean = cacheLock.write { - cache.remove(virtualFile.path) != null + fun delete(virtualFile: VirtualFile): Boolean { + val changed = cacheLock.write { + cache.remove(virtualFile.path) != null + } + if (changed) { + onChange(virtualFile) + } + return changed } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt index 9118cd34b1e..ed357618014 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesManager.kt @@ -89,9 +89,8 @@ class ScriptDependenciesManager internal constructor( fun updateScriptDependenciesSynchronously(virtualFile: VirtualFile, project: Project) { with(getInstance(project)) { val scriptDefinition = KotlinScriptDefinitionProvider.getInstance(project)!!.findScriptDefinition(virtualFile)!! - val updated = cacheUpdater.updateSync(virtualFile, scriptDefinition) - assert(updated) - cacheUpdater.onChange() + cacheUpdater.updateSync(virtualFile, scriptDefinition) + cacheUpdater.notifyRootsChanged() } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt index 809223083d9..f1184efd68a 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt @@ -80,8 +80,11 @@ internal class ScriptDependenciesUpdater( private fun tryLoadingFromDisk(file: VirtualFile) { ScriptDependenciesFileAttribute.read(file)?.let { deserialized -> + val rootsChanged = cache.hasNotCachedRoots(deserialized) cache.save(file, deserialized) - onChange() + if (rootsChanged) { + notifyRootsChanged() + } } } @@ -186,8 +189,8 @@ internal class ScriptDependenciesUpdater( } ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports) val resultingDependencies = (result.dependencies ?: ScriptDependencies.Empty).adjustByDefinition(scriptDef) - if (cache(resultingDependencies, file)) { - onChange() + if (saveNewDependencies(resultingDependencies, file)) { + notifyRootsChanged() } } } @@ -195,26 +198,21 @@ internal class ScriptDependenciesUpdater( fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean { val newDeps = contentLoader.loadContentsAndResolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty - return cache(newDeps, file) + return saveNewDependencies(newDeps, file) } - private fun cache( + private fun saveNewDependencies( new: ScriptDependencies, file: VirtualFile ): Boolean { - val updated = cache.save(file, new) - if (updated) { + val rootsChanged = cache.hasNotCachedRoots(new) + if (cache.save(file, new)) { ScriptDependenciesFileAttribute.write(file, new) } - return updated + return rootsChanged } - fun onChange() { - cache.onChange() - notifyRootsChanged() - } - - private fun notifyRootsChanged() { + fun notifyRootsChanged() { val rootsChangesRunnable = { runWriteAction { if (project.isDisposed) return@runWriteAction @@ -248,7 +246,7 @@ internal class ScriptDependenciesUpdater( (application.isUnitTestMode || projectFileIndex.isInContent(it)) && !ProjectUtil.isProjectOrWorkspaceFile(it) } })) { - onChange() + notifyRootsChanged() } } })