From fa45d294f1881d6c173684b5725f9256342645ad Mon Sep 17 00:00:00 2001 From: tzengshinfu Date: Tue, 27 May 2025 15:01:49 +0800 Subject: [PATCH] add options for handling errors encountered --- package.json | 21 ++++++++ package.nls.json | 3 +- src/extension/common/onErrorsAction.ts | 49 +++++++++++++++++++ .../debugConfigurationService.ts | 12 ++++- src/extension/extensionInit.ts | 20 ++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/extension/common/onErrorsAction.ts diff --git a/package.json b/package.json index 61c8c7a8..a2c5fb13 100644 --- a/package.json +++ b/package.json @@ -139,6 +139,27 @@ "tags": [ "experimental" ] + }, + "debugpy.onErrors": { + "default": "debugAnyway", + "description": "%debugpy.onErrors.description%", + "scope": "resource", + "type": "string", + "enum": [ + "debugAnyway", + "showErrors", + "abort", + "prompt" + ], + "enumDescriptions": [ + "Continue debugging.", + "Show errors and stop debugging.", + "Stop debugging.", + "Let the user choose the action." + ], + "tags": [ + "experimental" + ] } }, "title": "Python Debugger", diff --git a/package.nls.json b/package.nls.json index 5a53eb61..0db72986 100644 --- a/package.nls.json +++ b/package.nls.json @@ -5,5 +5,6 @@ "debugpy.command.reportIssue.title": "Report Issue...", "debugpy.command.viewOutput.title": "Show Output", "debugpy.debugJustMyCode.description": "When debugging only step through user-written code. Disable this to allow stepping into library code.", - "debugpy.showPythonInlineValues.description": "Whether to display inline values in the editor while debugging." + "debugpy.showPythonInlineValues.description": "Whether to display inline values in the editor while debugging.", + "debugpy.onErrors.description": "Controls what to do when errors are encountered before debugging." } diff --git a/src/extension/common/onErrorsAction.ts b/src/extension/common/onErrorsAction.ts new file mode 100644 index 00000000..bf2651a7 --- /dev/null +++ b/src/extension/common/onErrorsAction.ts @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +import { DiagnosticSeverity, l10n, languages, MessageOptions, window } from 'vscode'; +import { getConfiguration } from './vscodeapi'; + +export async function resolveOnErrorsAction(): Promise { + const onErrors = getConfiguration('debugpy').get('onErrors', OnErrorsActions.debugAnyway); + if (onErrors === OnErrorsActions.debugAnyway) { + return OnErrorsActions.debugAnyway; + } + + const hasErrors = languages + .getDiagnostics() + .map((d) => { + return d[1]; + }) + .flat() + .some((d) => { + return d.severity === DiagnosticSeverity.Error; + }); + if (!hasErrors) { + return OnErrorsActions.debugAnyway; + } + + if (onErrors === OnErrorsActions.prompt) { + const message = l10n.t('Error exists before debugging.'); + const options: MessageOptions = { modal: true }; + const actions = [ + { title: 'Debug Anyway', id: OnErrorsActions.debugAnyway }, + { title: 'Show Errors', id: OnErrorsActions.showErrors }, + { title: 'Abort', id: OnErrorsActions.abort, isCloseAffordance: true }, + ]; + + const result = await window.showWarningMessage(message, options, ...actions); + return (result?.id as OnErrorsActions) ?? OnErrorsActions.abort; + } + + return onErrors as OnErrorsActions; +} + +export enum OnErrorsActions { + debugAnyway = 'debugAnyway', + showErrors = 'showErrors', + abort = 'abort', + prompt = 'prompt', +} diff --git a/src/extension/debugger/configuration/debugConfigurationService.ts b/src/extension/debugger/configuration/debugConfigurationService.ts index 8776f9b6..5652c5eb 100644 --- a/src/extension/debugger/configuration/debugConfigurationService.ts +++ b/src/extension/debugger/configuration/debugConfigurationService.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { cloneDeep } from 'lodash'; -import { CancellationToken, DebugConfiguration, QuickPickItem, WorkspaceFolder } from 'vscode'; +import { CancellationToken, commands, DebugConfiguration, QuickPickItem, WorkspaceFolder } from 'vscode'; import { DebugConfigStrings } from '../../common/utils/localize'; import { IMultiStepInputFactory, InputStep, IQuickPickParameters, MultiStepInput } from '../../common/multiStepInput'; import { AttachRequestArguments, DebugConfigurationArguments, LaunchRequestArguments } from '../../types'; @@ -17,6 +17,7 @@ import { buildPyramidLaunchConfiguration } from './providers/pyramidLaunch'; import { buildRemoteAttachConfiguration } from './providers/remoteAttach'; import { IDebugConfigurationResolver } from './types'; import { buildFileWithArgsLaunchDebugConfiguration } from './providers/fileLaunchWithArgs'; +import { OnErrorsActions, resolveOnErrorsAction } from '../../common/onErrorsAction'; export class PythonDebugConfigurationService implements IDebugConfigurationService { private cacheDebugConfig: DebugConfiguration | undefined = undefined; @@ -48,6 +49,15 @@ export class PythonDebugConfigurationService implements IDebugConfigurationServi debugConfiguration: DebugConfiguration, token?: CancellationToken, ): Promise { + const action = await resolveOnErrorsAction(); + switch (action) { + case OnErrorsActions.showErrors: + await commands.executeCommand('workbench.panel.markers.view.focus'); + return undefined; + + case OnErrorsActions.abort: + return undefined; + } if (debugConfiguration.request === 'attach') { return this.attachResolver.resolveDebugConfiguration( folder, diff --git a/src/extension/extensionInit.ts b/src/extension/extensionInit.ts index c4f52b6c..3e188af2 100644 --- a/src/extension/extensionInit.ts +++ b/src/extension/extensionInit.ts @@ -4,6 +4,7 @@ 'use strict'; import { + commands, ConfigurationChangeEvent, debug, DebugConfigurationProviderTriggerKind, @@ -54,6 +55,7 @@ import { registerHexDebugVisualizationTreeProvider } from './debugger/visualizer import { PythonInlineValueProvider } from './debugger/inlineValue/pythonInlineValueProvider'; import { traceLog } from './common/log/logging'; import { registerNoConfigDebug } from './noConfigDebugInit'; +import { OnErrorsActions, resolveOnErrorsAction } from './common/onErrorsAction'; export async function registerDebugger(context: IExtensionContext): Promise { const childProcessAttachService = new ChildProcessAttachService(); @@ -87,6 +89,15 @@ export async function registerDebugger(context: IExtensionContext): Promise { + const action = await resolveOnErrorsAction(); + switch (action) { + case OnErrorsActions.showErrors: + await commands.executeCommand('workbench.panel.markers.view.focus'); + return; + + case OnErrorsActions.abort: + return; + } traceLog("Debugging using the editor button 'Debug in terminal'"); sendTelemetryEvent(EventName.DEBUG_IN_TERMINAL_BUTTON); const interpreter = await getInterpreterDetails(file); @@ -101,6 +112,15 @@ export async function registerDebugger(context: IExtensionContext): Promise { + const action = await resolveOnErrorsAction(); + switch (action) { + case OnErrorsActions.showErrors: + await commands.executeCommand('workbench.panel.markers.view.focus'); + return; + + case OnErrorsActions.abort: + return; + } traceLog("Debugging using the editor button 'Debug using the launch.json'"); sendTelemetryEvent(EventName.DEBUG_USING_LAUNCH_CONFIG_BUTTON); const interpreter = await getInterpreterDetails(file);