From 9d8ebbf2e380cc6a66487aaecf3c349d45ed2547 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 19 Sep 2011 16:44:45 +0200 Subject: [PATCH] ensure app entered dumb mode before starting post-startup activities (prevent Index-Not-Ready exceptions) --- .../ide/startup/impl/StartupManagerImpl.java | 38 ++++++++++----- .../project/impl/ProjectManagerImpl.java | 48 ++++++++++++------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java index 7cb04bfb2f60..588fa800423f 100644 --- a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java @@ -128,23 +128,39 @@ public class StartupManagerImpl extends StartupManagerEx { }); } - public void runPostStartupActivitiesNew() { + public void runPostStartupActivitiesFromExtensions() { final StartupActivity[] extensions = Extensions.getExtensions(StartupActivity.POST_STARTUP_ACTIVITY); - for (StartupActivity extension : extensions) { + if (extensions.length == 0) { + return; + } + + final List dumbAwareActivities = new ArrayList(); + final List normalActivities = new ArrayList(); + for (final StartupActivity extension : extensions) { + final Runnable runnable = new Runnable() { + public void run() { + extension.runActivity(myProject); + } + }; if (extension instanceof DumbAware) { - extension.runActivity(myProject); + dumbAwareActivities.add(runnable); + } + else { + normalActivities.add(runnable); } } - DumbService.getInstance(myProject).runWhenSmart(new Runnable() { - public void run() { - if (myProject.isDisposed()) return; - for (StartupActivity extension : extensions) { - if (!(extension instanceof DumbAware)) { - extension.runActivity(myProject); + + runActivities(dumbAwareActivities); + + if (!normalActivities.isEmpty()) { + DumbService.getInstance(myProject).runWhenSmart(new Runnable() { + public void run() { + if (!myProject.isDisposed()) { + runActivities(normalActivities); } } - } - }); + }); + } } public synchronized void runPostStartupActivities() { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 6283f8e31b4f..515b5038071b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -61,6 +61,7 @@ import com.intellij.util.containers.HashMap; import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.ui.UIUtil; import gnu.trove.TObjectLongHashMap; import org.jdom.Element; import org.jdom.JDOMException; @@ -384,26 +385,28 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } public boolean openProject(final Project project) { - if (ApplicationManager.getApplication().isUnitTestMode() && project.toString().contains("lighttemp")) { + final Application application = ApplicationManager.getApplication(); + + if (application.isUnitTestMode() && project.toString().contains("lighttemp")) { throw new AssertionError("must not open light project"); } - if (myOpenProjects.contains(project)) return false; - if (!ApplicationManager.getApplication().isUnitTestMode() && !((ProjectEx)project).getStateStore().checkVersion()) return false; + + if (myOpenProjects.contains(project)) { + return false; + } + + if (!application.isUnitTestMode() && !((ProjectEx)project).getStateStore().checkVersion()) { + return false; + } myOpenProjects.add(project); cacheOpenProjects(); - if (ApplicationManager.getApplication().isDispatchThread()) { - fireProjectOpened(project); - } - else { - ApplicationManager.getApplication().invokeAndWait(new Runnable() { - @Override - public void run() { - fireProjectOpened(project); - } - }, ModalityState.defaultModalityState()); - } + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + public void run() { + fireProjectOpened(project); + } + }); final StartupManagerImpl startupManager = (StartupManagerImpl)StartupManager.getInstance(project); @@ -423,6 +426,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ok = true; } catch (Throwable e) { + LOG.info(e); ok = false; } } @@ -433,17 +437,25 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return false; } - startupManager.runPostStartupActivitiesNew(); + // dumb mode should start before post-startup activities + // only when startCacheUpdate is called from UI thread, we can guarantee that + // when the method returns, the application has entered dumb mode + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + public void run() { + startupManager.startCacheUpdate(); + } + }); - ApplicationManager.getApplication().invokeLater(new Runnable() { + startupManager.runPostStartupActivitiesFromExtensions(); + + UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { startupManager.runPostStartupActivities(); } }); - startupManager.startCacheUpdate(); - if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) { + if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) { // should be invoked last StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { public void run() {