IDEA-CR-20931 address 'his is a non-transparent assumption, I'd argue noone except of the author of MessageBusUtil#subscribe knows about it'

Make code more maintainable and clear
This commit is contained in:
Vladimir Krivosheev
2017-05-12 15:55:55 +02:00
parent 42935f1335
commit dd0064b600
7 changed files with 56 additions and 84 deletions
@@ -17,23 +17,19 @@ package com.intellij.ide.script;
import com.intellij.ide.extensionResources.ExtensionsRootType;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.MessageBusUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -50,6 +46,7 @@ import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.stream.Collectors;
class IdeStartupScripts implements ApplicationComponent {
@@ -69,7 +66,7 @@ class IdeStartupScripts implements ApplicationComponent {
LOG.info(scripts.size() + " startup script(s) found");
if (scripts.isEmpty()) return;
MessageBusUtil.subscribe(ProjectManager.TOPIC, new MyProjectManagerListener(prepareScriptEnginesAsync(scripts)));
ProjectUtil.runWhenProjectOpened(project -> new MyProjectOpenedHandler(prepareScriptEnginesAsync(scripts)));
}
@NotNull
@@ -132,21 +129,20 @@ class IdeStartupScripts implements ApplicationComponent {
return ExtensionsRootType.getInstance().findResourceDirectory(corePlugin, SCRIPT_DIR, false);
}
private static class MyProjectManagerListener implements ProjectManagerListener, Disposable {
private static class MyProjectOpenedHandler implements Consumer<Project> {
final AtomicBoolean myScriptsExecutionStarted;
private final Future<List<Pair<VirtualFile, IdeScriptEngine>>> myScriptsAndEnginesFuture;
public MyProjectManagerListener(@NotNull Future<List<Pair<VirtualFile, IdeScriptEngine>>> scriptsAndEnginesFuture) {
public MyProjectOpenedHandler(@NotNull Future<List<Pair<VirtualFile, IdeScriptEngine>>> scriptsAndEnginesFuture) {
myScriptsAndEnginesFuture = scriptsAndEnginesFuture;
myScriptsExecutionStarted = new AtomicBoolean();
}
@Override
public void projectOpened(final Project project) {
public void accept(@NotNull Project project) {
StartupManager.getInstance(project).runWhenProjectIsInitialized(() -> {
if (project.isDisposed()) return;
if (!myScriptsExecutionStarted.compareAndSet(false, true)) return;
Disposer.dispose(this);
runAllScriptsImpl(project);
});
}
@@ -177,9 +173,5 @@ class IdeStartupScripts implements ApplicationComponent {
LOG.error(e);
}
}
@Override
public void dispose() {
}
}
}
@@ -19,6 +19,7 @@ package com.intellij.openapi.project
import com.intellij.ide.DataManager
import com.intellij.ide.highlighter.ProjectFileType
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.appSystemDir
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder
@@ -39,6 +40,7 @@ import java.nio.file.InvalidPathException
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.function.Consumer
import javax.swing.JComponent
val Module.rootManager: ModuleRootManager
@@ -164,4 +166,30 @@ fun Project.getProjectCachePath(cacheName: String, forceNameUse: Boolean = false
@JvmOverloads
fun Project.getProjectCachePath(baseDir: Path, forceNameUse: Boolean = false, hashSeparator: String = "."): Path {
return baseDir.resolve(getProjectCacheFileName(forceNameUse, hashSeparator))
}
/**
* Add one-time projectOpened listener.
*/
fun Project.runWhenProjectOpened(handler: Runnable) = runWhenProjectOpened(this) { handler.run() }
/**
* Add one-time first projectOpened listener.
*/
@JvmOverloads
fun runWhenProjectOpened(project: Project? = null, handler: Consumer<Project>) = runWhenProjectOpened(project) { handler.accept(it) }
/**
* Add one-time projectOpened listener.
*/
inline fun runWhenProjectOpened(project: Project? = null, crossinline handler: (project: Project) -> Unit) {
val connection = (project ?: ApplicationManager.getApplication()).messageBus.connect()
connection.subscribe(ProjectManager.TOPIC, object : ProjectManagerListener {
override fun projectOpened(eventProject: Project) {
if (project == null || project === eventProject) {
connection.disconnect()
handler(eventProject)
}
}
})
}
@@ -26,8 +26,7 @@ import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
@@ -66,16 +65,7 @@ public abstract class LightToolWindowManager implements Disposable {
myPropertiesComponent = PropertiesComponent.getInstance(myProject);
myEditorModeKey = EDITOR_MODE + getComponentName() + ".STATE";
MessageBusConnection connection = myProject.getMessageBus().connect();
connection.subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(Project project) {
if (myProject == project) {
connection.disconnect();
LightToolWindowManager.this.projectOpened();
}
}
});
ProjectUtil.runWhenProjectOpened(project, () -> projectOpened());
}
protected void projectOpened() {
@@ -16,17 +16,13 @@
package com.intellij.openapi.ui.playback.util;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.playback.PlaybackContext;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.MessageBusUtil;
import com.intellij.util.ui.UIUtil;
import java.io.File;
@@ -54,12 +50,12 @@ public class ProjectPlaybackCall {
public static AsyncResult<String> openProject(final PlaybackContext context, final String path) {
final AsyncResult<String> result = new AsyncResult<>();
final ProjectManager projectManager = ProjectManager.getInstance();
MessageBusUtil.subscribe(ProjectManager.TOPIC, new MyProjectManagerListener(result));
ProjectUtil.runWhenProjectOpened(project -> StartupManager.getInstance(project).registerPostStartupActivity(() -> {
DumbService.getInstance(project).runWhenSmart(() -> result.setDone("Opened successfully: " + project.getPresentableUrl()));
}));
UIUtil.invokeLaterIfNeeded(() -> {
try {
projectManager.loadAndOpenProject(path);
ProjectManager.getInstance().loadAndOpenProject(path);
}
catch (Exception e) {
context.error(e.getMessage(), context.getCurrentLine());
@@ -69,24 +65,4 @@ public class ProjectPlaybackCall {
return result;
}
private static class MyProjectManagerListener implements ProjectManagerListener, Disposable {
private final AsyncResult<String> myResult;
public MyProjectManagerListener(AsyncResult<String> result) {
myResult = result;
}
@Override
public void projectOpened(final Project project) {
StartupManager.getInstance(project).registerPostStartupActivity(() -> {
Disposer.dispose(this);
DumbService.getInstance(project).runWhenSmart(() -> myResult.setDone("Opened successfully: " + project.getPresentableUrl()));
});
}
@Override
public void dispose() {
}
}
}
@@ -27,8 +27,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.startup.StartupManager;
@@ -67,14 +66,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager implement
public EncodingProjectManagerImpl(Project project, EncodingManager ideEncodingManager) {
myProject = project;
myIdeEncodingManager = (EncodingManagerImpl)ideEncodingManager;
project.getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(Project project) {
if (project == myProject) {
StartupManager.getInstance(project).runWhenProjectIsInitialized(EncodingProjectManagerImpl.this::reloadAlreadyLoadedDocuments);
}
}
});
ProjectUtil.runWhenProjectOpened(project, () -> StartupManager.getInstance(project).runWhenProjectIsInitialized(this::reloadAlreadyLoadedDocuments));
}
private final Map<VirtualFile, Charset> myMapping = ContainerUtil.newConcurrentMap();
@@ -51,12 +51,4 @@ public class MessageBusUtil {
}
};
}
public static <L> void subscribe(@NotNull Topic<L> topic, @NotNull L handler) {
subscribe(ApplicationManager.getApplication().getMessageBus(), topic, handler);
}
public static <L> void subscribe(@NotNull MessageBus messageBus, @NotNull Topic<L> topic, @NotNull L handler) {
(handler instanceof Disposable ? messageBus.connect((Disposable)handler) : messageBus.connect()).subscribe(topic, handler);
}
}
@@ -19,7 +19,6 @@ import com.intellij.diagnostic.AbstractMessage;
import com.intellij.diagnostic.MessagePool;
import com.intellij.ide.PrivacyPolicy;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.application.ApplicationBundle;
@@ -33,8 +32,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SwitchBootJdkAction;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -50,8 +49,8 @@ import com.intellij.ui.components.JBList;
import com.intellij.ui.popup.PopupFactoryImpl;
import com.intellij.ui.popup.list.ListPopupModel;
import com.intellij.util.JdkBundle;
import com.intellij.util.MessageBusUtil;
import com.intellij.util.Producer;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.EdtInvocationManager;
import org.fest.swing.core.*;
import org.fest.swing.core.Robot;
@@ -207,20 +206,23 @@ GuiTestUtil {
Robot robot = null;
try {
robot = BasicRobot.robotWithCurrentAwtHierarchy();
final MyProjectManagerListener listener = new MyProjectManagerListener();
//[ACCEPT IntelliJ IDEA Privacy Policy Agreement]
acceptAgreementIfNeeded(robot);
if(isFirstStart) (new FirstStart(robot)).completeBefore();
final MyProjectManagerListener listener = new MyProjectManagerListener();
final Ref<MessageBusConnection> connection = new Ref<>();
findFrame(new GenericTypeMatcher<Frame>(Frame.class) {
@Override
protected boolean isMatching(@NotNull Frame frame) {
if (frame instanceof IdeFrame) {
if (frame instanceof IdeFrameImpl) {
listener.myActive = true;
MessageBusUtil.subscribe(ProjectManager.TOPIC, listener);
connection.set(ApplicationManager.getApplication().getMessageBus().connect());
connection.get().subscribe(ProjectManager.TOPIC, listener);
}
return true;
}
@@ -253,7 +255,11 @@ GuiTestUtil {
!progressManager.hasProgressIndicator() &&
!progressManager.hasUnsafeProgressIndicator();
if (isIdle) {
Disposer.dispose(listener);
MessageBusConnection busConnection = connection.get();
if (busConnection != null) {
connection.set(null);
busConnection.disconnect();
}
}
return isIdle;
}
@@ -728,7 +734,7 @@ GuiTestUtil {
return s == null ? System.getenv(name) : s;
}
private static class MyProjectManagerListener implements ProjectManagerListener, Disposable {
private static class MyProjectManagerListener implements ProjectManagerListener {
boolean myActive;
boolean myNotified;
@@ -736,10 +742,6 @@ GuiTestUtil {
public void projectOpened(Project project) {
myNotified = true;
}
@Override
public void dispose() {
}
}
private static class PrefixMatcher extends BaseMatcher<String> {