IJPL-160901 IJPL-164346 platform: migrate 'checkUnloadPlugin' usages

(cherry picked from commit deafeb85d62fbd9b3ec255c024c7c6f88f33ab7f)

IJ-CR-150055

GitOrigin-RevId: e7c5497ba5b7eb06eaf431939d315a837d210b1d
This commit is contained in:
Aleksey Pivovarov
2024-10-18 18:35:48 +02:00
committed by intellij-monorepo-bot
parent a501d4c5b2
commit b4671a4ba6
10 changed files with 85 additions and 48 deletions

View File

@@ -281,6 +281,10 @@ com.intellij.ide.plugins.DynamicPluginListener
- pluginLoaded(com.intellij.ide.plugins.IdeaPluginDescriptor):V
- pluginUnloaded(com.intellij.ide.plugins.IdeaPluginDescriptor,Z):V
f:com.intellij.ide.plugins.DynamicPluginListener$Companion
com.intellij.ide.plugins.DynamicPluginVetoer
- sf:Companion:com.intellij.ide.plugins.DynamicPluginVetoer$Companion
- a:vetoPluginUnload(com.intellij.ide.plugins.IdeaPluginDescriptor):java.lang.String
f:com.intellij.ide.plugins.DynamicPluginVetoer$Companion
@:com.intellij.ide.plugins.DynamicallyLoaded
- java.lang.annotation.Annotation
com.intellij.ide.plugins.IdeaPluginDependency

View File

