diff --git a/platform/analysis-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java b/platform/analysis-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java index dc27555c84d8..5c0b4f594e2b 100644 --- a/platform/analysis-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java +++ b/platform/analysis-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java @@ -1,11 +1,11 @@ -// Copyright 2000-2020 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-2021 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.openapi.progress.util; import com.intellij.openapi.progress.StandardProgressIndicator; public class ProgressIndicatorBase extends AbstractProgressIndicatorExBase implements StandardProgressIndicator { public ProgressIndicatorBase() { - this(false); + super(); } public ProgressIndicatorBase(boolean reusable) { diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java index 02d5e31fc0cd..03c217116286 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.openapi.progress.util; import com.intellij.openapi.Disposable; @@ -16,12 +16,10 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.CoreAwareIconManager; import com.intellij.ui.IconManager; import com.intellij.util.DeprecatedMethodException; import com.intellij.util.ObjectUtils; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import org.jetbrains.annotations.NonNls; @@ -29,8 +27,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collections; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; public class AbstractProgressIndicatorBase extends UserDataHolderBase implements ProgressIndicator { private static final Logger LOG = Logger.getInstance(AbstractProgressIndicatorBase.class); @@ -43,10 +43,10 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements private volatile boolean myRunning; private volatile boolean myStopped; - private volatile boolean myIndeterminate = Registry.is("ide.progress.indeterminate.by.default", true); + private volatile boolean myIndeterminate = Boolean.parseBoolean(System.getProperty("ide.progress.indeterminate.by.default", "true")); private volatile Runnable myMacActivity; // false by default - do not attempt to use such a relatively heavy code on start-up - private volatile boolean myShouldStartActivity = SystemInfoRt.isMac && Registry.is("idea.mac.prevent.app.nap", false); + private volatile boolean myShouldStartActivity = SystemInfoRt.isMac && Boolean.parseBoolean(System.getProperty("idea.mac.prevent.app.nap", "true")); private Stack<@NlsContexts.ProgressText String> myTextStack; // guarded by this private DoubleArrayList myFractionStack; // guarded by this @@ -88,7 +88,8 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements } } - private static final Set> ourReportedReuseExceptions = ContainerUtil.newConcurrentSet(); + @SuppressWarnings("SSBasedInspection") + private static final Set> ourReportedReuseExceptions = Collections.newSetFromMap(new ConcurrentHashMap<>()); protected boolean isReuseable() { return false; diff --git a/platform/diagnostic/format-changelog.md b/platform/diagnostic/format-changelog.md index 153959c7293a..88797bcba3d3 100644 --- a/platform/diagnostic/format-changelog.md +++ b/platform/diagnostic/format-changelog.md @@ -1,3 +1,7 @@ +# 31 + + * Rename `add registry keys` to `registry keys adding`. + # 30 * Add `preloading activity executing`. diff --git a/platform/diagnostic/src/startUpPerformanceReporter/StartUpPerformanceReporter.kt b/platform/diagnostic/src/startUpPerformanceReporter/StartUpPerformanceReporter.kt index 11b1c700806f..83e6db8b0329 100644 --- a/platform/diagnostic/src/startUpPerformanceReporter/StartUpPerformanceReporter.kt +++ b/platform/diagnostic/src/startUpPerformanceReporter/StartUpPerformanceReporter.kt @@ -38,7 +38,7 @@ class StartUpPerformanceReporter : StartupActivity, StartUpPerformanceService { companion object { internal val LOG = logger() - internal const val VERSION = "30" + internal const val VERSION = "31" internal fun sortItems(items: MutableList) { items.sortWith(Comparator { o1, o2 -> diff --git a/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java b/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java index ad71bc8b11bf..db3db9a79446 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/WeakFocusStackManager.java @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2021 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.openapi.wm; import com.intellij.util.containers.WeakList; @@ -12,20 +12,19 @@ import java.awt.event.FocusEvent; import java.util.List; public final class WeakFocusStackManager { + private static final WeakFocusStackManager INSTANCE = new WeakFocusStackManager(); + private final WeakList focusOwners = new WeakList<>(); - private static final WeakFocusStackManager instance = new WeakFocusStackManager(); - - @NotNull - public static WeakFocusStackManager getInstance() { - return instance; + public static @NotNull WeakFocusStackManager getInstance() { + return INSTANCE; } private WeakFocusStackManager() { Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { @Override public void eventDispatched(AWTEvent event) { - // We are interested only in FOCUS_GAINED events + // we are interested only in FOCUS_GAINED events if (event.getID() == FocusEvent.FOCUS_GAINED) { focusOwners.add((Component)event.getSource()); } @@ -33,8 +32,7 @@ public final class WeakFocusStackManager { }, AWTEvent.FOCUS_EVENT_MASK); } - @Nullable - public Component getLastFocusedOutside(Container container) { + public @Nullable Component getLastFocusedOutside(Container container) { List components = focusOwners.toStrongList(); for (int i = components.size() - 1; i >= 0; i--) { if (!SwingUtilities.isDescendingFrom(components.get(i), container)) { diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.kt b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.kt index b6bcadf5a921..25481dfaa547 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.kt +++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.kt @@ -492,8 +492,10 @@ open class RecentProjectsManagerBase : RecentProjectsManager(), PersistentStateC projectManager.openProject(entry.first, entry.second) } catch (e: Exception) { + @Suppress("SSBasedInspection") (entry.second.frameManager as MyProjectUiFrameManager?)?.dispose() while (iterator.hasNext()) { + @Suppress("SSBasedInspection") (iterator.next().second.frameManager as MyProjectUiFrameManager?)?.dispose() } diff --git a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt index 77e977e9a608..ded9f4d0a520 100644 --- a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt +++ b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt @@ -17,24 +17,19 @@ import com.intellij.openapi.components.stateStore import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.extensions.ExtensionNotApplicableException import com.intellij.openapi.extensions.PluginDescriptor -import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl import com.intellij.openapi.progress.EmptyProgressIndicator import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase -import com.intellij.openapi.progress.util.ProgressIndicatorBase import com.intellij.openapi.ui.DialogEarthquakeShaker -import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.IconLoader import com.intellij.openapi.util.SystemInfoRt import com.intellij.openapi.util.SystemPropertyBean import com.intellij.openapi.util.registry.RegistryKeyBean -import com.intellij.openapi.wm.WeakFocusStackManager import com.intellij.openapi.wm.WindowManager import com.intellij.serviceContainer.ComponentManagerImpl import com.intellij.ui.AnimatedIcon import com.intellij.ui.AppIcon -import com.intellij.ui.mac.MacOSApplicationProvider import com.intellij.ui.mac.foundation.Foundation import com.intellij.ui.mac.touchbar.TouchBarsManager import com.intellij.util.TimeoutUtil @@ -151,69 +146,89 @@ private fun startApp(app: ApplicationImpl, plugins } - val preloadSyncServiceFuture = initStoreFuture.thenAccept { - preloadServices(it, app, activityPrefix = "") + val appInitializedFuture = initStoreFuture.thenCompose { + val preloadSyncServiceFuture = preloadServices(it, app, activityPrefix = "") + + val placeOnEventQueueActivity = initAppActivity.startChild(Activities.PLACE_ON_EVENT_QUEUE) + val loadComponentInEdtFuture = CompletableFuture.runAsync({ + placeOnEventQueueActivity.end() + + val indicator = if (SplashManager.SPLASH_WINDOW == null) { + null + } + else object : EmptyProgressIndicator() { + override fun setFraction(fraction: Double) { + SplashManager.SPLASH_WINDOW.showProgress(fraction) + } + } + app.loadComponents(indicator) + }, Executor(app::invokeLater)) + + CompletableFuture.allOf(loadComponentInEdtFuture, preloadSyncServiceFuture, StartupUtil.getServerFuture()) } initStoreFuture.thenRunAsync({ - runActivity("add registry keys") { + runActivity("registry keys adding") { RegistryKeyBean.addKeysFromPlugins() } }, ForkJoinPool.commonPool()) - if (!app.isHeadlessEnvironment) { - if (SystemInfoRt.isMac) { - runActivity("mac app init") { - MacOSApplicationProvider.initApplication() - } - - initStoreFuture.thenRunAsync(Runnable { - // ensure that TouchBarsManager is loaded before WelcomeFrame/project - // do not wait completion - it is thread safe and not required for application start - runActivity("mac touchbar") { - if (app.isDisposed) { - return@Runnable - } - - Foundation.init() - if (app.isDisposed) { - return@Runnable - } - TouchBarsManager.initialize() + if (!app.isHeadlessEnvironment && SystemInfoRt.isMac) { + initStoreFuture.thenRunAsync(Runnable { + // ensure that TouchBarsManager is loaded before WelcomeFrame/project + // do not wait completion - it is thread safe and not required for application start + runActivity("mac touchbar") { + if (app.isDisposed) { + return@Runnable } - }, ForkJoinPool.commonPool()) - } - WeakFocusStackManager.getInstance() + Foundation.init() + if (app.isDisposed) { + return@Runnable + } + TouchBarsManager.initialize() + } + }, ForkJoinPool.commonPool()) } - initStoreFuture - .thenCompose { - val placeOnEventQueueActivity = initAppActivity.startChild(Activities.PLACE_ON_EVENT_QUEUE) - val loadComponentInEdtFuture = CompletableFuture.runAsync({ - placeOnEventQueueActivity.end() + appInitializedFuture + .thenComposeAsync({ + val pool = ForkJoinPool.commonPool() - val indicator = if (SplashManager.SPLASH_WINDOW == null) { - null + val future = CompletableFuture.runAsync({ + initAppActivity.runChild("app initialized callback") { + ForkJoinTask.invokeAll(callAppInitialized(app)) } - else object : EmptyProgressIndicator() { - override fun setFraction(fraction: Double) { - SplashManager.SPLASH_WINDOW.showProgress(fraction) + }, pool) + + if (!app.isUnitTestMode && !app.isHeadlessEnvironment && + java.lang.Boolean.parseBoolean(System.getProperty("enable.activity.preloading", "true"))) { + pool.execute { executePreloadActivities(app) } + } + + pool.execute { + runActivity("create locator file") { + val locatorFile = Path.of(PathManager.getSystemPath(), ApplicationEx.LOCATOR_FILE_NAME) + try { + locatorFile.parent?.createDirectories() + Files.writeString(locatorFile, PathManager.getHomePath(), StandardCharsets.UTF_8) + } + catch (e: IOException) { + LOG.warn("Can't store a location in '$locatorFile'", e) } } - app.loadComponents(indicator) - }, Executor { ApplicationManager.getApplication().invokeLater(it) }) + } - CompletableFuture.allOf(loadComponentInEdtFuture, preloadSyncServiceFuture, StartupUtil.getServerFuture()) - } - .thenRunAsync({ - initAppActivity.runChild("app initialized callback") { - ForkJoinTask.invokeAll(callAppInitialized(app)) + if (!Main.isLightEdit()) { + // this functionality should be used only by plugin functionality that is used after start-up + pool.execute { + runActivity("system properties setting") { + SystemPropertyBean.initSystemProperties() + } + } } - if (!app.isHeadlessEnvironment) { - addActivateAndWindowsCliListeners() - } - initAppActivity.end() + + future }, Executor { // if `loadComponentInEdtFuture` is completed after `preloadSyncServiceFuture`, // then this task will be executed in EDT, so force execution out of EDT @@ -225,6 +240,11 @@ private fun startApp(app: ApplicationImpl, } }) .thenRun { + if (!app.isHeadlessEnvironment) { + addActivateAndWindowsCliListeners() + } + initAppActivity.end() + if (starter.requiredModality == ApplicationStarter.NOT_IN_EDT) { starter.main(args) // no need to use pool once plugins are loaded @@ -261,8 +281,8 @@ fun preloadServices(plugins: List, } } - logError(result.asyncPreloadedServices) - return logError(result.syncPreloadedServices) + logError(result.first) + return logError(result.second) } private fun addActivateAndWindowsCliListeners() { @@ -398,139 +418,117 @@ private fun processProgramArguments(args: List): List { return arguments } -fun callAppInitialized(app: Application): List { - val extensionArea = app.extensionArea as ExtensionsAreaImpl + +fun callAppInitialized(app: ApplicationImpl): List> { + val extensionArea = app.extensionArea val extensionPoint = extensionArea.getExtensionPoint("com.intellij.applicationInitializedListener") - val result = ArrayList(extensionPoint.size()) + val result = ArrayList>(extensionPoint.size()) extensionPoint.processImplementations(/* shouldBeSorted = */ false) { supplier, _ -> - result.add(object : RecursiveAction() { - override fun compute() { - try { - supplier.get().componentsInitialized() - } - catch (ignore: ExtensionNotApplicableException) { - } - catch (e: Throwable) { - LOG.error(e) - } + result.add(ForkJoinTask.adapt { + try { + supplier.get().componentsInitialized() + } + catch (ignore: ExtensionNotApplicableException) { + } + catch (e: Throwable) { + LOG.error(e) } }) } extensionPoint.reset() - - if (!app.isUnitTestMode && !app.isHeadlessEnvironment && - java.lang.Boolean.parseBoolean(System.getProperty("enable.activity.preloading", "true"))) { - result.add(Preloader(extensionArea)) - } - - // should be after scheduling all app initialized listeners (because this activity is not important) - result.add(object : RecursiveAction() { - override fun compute() { - val pool = ForkJoinPool.commonPool() - pool.execute { - runActivity("create locator file") { - val locatorFile = Path.of(PathManager.getSystemPath(), ApplicationEx.LOCATOR_FILE_NAME) - try { - locatorFile.parent?.createDirectories() - Files.writeString(locatorFile, PathManager.getHomePath(), StandardCharsets.UTF_8) - } - catch (e: IOException) { - LOG.warn("Can't store a location in '$locatorFile'", e) - } - } - } - - if (!Main.isLightEdit()) { - // this functionality should be used only by plugin functionality that is used after start-up - pool.execute { - runActivity("system properties setting") { - SystemPropertyBean.initSystemProperties() - } - } - } - } - }) - return result } -private class Preloader(private val extensionArea: ExtensionsAreaImpl) : RecursiveAction() { - companion object { - @JvmStatic - private fun checkHeavyProcessRunning() { - if (HeavyProcessLatch.INSTANCE.isRunning) { - TimeoutUtil.sleep(1) - } +private fun checkHeavyProcessRunning() { + if (HeavyProcessLatch.INSTANCE.isRunning) { + TimeoutUtil.sleep(1) + } +} + +private fun executePreloadActivity(activity: PreloadingActivity, descriptor: PluginDescriptor?, app: ApplicationImpl) { + checkHeavyProcessRunning() + + val indicator = AbstractProgressIndicatorBase() + if (app.isDisposed) { + return + } + + val isDebugEnabled = LOG.isDebugEnabled + ProgressManager.getInstance().executeProcessUnderProgress({ + val measureActivity = if (descriptor == null) { + null + } + else { + StartUpMeasurer.startActivity(activity.javaClass.name, ActivityCategory.PRELOAD_ACTIVITY, descriptor.pluginId.idString) } - @JvmStatic - private fun preload(activity: PreloadingActivity, descriptor: PluginDescriptor?) { - val indicator = ProgressIndicatorBase() - Disposer.register(ApplicationManager.getApplication()) { indicator.cancel() } - val wrappingIndicator = object : AbstractProgressIndicatorBase() { + try { + indicator.start() + activity.preload(object : AbstractProgressIndicatorBase() { override fun checkCanceled() { checkHeavyProcessRunning() indicator.checkCanceled() } - override fun isCanceled() = indicator.isCanceled + override fun isCanceled() = indicator.isCanceled || app.isDisposed + }) + if (isDebugEnabled) { + LOG.debug("${activity.javaClass.name} finished") } + } + catch (ignore: ProcessCanceledException) { + return@executeProcessUnderProgress + } + finally { + measureActivity?.end() + if (indicator.isRunning) { + indicator.stop() + } + } + }, indicator) +} - if (indicator.isCanceled) { - return - } - checkHeavyProcessRunning() - if (indicator.isCanceled) { +private fun executePreloadActivities(app: ApplicationImpl) { + val activity = StartUpMeasurer.startActivity("preloading activity executing", ActivityCategory.APP_INIT) + val list = mutableListOf>() + val extensionPoint = app.extensionArea.getExtensionPoint("com.intellij.preloadingActivity") + extensionPoint.processImplementations(/* shouldBeSorted = */ false) { supplier, pluginDescriptor -> + val preloadingActivity: PreloadingActivity + try { + preloadingActivity = supplier.get() + } + catch (ignore: ExtensionNotApplicableException) { + return@processImplementations + } + catch (e: Throwable) { + LOG.error(e) + return@processImplementations + } + list.add(Pair(preloadingActivity, pluginDescriptor)) + } + extensionPoint.reset() + + if (list.isEmpty()) { + return + } + + // don't execute as one long task, make sure that other more important tasks maybe executed in between + ForkJoinPool.commonPool().execute(object : Runnable { + private var index = 0 + + override fun run() { + if (app.isDisposed) { return } - val isDebugEnabled = LOG.isDebugEnabled - ProgressManager.getInstance().runProcess({ - val measureActivity = if (descriptor == null) { - null - } - else { - StartUpMeasurer.startActivity(activity.javaClass.name, - ActivityCategory.PRELOAD_ACTIVITY, - descriptor.pluginId.idString) - } - - try { - activity.preload(wrappingIndicator) - } - catch (ignore: ProcessCanceledException) { - return@runProcess - } - finally { - measureActivity?.end() - } - if (isDebugEnabled) { - LOG.debug("${activity.javaClass.name} finished") - } - }, indicator) - } - - } - - override fun compute() { - runActivity("preloading activity executing") { - val extensionPoint = extensionArea.getExtensionPoint("com.intellij.preloadingActivity") - extensionPoint.processImplementations(/* shouldBeSorted = */ false) { supplier, pluginDescriptor -> - val activity: PreloadingActivity - try { - activity = supplier.get() - } - catch (ignore: ExtensionNotApplicableException) { - return@processImplementations - } - catch (e: Throwable) { - LOG.error(e) - return@processImplementations - } - - preload(activity, pluginDescriptor) + val item = list.get(index++) + executePreloadActivity(item.first, item.second, app) + if (index == list.size || app.isDisposed) { + activity.end() + } + else { + ForkJoinPool.commonPool().execute(this) } - extensionPoint.reset() } - } + }) } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/idea/IdeStarter.kt b/platform/platform-impl/src/com/intellij/idea/IdeStarter.kt index e75fae018e8f..fb728940960d 100644 --- a/platform/platform-impl/src/com/intellij/idea/IdeStarter.kt +++ b/platform/platform-impl/src/com/intellij/idea/IdeStarter.kt @@ -40,11 +40,14 @@ import com.intellij.util.ui.accessibility.ScreenReader import java.awt.EventQueue import java.beans.PropertyChangeListener import java.nio.file.Path +import java.util.concurrent.ForkJoinPool import javax.swing.JOptionPane open class IdeStarter : ApplicationStarter { companion object { + @JvmStatic private var filesToLoad: List = emptyList() + @JvmStatic private var wizardStepProvider: CustomizeIDEWizardStepsProvider? = null @JvmStatic @@ -79,15 +82,9 @@ open class IdeStarter : ApplicationStarter { val frameInitActivity = StartUpMeasurer.startMainActivity("frame initialization") - // Event queue should not be changed during initialization of application components. - // It also cannot be changed before initialization of application components because IdeEventQueue uses other - // application components. So it is proper to perform replacement only here. - // out of EDT val windowManager = WindowManagerEx.getInstanceEx() - app.invokeLater { - runMainActivity("IdeEventQueue informing about WindowManager") { - IdeEventQueue.getInstance().setWindowManager(windowManager) - } + runMainActivity("IdeEventQueue informing about WindowManager") { + IdeEventQueue.getInstance().setWindowManager(windowManager) } val lifecyclePublisher = app.messageBus.syncPublisher(AppLifecycleListener.TOPIC) @@ -222,7 +219,7 @@ private fun loadProjectFromExternalCommandLine(commandLineArgs: List): P private fun postOpenUiTasks(app: Application) { if (SystemInfoRt.isMac) { - NonUrgentExecutor.getInstance().execute { + ForkJoinPool.commonPool().execute { runActivity("mac touchbar on app init") { TouchBarsManager.onApplicationInitialized() if (TouchBarsManager.isTouchBarAvailable()) { @@ -232,7 +229,7 @@ private fun postOpenUiTasks(app: Application) { } } else if (SystemInfoRt.isXWindow && SystemInfo.isJetBrainsJvm) { - NonUrgentExecutor.getInstance().execute { + ForkJoinPool.commonPool().execute { runActivity("input method disabling on Linux") { disableInputMethodsIfPossible() } diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index cbef5e0e1f1d..e6f992c732e9 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -32,10 +32,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.win32.IdeaWin32; +import com.intellij.openapi.wm.WeakFocusStackManager; import com.intellij.openapi.wm.impl.X11UiUtil; import com.intellij.ui.AppUIUtil; import com.intellij.ui.CoreIconManager; import com.intellij.ui.IconManager; +import com.intellij.ui.mac.MacOSApplicationProvider; import com.intellij.ui.scale.JBUIScale; import com.intellij.util.EnvironmentUtil; import com.intellij.util.lang.ZipFilePool; @@ -86,7 +88,8 @@ public final class StartupUtil { public static BiFunction LISTENER = (integer, s) -> Main.ACTIVATE_NOT_INITIALIZED; private static final String IDEA_CLASS_BEFORE_APPLICATION_PROPERTY = "idea.class.before.app"; - private static final String USE_SEPARATE_WRITE_THREAD_PROPERTY = "idea.use.separate.write.thread"; // see `ApplicationImpl#USE_SEPARATE_WRITE_THREAD` + // see `ApplicationImpl#USE_SEPARATE_WRITE_THREAD` + private static final String USE_SEPARATE_WRITE_THREAD_PROPERTY = "idea.use.separate.write.thread"; private static final String MAGIC_MAC_PATH = "/AppTranslocation/"; @@ -312,7 +315,22 @@ public final class StartupUtil { } prepareUiFuture.complete(null); + + if (!Main.isHeadless()) { + // not important + EventQueue.invokeLater(() -> { + //noinspection ResultOfMethodCallIgnored + WeakFocusStackManager.getInstance(); + }); + } }); + if (!Main.isHeadless() && SystemInfoRt.isMac) { + ForkJoinPool.commonPool().execute(() -> { + Activity subActivity = StartUpMeasurer.startActivity("mac app init", ActivityCategory.APP_INIT); + MacOSApplicationProvider.initApplication(); + subActivity.end(); + }); + } }); startApp(Arrays.asList(args), prepareUiFuture, log, configImportNeeded, appStarterFuture, euaDocument); } 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 de3c591599dc..3c86594281af 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 @@ -359,7 +359,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application List plugins = PluginManagerCore.getLoadedPlugins(null); registerComponents(plugins, this, null); ApplicationLoader.initConfigurationStore(this); - preloadServices(plugins, "", false).getSyncPreloadedServices().join(); + preloadServices(plugins, "", false).getSecond().join(); loadComponents(null); ForkJoinTask.invokeAll(ApplicationLoader.callAppInitialized(this)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/SystemDock.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/SystemDock.java index ffe4ccf6ef81..4786ce94af77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/SystemDock.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/SystemDock.java @@ -1,10 +1,10 @@ -// 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. +// Copyright 2000-2021 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.openapi.wm.impl; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.ui.mac.MacDockDelegate; import com.intellij.ui.win.WinDockDelegate; import org.jetbrains.annotations.Nullable; @@ -18,35 +18,32 @@ public final class SystemDock { void updateRecentProjectsMenu(); } - - synchronized public static void updateMenu() { - try { - if (ourDelegate != null) { - ourDelegate.updateRecentProjectsMenu(); - } - } - catch (Throwable err) { - log.error(err); - } - } - - - private static final Logger log = Logger.getInstance(SystemDock.class); - private static final @Nullable Delegate ourDelegate; + private static final @Nullable Delegate impl; static { SystemDock.Delegate delegate = null; - final Application app = ApplicationManager.getApplication(); + Application app = ApplicationManager.getApplication(); if (app != null && !app.isUnitTestMode()) { - if (SystemInfo.isMac) { + if (SystemInfoRt.isMac) { delegate = MacDockDelegate.getInstance(); } - else if (SystemInfo.isWindows) { + else if (SystemInfoRt.isWindows) { delegate = WinDockDelegate.getInstance(); } } - ourDelegate = delegate; + impl = delegate; + } + + public synchronized static void updateMenu() { + try { + if (impl != null) { + impl.updateRecentProjectsMenu(); + } + } + catch (Throwable err) { + Logger.getInstance(SystemDock.class).error(err); + } } } diff --git a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt index a605a0030bf7..f9b2ad9d738c 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt @@ -822,8 +822,8 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren final override fun createError(error: Throwable, pluginId: PluginId): RuntimeException { return when (val effectiveError: Throwable = if (error is InvocationTargetException) error.targetException else error) { - is ProcessCanceledException, is ExtensionNotApplicableException -> effectiveError as RuntimeException - else -> createPluginExceptionIfNeeded(effectiveError, pluginId) + is ProcessCanceledException, is ExtensionNotApplicableException, is PluginException -> effectiveError as RuntimeException + else -> PluginException(effectiveError, pluginId) } } @@ -871,13 +871,10 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren @Internal open fun activityNamePrefix(): String? = null - data class ServicePreloadingResult(val asyncPreloadedServices: CompletableFuture, - val syncPreloadedServices: CompletableFuture) - @ApiStatus.Internal fun preloadServices(plugins: List, activityPrefix: String, - onlyIfAwait: Boolean = false): ServicePreloadingResult { + onlyIfAwait: Boolean = false): Pair, CompletableFuture> { val asyncPreloadedServices = mutableListOf() val syncPreloadedServices = mutableListOf() for (plugin in plugins) { @@ -934,13 +931,13 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren } } - return ServicePreloadingResult( - asyncPreloadedServices = CompletableFuture.runAsync({ + return Pair( + CompletableFuture.runAsync({ runActivity("${activityPrefix}service async preloading") { ForkJoinTask.invokeAll(asyncPreloadedServices) } }, ForkJoinPool.commonPool()), - syncPreloadedServices = CompletableFuture.runAsync({ + CompletableFuture.runAsync({ runActivity("${activityPrefix}service sync preloading") { ForkJoinTask.invokeAll(syncPreloadedServices) } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index d31cf0b1bdf6..31138601b06a 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -170,9 +170,6 @@ ide.hide.excluded.files.description=Do not show excluded files in Project View a use.tty.for.external.tools=false use.tty.for.external.tools.description=Use command line with TTY support to run 'External Tools' -idea.mac.prevent.app.nap=true -idea.mac.prevent.app.nap.description=Prevent app nap during indexing and inspection - ide.appIcon.badge=true ide.appIcon.requestAttention=true ide.appIcon.requestAttention.after.indexing=false @@ -1077,7 +1074,6 @@ project.tree.structure.show.url.description=Show URL in the ProjectView nodes fo ide.show.progress.without.status.bar=true ide.show.progress.without.status.bar.description=Disables transparent progress indicator when status bar is switched off -ide.progress.indeterminate.by.default=true editor.injected.highlighting.enabled=true editor.injected.highlighting.enabled.description=Disables injected fragments highlighting (requires project reopening) diff --git a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java index d43784c38242..ddc663d3cbc8 100644 --- a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java +++ b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java @@ -1,11 +1,10 @@ // Copyright 2000-2021 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.containers; -import com.intellij.reference.SoftReference; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.*; @@ -49,10 +48,11 @@ public class UnsafeWeakList extends AbstractCollection { boolean processQueue() { boolean processed = false; MyReference reference; + //noinspection unchecked while ((reference = (MyReference)myQueue.poll()) != null) { int index = reference.index; - - if (index < myList.size() && reference == myList.get(index)) { // list may have changed while the reference was dangling in queue + // list may have changed while the reference was dangling in queue + if (index < myList.size() && reference == myList.get(index)) { nullizeAt(index); } processed = true; @@ -151,7 +151,8 @@ public class UnsafeWeakList extends AbstractCollection { nextElement = null; nextIndex = -1; for (int i= curIndex +1; i ref = myList.get(i); + T t = ref == null ? null : ref.get(); if (t != null) { nextElement = t; nextIndex = i; @@ -188,7 +189,8 @@ public class UnsafeWeakList extends AbstractCollection { public boolean remove(@NotNull Object o) { processQueue(); for (int i = 0; i < myList.size(); i++) { - T t = SoftReference.dereference(myList.get(i)); + Reference ref = myList.get(i); + T t = ref == null ? null : ref.get(); if (t != null && t.equals(o)) { nullizeAt(i); modCount++; @@ -238,7 +240,7 @@ public class UnsafeWeakList extends AbstractCollection { } private static void throwNotAllowedException() { - throw new IncorrectOperationException("index/size-based operations in UnsafeWeakList are not supported because they don't make sense in the presence of weak references. Use .iterator() (which retains its elements to avoid sudden GC) instead."); + throw new UnsupportedOperationException("index/size-based operations in UnsafeWeakList are not supported because they don't make sense in the presence of weak references. Use .iterator() (which retains its elements to avoid sudden GC) instead."); } @Override