From 89f6f95f38985f63accf32ae59730340a3195a7c Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 20 Jul 2020 08:31:33 +0200 Subject: [PATCH] IDEA-246164 `Loading components` takes lots of time, sometimes hangs forever GitOrigin-RevId: 63ba3f31f512878d96ffa2fe9fce510fb53a0099 --- .../src/HeadlessSaveAndSyncHandler.kt | 6 +---- .../src/ProjectStoreBase.kt | 5 +--- .../src/SaveAndSyncHandlerImpl.kt | 17 +++++++++---- .../messages/CommonBundle.properties | 4 ++++ .../com/intellij/ide/SaveAndSyncHandler.kt | 6 +---- .../intellij/configurationStore/storeUtil.kt | 24 +++++++++---------- .../project/impl/ProjectFrameAllocator.kt | 17 +++++++++++-- .../project/impl/ProjectManagerExImpl.kt | 2 +- 8 files changed, 46 insertions(+), 35 deletions(-) diff --git a/platform/configuration-store-impl/src/HeadlessSaveAndSyncHandler.kt b/platform/configuration-store-impl/src/HeadlessSaveAndSyncHandler.kt index cae8857f9326..89928c03be93 100644 --- a/platform/configuration-store-impl/src/HeadlessSaveAndSyncHandler.kt +++ b/platform/configuration-store-impl/src/HeadlessSaveAndSyncHandler.kt @@ -1,7 +1,6 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.configurationStore -import com.intellij.openapi.application.AccessToken import com.intellij.openapi.components.ComponentManager /** @@ -22,8 +21,5 @@ internal class HeadlessSaveAndSyncHandler : BaseSaveAndSyncHandler() { override fun unblockSyncOnFrameActivation() {} - override fun saveSettingsUnderModalProgress(componentManager: ComponentManager): Boolean { - StoreUtil.saveSettings(componentManager, forceSavingAllSettings = true) - return true - } + override fun saveSettingsUnderModalProgress(componentManager: ComponentManager) = true } diff --git a/platform/configuration-store-impl/src/ProjectStoreBase.kt b/platform/configuration-store-impl/src/ProjectStoreBase.kt index b78608499ce8..74b8fb7d2024 100644 --- a/platform/configuration-store-impl/src/ProjectStoreBase.kt +++ b/platform/configuration-store-impl/src/ProjectStoreBase.kt @@ -22,7 +22,6 @@ import com.intellij.util.io.exists import com.intellij.util.io.systemIndependentPath import com.intellij.util.messages.MessageBus import com.intellij.util.text.nullize -import kotlinx.coroutines.runBlocking import java.nio.file.Path import java.util.* import kotlin.collections.ArrayList @@ -60,9 +59,7 @@ abstract class ProjectStoreBase(final override val project: Project) : Component final override fun clearStorages() = storageManager.clearStorages() private fun loadProjectFromTemplate(defaultProject: Project) { - val stateStore = defaultProject.stateStore as DefaultProjectStoreImpl - runBlocking { stateStore.save() } - val element = stateStore.getStateCopy() ?: return + val element = (defaultProject.stateStore as DefaultProjectStoreImpl).getStateCopy() ?: return LOG.runAndLogException { val dotIdea = dotIdea if (dotIdea != null) { diff --git a/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt b/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt index 4ca1611cbbb5..969bc263e45a 100644 --- a/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt +++ b/platform/configuration-store-impl/src/SaveAndSyncHandlerImpl.kt @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.configurationStore +import com.intellij.CommonBundle import com.intellij.conversion.ConversionService import com.intellij.ide.FrameStateListener import com.intellij.ide.GeneralSettings @@ -173,10 +174,6 @@ internal class SaveAndSyncHandlerImpl : BaseSaveAndSyncHandler(), Disposable { } } - override fun cancelScheduledSave() { - saveAlarm.cancel() - } - private fun waitForScheduledSave() { if (saveAlarm.isEmpty) { return @@ -212,7 +209,8 @@ internal class SaveAndSyncHandlerImpl : BaseSaveAndSyncHandler(), Disposable { runInAutoSaveDisabledMode { edtPoolDispatcherManager.processTasks() - ProgressManager.getInstance().run(object : Task.Modal(componentManager as? Project, "Saving " + (if (componentManager is Application) "Application" else "Project"), /* canBeCancelled = */ false) { + val project = (componentManager as? Project)?.takeIf { !it.isDefault } + ProgressManager.getInstance().run(object : Task.Modal(project, getProgressTitle(componentManager), /* canBeCancelled = */ false) { override fun run(indicator: ProgressIndicator) { indicator.isIndeterminate = true @@ -301,6 +299,7 @@ internal class SaveAndSyncHandlerImpl : BaseSaveAndSyncHandler(), Disposable { override fun blockSaveOnFrameDeactivation() { LOG.debug("save blocked") + saveAlarm.cancel() blockSaveOnFrameDeactivationCount.incrementAndGet() } @@ -324,4 +323,12 @@ private val saveAppAndProjectsSettingsTask = SaveAndSyncHandler.SaveTask(saveDoc internal abstract class BaseSaveAndSyncHandler : SaveAndSyncHandler() { internal val edtPoolDispatcherManager = EdtPoolDispatcherManager() +} + +private fun getProgressTitle(componentManager: ComponentManager): String { + return when { + componentManager is Application -> CommonBundle.message("title.save.app") + (componentManager as Project).isDefault -> CommonBundle.message("title.save.default.project") + else -> CommonBundle.message("title.save.project") + } } \ No newline at end of file diff --git a/platform/platform-api/resources/messages/CommonBundle.properties b/platform/platform-api/resources/messages/CommonBundle.properties index 267fb3d541e7..458d272f1239 100644 --- a/platform/platform-api/resources/messages/CommonBundle.properties +++ b/platform/platform-api/resources/messages/CommonBundle.properties @@ -100,3 +100,7 @@ title.input=Input title.name=Name title.confirmation=Confirmation title.console=Console + +title.save.app=Saving Application +title.save.project=Saving Project +title.save.default.project=Saving Default Project \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.kt b/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.kt index 0df2e909aabb..f7cc20f42fce 100644 --- a/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.kt +++ b/platform/platform-api/src/com/intellij/ide/SaveAndSyncHandler.kt @@ -72,11 +72,7 @@ abstract class SaveAndSyncHandler { open fun maybeRefresh(modalityState: ModalityState) { } - @ApiStatus.Experimental - open fun cancelScheduledSave() { - } - - @ApiStatus.Experimental + @ApiStatus.Internal abstract fun saveSettingsUnderModalProgress(componentManager: ComponentManager): Boolean /** diff --git a/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt b/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt index 2c6cfea9d354..f454885898c1 100644 --- a/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt +++ b/platform/platform-impl/src/com/intellij/configurationStore/storeUtil.kt @@ -9,7 +9,6 @@ import com.intellij.ide.plugins.PluginUtil import com.intellij.notification.Notification import com.intellij.notification.NotificationGroup import com.intellij.notification.NotificationType -import com.intellij.openapi.application.Application import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationNamesInfo import com.intellij.openapi.application.TransactionGuardImpl @@ -21,7 +20,7 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.project.Project import com.intellij.openapi.project.processOpenedProjects -import com.intellij.openapi.util.text.StringUtil +import com.intellij.util.ExceptionUtil import kotlinx.coroutines.runBlocking import org.jetbrains.annotations.CalledInAny import org.jetbrains.annotations.CalledInAwt @@ -41,11 +40,10 @@ class StoreUtil private constructor() { @JvmStatic @CalledInAny fun saveSettings(componentManager: ComponentManager, forceSavingAllSettings: Boolean = false) { - if (componentManager is Application) { - SaveAndSyncHandler.getInstance().cancelScheduledSave() - } - runBlocking { - com.intellij.configurationStore.saveSettings(componentManager, forceSavingAllSettings) + runInAutoSaveDisabledMode { + runBlocking { + com.intellij.configurationStore.saveSettings(componentManager, forceSavingAllSettings) + } } } @@ -69,11 +67,11 @@ class StoreUtil private constructor() { @CalledInAwt @JvmStatic fun saveDocumentsAndProjectsAndApp(forceSavingAllSettings: Boolean) { - SaveAndSyncHandler.getInstance().cancelScheduledSave() - - FileDocumentManager.getInstance().saveAllDocuments() - runBlocking { - saveProjectsAndApp(forceSavingAllSettings) + runInAutoSaveDisabledMode { + FileDocumentManager.getInstance().saveAllDocuments() + runBlocking { + saveProjectsAndApp(forceSavingAllSettings) + } } } } @@ -101,7 +99,7 @@ suspend fun saveSettings(componentManager: ComponentManager, forceSavingAllSetti } val messagePostfix = IdeBundle.message("notification.content.please.restart.0", ApplicationNamesInfo.getInstance().fullProductName, - (if (ApplicationManager.getApplication().isInternal) "

" + StringUtil.getThrowableText(e) + "

" else "")) + (if (ApplicationManager.getApplication().isInternal) "

" + ExceptionUtil.getThrowableText(e) + "

" else "")) val pluginId = PluginUtil.getInstance().findPluginId(e) val groupId = NotificationGroup.createIdWithTitle("Settings Error", IdeBundle.message("notification.group.settings.error")) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectFrameAllocator.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectFrameAllocator.kt index fabffcc7d88b..83e17915487f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectFrameAllocator.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectFrameAllocator.kt @@ -1,12 +1,14 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.project.impl +import com.intellij.configurationStore.saveSettings import com.intellij.conversion.CannotConvertException import com.intellij.diagnostic.PluginException import com.intellij.diagnostic.runActivity import com.intellij.diagnostic.runMainActivity import com.intellij.ide.RecentProjectsManager import com.intellij.ide.RecentProjectsManagerBase +import com.intellij.ide.SaveAndSyncHandler import com.intellij.ide.impl.OpenProjectTask import com.intellij.ide.plugins.StartupAbortedException import com.intellij.idea.SplashManager @@ -17,6 +19,7 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task import com.intellij.openapi.progress.impl.CoreProgressManager import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.wm.WindowManager @@ -27,6 +30,7 @@ import com.intellij.ui.ComponentUtil import com.intellij.ui.IdeUICustomization import com.intellij.ui.ScreenUtil import com.intellij.ui.scale.ScaleContext +import kotlinx.coroutines.runBlocking import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.CalledInAwt import java.awt.Dimension @@ -36,8 +40,13 @@ import java.io.EOFException import java.nio.file.Path import kotlin.math.min -internal open class ProjectFrameAllocator { +internal open class ProjectFrameAllocator(private val options: OpenProjectTask) { open fun run(task: () -> T?): T? { + if (options.isNewProject && options.useDefaultProjectAsTemplate && options.project == null) { + runBlocking { + saveSettings(ProjectManager.getInstance().defaultProject, forceSavingAllSettings = true) + } + } return task() } @@ -53,7 +62,7 @@ internal open class ProjectFrameAllocator { open fun projectOpened(project: Project) {} } -internal class ProjectUiFrameAllocator(private var options: OpenProjectTask, private val projectStoreBaseDir: Path) : ProjectFrameAllocator() { +internal class ProjectUiFrameAllocator(private var options: OpenProjectTask, private val projectStoreBaseDir: Path) : ProjectFrameAllocator(options) { // volatile not required because created in run (before executing run task) private var frameHelper: ProjectFrameHelper? = null @@ -66,6 +75,10 @@ internal class ProjectUiFrameAllocator(private var options: OpenProjectTask, pri var result: T? = null val progressTitle = getProgressTitle() ApplicationManager.getApplication().invokeAndWait { + if (options.isNewProject && options.useDefaultProjectAsTemplate && options.project == null) { + SaveAndSyncHandler.getInstance().saveSettingsUnderModalProgress(ProjectManager.getInstance().defaultProject) + } + val frame = createFrameIfNeeded() val progressTask = object : Task.Modal(null, progressTitle, true) { override fun run(indicator: ProgressIndicator) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt index 4bcfc071403b..260b29ec9c5d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt @@ -92,7 +92,7 @@ open class ProjectManagerExImpl : ProjectManagerImpl() { } } - val frameAllocator = if (app.isHeadlessEnvironment) ProjectFrameAllocator() else ProjectUiFrameAllocator(options, projectStoreBaseDir) + val frameAllocator = if (app.isHeadlessEnvironment) ProjectFrameAllocator(options) else ProjectUiFrameAllocator(options, projectStoreBaseDir) val result = runInAutoSaveDisabledMode { frameAllocator.run { activity.end()