scripting ucache: update synchronously in unit test mode

This commit is contained in:
Sergey Rostov
2020-05-09 12:39:50 +03:00
parent ac70234342
commit 14bd6fe781
3 changed files with 25 additions and 8 deletions
@@ -96,7 +96,7 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
default.updateScriptDefinitionsReferences()
if (classpathRoots.customDefinitionsUsed) {
updater.ensureUpdateScheduled()
updater.invalidateAndCommit()
}
}
@@ -34,12 +34,22 @@ import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
/**
* Utility for postponing indexing of new roots to the end of some bulk operation.
* Holder for [ScriptClassRootsCache].
*
* Updates of [classpathRoots] performed asynchronously using the copy-on-write strategy.
* [gatherRoots] called when updating is required. Cache will built from the scratch.
*
* Updates can be coalesced by using `update { invalidate() }` transaction.
* As an alternative you can just call [invalidateAndCommit].
*
* After update roots changed event will be triggered if there are new root.
* This will start indexing.
* Also analysis cache will be cleared and changed opened script files will be reanalyzed.
*/
class ScriptClassRootsUpdater(
val project: Project,
val manager: CompositeScriptConfigurationManager,
private val buildNewRoots: (ScriptClassRootsBuilder) -> Unit
private val gatherRoots: (ScriptClassRootsBuilder) -> Unit
) {
private var lastSeen: ScriptClassRootsCache? = null
private var invalidated: Boolean = false
@@ -48,10 +58,11 @@ class ScriptClassRootsUpdater(
private fun recreateRootsCache(): ScriptClassRootsCache {
val builder = ScriptClassRootsBuilder(project)
buildNewRoots(builder)
gatherRoots(builder)
return builder.build()
}
@Volatile
var classpathRoots: ScriptClassRootsCache = recreateRootsCache()
private set
@@ -77,6 +88,10 @@ class ScriptClassRootsUpdater(
}
}
fun invalidateAndCommit() {
update { invalidate() }
}
fun checkInTransaction() {
check(concurrentUpdates.get() > 0)
}
@@ -119,7 +134,7 @@ class ScriptClassRootsUpdater(
private var scheduledUpdate: ProgressIndicator? = null
@Synchronized
fun ensureUpdateScheduled() {
private fun ensureUpdateScheduled() {
scheduledUpdate?.cancel()
runReadAction {
if (project.isDisposed && !Disposer.isDisposing(project)) {
@@ -136,12 +151,14 @@ class ScriptClassRootsUpdater(
doUpdate(false)
}
fun checkInvalidSdks(remove: Sdk? = null) {
internal fun checkInvalidSdks(remove: Sdk? = null) {
// sdks should be updated synchronously to avoid disposed roots usage
syncLock.withLock {
val current = classpathRoots
val actualSdks = current.sdks.rebuild(remove = remove)
if (actualSdks != current.sdks) {
// don't call invalidateAndCommit as it may be synchronous
// let's update sdks immediately and schedule cache rebuilding
classpathRoots = current.withUpdatedSdks(actualSdks)
ensureUpdateScheduled()
}
@@ -342,7 +342,7 @@ class GradleBuildRootsManager(val project: Project) : ScriptingSupport() {
val old = roots.add(newRoot)
if (old is GradleBuildRoot.Imported) removeData(old.pathPrefix)
if (old is GradleBuildRoot.Imported || newRoot is GradleBuildRoot.Imported) {
updater.ensureUpdateScheduled()
updater.invalidateAndCommit()
}
updateNotifications(newRoot.pathPrefix)
@@ -352,7 +352,7 @@ class GradleBuildRootsManager(val project: Project) : ScriptingSupport() {
val removed = roots.remove(rootPath)
if (removed is GradleBuildRoot.Imported) {
removeData(rootPath)
updater.ensureUpdateScheduled()
updater.invalidateAndCommit()
}
updateNotifications(rootPath)