@@ -4,6 +4,7 @@ package com.intellij.ide.plugins
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.util.messages.Topic
@Deprecated("Use DynamicPluginVetoer instead")
class CannotUnloadPluginException(value: String) : ProcessCanceledException(RuntimeException(value))
interface DynamicPluginListener {
@@ -28,12 +29,7 @@ interface DynamicPluginListener {
fun pluginUnloaded(pluginDescriptor: IdeaPluginDescriptor, isUpdate: Boolean) {
}
/**
* Checks if the plugin can be dynamically unloaded at this moment.
* Method should throw [CannotUnloadPluginException] if it isn't possible for some reason.
*
* Not dispatched for a content modules (plugin model V2).
*/
@Deprecated("Use DynamicPluginVetoer instead")
@Throws(CannotUnloadPluginException::class)
fun checkUnloadPlugin(pluginDescriptor: IdeaPluginDescriptor) {
}

View File

@@ -0,0 +1,25 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.plugins
import com.intellij.openapi.extensions.ExtensionPointName
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.Nls
interface DynamicPluginVetoer {
/**
* Checks if the plugin can be dynamically unloaded at this moment.
*
* Not dispatched for content modules (plugin model V2).
*
* @return Error message to display
* 'null' to let the plugin be unloaded
*/
fun vetoPluginUnload(pluginDescriptor: IdeaPluginDescriptor): @Nls String?
companion object {
@JvmField
@ApiStatus.Internal
val EP_NAME: ExtensionPointName<DynamicPluginVetoer> = ExtensionPointName.create("com.intellij.ide.dynamicPluginVetoer");
}
}

View File

@@ -268,12 +268,10 @@ object DynamicPlugins {
return null
}
try {
app.messageBus.syncPublisher(DynamicPluginListener.TOPIC).checkUnloadPlugin(module)
}
catch (e: CannotUnloadPluginException) {
return e.cause?.localizedMessage ?: "checkUnloadPlugin listener blocked plugin unload"
val vetoMessage = DynamicPluginVetoer.EP_NAME.computeSafeIfAny {
it.vetoPluginUnload(module)
}
if (vetoMessage != null) return vetoMessage
}
if (!Registry.`is`("ide.plugins.allow.unload.from.sources")) {

View File

@@ -5,11 +5,10 @@ import com.intellij.ide.plugins.LocalizationPluginHelper.isActiveLocalizationPlu
import com.intellij.ide.ui.LanguageAndRegionUi
import com.intellij.l10n.LocalizationStateService
import com.intellij.openapi.diagnostic.logger
import java.util.Locale
import java.util.*
internal class LocalizationPluginListener : DynamicPluginListener {
override fun checkUnloadPlugin(pluginDescriptor: IdeaPluginDescriptor) {
override fun beforePluginUnload(pluginDescriptor: IdeaPluginDescriptor, isUpdate: Boolean) {
if (isActiveLocalizationPlugin(pluginDescriptor)) {
logger<LocalizationPluginListener>().info("[i18n] Language setting was reset to default during unload Localization plugin")

View File

@@ -504,6 +504,8 @@
<extensionPoint name="dependencyCollector" beanClass="com.intellij.ide.plugins.DependencyCollectorBean" dynamic="true">
<with attribute="implementation" implements="com.intellij.ide.plugins.DependencyCollector"/>
</extensionPoint>
<extensionPoint name="ide.dynamicPluginVetoer" interface="com.intellij.ide.plugins.DynamicPluginVetoer" dynamic="true"/>
<extensionPoint name="dependencySupport" beanClass="com.intellij.ide.plugins.DependencySupportBean" dynamic="true"/>
<extensionPoint name="actionOnSaveInfoProvider" interface="com.intellij.ide.actionsOnSave.ActionOnSaveInfoProvider" dynamic="true"/>
<extensionPoint name="actionOnSave" interface="com.intellij.ide.actionsOnSave.impl.ActionsOnSaveFileDocumentManagerListener$ActionOnSave" dynamic="true"/>

View File

@@ -43,6 +43,8 @@
<projectService serviceInterface="com.intellij.xdebugger.XDebuggerManager"
serviceImplementation="com.intellij.xdebugger.impl.XDebuggerManagerImpl"
preload="notLightEdit"/>
<ide.dynamicPluginVetoer implementation="com.intellij.xdebugger.impl.XDebuggerManagerImpl$XDebuggerPluginVetoer"/>
<projectService serviceImplementation="com.intellij.xdebugger.impl.inline.DebuggerInlayListener"/>
<projectService serviceImplementation="com.intellij.xdebugger.impl.XDebuggerLineChangeIconProvider"/>

View File

@@ -14,8 +14,7 @@ import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunContentManager;
import com.intellij.execution.ui.RunContentWithExecutorListener;
import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.CannotUnloadPluginException;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.DynamicPluginVetoer;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.idea.ActionsBundle;
import com.intellij.notification.NotificationGroup;
@@ -40,6 +39,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileDocumentManagerListener;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
@@ -76,8 +76,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import static com.intellij.xdebugger.impl.CoroutineUtilsKt.createMutableStateFlow;
@@ -174,19 +174,6 @@ public final class XDebuggerManagerImpl extends XDebuggerManager implements Pers
}
});
messageBusConnection.subscribe(DynamicPluginListener.TOPIC, new DynamicPluginListener() {
@Override
public void checkUnloadPlugin(@NotNull IdeaPluginDescriptor pluginDescriptor) {
XDebugSession[] sessions = getDebugSessions();
for (XDebugSession session : sessions) {
XDebugProcess process = session.getDebugProcess();
if (process.dependsOnPlugin(pluginDescriptor)) {
throw new CannotUnloadPluginException("Plugin is not unload-safe because of the started debug session");
}
}
}
});
GutterUiRunToCursorEditorListener listener = new GutterUiRunToCursorEditorListener();
EditorMouseMotionListener bpPromoter = new BreakpointPromoterEditorListener(coroutineScope);
EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
@@ -611,6 +598,25 @@ public final class XDebuggerManagerImpl extends XDebuggerManager implements Pers
return documentLine < editor.getDocument().getLineCount() ? documentLine : -1;
}
static class XDebuggerPluginVetoer implements DynamicPluginVetoer {
@Override
public @Nls @Nullable String vetoPluginUnload(@NotNull IdeaPluginDescriptor pluginDescriptor) {
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
XDebuggerManager manager = project.getServiceIfCreated(XDebuggerManager.class);
if (manager == null) continue;
XDebugSession[] sessions = manager.getDebugSessions();
for (XDebugSession session : sessions) {
XDebugProcess process = session.getDebugProcess();
if (process.dependsOnPlugin(pluginDescriptor)) {
return "Plugin is not unload-safe because of the started debug session";
}
}
}
return null;
}
}
@ApiStatus.Internal
public CoroutineScope getCoroutineScope() {
return myCoroutineScope;

View File

@@ -60,6 +60,8 @@
<projectService overrides="true"
serviceInterface="com.intellij.internal.performanceTests.ProjectInitializationDiagnosticService"
serviceImplementation="com.jetbrains.performancePlugin.ProjectInitializationDiagnosticServiceImpl"/>
<ide.dynamicPluginVetoer implementation="com.jetbrains.performancePlugin.PlaybackRunnerExtended$PlaybackRunnerExtendedPluginUnloadVetoer"/>
</extensions>
<applicationListeners>

View File

@@ -1,7 +1,6 @@
package com.jetbrains.performancePlugin;
import com.intellij.ide.plugins.CannotUnloadPluginException;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.DynamicPluginVetoer;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
@@ -10,31 +9,28 @@ import com.intellij.openapi.ui.playback.PlaybackRunner;
import com.intellij.openapi.ui.playback.commands.AbstractCommand;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
public final class PlaybackRunnerExtended extends PlaybackRunner {
public static final String NOTIFICATION_GROUP = "PerformancePlugin";
private Project myProject;
private boolean myStopped;
private final DynamicPluginListener myDynamicPluginListener;
public PlaybackRunnerExtended(String script, StatusCallback callback, @NotNull Project project) {
super(script, callback, Registry.is("performance.plugin.playback.runner.useDirectActionCall", false), false, true);
setProject(project);
myDynamicPluginListener = new DynamicPluginListener() {
@Override
public void checkUnloadPlugin(@NotNull IdeaPluginDescriptor pluginDescriptor) throws CannotUnloadPluginException {
if (PluginId.getId("com.jetbrains.performancePlugin").equals(pluginDescriptor.getPluginId())) {
throw new CannotUnloadPluginException("Cannot unload plugin during playback execution");
}
}
};
PlaybackRunnerExtendedPluginUnloadVetoer.activeExecutionCount.incrementAndGet();
Disposer.register(onStop, () -> {
PlaybackRunnerExtendedPluginUnloadVetoer.activeExecutionCount.decrementAndGet();
});
}
@Override
@@ -56,12 +52,6 @@ public final class PlaybackRunnerExtended extends PlaybackRunner {
return myProject;
}
@Override
protected void subscribeListeners(MessageBusConnection connection) {
super.subscribeListeners(connection);
connection.subscribe(DynamicPluginListener.TOPIC, myDynamicPluginListener);
}
@Override
protected void onStop() {
super.onStop();
@@ -99,4 +89,17 @@ public final class PlaybackRunnerExtended extends PlaybackRunner {
RunCallbackHandler.applyPatchesToCommandCallback(myProject, callback);
return callback;
}
static class PlaybackRunnerExtendedPluginUnloadVetoer implements DynamicPluginVetoer {
static final AtomicInteger activeExecutionCount = new AtomicInteger();
@Override
public @Nls @Nullable String vetoPluginUnload(@NotNull IdeaPluginDescriptor pluginDescriptor) {
if (activeExecutionCount.get() > 0 &&
PluginId.getId("com.jetbrains.performancePlugin").equals(pluginDescriptor.getPluginId())) {
return "Cannot unload plugin during playback execution";
}
return null;
}
}
}