ability to preload service

GitOrigin-RevId: 4aa43f08a5d8dca5be65ec288b22539346654ca1
This commit is contained in:
Vladimir Krivosheev
2019-08-01 12:04:14 +03:00
committed by intellij-monorepo-bot
parent a4c6f8d8bd
commit 983f0f9950
27 changed files with 295 additions and 238 deletions
@@ -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();
}
@@ -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) {
}
@@ -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<ServiceDescriptor> services;
@Nullable
@@ -22,7 +24,22 @@ final class ContainerDescriptor {
@Nullable
List<Element> extensionsPoints;
public void addService(@NotNull ServiceDescriptor serviceDescriptor) {
@NotNull
public List<ServiceDescriptor> getServices() {
return ContainerUtil.notNullize(services);
}
@NotNull
public List<ComponentConfig> getComponents() {
return ContainerUtil.notNullize(components);
}
@NotNull
public List<ListenerDescriptor> 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<ComponentConfig> getComponentListToAdd(int size) {
List<ComponentConfig> getComponentListToAdd(int size) {
List<ComponentConfig> 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);
@@ -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<ServiceDescriptor> getAppServices() {
return ContainerUtil.notNullize(myAppContainerDescriptor.services);
}
@NotNull
public List<ListenerDescriptor> getListeners() {
return ContainerUtil.notNullize(myAppContainerDescriptor.listeners);
}
@NotNull
public List<ServiceDescriptor> getProjectServices() {
return ContainerUtil.notNullize(myProjectContainerDescriptor.services);
}
@NotNull
public List<ServiceDescriptor> getModuleServices() {
return ContainerUtil.notNullize(myModuleContainerDescriptor.services);
}
@Override
public String getVendorEmail() {
return myVendorEmail;
@@ -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) {
@@ -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<VirtualFileSystem> {
@@ -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<ServiceDescriptor> getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) {
return ((IdeaPluginDescriptorImpl)pluginDescriptor).getModuleServices();
protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) {
return pluginDescriptor.getModule();
}
@Override
@@ -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);
}
@@ -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
@@ -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<HttpConfigurab
public transient Getter<PasswordAuthentication> 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<HttpConfigurab
}
@Override
public void initializeComponent() {
final HttpConfigurable currentState = getState();
if (currentState != null) {
final Element serialized = XmlSerializer.serialize(currentState);
if (serialized == null) {
// all settings are defaults
// trying user's proxy configuration entered while obtaining the license
final SharedProxyConfig.ProxyParameters cfg = SharedProxyConfig.load();
if (cfg != null) {
SharedProxyConfig.clear();
if (cfg.host != null) {
USE_HTTP_PROXY = true;
PROXY_HOST = cfg.host;
PROXY_PORT = cfg.port;
if (cfg.login != null) {
setPlainProxyPassword(new String(cfg.password));
storeSecure("proxy.login", cfg.login);
PROXY_AUTHENTICATION = true;
KEEP_PROXY_PASSWORD = true;
}
}
}
}
public void noStateLoaded() {
// all settings are defaults
// trying user's proxy configuration entered while obtaining the license
SharedProxyConfig.ProxyParameters cfg = SharedProxyConfig.load();
if (cfg == null) {
return;
}
SharedProxyConfig.clear();
if (cfg.host == null) {
return;
}
USE_HTTP_PROXY = true;
PROXY_HOST = cfg.host;
PROXY_PORT = cfg.port;
if (cfg.login != null) {
setPlainProxyPassword(new String(cfg.password));
storeSecure("proxy.login", cfg.login);
PROXY_AUTHENTICATION = true;
KEEP_PROXY_PASSWORD = true;
}
}
@Override
public void initializeComponent() {
mySelector = new IdeaWideProxySelector(this);
String name = getClass().getName();
CommonProxy.getInstance().setCustom(name, mySelector);
@@ -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.util.net;
import com.intellij.openapi.application.Application;
@@ -20,15 +6,16 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.proxy.CommonProxy;
import com.intellij.util.proxy.NonStaticAuthenticator;
import org.jetbrains.annotations.NotNull;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class IdeaWideAuthenticator extends NonStaticAuthenticator {
public final class IdeaWideAuthenticator extends NonStaticAuthenticator {
private final static Logger LOG = Logger.getInstance("#com.intellij.util.net.IdeaWideAuthenticator");
private final HttpConfigurable myHttpConfigurable;
public IdeaWideAuthenticator(HttpConfigurable configurable) {
public IdeaWideAuthenticator(@NotNull HttpConfigurable configurable) {
myHttpConfigurable = configurable;
}
@@ -18,16 +18,13 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Irina.Chernushina
*/
public class IdeaWideProxySelector extends ProxySelector {
public final class IdeaWideProxySelector extends ProxySelector {
private final static Logger LOG = Logger.getInstance("#com.intellij.util.net.IdeaWideProxySelector");
private final HttpConfigurable myHttpConfigurable;
private final AtomicReference<Pair<ProxySelector, String>> myPacProxySelector = new AtomicReference<>();
public IdeaWideProxySelector(HttpConfigurable configurable) {
public IdeaWideProxySelector(@NotNull HttpConfigurable configurable) {
myHttpConfigurable = configurable;
}
@@ -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<DebugLogManager>()
}
init {
@@ -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") {
@@ -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<String>,
starter.premain(args)
val futures = mutableListOf<Future<*>>()
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<Void?> {
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<String>,
}
}
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<String>,
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<List<IdeaPluginDescriptor>>,
app: ApplicationImpl,
initAppActivity: Activity): CompletableFuture<Void> {
initAppActivity: Activity): CompletableFuture<Void?> {
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<String>): Array<String> {
arguments.add(arg)
}
return ArrayUtilRt.toStringArray(arguments)
}
private fun preloadServices(app: ApplicationImpl): CompletableFuture<Void?> {
val toPreload = mutableListOf<String>()
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)
})
}
@@ -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<String, List<ListenerDescriptor>> map = ContainerUtil.newConcurrentMap();
boolean isHeadlessMode = isHeadlessEnvironment();
for (IdeaPluginDescriptor descriptor : pluginDescriptors) {
List<ListenerDescriptor> listeners = ((IdeaPluginDescriptorImpl)descriptor).getListeners();
List<ListenerDescriptor> 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<ServiceDescriptor> getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) {
return ((IdeaPluginDescriptorImpl)pluginDescriptor).getAppServices();
protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) {
return pluginDescriptor.getApp();
}
@Override
@@ -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<ServiceDescriptor> getServices(@NotNull IdeaPluginDescriptor pluginDescriptor);
protected abstract ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor);
}
@@ -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<? super ServiceDescriptor> consumer, @NotNull ComponentManager componentManager) {
for (IdeaPluginDescriptor plugin : PluginManagerCore.getLoadedPlugins()) {
IdeaPluginDescriptorImpl pluginDescriptor = (IdeaPluginDescriptorImpl)plugin;
List<ServiceDescriptor> 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<? super ServiceDescriptor, ? super PluginDescriptor> consumer) {
for (IdeaPluginDescriptor plugin : PluginManagerCore.getLoadedPlugins()) {
for (ServiceDescriptor serviceDescriptor : ((IdeaPluginDescriptorImpl)plugin).getProjectServices()) {
for (ServiceDescriptor serviceDescriptor : ((IdeaPluginDescriptorImpl)plugin).getProject().getServices()) {
consumer.accept(serviceDescriptor, plugin);
}
}
@@ -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<ServiceDescriptor> getServices(@NotNull IdeaPluginDescriptor pluginDescriptor) {
return ((IdeaPluginDescriptorImpl)pluginDescriptor).getProjectServices();
protected ContainerDescriptor getContainerDescriptor(@NotNull IdeaPluginDescriptorImpl pluginDescriptor) {
return pluginDescriptor.getProject();
}
@Nullable
@@ -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() {
@@ -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<String, VirtualFileSystemEntry> 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();
@@ -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
}
@@ -12,6 +12,10 @@
<appStarter implementation="com.intellij.help.impl.ShowProductVersion"/>
<appStarter implementation="com.intellij.ide.plugins.BundledPluginsLister"/>
<applicationService serviceImplementation="com.intellij.diagnostic.DebugLogManager" preload="true"/>
<applicationService serviceInterface="com.intellij.history.LocalHistory"
serviceImplementation="com.intellij.history.integration.LocalHistoryImpl" preload="true"/>
<applicationService serviceImplementation="com.intellij.util.net.HttpConfigurable" preload="true"/>
<applicationService serviceInterface="com.intellij.openapi.keymap.KeymapManager"
serviceImplementation="com.intellij.openapi.keymap.impl.KeymapManagerImpl"/>
@@ -27,6 +31,8 @@
<virtualFileSystem implementationClass="com.intellij.openapi.vfs.impl.jar.JarFileSystemImpl" key="jar" physical="true"/>
<virtualFileSystem implementationClass="com.intellij.openapi.vfs.ex.temp.TempFileSystem" key="temp" physical="true"/>
<applicationService serviceImplementation="com.intellij.openapi.util.registry.RegistryState" preload="true"/>
<applicationService serviceInterface="com.intellij.execution.ExecutorRegistry"
serviceImplementation="com.intellij.execution.ExecutorRegistryImpl"/>
@@ -39,11 +39,6 @@
<implementation-class>com.intellij.openapi.editor.impl.EditorFactoryImpl</implementation-class>
</component>
<component>
<interface-class>com.intellij.history.LocalHistory</interface-class>
<implementation-class>com.intellij.history.integration.LocalHistoryImpl</implementation-class>
</component>
<component>
<interface-class>com.intellij.openapi.command.undo.UndoManager</interface-class>
<implementation-class>com.intellij.openapi.command.impl.UndoManagerImpl</implementation-class>
@@ -95,10 +90,6 @@
<headless-implementation-class/>
</component>
<component>
<implementation-class>com.intellij.util.net.HttpConfigurable</implementation-class>
</component>
<component>
<implementation-class>com.intellij.ide.SystemHealthMonitor</implementation-class>
<headless-implementation-class/>
@@ -109,10 +100,6 @@
<headless-implementation-class/>
</component>
<component>
<implementation-class>com.intellij.diagnostic.DebugLogManager</implementation-class>
</component>
<component>
<interface-class>com.intellij.openapi.editor.EditorLastActionTracker</interface-class>
<implementation-class>com.intellij.openapi.editor.impl.EditorLastActionTrackerImpl</implementation-class>
@@ -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">
<application-components>
<component>
<implementation-class>com.intellij.openapi.util.registry.RegistryState</implementation-class>
</component>
</application-components>
<project-components>
<component>
<implementation-class>com.intellij.profile.codeInspection.ProjectInspectionProfileManager</implementation-class>
@@ -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();
@@ -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";