From 4a84f713d2dfd904c46bc498197d2a5b916fc6ac Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 1 Aug 2019 15:09:12 +0200 Subject: [PATCH] =?UTF-8?q?lazy=20message=20bus=20listeners=20on=20project?= =?UTF-8?q?=20level=20=E2=80=94=20part=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitOrigin-RevId: 67c8099192afbb8abec4b031439391a634712f46 --- .../codeInsight/ExternalAnnotationsTest.java | 34 +++----- .../ide/plugins/IdeaPluginDescriptor.java | 14 +--- .../com/intellij/psi/PsiDocumentListener.java | 31 +++++++ .../com/intellij/psi/PsiDocumentManager.java | 3 - .../ide/plugins/IdeaPluginDescriptorImpl.java | 32 ++----- .../components/impl/ComponentManagerImpl.java | 56 ++----------- .../psi/impl/PsiDocumentManagerBase.java | 4 +- .../ide/bookmarks/BookmarkManager.java | 47 ++++++----- .../openapi/module/impl/ModuleImpl.java | 7 -- .../com/intellij/ide/plugins/PluginNode.java | 19 ----- .../src/com/intellij/idea/IdeaApplication.kt | 28 ------- .../application/impl/ApplicationImpl.java | 2 + .../impl/PlatformComponentManagerImpl.kt | 84 ++++++++++++++++--- .../components/impl/ServiceManagerImpl.java | 2 +- .../openapi/project/impl/DefaultProject.java | 6 -- .../openapi/project/impl/ProjectImpl.java | 13 +-- .../componentSets/PlatformLangComponents.xml | 3 + .../testFramework/EditorListenerTracker.java | 18 +--- .../impl/HeavyIdeaTestFixtureImpl.java | 13 ++- .../devkit-core/src/dom/IdeaPlugin.java | 7 ++ 20 files changed, 182 insertions(+), 241 deletions(-) create mode 100644 platform/core-api/src/com/intellij/psi/PsiDocumentListener.java diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/ExternalAnnotationsTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/ExternalAnnotationsTest.java index 2675e222f0b6..4bc21881bd37 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/ExternalAnnotationsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/ExternalAnnotationsTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 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.java.codeInsight; import com.intellij.codeInsight.intention.AddAnnotationPsiFix; @@ -42,7 +28,7 @@ public class ExternalAnnotationsTest extends UsefulTestCase { myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); final String dataPath = PathManagerEx.getTestDataPath() + "/codeInsight/externalAnnotations"; myFixture.setTestDataPath(dataPath); - final JavaModuleFixtureBuilder builder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); + JavaModuleFixtureBuilder builder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15); myFixture.setUp(); @@ -85,9 +71,9 @@ public class ExternalAnnotationsTest extends UsefulTestCase { myFixture.configureByFiles("src/rename/Foo.java", "content/anno/rename/annotations.xml"); myFixture.renameElementAtCaret("Bar"); - + myFixture.checkResultByFile("content/anno/rename/annotations.xml", - "content/anno/rename/annotations_after.xml", + "content/anno/rename/annotations_after.xml", true); } @@ -96,12 +82,12 @@ public class ExternalAnnotationsTest extends UsefulTestCase { IntentionAction action = myFixture.findSingleIntention("Insert '@Deprecated'"); assertNotNull(action); - + myFixture.launchAction(action); - + myFixture.checkResultByFile("src/toSrc/Foo_after.java"); myFixture.checkResultByFile("content/anno/toSrc/annotations.xml", - "content/anno/toSrc/annotations_after.xml", + "content/anno/toSrc/annotations_after.xml", true); } @@ -110,12 +96,12 @@ public class ExternalAnnotationsTest extends UsefulTestCase { IntentionAction action = myFixture.findSingleIntention("Annotate externally"); assertNotNull(action); - + myFixture.launchAction(action); - + myFixture.checkResultByFile("src/fromSrc/Foo_after.java"); myFixture.checkResultByFile("content/anno/fromSrc/annotations.xml", - "content/anno/fromSrc/annotations_after.xml", + "content/anno/fromSrc/annotations_after.xml", true); } diff --git a/platform/core-api/src/com/intellij/ide/plugins/IdeaPluginDescriptor.java b/platform/core-api/src/com/intellij/ide/plugins/IdeaPluginDescriptor.java index e63a2fbb879c..87d4607ac807 100644 --- a/platform/core-api/src/com/intellij/ide/plugins/IdeaPluginDescriptor.java +++ b/platform/core-api/src/com/intellij/ide/plugins/IdeaPluginDescriptor.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 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.ide.plugins; -import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.extensions.PluginId; import org.jdom.Element; @@ -52,15 +51,6 @@ public interface IdeaPluginDescriptor extends PluginDescriptor { @Nullable List getAndClearActionDescriptionElements(); - @NotNull - List getAppComponents(); - - @NotNull - List getProjectComponents(); - - @NotNull - List getModuleComponents(); - String getVendorEmail(); String getVendorUrl(); @@ -74,7 +64,9 @@ public interface IdeaPluginDescriptor extends PluginDescriptor { /** @deprecated doesn't make sense for installed plugins; use PluginNode#getDownloads (to be removed in IDEA 2019) */ @ApiStatus.ScheduledForRemoval(inVersion = "2019") @Deprecated - String getDownloads(); + default String getDownloads() { + return null; + } String getSinceBuild(); diff --git a/platform/core-api/src/com/intellij/psi/PsiDocumentListener.java b/platform/core-api/src/com/intellij/psi/PsiDocumentListener.java new file mode 100644 index 000000000000..cd60ae1ea351 --- /dev/null +++ b/platform/core-api/src/com/intellij/psi/PsiDocumentListener.java @@ -0,0 +1,31 @@ +// Copyright 2000-2019 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.psi; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface PsiDocumentListener { + Topic TOPIC = new Topic<>(PsiDocumentListener.class); + + /** + * Called when a document instance is created for a file. + * + * @param document the created document instance. + * @param psiFile the file for which the document was created. + * @see PsiDocumentManager#getDocument(PsiFile) + */ + void documentCreated(@NotNull Document document, @Nullable PsiFile psiFile, @NotNull Project project); + + /** + * Called when a file instance is created for a document. + * + * @param file the created file instance. + * @param document the document for which the file was created. + * @see PsiDocumentManager#getDocument(PsiFile) + */ + default void fileCreated(@NotNull PsiFile file, @NotNull Document document) { + } +} diff --git a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java index 5c43c819b882..e48bdd8dd667 100644 --- a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java +++ b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java @@ -6,7 +6,6 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.messages.Topic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -179,8 +178,6 @@ public abstract class PsiDocumentManager { * Listener for receiving notifications about creation of {@link Document} and {@link PsiFile} instances. */ public interface Listener extends EventListener { - Topic TOPIC = new Topic<>("PsiDocumentManager.Listener", Listener.class); - /** * Called when a document instance is created for a file. * diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java index 25078ff2e92f..ba67b8604385 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java @@ -348,6 +348,10 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { case "applicationListeners": readListeners(child, myAppContainerDescriptor); break; + + case "projectListeners": + readListeners(child, myProjectContainerDescriptor); + break; } child.getContent().clear(); @@ -511,7 +515,7 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { if (myExtensions == null) { return; } - ((ExtensionPointImpl)extensionPoint).createAndRegisterAdapters(myExtensions.get(extensionPoint.getName()), this, area.getPicoContainer()); + ((ExtensionPointImpl)extensionPoint).createAndRegisterAdapters(myExtensions.get(extensionPoint.getName()), this, area.getPicoContainer()); } @Override @@ -639,24 +643,6 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { return result; } - @Override - @NotNull - public List getAppComponents() { - return ContainerUtil.notNullize(myAppContainerDescriptor.components); - } - - @Override - @NotNull - public List getProjectComponents() { - return ContainerUtil.notNullize(myProjectContainerDescriptor.components); - } - - @Override - @NotNull - public List getModuleComponents() { - return ContainerUtil.notNullize(myModuleContainerDescriptor.components); - } - @Override public String getVendorEmail() { return myVendorEmail; @@ -693,14 +679,6 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { return myId; } - /** @deprecated doesn't make sense for installed plugins; use PluginNode#getDownloads (to be removed in IDEA 2019) */ - @ApiStatus.ScheduledForRemoval(inVersion = "2019") - @Override - @Deprecated - public String getDownloads() { - return null; - } - @Override public ClassLoader getPluginClassLoader() { return myLoader != null ? myLoader : getClass().getClassLoader(); diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index a390da257e0c..22c044b5d29d 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -4,10 +4,8 @@ package com.intellij.openapi.components.impl; import com.intellij.diagnostic.*; import com.intellij.diagnostic.StartUpMeasurer.Level; import com.intellij.diagnostic.StartUpMeasurer.Phases; -import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.plugins.cl.PluginClassLoader; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.components.BaseComponent; @@ -61,7 +59,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private final Map myNameToComponent = new THashMap<>(); // contents guarded by this @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") - private int myComponentConfigCount; + protected int myComponentConfigCount; @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private int myInstantiatedComponentCount; private boolean myComponentsCreated; @@ -85,36 +83,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements return null; } - protected void registerComponents(@NotNull List plugins) { - Application app = ApplicationManager.getApplication(); - boolean headless = app == null || app.isHeadlessEnvironment(); - - int componentConfigCount = 0; - for (IdeaPluginDescriptor plugin : plugins) { - for (ComponentConfig config : getMyComponentConfigsFromDescriptor(plugin)) { - if (!config.prepareClasses(headless)) { - continue; - } - - if (isComponentSuitable(config)) { - registerComponents(config, plugin); - componentConfigCount++; - } - } - - registerServices(plugin); - } - myComponentConfigCount = componentConfigCount; - - // app - phase must be set before getMessageBus() - if (getPicoContainer().getParent() == null) { - LoadingPhase.setCurrentPhase(LoadingPhase.COMPONENT_REGISTERED); - } - - //register message bus in pico container - getMessageBus(); - } - protected final void createComponents(@Nullable ProgressIndicator indicator) { LOG.assertTrue(!myComponentsCreated); @@ -139,9 +107,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements myComponentsCreated = true; } - protected void registerServices(@NotNull IdeaPluginDescriptor pluginDescriptor) { - } - protected void setProgressDuringInit(@NotNull ProgressIndicator indicator) { indicator.setFraction(getPercentageOfComponentsLoaded()); } @@ -152,16 +117,19 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements @NotNull @Override - public MessageBus getMessageBus() { + public final MessageBus getMessageBus() { if (myDisposed) { throwAlreadyDisposed(); } + MessageBus messageBus = myMessageBus; if (messageBus == null) { + //noinspection SynchronizeOnThis synchronized (this) { messageBus = myMessageBus; if (messageBus == null) { - myMessageBus = messageBus = createMessageBus(); + messageBus = createMessageBus(); + myMessageBus = messageBus; } } } @@ -343,17 +311,11 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements return myDisposed; } - // used in upsource - @NotNull - public List getMyComponentConfigsFromDescriptor(@NotNull IdeaPluginDescriptor plugin) { - return plugin.getAppComponents(); - } - protected MutablePicoContainer bootstrapPicoContainer(@NotNull String name) { return createPicoContainer(); } - protected void logMessageBusDelivery(Topic topic, String messageName, Object handler, long durationNanos) { + protected void logMessageBusDelivery(Topic topic, String messageName, Object handler, long durationNanos) { if (!StartUpMeasurer.isMeasuringPluginStartupCosts()) { ((MessageBusImpl) myMessageBus).setMessageDeliveryListener(null); return; @@ -402,7 +364,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements return component.getClass().getName(); } - private void registerComponents(@NotNull ComponentConfig config, @NotNull PluginDescriptor pluginDescriptor) { + protected final void registerComponents(@NotNull ComponentConfig config, @NotNull PluginDescriptor pluginDescriptor) { ClassLoader loader = pluginDescriptor.getPluginClassLoader(); try { Class interfaceClass = Class.forName(config.getInterfaceClass(), true, loader); @@ -541,7 +503,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements throw e; } catch (Throwable t) { - handleInitComponentError(t, ((Class)getComponentKey()).getName(), myPluginId); + handleInitComponentError(t, ((Class)getComponentKey()).getName(), myPluginId); } return instance; diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 7ea064307d45..5d8569e0d5be 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -676,14 +676,14 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen } void fireDocumentCreated(@NotNull Document document, PsiFile file) { - myProject.getMessageBus().syncPublisher(Listener.TOPIC).documentCreated(document, file); + myProject.getMessageBus().syncPublisher(PsiDocumentListener.TOPIC).documentCreated(document, file, myProject); for (Listener listener : myListeners) { listener.documentCreated(document, file); } } private void fireFileCreated(@NotNull Document document, @NotNull PsiFile file) { - myProject.getMessageBus().syncPublisher(Listener.TOPIC).fileCreated(file, document); + myProject.getMessageBus().syncPublisher(PsiDocumentListener.TOPIC).fileCreated(file, document); for (Listener listener : myListeners) { listener.fileCreated(file, document); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java index 676eb36f8e4a..db8c2843b646 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkManager.java @@ -26,6 +26,7 @@ import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.psi.PsiDocumentListener; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.AppUIUtil; @@ -68,35 +69,39 @@ public final class BookmarkManager implements PersistentStateComponent multicaster.addDocumentListener(new MyDocumentListener(), myProject); multicaster.addEditorMouseListener(new MyEditorMouseListener(), myProject); - connection.subscribe(PsiDocumentManager.Listener.TOPIC, new PsiDocumentManager.Listener() { - @Override - public void documentCreated(@NotNull Document document, @Nullable PsiFile psiFile) { - VirtualFile file = FileDocumentManager.getInstance().getFile(document); - if (file == null) { - return; - } - - Collection fileBookmarks = myBookmarks.get(file); - if (!fileBookmarks.isEmpty()) { - AppUIUtil.invokeLaterIfProjectAlive(project, () -> { - MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, myProject, true); - for (Bookmark bookmark : fileBookmarks) { - bookmark.createHighlighter(markup); - } - }); - } - } - }); - mySortedState = UISettings.getInstance().getSortBookmarks(); connection.subscribe(UISettingsListener.TOPIC, uiSettings -> { if (mySortedState != uiSettings.getSortBookmarks()) { mySortedState = uiSettings.getSortBookmarks(); - ApplicationManager.getApplication().invokeLater(() -> project.getMessageBus().syncPublisher(BookmarksListener.TOPIC).bookmarksOrderChanged()); + ApplicationManager.getApplication().invokeLater(() -> { + if (!project.isDisposed()) { + project.getMessageBus().syncPublisher(BookmarksListener.TOPIC).bookmarksOrderChanged(); + } + }); } }); } + static final class BookmarkManagerPsiDocumentManagerListener implements PsiDocumentListener { + @Override + public void documentCreated(@NotNull Document document, @Nullable PsiFile psiFile, @NotNull Project project) { + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null) { + return; + } + + Collection fileBookmarks = getInstance(project).myBookmarks.get(file); + if (!fileBookmarks.isEmpty()) { + AppUIUtil.invokeLaterIfProjectAlive(project, () -> { + MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true); + for (Bookmark bookmark : fileBookmarks) { + bookmark.createHighlighter(markup); + } + }); + } + } + } + public void editDescription(@NotNull Bookmark bookmark, @NotNull JComponent popup) { ApplicationManager.getApplication().assertIsDispatchThread(); String description = Messages.showInputDialog(popup, IdeBundle.message("action.bookmark.edit.description.dialog.message"), diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java index 97bc703a1205..322a5d3ac14f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java @@ -3,7 +3,6 @@ package com.intellij.openapi.module.impl; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.ide.plugins.ContainerDescriptor; -import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.application.ApplicationManager; @@ -154,12 +153,6 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx super.dispose(); } - @NotNull - @Override - public List getMyComponentConfigsFromDescriptor(@NotNull IdeaPluginDescriptor plugin) { - return plugin.getModuleComponents(); - } - @NotNull @Override protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java index d9e0199a2506..ffad2fb643f4 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 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.ide.plugins; -import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.extensions.PluginId; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -304,24 +303,6 @@ public class PluginNode implements IdeaPluginDescriptor { return null; } - @Override - @NotNull - public List getAppComponents() { - throw new IllegalStateException(); - } - - @Override - @NotNull - public List getProjectComponents() { - throw new IllegalStateException(); - } - - @Override - @NotNull - public List getModuleComponents() { - throw new IllegalStateException(); - } - @Override @Nullable public String getVendorLogoPath() { diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt index 43701b216adf..eb5382785b32 100644 --- a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt +++ b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt @@ -40,12 +40,8 @@ import com.intellij.ui.CustomProtocolHandler import com.intellij.ui.mac.MacOSApplicationProvider import com.intellij.ui.mac.touchbar.TouchBarsManager import com.intellij.util.ArrayUtilRt -import com.intellij.util.SmartList import com.intellij.util.concurrency.AppExecutorUtil -import com.intellij.util.containers.ContainerUtil import com.intellij.util.io.exists -import com.intellij.util.messages.ListenerDescriptor -import com.intellij.util.messages.impl.MessageBusImpl import com.intellij.util.ui.AsyncProcessIcon import com.intellij.util.ui.accessibility.ScreenReader import net.miginfocom.layout.PlatformDefaults @@ -187,9 +183,6 @@ fun registerRegistryAndContainerAndInitStore(pluginDescriptorsFuture: Completabl initAppActivity.runChild("app component registration") { app.registerComponents(pluginDescriptors) } - initAppActivity.runChild("add message bus listeners") { - registerMessageBusListeners(pluginDescriptors, app) - } // yes, at this moment initSystemProperties or RegistryKeyBean.addKeysFromPlugins maybe not yet performed, but it doesn't affect because not used. IdeaApplication.initConfigurationStore(app, null) @@ -529,25 +522,4 @@ fun preloadServices(app: ApplicationImpl): CompletableFuture { } }, appExecutorService) }) -} - -private fun registerMessageBusListeners(pluginDescriptors: List, app: ApplicationImpl) { - val map = ContainerUtil.newConcurrentMap>() - val isHeadlessMode = app.isHeadlessEnvironment - val isUnitTestMode = app.isUnitTestMode - for (descriptor in pluginDescriptors) { - val listeners = (descriptor as IdeaPluginDescriptorImpl).app.listeners - for (listener in listeners) { - if (isUnitTestMode && !listener.activeInTestMode) { - continue - } - if (isHeadlessMode && !listener.activeInHeadlessMode) { - continue - } - - map.getOrPut(listener.topicClassName) { SmartList() }.add(listener) - } - } - - (app.messageBus as MessageBusImpl).setLazyListeners(map) } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 0a3395c2e9e2..ce00973ba0fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -368,10 +368,12 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App } @Override + @ApiStatus.Internal public final void registerComponents(@NotNull List plugins) { super.registerComponents(plugins); } + @ApiStatus.Internal public final void loadComponents(@Nullable ProgressIndicator indicator) { AccessToken token = HeavyProcessLatch.INSTANCE.processStarted("Loading application components"); try { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt index c256408a354f..6be4259227c7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt @@ -6,13 +6,19 @@ import com.intellij.ide.plugins.ContainerDescriptor import com.intellij.ide.plugins.IdeaPluginDescriptor import com.intellij.ide.plugins.IdeaPluginDescriptorImpl import com.intellij.ide.plugins.PluginManager +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ComponentManager import com.intellij.openapi.components.PathMacroManager import com.intellij.openapi.components.ServiceDescriptor import com.intellij.openapi.components.impl.stores.IComponentStore import com.intellij.openapi.components.stateStore import com.intellij.openapi.extensions.PluginId +import com.intellij.util.SmartList +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.messages.ListenerDescriptor import com.intellij.util.messages.MessageBusFactory +import com.intellij.util.messages.impl.MessageBusImpl +import java.util.concurrent.ConcurrentMap abstract class PlatformComponentManagerImpl : ComponentManagerImpl { private var handlingInitComponentError = false @@ -24,15 +30,72 @@ abstract class PlatformComponentManagerImpl : ComponentManagerImpl { protected constructor(parent: ComponentManager?, name: String) : super(parent, name) + protected open fun registerComponents(plugins: List) { + val app = ApplicationManager.getApplication() + val headless = app == null || app.isHeadlessEnvironment + + var map: ConcurrentMap>? = null + val isHeadlessMode = app.isHeadlessEnvironment + val isUnitTestMode = app.isUnitTestMode + + var componentConfigCount = 0 + for (plugin in plugins) { + val containerDescriptor = getContainerDescriptor(plugin as IdeaPluginDescriptorImpl) + + for (config in containerDescriptor.components) { + if (!config.prepareClasses(headless)) { + continue + } + + if (isComponentSuitable(config)) { + registerComponents(config, plugin) + componentConfigCount++ + } + } + + ServiceManagerImpl.registerServices(containerDescriptor.services, plugin, this) + + val listeners = containerDescriptor.listeners + if (listeners.isNotEmpty()) { + if (map == null) { + map = ContainerUtil.newConcurrentMap() + } + + for (listener in listeners) { + if ((isUnitTestMode && !listener.activeInTestMode) || (isHeadlessMode && !listener.activeInHeadlessMode)) { + continue + } + + map.getOrPut(listener.topicClassName) { SmartList() }.add(listener) + } + } + } + + myComponentConfigCount = componentConfigCount + + // app - phase must be set before getMessageBus() + if (picoContainer.parent == null) { + LoadingPhase.setCurrentPhase(LoadingPhase.COMPONENT_REGISTERED) + } + + // ensure that messageBus is created, regardless of lazy listeners map state + val messageBus = messageBus as MessageBusImpl + if (map != null) { + messageBus.setLazyListeners(map) + } + } + override fun handleInitComponentError(t: Throwable, componentClassName: String, pluginId: PluginId) { - if (!handlingInitComponentError) { - handlingInitComponentError = true - try { - PluginManager.handleComponentError(t, componentClassName, pluginId) - } - finally { - handlingInitComponentError = false - } + if (handlingInitComponentError) { + return + } + + handlingInitComponentError = true + try { + PluginManager.handleComponentError(t, componentClassName, pluginId) + } + finally { + handlingInitComponentError = false } } @@ -43,10 +106,5 @@ abstract class PlatformComponentManagerImpl : ComponentManagerImpl { } } - override fun registerServices(pluginDescriptor: IdeaPluginDescriptor) { - ServiceManagerImpl.registerServices(getContainerDescriptor(pluginDescriptor as IdeaPluginDescriptorImpl).services, pluginDescriptor, - this) - } - protected abstract fun getContainerDescriptor(pluginDescriptor: IdeaPluginDescriptorImpl): ContainerDescriptor } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index 8d8e62b16f38..f666e25156b6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -186,7 +186,7 @@ public final class ServiceManagerImpl implements Disposable { } @Override - public Class getComponentImplementation() { + public Class getComponentImplementation() { return getDelegate().getComponentImplementation(); } 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 bd5fdfe8ee7b..c0dc86c23236 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 @@ -66,12 +66,6 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj return null; } - @NotNull - @Override - public synchronized MessageBus getMessageBus() { - return super.getMessageBus(); - } - @Override protected boolean isComponentSuitable(@NotNull ComponentConfig componentConfig) { return super.isComponentSuitable(componentConfig) && componentConfig.isLoadForDefaultProject(); 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 98dcaae26fc6..0e4a74987f46 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 @@ -6,7 +6,6 @@ import com.intellij.diagnostic.Activity; import com.intellij.diagnostic.StartUpMeasurer; import com.intellij.diagnostic.StartUpMeasurer.Phases; import com.intellij.ide.plugins.ContainerDescriptor; -import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.startup.StartupManagerEx; @@ -14,7 +13,10 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.LaterInvocator; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.ExtensionAreas; +import com.intellij.openapi.components.PathMacroManager; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.impl.PlatformComponentManagerImpl; import com.intellij.openapi.components.impl.ProjectPathMacroManager; import com.intellij.openapi.components.impl.stores.IComponentStore; @@ -49,7 +51,6 @@ import org.picocontainer.MutablePicoContainer; import javax.swing.*; import java.nio.file.Path; -import java.util.List; public class ProjectImpl extends PlatformComponentManagerImpl implements ProjectEx, ProjectStoreOwner { private static final Logger LOG = Logger.getInstance("#com.intellij.project.impl.ProjectImpl"); @@ -173,12 +174,6 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project return !isDisposed() && isOpen() && StartupManagerEx.getInstanceEx(this).startupActivityPassed(); } - @NotNull - @Override - public List getMyComponentConfigsFromDescriptor(@NotNull IdeaPluginDescriptor plugin) { - return plugin.getProjectComponents(); - } - @NotNull @Override protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) { diff --git a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml index c97cae39b5d7..4a01e4a28206 100644 --- a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml +++ b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml @@ -28,4 +28,7 @@ + + + diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorListenerTracker.java b/platform/testFramework/src/com/intellij/testFramework/EditorListenerTracker.java index 90a2d84e2104..1af787fbae9f 100644 --- a/platform/testFramework/src/com/intellij/testFramework/EditorListenerTracker.java +++ b/platform/testFramework/src/com/intellij/testFramework/EditorListenerTracker.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 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.testFramework; import com.intellij.openapi.editor.EditorFactory; @@ -33,7 +19,7 @@ import java.util.Map; * @author cdr */ @TestOnly -public class EditorListenerTracker { +public final class EditorListenerTracker { private final Map, List> before; public EditorListenerTracker() { diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java index 92c7bc997cb8..79d30f5e8351 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java @@ -51,14 +51,13 @@ import java.util.stream.Stream; /** * Creates new project for each test. - * @author mike */ @SuppressWarnings("TestOnlyProblems") final class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixture { private Project myProject; private final Set myFilesToDelete = new HashSet<>(); private IdeaTestApplication myApplication; - private final Set myModuleFixtureBuilders = new LinkedHashSet<>(); + private final Set> myModuleFixtureBuilders = new LinkedHashSet<>(); private EditorListenerTracker myEditorListenerTracker; private ThreadTracker myThreadTracker; private final String myName; @@ -70,7 +69,7 @@ final class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTes myIsDirectoryBasedProject = isDirectoryBasedProject; } - void addModuleFixtureBuilder(ModuleFixtureBuilder builder) { + void addModuleFixtureBuilder(ModuleFixtureBuilder builder) { myModuleFixtureBuilders.add(builder); } @@ -89,14 +88,14 @@ final class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTes } @Override - public void tearDown() throws Exception { + public void tearDown() { RunAll runAll = new RunAll(); if (myProject != null) { runAll = runAll .append(() -> LightPlatformTestCase.doTearDown(getProject(), myApplication)) .append(() -> { - for (ModuleFixtureBuilder moduleFixtureBuilder : myModuleFixtureBuilders) { + for (ModuleFixtureBuilder moduleFixtureBuilder : myModuleFixtureBuilders) { moduleFixtureBuilder.getFixture().tearDown(); } }) @@ -163,7 +162,7 @@ final class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTes EdtTestUtil.runInEdtAndWait(() -> { ProjectManagerEx.getInstanceEx().openTestProject(myProject); - for (ModuleFixtureBuilder moduleFixtureBuilder : myModuleFixtureBuilders) { + for (ModuleFixtureBuilder moduleFixtureBuilder : myModuleFixtureBuilders) { moduleFixtureBuilder.getFixture().setUp(); } @@ -173,7 +172,7 @@ final class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTes } @NotNull - protected Path generateProjectPath(@NotNull Path tempDirectory) { + private Path generateProjectPath(@NotNull Path tempDirectory) { String suffix = myIsDirectoryBasedProject ? "" : ProjectFileType.DOT_DEFAULT_EXTENSION; return tempDirectory.resolve(myName + suffix); } diff --git a/plugins/devkit/devkit-core/src/dom/IdeaPlugin.java b/plugins/devkit/devkit-core/src/dom/IdeaPlugin.java index 2f6972b17d90..f7fac8c866ca 100644 --- a/plugins/devkit/devkit-core/src/dom/IdeaPlugin.java +++ b/plugins/devkit/devkit-core/src/dom/IdeaPlugin.java @@ -145,6 +145,13 @@ public interface IdeaPlugin extends DomElement { @SubTagList("applicationListeners") List getApplicationListeners(); + /** + * Available since 192. + */ + @NotNull + @SubTagList("projectListeners") + List getProjectListeners(); + /** * @deprecated not used anymore */