From b9fda902fb6d6fc27f0e657761a71a2dd0d80b67 Mon Sep 17 00:00:00 2001 From: Sergey Rostov Date: Tue, 16 Jun 2020 11:01:16 +0300 Subject: [PATCH] gradle.kts: update notification only after caches updated --- .../CompositeScriptConfigurationManager.kt | 13 +++++++--- .../script/configuration/ScriptingSupport.kt | 1 + .../script/ucache/ScriptClassRootsUpdater.kt | 15 ++++++++--- .../scripting/gradle/roots/GradleBuildRoot.kt | 8 ++++-- .../gradle/roots/GradleBuildRootsLocator.kt | 6 ++++- .../gradle/roots/GradleBuildRootsManager.kt | 26 +++++++++++++------ 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/CompositeScriptConfigurationManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/CompositeScriptConfigurationManager.kt index 1e37203afe8..de8f60392b4 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/CompositeScriptConfigurationManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/CompositeScriptConfigurationManager.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager 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.utils.getKtFile +import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsBuilder import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsCache import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsUpdater import org.jetbrains.kotlin.psi.KtFile @@ -52,9 +53,15 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur val default = DefaultScriptingSupport(this) - val updater = ScriptClassRootsUpdater(project, this) { builder -> - default.collectConfigurations(builder) - plugins.forEach { it.collectConfigurations(builder) } + val updater = object : ScriptClassRootsUpdater(project, this) { + override fun gatherRoots(builder: ScriptClassRootsBuilder) { + default.collectConfigurations(builder) + plugins.forEach { it.collectConfigurations(builder) } + } + + override fun afterUpdate() { + plugins.forEach { it.afterUpdate() } + } } fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/ScriptingSupport.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/ScriptingSupport.kt index bad6d933696..a647eb0310b 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/ScriptingSupport.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/configuration/ScriptingSupport.kt @@ -35,6 +35,7 @@ interface ScriptingSupport { fun isApplicable(file: VirtualFile): Boolean fun isConfigurationLoadingInProgress(file: KtFile): Boolean fun collectConfigurations(builder: ScriptClassRootsBuilder) + fun afterUpdate() companion object { val EPN: ExtensionPointName = diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt index 7aeaf48a7bb..416f089a4e0 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsUpdater.kt @@ -47,16 +47,19 @@ import java.util.concurrent.atomic.AtomicReference * This will start indexing. * Also analysis cache will be cleared and changed opened script files will be reanalyzed. */ -class ScriptClassRootsUpdater( +abstract class ScriptClassRootsUpdater( val project: Project, - val manager: CompositeScriptConfigurationManager, - private val gatherRoots: (ScriptClassRootsBuilder) -> Unit + val manager: CompositeScriptConfigurationManager ) { private var lastSeen: ScriptClassRootsCache? = null private var invalidated: Boolean = false private var syncUpdateRequired: Boolean = false private val concurrentUpdates = AtomicInteger() + abstract fun gatherRoots(builder: ScriptClassRootsBuilder) + + abstract fun afterUpdate() + private fun recreateRootsCache(): ScriptClassRootsCache { val builder = ScriptClassRootsBuilder(project) gatherRoots(builder) @@ -68,6 +71,11 @@ class ScriptClassRootsUpdater( */ private val cache: AtomicReference = AtomicReference(recreateRootsCache()) + init { + @Suppress("LeakingThis") + afterUpdate() + } + val classpathRoots: ScriptClassRootsCache get() = cache.get() @@ -196,6 +204,7 @@ class ScriptClassRootsUpdater( val old = cache.get() val new = recreateRootsCache() if (cache.compareAndSet(old, new)) { + afterUpdate() return new.diff(lastSeen) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt index 0e1ee71a9a5..9ed731d327b 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRoot.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import org.jetbrains.plugins.gradle.settings.GradleProjectSettings import java.io.File +import java.util.concurrent.atomic.AtomicReference /** * [GradleBuildRoot] is a linked gradle build (don't confuse with gradle project and included build). @@ -28,8 +29,11 @@ import java.io.File sealed class GradleBuildRoot( private val lastModifiedFiles: LastModifiedFiles ) { - @Volatile - var importing = false + enum class ImportingStatus { + importing, updatingCaches, updated + } + + val importing = AtomicReference(ImportingStatus.updated) abstract val pathPrefix: String diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt index 2f712437cd4..98d036dcdad 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsLocator.kt @@ -86,7 +86,7 @@ abstract class GradleBuildRootsLocator { isImported -> NotificationKind.dontCare standalone -> NotificationKind.standalone nearest == null -> NotificationKind.outsideAnything - nearest.importing -> NotificationKind.dontCare + importing -> NotificationKind.dontCare else -> when (nearest) { is Legacy -> NotificationKind.dontCare is New -> NotificationKind.wasNotImportedAfterCreation @@ -97,6 +97,10 @@ abstract class GradleBuildRootsLocator { } } + private val importing: Boolean + get() = nearest != null && + nearest.importing.get() != GradleBuildRoot.ImportingStatus.updated + private val isImported: Boolean get() = script != null diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt index fe8545fe848..cd4012991f8 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/roots/GradleBuildRootsManager.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsBuilder import org.jetbrains.kotlin.idea.core.util.EDT import org.jetbrains.kotlin.idea.scripting.gradle.* import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslGradleBuildSync +import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRoot.ImportingStatus.* import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance @@ -88,8 +89,8 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), } override fun isConfigurationLoadingInProgress(file: KtFile): Boolean { - return when (val root = findScriptBuildRoot(file.originalFile.virtualFile)?.root) { - is GradleBuildRoot -> root.importing + return when (val root = findScriptBuildRoot(file.originalFile.virtualFile)?.nearest) { + is GradleBuildRoot -> root.importing.get() != updated else -> false } } @@ -108,6 +109,14 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), } } + override fun afterUpdate() { + roots.list.forEach { root -> + if (root.importing.compareAndSet(updatingCaches, updated)) { + updateNotifications { it.startsWith(root.pathPrefix) } + } + } + } + ////////////////// override fun getScriptInfo(localPath: String): GradleScriptInfo? = @@ -126,7 +135,7 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), } fun markImportingInProgress(workingDir: String, inProgress: Boolean = true) { - actualizeBuildRoot(workingDir)?.importing = inProgress + actualizeBuildRoot(workingDir)?.importing?.set(if (inProgress) importing else updated) updateNotifications { it.startsWith(workingDir) } } @@ -137,10 +146,10 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), if (root is Imported && root.data.models.isEmpty()) return } - try { - val oldRoot = actualizeBuildRoot(sync.workingDir) ?: return - oldRoot.importing = false + val oldRoot = actualizeBuildRoot(sync.workingDir) ?: return + oldRoot.importing.set(updatingCaches) + try { if (oldRoot is Legacy) return val templateClasspath = GradleScriptDefinitionsContributor.getDefinitionsTemplateClasspath(project) @@ -153,8 +162,9 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(), newRoot.saveLastModifiedFiles() add(newRoot) - } finally { - updateNotifications { it.startsWith(sync.workingDir) } + } catch (e: Throwable) { + markImportingInProgress(sync.workingDir, false) + throw e } }