From e2520e973f17beabbc8745e12bfde4c9d72b52b3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Sun, 31 Mar 2019 00:22:17 +0300 Subject: [PATCH] update theOnlyProject field after project dispose because otherwise "projectDisposed" listeners from the other project might get the wrong project to fix IDEA-209724 Smart pointer creation during project disposal leads to "Element from alien project" assertion --- .../openapi/project/impl/DefaultProject.java | 2 -- .../project/impl/DefaultProjectTimed.java | 4 ++-- .../openapi/project/impl/ProjectImpl.java | 3 +++ .../project/impl/ProjectManagerImpl.java | 23 +++++++++++-------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java index ea5c77fe982f..64146c8ca963 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java @@ -3,7 +3,6 @@ package com.intellij.openapi.project.impl; import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.ProjectManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,6 +50,5 @@ final class DefaultProject extends ProjectImpl { if (LOG.isDebugEnabled()) { LOG.debug("Disposed DefaultProject "+this); } - ((ProjectManagerImpl)ProjectManager.getInstance()).updateTheOnlyProjectField(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProjectTimed.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProjectTimed.java index b142c117e5e7..06cd563892ba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProjectTimed.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProjectTimed.java @@ -40,7 +40,7 @@ public class DefaultProjectTimed extends TimedReference { @NotNull @Override - public synchronized Project get() { + public Project get() { Project value = super.get(); if (value == null) { value = compute(); @@ -50,7 +50,7 @@ public class DefaultProjectTimed extends TimedReference { } @Override - public synchronized void dispose() { + public void dispose() { // project must be disposed in EDT in write action Runnable doDispose = () -> WriteCommandAction.runWriteCommandAction(null, () -> super.dispose()); if (ApplicationManager.getApplication().isDispatchThread()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 6f953708da07..b8e44c862a89 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -29,6 +29,7 @@ import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.startup.StartupManager; @@ -347,6 +348,8 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project if (!application.isDisposed()) { application.getMessageBus().syncPublisher(ProjectLifecycleListener.TOPIC).afterProjectClosed(this); } + ((ProjectManagerImpl)ProjectManager.getInstance()).updateTheOnlyProjectField(); + TimedReference.disposeTimed(); LaterInvocator.purgeExpiredItems(); } 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 764d5e81deb9..3b52603188be 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 @@ -328,19 +328,23 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { @Override @TestOnly - public synchronized boolean isDefaultProjectInitialized() { - return myDefaultProjectTimed.isCached(); + public boolean isDefaultProjectInitialized() { + synchronized (lock) { + return myDefaultProjectTimed.isCached(); + } } @Override @NotNull - public synchronized Project getDefaultProject() { - LOG.assertTrue(!ApplicationManager.getApplication().isDisposed(), "Default project has been already disposed!"); - Project defaultProject = myDefaultProjectTimed.get(); - // disable "the only project" optimization since we have now more than one project. - // (even though the default project is not a real project, it can be used indirectly in e.g. "Settings|Code Style" code fragments PSI) - updateTheOnlyProjectField(); - return defaultProject; + public Project getDefaultProject() { + synchronized (lock) { + LOG.assertTrue(!ApplicationManager.getApplication().isDisposed(), "Default project has been already disposed!"); + Project defaultProject = myDefaultProjectTimed.get(); + // disable "the only project" optimization since we have now more than one project. + // (even though the default project is not a real project, it can be used indirectly in e.g. "Settings|Code Style" code fragments PSI) + updateTheOnlyProjectField(); + return defaultProject; + } } @Override @@ -459,7 +463,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { private void removeFromOpened(@NotNull Project project) { synchronized (lock) { myOpenProjects = ArrayUtil.remove(myOpenProjects, project); - updateTheOnlyProjectField(); myOpenProjectByHash.values().remove(project); // remove by value and not by key! } }