gradle.kts: update notification only after caches updated

This commit is contained in:
Sergey Rostov
2020-06-16 11:01:16 +03:00
parent ce20196006
commit b9fda902fb
6 changed files with 52 additions and 17 deletions
@@ -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.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.getKtFile 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.ScriptClassRootsCache
import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsUpdater import org.jetbrains.kotlin.idea.core.script.ucache.ScriptClassRootsUpdater
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -52,9 +53,15 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
val default = DefaultScriptingSupport(this) val default = DefaultScriptingSupport(this)
val updater = ScriptClassRootsUpdater(project, this) { builder -> val updater = object : ScriptClassRootsUpdater(project, this) {
default.collectConfigurations(builder) override fun gatherRoots(builder: ScriptClassRootsBuilder) {
plugins.forEach { it.collectConfigurations(builder) } default.collectConfigurations(builder)
plugins.forEach { it.collectConfigurations(builder) }
}
override fun afterUpdate() {
plugins.forEach { it.afterUpdate() }
}
} }
fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? { fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? {
@@ -35,6 +35,7 @@ interface ScriptingSupport {
fun isApplicable(file: VirtualFile): Boolean fun isApplicable(file: VirtualFile): Boolean
fun isConfigurationLoadingInProgress(file: KtFile): Boolean fun isConfigurationLoadingInProgress(file: KtFile): Boolean
fun collectConfigurations(builder: ScriptClassRootsBuilder) fun collectConfigurations(builder: ScriptClassRootsBuilder)
fun afterUpdate()
companion object { companion object {
val EPN: ExtensionPointName<ScriptingSupport> = val EPN: ExtensionPointName<ScriptingSupport> =
@@ -47,16 +47,19 @@ import java.util.concurrent.atomic.AtomicReference
* This will start indexing. * This will start indexing.
* Also analysis cache will be cleared and changed opened script files will be reanalyzed. * Also analysis cache will be cleared and changed opened script files will be reanalyzed.
*/ */
class ScriptClassRootsUpdater( abstract class ScriptClassRootsUpdater(
val project: Project, val project: Project,
val manager: CompositeScriptConfigurationManager, val manager: CompositeScriptConfigurationManager
private val gatherRoots: (ScriptClassRootsBuilder) -> Unit
) { ) {
private var lastSeen: ScriptClassRootsCache? = null 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()
abstract fun gatherRoots(builder: ScriptClassRootsBuilder)
abstract fun afterUpdate()
private fun recreateRootsCache(): ScriptClassRootsCache { private fun recreateRootsCache(): ScriptClassRootsCache {
val builder = ScriptClassRootsBuilder(project) val builder = ScriptClassRootsBuilder(project)
gatherRoots(builder) gatherRoots(builder)
@@ -68,6 +71,11 @@ class ScriptClassRootsUpdater(
*/ */
private val cache: AtomicReference<ScriptClassRootsCache> = AtomicReference(recreateRootsCache()) private val cache: AtomicReference<ScriptClassRootsCache> = AtomicReference(recreateRootsCache())
init {
@Suppress("LeakingThis")
afterUpdate()
}
val classpathRoots: ScriptClassRootsCache val classpathRoots: ScriptClassRootsCache
get() = cache.get() get() = cache.get()
@@ -196,6 +204,7 @@ class ScriptClassRootsUpdater(
val old = cache.get() val old = cache.get()
val new = recreateRootsCache() val new = recreateRootsCache()
if (cache.compareAndSet(old, new)) { if (cache.compareAndSet(old, new)) {
afterUpdate()
return new.diff(lastSeen) return new.diff(lastSeen)
} }
} }
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
import java.io.File 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). * [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( sealed class GradleBuildRoot(
private val lastModifiedFiles: LastModifiedFiles private val lastModifiedFiles: LastModifiedFiles
) { ) {
@Volatile enum class ImportingStatus {
var importing = false importing, updatingCaches, updated
}
val importing = AtomicReference(ImportingStatus.updated)
abstract val pathPrefix: String abstract val pathPrefix: String
@@ -86,7 +86,7 @@ abstract class GradleBuildRootsLocator {
isImported -> NotificationKind.dontCare isImported -> NotificationKind.dontCare
standalone -> NotificationKind.standalone standalone -> NotificationKind.standalone
nearest == null -> NotificationKind.outsideAnything nearest == null -> NotificationKind.outsideAnything
nearest.importing -> NotificationKind.dontCare importing -> NotificationKind.dontCare
else -> when (nearest) { else -> when (nearest) {
is Legacy -> NotificationKind.dontCare is Legacy -> NotificationKind.dontCare
is New -> NotificationKind.wasNotImportedAfterCreation 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 private val isImported: Boolean
get() = script != null get() = script != null
@@ -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.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
import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRoot.ImportingStatus.*
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
@@ -88,8 +89,8 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
} }
override fun isConfigurationLoadingInProgress(file: KtFile): Boolean { override fun isConfigurationLoadingInProgress(file: KtFile): Boolean {
return when (val root = findScriptBuildRoot(file.originalFile.virtualFile)?.root) { return when (val root = findScriptBuildRoot(file.originalFile.virtualFile)?.nearest) {
is GradleBuildRoot -> root.importing is GradleBuildRoot -> root.importing.get() != updated
else -> false 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? = override fun getScriptInfo(localPath: String): GradleScriptInfo? =
@@ -126,7 +135,7 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
} }
fun markImportingInProgress(workingDir: String, inProgress: Boolean = true) { fun markImportingInProgress(workingDir: String, inProgress: Boolean = true) {
actualizeBuildRoot(workingDir)?.importing = inProgress actualizeBuildRoot(workingDir)?.importing?.set(if (inProgress) importing else updated)
updateNotifications { it.startsWith(workingDir) } updateNotifications { it.startsWith(workingDir) }
} }
@@ -137,10 +146,10 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
if (root is Imported && root.data.models.isEmpty()) return if (root is Imported && root.data.models.isEmpty()) return
} }
try { val oldRoot = actualizeBuildRoot(sync.workingDir) ?: return
val oldRoot = actualizeBuildRoot(sync.workingDir) ?: return oldRoot.importing.set(updatingCaches)
oldRoot.importing = false
try {
if (oldRoot is Legacy) return if (oldRoot is Legacy) return
val templateClasspath = GradleScriptDefinitionsContributor.getDefinitionsTemplateClasspath(project) val templateClasspath = GradleScriptDefinitionsContributor.getDefinitionsTemplateClasspath(project)
@@ -153,8 +162,9 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
newRoot.saveLastModifiedFiles() newRoot.saveLastModifiedFiles()
add(newRoot) add(newRoot)
} finally { } catch (e: Throwable) {
updateNotifications { it.startsWith(sync.workingDir) } markImportingInProgress(sync.workingDir, false)
throw e
} }
} }