From b5e04378ed240280431b59228b8e539d230a09c0 Mon Sep 17 00:00:00 2001 From: Sergey Rostov Date: Fri, 17 Jul 2020 11:11:12 +0300 Subject: [PATCH] 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 --- .../script/ucache/ScriptClassRootsBuilder.kt | 2 +- .../script/ucache/ScriptClassRootsCache.kt | 11 +++++-- .../script/ucache/ScriptClassRootsUpdater.kt | 7 ++--- .../idea/core/script/ucache/ScriptSdks.kt | 30 ++++--------------- .../core/script/ucache/ScriptSdksBuilder.kt | 26 +++++++++++++++- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsBuilder.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsBuilder.kt index a37d7bc3bf9..29aa3e0b556 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsBuilder.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsBuilder.kt @@ -22,7 +22,7 @@ class ScriptClassRootsBuilder( fun build(): ScriptClassRootsCache = ScriptClassRootsCache( - project, scripts, classes, sources, + scripts, classes, sources, customDefinitionsUsed, sdks.build() ) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsCache.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsCache.kt index b61eed18620..1ecc912fe3e 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsCache.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptClassRootsCache.kt @@ -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, private val classes: Set, private val sources: Set, 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 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 1a6b0030faf..f1aa7abcaf4 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 @@ -68,11 +68,10 @@ abstract class ScriptClassRootsUpdater( /** * Wee need CAS due to concurrent unblocking sync update in [checkInvalidSdks] */ - private val cache: AtomicReference = AtomicReference(recreateRootsCache()) + private val cache: AtomicReference = 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)) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdks.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdks.kt index f2f7b240403..62a79e37574 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdks.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdks.kt @@ -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) { - fun rebuild(remove: Sdk?): ScriptSdks { +class ScriptSdks( + private val sdks: Map, + val nonIndexedClassRoots: Set, + val nonIndexedSourceRoots: Set +) { + 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) { return builder.build() } - val nonIndexedClassRoots = mutableSetOf() - val nonIndexedSourceRoots = mutableSetOf() - 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 diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdksBuilder.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdksBuilder.kt index e92d82b60e1..8bd232186ed 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdksBuilder.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ucache/ScriptSdksBuilder.kt @@ -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() + val nonIndexedSourceRoots = mutableSetOf() + + 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) {