From df12b53953fa34d279ab22db79396fcfa69cbb54 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 24 Mar 2024 09:01:46 +0100 Subject: [PATCH] IJPL-846 remove virtual file preloading (quite questionable) and instead, compute document in a separate coroutine GitOrigin-RevId: 491dc693a58478d916a819057d4e7fc7e98bb5f0 --- .../fileEditor/impl/EditorsSplitters.kt | 71 ++++++++++--------- .../fileEditor/impl/FileEditorManagerImpl.kt | 52 ++++++++------ 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.kt b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.kt index efbd70840937..e427637ebfa8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.kt +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.kt @@ -18,6 +18,7 @@ import com.intellij.openapi.client.ClientSessionsManager import com.intellij.openapi.components.serviceAsync import com.intellij.openapi.components.serviceOrNull import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.colors.CodeInsightColors import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.editor.markup.TextAttributes @@ -29,7 +30,6 @@ import com.intellij.openapi.fileEditor.impl.text.FileDropHandler import com.intellij.openapi.keymap.Keymap import com.intellij.openapi.keymap.KeymapManagerListener import com.intellij.openapi.keymap.KeymapUtil -import com.intellij.openapi.progress.blockingContext import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Divider import com.intellij.openapi.ui.OnePixelDivider @@ -913,7 +913,7 @@ private class UiBuilder(private val splitters: EditorsSplitters) { } val fileEditorManager = splitters.manager - val fileDocumentManager = serviceAsync() + var fileDocumentManager: FileDocumentManager? = null val fileEditorProviderManager = serviceAsync() fun weight(item: FileEntry) = (if (item.currentInTab) 1 else 0) @@ -930,27 +930,34 @@ private class UiBuilder(private val splitters: EditorsSplitters) { span("opening editor") { val file = resolveFileOrLogError(virtualFileManager, fileEntry) ?: return@span file.putUserData(AsyncEditorLoader.OPENED_IN_BULK, true) - // preload filetype - splitters.coroutineScope.launch { - blockingContext { - file.fileType - } - } - - if (isFirstInBulk) { - // Add the selected tab to EditorTabs without waiting for the other tabs to load on startup. - // This enables painting the first editor as soon as it's ready (IJPL-687). - file.putUserData(AsyncEditorLoader.FIRST_IN_BULK, true) - isFirstInBulk = false - } try { - openFile(file = file, - fileEntry = fileEntry, - fileEditorProviderManager = fileEditorProviderManager, - fileEditorManager = fileEditorManager, - fileDocumentManager = fileDocumentManager, - windowDeferred = windowDeferred, - index = index) + if (isFirstInBulk) { + // Add the selected tab to EditorTabs without waiting for the other tabs to load on startup. + // This enables painting the first editor as soon as it's ready (IJPL-687). + file.putUserData(AsyncEditorLoader.FIRST_IN_BULK, true) + isFirstInBulk = false + } + + val document = async { + var m = fileDocumentManager + if (m == null) { + m = serviceAsync() + fileDocumentManager = m + } + readAction { + m.getDocument(file) + } + } + + openFile( + file = file, + fileEntry = fileEntry, + fileEditorProviderManager = fileEditorProviderManager, + fileEditorManager = fileEditorManager, + document = document, + windowDeferred = windowDeferred, + index = index, + ) if (fileEntry.currentInTab) { focusedFile = file } @@ -990,13 +997,15 @@ private fun resolveFileOrLogError(virtualFileManager: VirtualFileManager, fileEn return null } -private suspend fun openFile(file: VirtualFile, - fileEntry: FileEntry, - fileEditorProviderManager: FileEditorProviderManager, - fileEditorManager: FileEditorManagerImpl, - fileDocumentManager: FileDocumentManager, - windowDeferred: Deferred, - index: Int) { +private suspend fun openFile( + file: VirtualFile, + fileEntry: FileEntry, + fileEditorProviderManager: FileEditorProviderManager, + fileEditorManager: FileEditorManagerImpl, + document: Deferred, + windowDeferred: Deferred, + index: Int, +) { coroutineScope { val deferredProviders: Deferred> = if (fileEntry.ideFingerprint == ideFingerprint()) { async(CoroutineName("editor provider resolving")) { @@ -1039,10 +1048,6 @@ private suspend fun openFile(file: VirtualFile, } } - val document = readAction { - fileDocumentManager.getDocument(file) - } - val session = fileEditorManager.project.serviceAsync>().getSession(ClientId.current) val options = FileEditorOpenOptions( selectAsCurrent = false, diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.kt index 61db306e9ba8..3a9d63a7bbda 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.kt @@ -2101,12 +2101,14 @@ open class FileEditorManagerImpl( } } - internal suspend fun openFileOnStartup(windowDeferred: Deferred, - file: VirtualFile, - document: Document?, - fileEditorStateProvider: FileEditorStateProvider, - options: FileEditorOpenOptions, - providers: List) { + internal suspend fun openFileOnStartup( + windowDeferred: Deferred, + file: VirtualFile, + document: Deferred, + fileEditorStateProvider: FileEditorStateProvider, + options: FileEditorOpenOptions, + providers: List, + ) { if (!canOpenFile(file = file, providers = providers)) { return } @@ -2114,17 +2116,19 @@ open class FileEditorManagerImpl( // the file is not opened yet - in this case we have to create editors and select the created EditorComposite coroutineScope { val providerWithBuilderList = async { - createBuilders(providers = providers, file = file, project = project, document = document) + createBuilders(providers = providers, file = file, project = project, document = document.await()) } val window = windowDeferred.await() val existingComposite = withContext(Dispatchers.EDT) { window.getComposite(file) } - openFileInEdt(existingComposite = existingComposite, - window = window, - file = file, - fileEditorStateProvider = fileEditorStateProvider, - options = options, - providerWithBuilderList = providerWithBuilderList.await()) + openFileInEdt( + existingComposite = existingComposite, + window = window, + file = file, + fileEditorStateProvider = fileEditorStateProvider, + options = options, + providerWithBuilderList = providerWithBuilderList.await(), + ) } } @@ -2178,11 +2182,13 @@ open class FileEditorManagerImpl( } else { for (editorWithProvider in composite.allEditorsWithProviders) { - restoreEditorState(file = file, - editorWithProvider = editorWithProvider, - storedState = fileEditorStateProvider?.getState(editorWithProvider.provider), - isNewEditor = isNewEditor, - exactState = options.isExactState) + restoreEditorState( + file = file, + editorWithProvider = editorWithProvider, + storedState = fileEditorStateProvider?.getState(editorWithProvider.provider), + isNewEditor = isNewEditor, + exactState = options.isExactState, + ) } openInEdtImpl( @@ -2389,10 +2395,12 @@ private fun getEffectiveOptions(options: FileEditorOpenOptions, entry: HistoryEn return options } -private suspend fun createBuilders(providers: List, - file: VirtualFile, - project: Project, - document: Document?): List> { +private suspend fun createBuilders( + providers: List, + file: VirtualFile, + project: Project, + document: Document?, +): List> { return coroutineScope { providers.map { provider -> async {