scripting, ucache: don't init caches at start up

init it in async instead. all usages will be updated thanks to
highlighting/reindexing that is called after cache is constructed.

#KT-40242 Fixed
This commit is contained in:
Sergey Rostov
2020-07-17 11:11:12 +03:00
committed by Vladimir Dolzhenko
parent 43fcb2330e
commit b5e04378ed
5 changed files with 43 additions and 33 deletions
@@ -22,7 +22,7 @@ class ScriptClassRootsBuilder(
fun build(): ScriptClassRootsCache =
ScriptClassRootsCache(
project, scripts, classes, sources,
scripts, classes, sources,
customDefinitionsUsed, sdks.build()
)
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.vfs.VirtualFile
@@ -20,15 +19,21 @@ import java.lang.ref.Reference
import java.lang.ref.SoftReference
class ScriptClassRootsCache(
val project: Project,
private val scripts: Map<String, LightScriptInfo>,
private val classes: Set<String>,
private val sources: Set<String>,
val customDefinitionsUsed: Boolean,
val sdks: ScriptSdks
) {
companion object {
val EMPTY = ScriptClassRootsCache(
mapOf(), setOf(), setOf(), true,
ScriptSdks(mapOf(), setOf(), setOf())
)
}
fun withUpdatedSdks(newSdks: ScriptSdks) =
ScriptClassRootsCache(project, scripts, classes, sources, customDefinitionsUsed, newSdks)
ScriptClassRootsCache(scripts, classes, sources, customDefinitionsUsed, newSdks)
abstract class LightScriptInfo(val definition: ScriptDefinition?) {
@Volatile
@@ -68,11 +68,10 @@ abstract class ScriptClassRootsUpdater(
/**
* Wee need CAS due to concurrent unblocking sync update in [checkInvalidSdks]
*/
private val cache: AtomicReference<ScriptClassRootsCache> = AtomicReference(recreateRootsCache())
private val cache: AtomicReference<ScriptClassRootsCache> = AtomicReference(ScriptClassRootsCache.EMPTY)
init {
@Suppress("LeakingThis")
afterUpdate()
ensureUpdateScheduled()
}
val classpathRoots: ScriptClassRootsCache
@@ -213,7 +212,7 @@ abstract class ScriptClassRootsUpdater(
// sdks should be updated synchronously to avoid disposed roots usage
do {
val old = cache.get()
val actualSdks = old.sdks.rebuild(remove = remove)
val actualSdks = old.sdks.rebuild(project, remove = remove)
if (actualSdks == old.sdks) return
val new = old.withUpdatedSdks(actualSdks)
} while (!cache.compareAndSet(old, new))
@@ -5,16 +5,16 @@
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.util.application.runReadAction
class ScriptSdks(val project: Project, private val sdks: Map<SdkId, Sdk?>) {
fun rebuild(remove: Sdk?): ScriptSdks {
class ScriptSdks(
private val sdks: Map<SdkId, Sdk?>,
val nonIndexedClassRoots: Set<VirtualFile>,
val nonIndexedSourceRoots: Set<VirtualFile>
) {
fun rebuild(project: Project, remove: Sdk?): ScriptSdks {
val builder = ScriptSdksBuilder(project, remove = remove)
sdks.keys.forEach { id ->
builder.addSdk(id)
@@ -22,28 +22,10 @@ class ScriptSdks(val project: Project, private val sdks: Map<SdkId, Sdk?>) {
return builder.build()
}
val nonIndexedClassRoots = mutableSetOf<VirtualFile>()
val nonIndexedSourceRoots = mutableSetOf<VirtualFile>()
val first: Sdk? = sdks.values.firstOrNull()
operator fun get(sdkId: SdkId) = sdks[sdkId]
init {
val nonIndexedSdks = sdks.values.filterNotNullTo(mutableSetOf())
runReadAction {
ModuleManager.getInstance(project).modules.map {
nonIndexedSdks.remove(ModuleRootManager.getInstance(it).sdk)
}
nonIndexedSdks.forEach {
nonIndexedClassRoots.addAll(it.rootProvider.getFiles(OrderRootType.CLASSES))
nonIndexedSourceRoots.addAll(it.rootProvider.getFiles(OrderRootType.SOURCES))
}
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -5,13 +5,18 @@
package org.jetbrains.kotlin.idea.core.script.ucache
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.JavaSdkType
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.caches.project.getAllProjectSdks
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsStorage
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.core.script.scriptingWarnLog
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
import java.io.File
@@ -23,7 +28,26 @@ class ScriptSdksBuilder(
) {
private val defaultSdk by lazy { getScriptDefaultSdk() }
fun build() = ScriptSdks(project, sdks)
fun build(): ScriptSdks {
val nonIndexedClassRoots = mutableSetOf<VirtualFile>()
val nonIndexedSourceRoots = mutableSetOf<VirtualFile>()
val nonIndexedSdks = sdks.values.filterNotNullTo(mutableSetOf())
runReadAction {
for (module in ModuleManager.getInstance(project).modules) {
if (nonIndexedSdks.isEmpty()) break
nonIndexedSdks.remove(ModuleRootManager.getInstance(module).sdk)
}
nonIndexedSdks.forEach {
nonIndexedClassRoots.addAll(it.rootProvider.getFiles(OrderRootType.CLASSES))
nonIndexedSourceRoots.addAll(it.rootProvider.getFiles(OrderRootType.SOURCES))
}
}
return ScriptSdks(sdks, nonIndexedClassRoots, nonIndexedSourceRoots)
}
@Deprecated("Don't use, used only from DefaultScriptingSupport for saving to storage")
fun addAll(other: ScriptSdksBuilder) {