mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
execute "mac app init" in parallel to appStarter, don't execute preloading activity as part of app initialized callback
GitOrigin-RevId: 15220b09d4226062df111b35ee034f80eb1bc62c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cb9b4388ab
commit
08b6e26a77
+2
-2
@@ -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) {
|
||||
|
||||
+7
-6
@@ -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<Class<?>> ourReportedReuseExceptions = ContainerUtil.newConcurrentSet();
|
||||
@SuppressWarnings("SSBasedInspection")
|
||||
private static final Set<Class<?>> ourReportedReuseExceptions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
protected boolean isReuseable() {
|
||||
return false;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# 31
|
||||
|
||||
* Rename `add registry keys` to `registry keys adding`.
|
||||
|
||||
# 30
|
||||
|
||||
* Add `preloading activity executing`.
|
||||
|
||||
@@ -38,7 +38,7 @@ class StartUpPerformanceReporter : StartupActivity, StartUpPerformanceService {
|
||||
companion object {
|
||||
internal val LOG = logger<StartUpMeasurer>()
|
||||
|
||||
internal const val VERSION = "30"
|
||||
internal const val VERSION = "31"
|
||||
|
||||
internal fun sortItems(items: MutableList<ActivityImpl>) {
|
||||
items.sortWith(Comparator { o1, o2 ->
|
||||
|
||||
@@ -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<Component> 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<Component> components = focusOwners.toStrongList();
|
||||
for (int i = components.size() - 1; i >= 0; i--) {
|
||||
if (!SwingUtilities.isDescendingFrom(components.get(i), container)) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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<IdeaPluginDescriptorImpl>,
|
||||
}
|
||||
}
|
||||
|
||||
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<String>): List<String> {
|
||||
return arguments
|
||||
}
|
||||
|
||||
fun callAppInitialized(app: Application): List<RecursiveAction> {
|
||||
val extensionArea = app.extensionArea as ExtensionsAreaImpl
|
||||
|
||||
fun callAppInitialized(app: ApplicationImpl): List<ForkJoinTask<*>> {
|
||||
val extensionArea = app.extensionArea
|
||||
val extensionPoint = extensionArea.getExtensionPoint<ApplicationInitializedListener>("com.intellij.applicationInitializedListener")
|
||||
val result = ArrayList<RecursiveAction>(extensionPoint.size())
|
||||
val result = ArrayList<ForkJoinTask<*>>(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<Pair<PreloadingActivity, PluginDescriptor>>()
|
||||
val extensionPoint = app.extensionArea.getExtensionPoint<PreloadingActivity>("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<PreloadingActivity>("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()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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<Path> = 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<String>): 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()
|
||||
}
|
||||
|
||||
@@ -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<String, String[], Integer> 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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -359,7 +359,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application
|
||||
List<IdeaPluginDescriptorImpl> 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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -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<Void?>,
|
||||
val syncPreloadedServices: CompletableFuture<Void?>)
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun preloadServices(plugins: List<IdeaPluginDescriptorImpl>,
|
||||
activityPrefix: String,
|
||||
onlyIfAwait: Boolean = false): ServicePreloadingResult {
|
||||
onlyIfAwait: Boolean = false): Pair<CompletableFuture<Void?>, CompletableFuture<Void?>> {
|
||||
val asyncPreloadedServices = mutableListOf<RecursiveAction>()
|
||||
val syncPreloadedServices = mutableListOf<RecursiveAction>()
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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<T> extends AbstractCollection<T> {
|
||||
boolean processQueue() {
|
||||
boolean processed = false;
|
||||
MyReference<T> reference;
|
||||
//noinspection unchecked
|
||||
while ((reference = (MyReference<T>)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<T> extends AbstractCollection<T> {
|
||||
nextElement = null;
|
||||
nextIndex = -1;
|
||||
for (int i= curIndex +1; i<myList.size();i++) {
|
||||
T t = SoftReference.dereference(myList.get(i));
|
||||
Reference<T> 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<T> extends AbstractCollection<T> {
|
||||
public boolean remove(@NotNull Object o) {
|
||||
processQueue();
|
||||
for (int i = 0; i < myList.size(); i++) {
|
||||
T t = SoftReference.dereference(myList.get(i));
|
||||
Reference<T> 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<T> extends AbstractCollection<T> {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user