diff --git a/platform/core-api/src/com/intellij/openapi/components/ServiceDescriptor.java b/platform/core-api/src/com/intellij/openapi/components/ServiceDescriptor.java index b606bacc63cc..8f6dbb3ee0a3 100644 --- a/platform/core-api/src/com/intellij/openapi/components/ServiceDescriptor.java +++ b/platform/core-api/src/com/intellij/openapi/components/ServiceDescriptor.java @@ -27,6 +27,15 @@ public final class ServiceDescriptor { @Nullable public String configurationSchemaKey; + /** + * Preload service (before component creation). Applicable for application level only. + * + * Loading order and thread are not guaranteed, service should be decoupled as much as possible. + */ + @Attribute + @ApiStatus.Experimental + public boolean preload; + public String getInterface() { return serviceInterface != null ? serviceInterface : getImplementation(); } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManagerListener.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManagerListener.java index 70649864a4ac..d247d415373d 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManagerListener.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManagerListener.java @@ -3,6 +3,9 @@ package com.intellij.openapi.vfs; import java.util.EventListener; +/** + * Message bus cannot be used because before / after events are not supported - order of events maybe changed by message bus. + */ public interface VirtualFileManagerListener extends EventListener { default void beforeRefreshStart(boolean asynchronous) { } diff --git a/platform/core-impl/src/com/intellij/ide/plugins/ContainerDescriptor.java b/platform/core-impl/src/com/intellij/ide/plugins/ContainerDescriptor.java index 0cb497f358a1..798263a4ddb4 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/ContainerDescriptor.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/ContainerDescriptor.java @@ -6,13 +6,15 @@ import com.intellij.openapi.components.ServiceDescriptor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.ListenerDescriptor; import org.jdom.Element; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -final class ContainerDescriptor { +@ApiStatus.Internal +public final class ContainerDescriptor { @Nullable List services; @Nullable @@ -22,7 +24,22 @@ final class ContainerDescriptor { @Nullable List extensionsPoints; - public void addService(@NotNull ServiceDescriptor serviceDescriptor) { + @NotNull + public List getServices() { + return ContainerUtil.notNullize(services); + } + + @NotNull + public List getComponents() { + return ContainerUtil.notNullize(components); + } + + @NotNull + public List getListeners() { + return ContainerUtil.notNullize(listeners); + } + + void addService(@NotNull ServiceDescriptor serviceDescriptor) { if (services == null) { services = new ArrayList<>(); } @@ -30,7 +47,7 @@ final class ContainerDescriptor { } @NotNull - public List getComponentListToAdd(int size) { + List getComponentListToAdd(int size) { List result = components; if (result == null) { result = new ArrayList<>(size); @@ -42,7 +59,7 @@ final class ContainerDescriptor { return result; } - public void merge(@NotNull ContainerDescriptor another) { + void merge(@NotNull ContainerDescriptor another) { components = concatOrNull(components, another.components); services = concatOrNull(services, another.services); extensionsPoints = concatOrNull(extensionsPoints, another.extensionsPoints); 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 0f362e59a21d..25078ff2e92f 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java @@ -106,6 +106,24 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { myBundled = bundled; } + @NotNull + @ApiStatus.Internal + public ContainerDescriptor getApp() { + return myAppContainerDescriptor; + } + + @NotNull + @ApiStatus.Internal + public ContainerDescriptor getProject() { + return myProjectContainerDescriptor; + } + + @NotNull + @ApiStatus.Internal + public ContainerDescriptor getModule() { + return myModuleContainerDescriptor; + } + @Override public File getPath() { return myPath; @@ -377,6 +395,7 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { descriptor.serviceImplementation = element.getAttributeValue("serviceImplementation"); descriptor.testServiceImplementation = element.getAttributeValue("testServiceImplementation"); descriptor.configurationSchemaKey = element.getAttributeValue("configurationSchemaKey"); + descriptor.preload = Boolean.parseBoolean(element.getAttributeValue("preload")); descriptor.overrides = Boolean.parseBoolean(element.getAttributeValue("overrides")); return descriptor; } @@ -638,26 +657,6 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { return ContainerUtil.notNullize(myModuleContainerDescriptor.components); } - @NotNull - public List getAppServices() { - return ContainerUtil.notNullize(myAppContainerDescriptor.services); - } - - @NotNull - public List getListeners() { - return ContainerUtil.notNullize(myAppContainerDescriptor.listeners); - } - - @NotNull - public List getProjectServices() { - return ContainerUtil.notNullize(myProjectContainerDescriptor.services); - } - - @NotNull - public List getModuleServices() { - return ContainerUtil.notNullize(myModuleContainerDescriptor.services); - } - @Override public String getVendorEmail() { return myVendorEmail; 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 c28a9d31fced..a390da257e0c 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 @@ -105,11 +105,14 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements registerServices(plugin); } myComponentConfigCount = componentConfigCount; - Level level = DefaultPicoContainer.getActivityLevel(getPicoContainer()); - if (level == Level.APPLICATION) { + + // app - phase must be set before getMessageBus() + if (getPicoContainer().getParent() == null) { LoadingPhase.setCurrentPhase(LoadingPhase.COMPONENT_REGISTERED); } - getMessageBus(); //register message bus in pico container + + //register message bus in pico container + getMessageBus(); } protected final void createComponents(@Nullable ProgressIndicator indicator) { diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java index a91aec979b68..847d5e3d4cb1 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java @@ -31,7 +31,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -public class VirtualFileManagerImpl extends VirtualFileManagerEx implements Disposable { +public class VirtualFileManagerImpl extends VirtualFileManagerEx implements Disposable { protected static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.VirtualFileManagerImpl"); private static class VirtualFileSystemBean extends KeyedLazyInstanceEP { 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 5ae6ef798323..97bc703a1205 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 @@ -2,6 +2,7 @@ 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; @@ -161,8 +162,8 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx @NotNull @Override - protected List getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) { - return ((IdeaPluginDescriptorImpl)pluginDescriptor).getModuleServices(); + protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) { + return pluginDescriptor.getModule(); } @Override diff --git a/platform/lvcs-api/src/com/intellij/history/LocalHistory.java b/platform/lvcs-api/src/com/intellij/history/LocalHistory.java index 58fe4734e5d8..23c24109f645 100644 --- a/platform/lvcs-api/src/com/intellij/history/LocalHistory.java +++ b/platform/lvcs-api/src/com/intellij/history/LocalHistory.java @@ -1,22 +1,7 @@ -/* - * Copyright 2000-2009 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.history; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -26,9 +11,10 @@ public abstract class LocalHistory { public static final Object VFS_EVENT_REQUESTOR = new Object(); private static class LocalHistoryHolder { - static final LocalHistory ourInstance = ApplicationManager.getApplication().getComponent(LocalHistory.class); + static final LocalHistory ourInstance = ServiceManager.getService(LocalHistory.class); } + @NotNull public static LocalHistory getInstance() { return LocalHistoryHolder.ourInstance; } @@ -47,5 +33,4 @@ public abstract class LocalHistory { public abstract byte[] getByteContent(VirtualFile f, FileRevisionTimestampComparator c); public abstract boolean isUnderControl(@NotNull VirtualFile f); - } diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java index 792114e80c49..bd0f6abeb7f4 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 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. +// 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.history.integration; import com.intellij.history.*; @@ -8,11 +8,11 @@ import com.intellij.history.integration.ui.models.EntireFileHistoryDialogModel; import com.intellij.history.integration.ui.models.HistoryDialogModel; import com.intellij.history.utils.LocalHistoryLog; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.command.CommandListener; -import com.intellij.openapi.components.BaseComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; @@ -20,7 +20,6 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; -import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -32,8 +31,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import static com.intellij.history.integration.LocalHistoryUtil.findRevisionIndexToRevert; -public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Disposable { - private final MessageBus myBus; +public final class LocalHistoryImpl extends LocalHistory implements Disposable { private MessageBusConnection myConnection; private ChangeList myChangeList; private LocalHistoryFacade myVcs; @@ -44,17 +42,20 @@ public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Dis private final AtomicBoolean isInitialized = new AtomicBoolean(); private Runnable myShutdownTask; + @NotNull public static LocalHistoryImpl getInstanceImpl() { return (LocalHistoryImpl)getInstance(); } - public LocalHistoryImpl(@NotNull MessageBus bus) { - myBus = bus; + public LocalHistoryImpl() { + init(); } - @Override - public void initComponent() { - if (!ApplicationManager.getApplication().isUnitTestMode() && ApplicationManager.getApplication().isHeadlessEnvironment()) return; + private void init() { + Application app = ApplicationManager.getApplication(); + if (!app.isUnitTestMode() && app.isHeadlessEnvironment()) { + return; + } myShutdownTask = () -> doDispose(); ShutDownTracker.getInstance().registerShutdownTask(myShutdownTask); @@ -63,7 +64,7 @@ public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Dis isInitialized.set(true); } - protected void initHistory() { + private void initHistory() { ChangeListStorage storage; try { storage = new ChangeListStorageImpl(getStorageDir()); @@ -72,6 +73,7 @@ public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Dis LocalHistoryLog.LOG.warn("cannot create storage, in-memory implementation will be used", e); storage = new InMemoryChangeListStorage(); } + myChangeList = new ChangeList(storage); myVcs = new LocalHistoryFacade(myChangeList); @@ -79,19 +81,19 @@ public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Dis myEventDispatcher = new LocalHistoryEventDispatcher(myVcs, myGateway); - myConnection = myBus.connect(this); + myConnection = ApplicationManager.getApplication().getMessageBus().connect(this); myConnection.subscribe(VirtualFileManager.VFS_CHANGES, myEventDispatcher); myConnection.subscribe(CommandListener.TOPIC, myEventDispatcher); - VirtualFileManager fm = VirtualFileManager.getInstance(); - fm.addVirtualFileManagerListener(myEventDispatcher, this); + VirtualFileManager.getInstance().addVirtualFileManagerListener(myEventDispatcher, this); } - public File getStorageDir() { + @NotNull + public static File getStorageDir() { return new File(getSystemPath(), "LocalHistory"); } - protected String getSystemPath() { + private static String getSystemPath() { return PathManager.getSystemPath(); } @@ -120,7 +122,7 @@ public class LocalHistoryImpl extends LocalHistory implements BaseComponent, Dis public void cleanupForNextTest() { doDispose(); FileUtil.delete(getStorageDir()); - initComponent(); + init(); } @Override diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java index 9c80bebdc418..e1a13d5b09bc 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java @@ -8,6 +8,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.diagnostic.Logger; @@ -102,7 +103,7 @@ public class HttpConfigurable implements PersistentStateComponent myTestGenericAuthRunnable = new StaticGetter<>(null); public static HttpConfigurable getInstance() { - return ApplicationManager.getApplication().getComponent(HttpConfigurable.class); + return ServiceManager.getService(HttpConfigurable.class); } public static boolean editConfigurable(@Nullable JComponent parent) { @@ -123,31 +124,32 @@ public class HttpConfigurable implements PersistentStateComponent> myPacProxySelector = new AtomicReference<>(); - public IdeaWideProxySelector(HttpConfigurable configurable) { + public IdeaWideProxySelector(@NotNull HttpConfigurable configurable) { myHttpConfigurable = configurable; } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.kt b/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.kt index 8a09dcddfd4f..a9aca592de75 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/DebugLogManager.kt @@ -2,7 +2,7 @@ package com.intellij.diagnostic import com.intellij.ide.util.PropertiesComponent -import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.logger import com.intellij.util.containers.ContainerUtil import org.apache.log4j.Level @@ -21,7 +21,7 @@ class DebugLogManager { companion object { @JvmStatic - fun getInstance(): DebugLogManager = ApplicationManager.getApplication().getComponent(DebugLogManager::class.java) + fun getInstance() = service() } init { diff --git a/platform/platform-impl/src/com/intellij/diagnostic/startUpPerformanceReporter/serviceReporter.kt b/platform/platform-impl/src/com/intellij/diagnostic/startUpPerformanceReporter/serviceReporter.kt index 5402baa19599..96cb6f9e1590 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/startUpPerformanceReporter/serviceReporter.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/startUpPerformanceReporter/serviceReporter.kt @@ -65,13 +65,13 @@ internal fun writeServiceStats(writer: JsonGenerator) { val plugins = PluginManagerCore.getLoadedPlugins() for (plugin in plugins) { - service.app += (plugin as IdeaPluginDescriptorImpl).appServices.size - service.project += plugin.projectServices.size - service.module += plugin.moduleServices.size + service.app += (plugin as IdeaPluginDescriptorImpl).app.services.size + service.project += plugin.project.services.size + service.module += plugin.module.services.size - component.app += plugin.appComponents.size - component.project += plugin.projectComponents.size - component.module += plugin.moduleComponents.size + component.app += plugin.app.components.size + component.project += plugin.project.components.size + component.module += plugin.module.components.size } writer.obj("stats") { diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt index 8db0ef8e278a..7f580a165378 100644 --- a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt +++ b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.kt @@ -10,21 +10,21 @@ import com.intellij.ide.customize.CustomizeIDEWizardDialog import com.intellij.ide.customize.CustomizeIDEWizardStepsProvider import com.intellij.ide.impl.OpenProjectTask import com.intellij.ide.impl.ProjectUtil -import com.intellij.ide.plugins.IdeaPluginDescriptor -import com.intellij.ide.plugins.MainRunner -import com.intellij.ide.plugins.PluginManager -import com.intellij.ide.plugins.PluginManagerCore +import com.intellij.ide.plugins.* import com.intellij.ide.ui.customization.CustomActionsSchema import com.intellij.openapi.actionSystem.IdeActions import com.intellij.openapi.application.* import com.intellij.openapi.application.ex.ApplicationManagerEx import com.intellij.openapi.application.impl.ApplicationImpl +import com.intellij.openapi.components.stateStore import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogEarthquakeShaker import com.intellij.openapi.util.IconLoader import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemPropertyBean +import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.registry.RegistryKeyBean import com.intellij.openapi.wm.IdeFrame import com.intellij.openapi.wm.WeakFocusStackManager @@ -78,14 +78,30 @@ private fun executeInitAppInEdt(rawArgs: Array, starter.premain(args) - val futures = mutableListOf>() - futures.add(registerRegistryAndMessageBusAndComponent(pluginDescriptorsFuture, app, initAppActivity)) + // this code is here for one simple reason - here we have application, + // and after plugin loading we don't have - ApplicationManager.getApplication() can be used, but it doesn't matter + // but it is very important to call registerRegistryAndMessageBusAndComponent immediately after application creation + // and do not place any time-consuming code in between (e.g. showLicenseeInfoOnSplash) + var future = registerRegistryAndMessageBusAndComponent(pluginDescriptorsFuture, app, initAppActivity) if (!headless) { - // todo investigate why in test mode dummy icon manager is not suitable - IconLoader.activate() - IconLoader.setStrictGlobally(app.isInternal) + initAppActivity.runChild("icon loader activation") { + // todo investigate why in test mode dummy icon manager is not suitable + IconLoader.activate() + IconLoader.setStrictGlobally(app.isInternal) + } + } + // preload services only after icon activation + future = future.thenCompose { + val preloadServiceActivity = StartUpMeasurer.start("preload services") + preloadServices(app) + .thenRun(Runnable { + preloadServiceActivity.end() + }) + } + + if (!headless) { if (SystemInfo.isMac) { initAppActivity.runChild("mac app init") { MacOSApplicationProvider.initApplication() @@ -100,7 +116,10 @@ private fun executeInitAppInEdt(rawArgs: Array, } } - SplashManager.showLicenseeInfoOnSplash(LOG) + // disabled due to https://youtrack.jetbrains.com/issue/JBR-1399 + //initAppActivity.runChild("showLicenseeInfoOnSplash") { + // SplashManager.showLicenseeInfoOnSplash(LOG) + //} AppExecutorUtil.getAppExecutorService().execute { AsyncProcessIcon("") @@ -110,44 +129,42 @@ private fun executeInitAppInEdt(rawArgs: Array, AllIcons.Ide.Shadow.Top.iconHeight } - //IDEA-170295 - PlatformDefaults.setLogicalPixelBase(PlatformDefaults.BASE_FONT_SIZE) - + initAppActivity.runChild("migLayout") { + //IDEA-170295 + PlatformDefaults.setLogicalPixelBase(PlatformDefaults.BASE_FONT_SIZE) + } WeakFocusStackManager.getInstance() } - // this invokeLater() call is needed to place the app starting code on a freshly minted IdeEventQueue instance - val placeOnEventQueueActivity = initAppActivity.startChild(Phases.PLACE_ON_EVENT_QUEUE) - EventQueue.invokeLater { - placeOnEventQueueActivity.end() - StartupUtil.installExceptionHandler() - initAppActivity.runChild(Phases.WAIT_PLUGIN_INIT) { - for (future in futures) { - future.get() + future.thenRun(Runnable { + // this invokeLater() call is needed not only because current thread maybe not EDT, but to place the app starting code on a freshly minted IdeEventQueue instance + val placeOnEventQueueActivity = initAppActivity.startChild(Phases.PLACE_ON_EVENT_QUEUE) + EventQueue.invokeLater { + placeOnEventQueueActivity.end() + StartupUtil.installExceptionHandler() + initAppActivity.end() + + app.load(null, SplashManager.getProgressIndicator(), true) + if (!headless) { + addActivateAndWindowsCliListeners(app) + } + + (TransactionGuard.getInstance() as TransactionGuardImpl).performUserActivity { + starter.main(args) + } + + if (PluginManagerCore.isRunningFromSources()) { + AppExecutorUtil.getAppExecutorService().execute { + AppUIUtil.updateWindowIcon(JOptionPane.getRootFrame()) + } } } - initAppActivity.end() - - app.load(null, SplashManager.getProgressIndicator()) - if (!headless) { - addActivateAndWindowsCliListeners(app) - } - - (TransactionGuard.getInstance() as TransactionGuardImpl).performUserActivity { - starter.main(args) - } - - if (PluginManagerCore.isRunningFromSources()) { - AppExecutorUtil.getAppExecutorService().execute { - AppUIUtil.updateWindowIcon(JOptionPane.getRootFrame()) - } - } - } + }) } private fun registerRegistryAndMessageBusAndComponent(pluginDescriptorsFuture: CompletableFuture>, app: ApplicationImpl, - initAppActivity: Activity): CompletableFuture { + initAppActivity: Activity): CompletableFuture { return pluginDescriptorsFuture .thenCompose { pluginDescriptors -> val future = CompletableFuture.runAsync(Runnable { @@ -167,6 +184,9 @@ private fun registerRegistryAndMessageBusAndComponent(pluginDescriptorsFuture: C app.registerMessageBusListeners(pluginDescriptors, false) } + // yes, at this moment initSystemProperties or RegistryKeyBean.addKeysFromPlugins maybe not yet performed, but it doesn't affect because not used. + IdeaApplication.initConfigurationStore(app, null) + future } } @@ -275,6 +295,30 @@ object IdeaApplication { fun setWizardStepsProvider(provider: CustomizeIDEWizardStepsProvider) { wizardStepProvider = provider } + + @JvmStatic + fun initConfigurationStore(app: ApplicationImpl, configPath: String?) { + val beforeApplicationLoadedActivity = StartUpMeasurer.start("beforeApplicationLoaded") + val effectiveConfigPath = FileUtilRt.toSystemIndependentName(configPath ?: PathManager.getConfigPath()) + for (listener in ApplicationLoadListener.EP_NAME.iterable) { + try { + (listener ?: break).beforeApplicationLoaded(app, effectiveConfigPath) + } + catch (e: ProcessCanceledException) { + throw e + } + catch (e: Throwable) { + LOG.error(e) + } + } + + val initStoreActivity = beforeApplicationLoadedActivity.endAndStart("init app store") + + // we set it after beforeApplicationLoaded call, because app store can depends on stream provider state + app.stateStore.setPath(effectiveConfigPath) + LoadingPhase.setCurrentPhase(LoadingPhase.CONFIGURATION_STORE_INITIALIZED) + initStoreActivity.end() + } } open class IdeStarter : ApplicationStarter { @@ -447,4 +491,34 @@ private fun processProgramArguments(args: Array): Array { arguments.add(arg) } return ArrayUtilRt.toStringArray(arguments) +} + +private fun preloadServices(app: ApplicationImpl): CompletableFuture { + val toPreload = mutableListOf() + val picoContainer = app.picoContainer + for (plugin in PluginManagerCore.getLoadedPlugins()) { + for (service in (plugin as IdeaPluginDescriptorImpl).app.services) { + if (service.preload) { + toPreload.add(service.getInterface()) + } + } + } + + if (toPreload.isEmpty()) { + return CompletableFuture.completedFuture(null) + } + + val appExecutorService = AppExecutorUtil.getAppExecutorService() + + val maxThreads = Runtime.getRuntime().availableProcessors() + val bucketSize = Math.max(toPreload.size / maxThreads, 1) + return CompletableFuture.allOf(*Array(Math.min(toPreload.size, maxThreads)) { + val startIndex = it * bucketSize + val list = toPreload.subList(startIndex, Math.min(startIndex + bucketSize, toPreload.size)) + CompletableFuture.runAsync(Runnable { + for (key in list) { + picoContainer.getComponentInstance(key) + } + }, appExecutorService) + }) } \ 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 c82ad83fdc73..53c3b269fa0a 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 @@ -10,9 +10,11 @@ import com.intellij.diagnostic.StartUpMeasurer.Phases; import com.intellij.execution.process.ProcessIOExecutorService; import com.intellij.featureStatistics.fusCollectors.LifecycleUsageTriggerCollector; import com.intellij.ide.*; +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.idea.IdeaApplication; import com.intellij.idea.Main; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ex.ActionUtil; @@ -21,7 +23,6 @@ import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.application.ex.ApplicationUtil; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ServiceDescriptor; -import com.intellij.openapi.components.ServiceKt; import com.intellij.openapi.components.impl.PlatformComponentManagerImpl; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; @@ -40,7 +41,6 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.*; -import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.*; @@ -175,7 +175,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App ConcurrentMap> map = ContainerUtil.newConcurrentMap(); boolean isHeadlessMode = isHeadlessEnvironment(); for (IdeaPluginDescriptor descriptor : pluginDescriptors) { - List listeners = ((IdeaPluginDescriptorImpl)descriptor).getListeners(); + List listeners = ((IdeaPluginDescriptorImpl)descriptor).getApp().getListeners(); if (!listeners.isEmpty()) { for (ListenerDescriptor listener : listeners) { if (isUnitTestMode && !listener.activeInTestMode) { @@ -383,7 +383,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App @Override public void load(@Nullable final String configPath) { registerComponents(PluginManagerCore.getLoadedPlugins()); - load(configPath, null); + load(configPath, null, false); } @Override @@ -391,29 +391,21 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App super.registerComponents(plugins); } - public void load(@Nullable String configPath, @Nullable ProgressIndicator indicator) { + public void load(@Nullable String configPath, @Nullable ProgressIndicator indicator, boolean isServicePreloaded) { AccessToken token = HeavyProcessLatch.INSTANCE.processStarted("Loading application components"); try { - Activity beforeApplicationLoadedActivity = StartUpMeasurer.start("beforeApplicationLoaded"); - String effectiveConfigPath = FileUtilRt.toSystemIndependentName(configPath == null ? PathManager.getConfigPath() : configPath); - for (ApplicationLoadListener listener : ApplicationLoadListener.EP_NAME.getIterable()) { - try { - listener.beforeApplicationLoaded(this, effectiveConfigPath); - } - catch (ProcessCanceledException e) { - throw e; - } - catch (Throwable e) { - LOG.error(e); + if (!isServicePreloaded) { + IdeaApplication.initConfigurationStore(this, configPath); + + MutablePicoContainer picoContainer = getPicoContainer(); + for (IdeaPluginDescriptor plugin : PluginManagerCore.getLoadedPlugins()) { + for (ServiceDescriptor service : ((IdeaPluginDescriptorImpl)plugin).getApp().getServices()) { + if (service.preload) { + picoContainer.getComponentInstance(service.getInterface()); + } + } } } - Activity initStoreActivity = beforeApplicationLoadedActivity.endAndStart("init app store"); - - // we set it after beforeApplicationLoaded call, because app store can depends on stream provider state - ServiceKt.getStateStore(this).setPath(effectiveConfigPath); - LoadingPhase.setCurrentPhase(LoadingPhase.CONFIGURATION_STORE_INITIALIZED); - - initStoreActivity.end(); if (indicator == null) { // no splash, no need to to use progress manager @@ -748,7 +740,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App doExit(force, exitConfirmed, restart, elevate, beforeRestart); } else { - invokeLater(() -> doExit(force, exitConfirmed, restart, elevate, beforeRestart), ModalityState.NON_MODAL); + invokeLater(() -> { + doExit(force, exitConfirmed, restart, elevate, beforeRestart); + }, ModalityState.NON_MODAL); } } @@ -1424,8 +1418,8 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App @NotNull @Override - protected List getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) { - return ((IdeaPluginDescriptorImpl)pluginDescriptor).getAppServices(); + protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) { + return pluginDescriptor.getApp(); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.java index cd456f8405af..3a54bd58c891 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.java @@ -2,7 +2,9 @@ package com.intellij.openapi.components.impl; import com.intellij.diagnostic.LoadingPhase; +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.components.ComponentManager; import com.intellij.openapi.components.PathMacroManager; @@ -14,8 +16,6 @@ import com.intellij.util.messages.MessageBusFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public abstract class PlatformComponentManagerImpl extends ComponentManagerImpl { private boolean myHandlingInitComponentError; @@ -55,9 +55,9 @@ public abstract class PlatformComponentManagerImpl extends ComponentManagerImpl @Override protected final void registerServices(@NotNull IdeaPluginDescriptor pluginDescriptor) { - ServiceManagerImpl.registerServices(getServices(pluginDescriptor), pluginDescriptor, this); + ServiceManagerImpl.registerServices(getContainerDescriptor((IdeaPluginDescriptorImpl)pluginDescriptor).getServices(), pluginDescriptor, this); } @NotNull - protected abstract List getServices(@NotNull IdeaPluginDescriptor pluginDescriptor); + protected abstract ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor); } 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 4f5c904eb2ee..8d8e62b16f38 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 @@ -5,10 +5,7 @@ import com.intellij.diagnostic.LoadingPhase; import com.intellij.diagnostic.ParallelActivity; import com.intellij.diagnostic.PluginException; import com.intellij.diagnostic.StartUpMeasurer; -import com.intellij.ide.plugins.IdeaPluginDescriptor; -import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; -import com.intellij.ide.plugins.PluginManager; -import com.intellij.ide.plugins.PluginManagerCore; +import com.intellij.ide.plugins.*; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; @@ -71,25 +68,25 @@ public final class ServiceManagerImpl implements Disposable { public static void processAllDescriptors(@NotNull Consumer consumer, @NotNull ComponentManager componentManager) { for (IdeaPluginDescriptor plugin : PluginManagerCore.getLoadedPlugins()) { IdeaPluginDescriptorImpl pluginDescriptor = (IdeaPluginDescriptorImpl)plugin; - List serviceDescriptors; + ContainerDescriptor containerDescriptor; if (componentManager instanceof Application) { - serviceDescriptors = pluginDescriptor.getAppServices(); + containerDescriptor = pluginDescriptor.getApp(); } else if (componentManager instanceof Project) { - serviceDescriptors = pluginDescriptor.getProjectServices(); + containerDescriptor = pluginDescriptor.getProject(); } else { - serviceDescriptors = pluginDescriptor.getModuleServices(); + containerDescriptor = pluginDescriptor.getModule(); } - serviceDescriptors.forEach(consumer); + containerDescriptor.getServices().forEach(consumer); } } @ApiStatus.Internal public static void processProjectDescriptors(@NotNull BiConsumer consumer) { for (IdeaPluginDescriptor plugin : PluginManagerCore.getLoadedPlugins()) { - for (ServiceDescriptor serviceDescriptor : ((IdeaPluginDescriptorImpl)plugin).getProjectServices()) { + for (ServiceDescriptor serviceDescriptor : ((IdeaPluginDescriptorImpl)plugin).getProject().getServices()) { consumer.accept(serviceDescriptor, plugin); } } 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 23b8f6cbe73e..98dcaae26fc6 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 @@ -5,6 +5,7 @@ import com.intellij.configurationStore.StoreUtil; 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; @@ -180,8 +181,8 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project @NotNull @Override - protected List getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) { - return ((IdeaPluginDescriptorImpl)pluginDescriptor).getProjectServices(); + protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) { + return pluginDescriptor.getProject(); } @Nullable diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/PlatformVirtualFileManager.java b/platform/platform-impl/src/com/intellij/openapi/vfs/PlatformVirtualFileManager.java index 0c93e3548839..94c0fba29331 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/PlatformVirtualFileManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/PlatformVirtualFileManager.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; -public class PlatformVirtualFileManager extends VirtualFileManagerImpl { +public final class PlatformVirtualFileManager extends VirtualFileManagerImpl { @NotNull private final ManagingFS myManagingFS; public PlatformVirtualFileManager() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index f3ff2ddd7f72..83b52554ae0e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -31,10 +31,12 @@ import com.intellij.util.containers.MostlySingularMultiMap; import com.intellij.util.containers.MultiMap; import com.intellij.util.io.ReplicatorInputStream; import com.intellij.util.io.URLUtil; -import com.intellij.util.messages.MessageBus; import com.intellij.util.text.CharArrayUtil; import com.intellij.util.text.CharSequenceHashingStrategy; -import gnu.trove.*; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import gnu.trove.TIntArrayList; +import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,7 +52,7 @@ import java.util.function.Function; /** * @author max */ -public class PersistentFSImpl extends PersistentFS implements Disposable { +public final class PersistentFSImpl extends PersistentFS implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.persistent.PersistentFS"); private final Map myRoots = @@ -65,10 +67,10 @@ public class PersistentFSImpl extends PersistentFS implements Disposable { private final BulkFileListener myPublisher; private final VfsData myVfsData = new VfsData(); - public PersistentFSImpl(@NotNull MessageBus bus) { + public PersistentFSImpl() { ShutDownTracker.getInstance().registerShutdownTask(this::performShutdown); LowMemoryWatcher.register(this::clearIdCache, this); - myPublisher = bus.syncPublisher(VirtualFileManager.VFS_CHANGES); + myPublisher = ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES); AsyncEventSupport.startListening(); diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectFrameAllocator.kt b/platform/platform-impl/src/com/intellij/platform/ProjectFrameAllocator.kt index fea1e996191c..f3da94839fdb 100644 --- a/platform/platform-impl/src/com/intellij/platform/ProjectFrameAllocator.kt +++ b/platform/platform-impl/src/com/intellij/platform/ProjectFrameAllocator.kt @@ -40,16 +40,15 @@ internal class ProjectUiFrameAllocator(private var options: OpenProjectTask) : P var completed = false TransactionGuard.getInstance().submitTransactionAndWait { val frame = createFrame(file) - completed = ProgressManager.getInstance() - .runProcessWithProgressSynchronously( - { - ApplicationManager.getApplication().invokeLater { - runActivity("init frame") { - initFrame(frame) - } + completed = ProgressManager.getInstance().runProcessWithProgressSynchronously( + { + ApplicationManager.getApplication().invokeLater { + runActivity("init frame") { + initFrame(frame) } - task.run() - }, "Loading Project...", true, null, frame.component) + } + task.run() + }, "Loading Project...", true, null, frame.component) } return completed } diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index e199c9f46786..6aea486be0fc 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -12,6 +12,10 @@ + + + @@ -27,6 +31,8 @@ + + diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml index d6b97e57bf49..b0db01d4784b 100644 --- a/platform/platform-resources/src/componentSets/Platform.xml +++ b/platform/platform-resources/src/componentSets/Platform.xml @@ -39,11 +39,6 @@ com.intellij.openapi.editor.impl.EditorFactoryImpl - - com.intellij.history.LocalHistory - com.intellij.history.integration.LocalHistoryImpl - - com.intellij.openapi.command.undo.UndoManager com.intellij.openapi.command.impl.UndoManagerImpl @@ -95,10 +90,6 @@ - - com.intellij.util.net.HttpConfigurable - - com.intellij.ide.SystemHealthMonitor @@ -109,10 +100,6 @@ - - com.intellij.diagnostic.DebugLogManager - - com.intellij.openapi.editor.EditorLastActionTracker com.intellij.openapi.editor.impl.EditorLastActionTrackerImpl diff --git a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml index 03ffbab14f48..c97cae39b5d7 100644 --- a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml +++ b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml @@ -2,12 +2,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/XInclude http://www.w3.org/2001/XInclude.xsd"> - - - - com.intellij.openapi.util.registry.RegistryState - - com.intellij.profile.codeInspection.ProjectInspectionProfileManager diff --git a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java index aa7b0f364626..6dc863c4bdf8 100644 --- a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java +++ b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java @@ -118,7 +118,7 @@ public final class IdeaTestApplication implements Disposable { app.registerComponents(loadedPlugins); app.registerMessageBusListeners(loadedPlugins, true); RegistryKeyBean.addKeysFromPlugins(); - app.load(configPath, null); + app.load(configPath, null, false); isBootstrappingAppNow = false; ourInstance = new IdeaTestApplication(); diff --git a/platform/util/src/com/intellij/diagnostic/StartUpMeasurer.java b/platform/util/src/com/intellij/diagnostic/StartUpMeasurer.java index 8aedf2ab7147..9bb74134959b 100644 --- a/platform/util/src/com/intellij/diagnostic/StartUpMeasurer.java +++ b/platform/util/src/com/intellij/diagnostic/StartUpMeasurer.java @@ -34,8 +34,6 @@ public final class StartUpMeasurer { public static final String PLACE_ON_EVENT_QUEUE = "place on event queue"; - public static final String WAIT_PLUGIN_INIT = "wait plugin initialization"; - // actually, now it is also registers services, not only components,but it doesn't worth to rename public static final String REGISTER_COMPONENTS_SUFFIX = "component registration"; public static final String CREATE_COMPONENTS_SUFFIX = "component creation";