diff --git a/CHANGELOG.md b/CHANGELOG.md index cbb94bb35..5eb6c4905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added * Add sections to breadcrumbs +* Improve performance when starting a run configuration and when using autocompletion directly after starting the IDE * Change order in structure view to match source file and sectioning level * Add command redefinitions to command definition filter in structure view * Add support for automatic language injection on the minted environment diff --git a/src/nl/hannahsten/texifyidea/index/file/LatexExternalPackageInclusionCache.kt b/src/nl/hannahsten/texifyidea/index/file/LatexExternalPackageInclusionCache.kt index e691989b3..693ba49cd 100644 --- a/src/nl/hannahsten/texifyidea/index/file/LatexExternalPackageInclusionCache.kt +++ b/src/nl/hannahsten/texifyidea/index/file/LatexExternalPackageInclusionCache.kt @@ -1,5 +1,7 @@ package nl.hannahsten.texifyidea.index.file +import com.intellij.openapi.application.runInEdt +import com.intellij.openapi.application.runReadAction import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope @@ -8,6 +10,8 @@ import com.jetbrains.rd.util.concurrentMapOf import nl.hannahsten.texifyidea.algorithm.DFS import nl.hannahsten.texifyidea.lang.LatexPackage import nl.hannahsten.texifyidea.util.files.removeFileExtension +import nl.hannahsten.texifyidea.util.runInBackground +import java.util.concurrent.atomic.AtomicBoolean /** * Compute and cache for each package style file all the other style files it includes (directly or indirectly). @@ -18,11 +22,13 @@ object LatexExternalPackageInclusionCache { private val cache = concurrentMapOf>() + private var isFillingCache = AtomicBoolean(false) + /** * Map every LaTeX package style file to all the style files it includes, directly or indirectly. */ @Synchronized - fun getAllPackageInclusions(project: Project): Map> { + fun updateOrGetCache(project: Project): Map> { if (cache.isNotEmpty() || DumbService.isDumb(project)) return cache // Make sure the index is ready (#3754) @@ -31,20 +37,34 @@ object LatexExternalPackageInclusionCache { val directChildren = mutableMapOf>() // Get direct children from the index - FileBasedIndex.getInstance().getAllKeys(LatexExternalPackageInclusionIndex.Cache.id, project).forEach { indexKey -> - FileBasedIndex.getInstance().processValues( - LatexExternalPackageInclusionIndex.Cache.id, indexKey, null, { file, _ -> - val key = LatexPackage(file.name.removeFileExtension()) - directChildren[key] = directChildren.getOrDefault(key, mutableSetOf()).also { it.add(LatexPackage((indexKey))) } - true - }, - GlobalSearchScope.everythingScope(project) - ) - } + if (isFillingCache.getAndSet(true)) return cache + // ??? + runInEdt { + runInBackground(project, "Retrieving LaTeX package inclusions...") { indicator -> + try { + runReadAction { FileBasedIndex.getInstance().getAllKeys(LatexExternalPackageInclusionIndex.Cache.id, project) }.forEach { indexKey -> + runReadAction { + FileBasedIndex.getInstance().processValues( + LatexExternalPackageInclusionIndex.Cache.id, indexKey, null, { file, _ -> + indicator.checkCanceled() + val key = LatexPackage(file.name.removeFileExtension()) + directChildren[key] = directChildren.getOrDefault(key, mutableSetOf()).also { it.add(LatexPackage((indexKey))) } + true + }, + GlobalSearchScope.everythingScope(project) + ) + } + } - // Do some DFS for indirect inclusions - for (latexPackage in directChildren.keys) { - cache[latexPackage] = DFS(latexPackage) { parent -> directChildren[parent] ?: emptySet() }.execute() + // Do some DFS for indirect inclusions + for (latexPackage in directChildren.keys) { + cache[latexPackage] = DFS(latexPackage) { parent -> directChildren[parent] ?: emptySet() }.execute() + } + } + finally { + isFillingCache.set(false) + } + } } return cache @@ -55,7 +75,7 @@ object LatexExternalPackageInclusionCache { */ fun getAllIndirectlyIncludedPackages(packages: Collection, project: Project): Set { val result = packages.toMutableSet() - val allInclusions = getAllPackageInclusions(project) + val allInclusions = updateOrGetCache(project) for (latexPackage in packages) { result.addAll(allInclusions[latexPackage] ?: emptySet()) } diff --git a/src/nl/hannahsten/texifyidea/run/compiler/LatexCompiler.kt b/src/nl/hannahsten/texifyidea/run/compiler/LatexCompiler.kt index 02de9d144..942a12a21 100644 --- a/src/nl/hannahsten/texifyidea/run/compiler/LatexCompiler.kt +++ b/src/nl/hannahsten/texifyidea/run/compiler/LatexCompiler.kt @@ -287,9 +287,9 @@ enum class LatexCompiler(private val displayName: String, val executableName: St */ fun getCommand(runConfig: LatexRunConfiguration, project: Project): List? { val rootManager = ProjectRootManager.getInstance(project) - val fileIndex = rootManager.fileIndex val mainFile = runConfig.mainFile ?: return null - val moduleRoot = fileIndex.getContentRootForFile(mainFile) + // Getting the content root is an expensive operation (See WorkspaceFileIndexDataImpl#ensureIsUpToDate), and since it probably won't change often we reuse a cached value + val moduleRoot = runConfig.outputPath.contentRoot // For now we disable module roots with Docker // Could be improved by mounting them to the right directory val moduleRoots = if (runConfig.getLatexDistributionType().isDocker()) { diff --git a/src/nl/hannahsten/texifyidea/util/General.kt b/src/nl/hannahsten/texifyidea/util/General.kt index d5db28d6b..15f3ed4c5 100644 --- a/src/nl/hannahsten/texifyidea/util/General.kt +++ b/src/nl/hannahsten/texifyidea/util/General.kt @@ -88,3 +88,9 @@ fun runInBackground(project: Project?, description: String, function: (indicator } }) } + +fun runInBackgroundWithoutProgress(function: () -> Unit) { + ApplicationManager.getApplication().invokeLater { + function() + } +}