mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-90402 [debugger]: add support for enabling disabled Python DAP Debugger plugin in plugin suggestions
Merge-request: IJ-MR-216357 Merged-by: Maxim Popov <maxim.popov@jetbrains.com> (cherry picked from commit 9b8343d4342d019ff4c4dffa7c14ae01d6318fde) IJ-MR-216357 GitOrigin-RevId: 051016e7b7d602705a508aced468ba21de2517bb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9846eddcab
commit
909c50a404
@@ -935,6 +935,7 @@ debugger.backend.debugpy.disabled.tooltip=debugpy requires Python 3.9 or later
|
||||
debugger.backend.debugpy.disabled.remote.tooltip=debugpy is not supported for remote Python interpreters
|
||||
debugger.backend.debugpy.disabled.not.installed.tooltip=Install the Python DAP Debugger plugin to use the debugpy backend
|
||||
debugger.backend.install.debugpy.plugin=Install Python DAP Debugger Plugin
|
||||
debugger.backend.enable.debugpy.plugin=Enable Python DAP Debugger Plugin
|
||||
debugger.backend.report.issue.debugpy=Report an Issue with debugpy
|
||||
debugger.backend.switch.after.install.title=Switch to debugpy
|
||||
debugger.backend.switch.after.install.message=The Python DAP Debugger plugin has been installed. Would you like to switch to the debugpy backend and restart your current debug sessions?
|
||||
@@ -1620,6 +1621,7 @@ advertiser.package.supported.by.pro=Maximize your efficiency with {0}
|
||||
advertiser.code.cells.supported.by.pro=Code cells are supported by PyCharm
|
||||
advertiser.python.dap.plugin=The Python DAP Debugger plugin is available for faster and more reliable Python debugging with the Debug Adapter Protocol
|
||||
advertiser.python.dap.plugin.install.text=Install Plugin
|
||||
advertiser.python.dap.plugin.enable.text=Enable Plugin
|
||||
|
||||
debugger.dap.plugin.install.got.it.header=Try the Python DAP Debugger plugin
|
||||
debugger.dap.plugin.install.got.it.text=Install the Python DAP Debugger plugin for faster and more reliable Python debugging with debugpy
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.ide.actions.ReportFeedbackService
|
||||
import com.intellij.ide.actions.SendFeedbackAction
|
||||
import com.intellij.ide.plugins.PluginEnabler
|
||||
import com.intellij.ide.plugins.PluginManager
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
@@ -198,6 +199,15 @@ internal class PyDebuggerBackendSwitcherAction : ComboBoxAction(), DumbAware {
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = !isPythonDapPluginInstalledAndEnabled()
|
||||
val enableOnly = isPythonDapPluginInstalledButDisabled()
|
||||
e.presentation.text = if (enableOnly) {
|
||||
PyBundle.message("debugger.backend.enable.debugpy.plugin")
|
||||
}
|
||||
else {
|
||||
PyBundle.message("debugger.backend.install.debugpy.plugin")
|
||||
}
|
||||
// The plugin is already on disk in the enable case, so nothing is downloaded and the badge would mislead.
|
||||
e.presentation.icon = if (enableOnly) null else AllIcons.Actions.Download
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
@@ -253,7 +263,15 @@ private fun getEffectiveSdk(project: Project): Sdk? =
|
||||
@ApiStatus.Internal
|
||||
fun installPythonDapPlugin(project: Project, onLoaded: Runnable? = null) {
|
||||
project.service<PyDapPluginLoadListener>().listen(onLoaded)
|
||||
installAndEnable(project, setOf(PluginId.getId(PYTHON_DAP_PLUGIN_ID)), showDialog = true) {}
|
||||
|
||||
val pluginId = PluginId.getId(PYTHON_DAP_PLUGIN_ID)
|
||||
val descriptor = PluginManagerCore.getPlugin(pluginId)
|
||||
if (descriptor != null && PluginManagerCore.isDisabled(pluginId)) {
|
||||
PluginEnabler.getInstance().enable(listOf(descriptor))
|
||||
return
|
||||
}
|
||||
|
||||
installAndEnable(project, setOf(pluginId), showDialog = true) {}
|
||||
}
|
||||
|
||||
// This method exists to provide backward compatibility with older versions of the DAP plugin
|
||||
@@ -323,6 +341,11 @@ internal fun isPythonDapPluginInstalledAndEnabled(): Boolean {
|
||||
return PluginManager.isPluginInstalled(pluginId) && !PluginManagerCore.isDisabled(pluginId)
|
||||
}
|
||||
|
||||
internal fun isPythonDapPluginInstalledButDisabled(): Boolean {
|
||||
val pluginId = PluginId.getId(PYTHON_DAP_PLUGIN_ID)
|
||||
return PluginManager.isPluginInstalled(pluginId) && PluginManagerCore.isDisabled(pluginId)
|
||||
}
|
||||
|
||||
private fun switchBackend(project: Project, backend: PyDebuggerBackend) {
|
||||
val fromBackend = PyDebuggerOptionsProvider.getInstance(project).selectedBackend
|
||||
if (fromBackend == backend) return
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
package com.jetbrains.python.debugger
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager
|
||||
import com.intellij.openapi.actionSystem.ActionStubBase
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.openapi.actionSystem.Separator
|
||||
import com.intellij.openapi.application.EDT
|
||||
@@ -17,6 +19,7 @@ import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
internal class PyDebuggerBackendToolWindowSetup : ProjectActivity {
|
||||
override suspend fun execute(project: Project) {
|
||||
@@ -43,12 +46,25 @@ internal class PyDebuggerBackendToolWindowSetup : ProjectActivity {
|
||||
|
||||
@RequiresEdt
|
||||
private fun setupTitleAction(toolWindow: ToolWindow) {
|
||||
val action = ActionManager.getInstance().getAction("Python.DebuggerBackendSwitcher") ?: return
|
||||
val action = ActionManager.getInstance().getAction(SWITCHER_ACTION_ID) ?: return
|
||||
val existing = ((toolWindow as? ToolWindowEx)?.decorator as? InternalDecoratorImpl)?.headerToolbarActions
|
||||
?.let { group -> (group as? DefaultActionGroup)?.getChildActionsOrStubs()?.filter { it !is Separator } }
|
||||
?: emptyList()
|
||||
if (action !in existing) {
|
||||
toolWindow.setTitleActions(existing + action)
|
||||
// The header can hold the switcher either as the action itself or as an unresolved stub, and a
|
||||
// dynamic plugin reload replaces the cached instance. Matching by identity therefore misses the
|
||||
// entry that is already there and appends a second switcher, so drop every copy by id first.
|
||||
val desired = existing.filterNot { it.isBackendSwitcher() } + action
|
||||
if (desired != existing) {
|
||||
toolWindow.setTitleActions(desired)
|
||||
}
|
||||
}
|
||||
|
||||
// Compared by class name rather than with `is`: a switcher left behind by a previous plugin
|
||||
// generation comes from a classloader that is already dead, so its class is not identical to ours.
|
||||
private fun AnAction.isBackendSwitcher(): Boolean =
|
||||
javaClass.name == PyDebuggerBackendSwitcherAction::class.java.name ||
|
||||
(this as? ActionStubBase)?.id == SWITCHER_ACTION_ID
|
||||
}
|
||||
|
||||
@Language("devkit-action-id")
|
||||
private const val SWITCHER_ACTION_ID = "Python.DebuggerBackendSwitcher"
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.PythonFileType
|
||||
import com.jetbrains.python.debugger.installPythonDapPlugin
|
||||
import com.jetbrains.python.debugger.isPythonDapPluginInstalledAndEnabled
|
||||
import com.jetbrains.python.debugger.isPythonDapPluginInstalledButDisabled
|
||||
|
||||
private const val PYTHON_DAP_PLUGIN_ID = "intellij.python.dap.plugin"
|
||||
private const val PYTHON_DAP_SUGGESTION_DISMISSED_KEY = "python.dap.suggestion.dismissed"
|
||||
@@ -50,7 +51,13 @@ internal class PythonDapPluginSuggestionProvider : PluginSuggestionProvider {
|
||||
val panel = EditorNotificationPanel(fileEditor, EditorNotificationPanel.Status.Info)
|
||||
panel.text = PyBundle.message("advertiser.python.dap.plugin")
|
||||
|
||||
panel.createActionLabel(PyBundle.message("advertiser.python.dap.plugin.install.text")) {
|
||||
val actionText = if (isPythonDapPluginInstalledButDisabled()) {
|
||||
PyBundle.message("advertiser.python.dap.plugin.enable.text")
|
||||
}
|
||||
else {
|
||||
PyBundle.message("advertiser.python.dap.plugin.install.text")
|
||||
}
|
||||
panel.createActionLabel(actionText) {
|
||||
FUSEventSource.EDITOR.logInstallPlugins(pluginIds, project)
|
||||
installPythonDapPlugin(project) {
|
||||
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||
|
||||
Reference in New Issue
Block a user