diff --git a/src/interactive-window/debugger/jupyter/debugCellControllers.ts b/src/interactive-window/debugger/jupyter/debugCellControllers.ts index 3b2a7811ccf..c5e653f8388 100644 --- a/src/interactive-window/debugger/jupyter/debugCellControllers.ts +++ b/src/interactive-window/debugger/jupyter/debugCellControllers.ts @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { DebugProtocolMessage, NotebookCell } from 'vscode'; +import { NotebookCell } from 'vscode'; import { DebugProtocol } from 'vscode-debugprotocol'; -import { IDebuggingDelegate, IKernelDebugAdapter } from '../../../notebooks/debugger/debuggingTypes'; -import { DebuggingTelemetry } from '../../../notebooks/debugger/constants'; import { IKernel } from '../../../kernels/types'; +import { DebuggingTelemetry } from '../../../notebooks/debugger/constants'; +import { IDebuggingDelegate, IKernelDebugAdapter } from '../../../notebooks/debugger/debuggingTypes'; import { cellDebugSetup } from '../../../notebooks/debugger/helper'; import { createDeferred } from '../../../platform/common/utils/async'; import { sendTelemetryEvent } from '../../../telemetry'; @@ -27,7 +27,7 @@ export class DebugCellController implements IDebuggingDelegate { sendTelemetryEvent(DebuggingTelemetry.successfullyStartedRunAndDebugCell); } - public async willSendEvent(_msg: DebugProtocolMessage): Promise { + public async willSendEvent(_msg: DebugProtocol.Event): Promise { return false; } private debugCellDumped?: Promise; diff --git a/src/notebooks/debugger/debugCellControllers.ts b/src/notebooks/debugger/debugCellControllers.ts index 5c3cfeb2a72..6218440fb6d 100644 --- a/src/notebooks/debugger/debugCellControllers.ts +++ b/src/notebooks/debugger/debugCellControllers.ts @@ -1,15 +1,20 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { DebugProtocolMessage, NotebookCell } from 'vscode'; +import { NotebookCell } from 'vscode'; import { DebugProtocol } from 'vscode-debugprotocol'; -import { ICommandManager } from '../../platform/common/application/types'; import { IKernel } from '../../kernels/types'; +import { ICommandManager } from '../../platform/common/application/types'; +import { noop } from '../../platform/common/utils/misc'; +import { traceVerbose } from '../../platform/logging'; import { sendTelemetryEvent } from '../../telemetry'; import { DebuggingTelemetry } from './constants'; -import { cellDebugSetup } from './helper'; import { IDebuggingDelegate, IKernelDebugAdapter } from './debuggingTypes'; -import { noop } from '../../platform/common/utils/misc'; +import { cellDebugSetup } from './helper'; + +export function isJustMyCodeNotification(msg: string): boolean { + return msg.includes('Frame skipped from debugging during step-in'); +} /** * Controls starting execution on a cell when debugging a cell. @@ -24,7 +29,18 @@ export class DebugCellController implements IDebuggingDelegate { sendTelemetryEvent(DebuggingTelemetry.successfullyStartedRunAndDebugCell); } - public async willSendEvent(_msg: DebugProtocolMessage): Promise { + private trace(tag: string, msg: string) { + traceVerbose(`[Debug-Cell] ${tag}: ${msg}`); + } + + public async willSendEvent(msg: DebugProtocol.Event): Promise { + if (msg.event === 'output') { + if (isJustMyCodeNotification(msg.body.output)) { + this.trace('intercept', 'justMyCode notification'); + return true; + } + } + return false; } diff --git a/src/notebooks/debugger/debuggingTypes.ts b/src/notebooks/debugger/debuggingTypes.ts index 5ea294fd047..a9e34e16b1e 100644 --- a/src/notebooks/debugger/debuggingTypes.ts +++ b/src/notebooks/debugger/debuggingTypes.ts @@ -9,7 +9,6 @@ import { DebugAdapter, DebugAdapterTracker, DebugConfiguration, - DebugProtocolMessage, DebugSession, Event, NotebookCell, @@ -86,7 +85,7 @@ export interface IDebuggingDelegate { /** * Called for every event sent from the debug adapter to the client. Returns true to signal that sending the message is vetoed. */ - willSendEvent(msg: DebugProtocolMessage): Promise; + willSendEvent(msg: DebugProtocol.Event): Promise; /** * Called for every request sent from the client to the debug adapter. diff --git a/src/notebooks/debugger/helper.ts b/src/notebooks/debugger/helper.ts index cd31fb79a64..544116086c1 100644 --- a/src/notebooks/debugger/helper.ts +++ b/src/notebooks/debugger/helper.ts @@ -4,6 +4,7 @@ import { DebugProtocol } from 'vscode-debugprotocol'; import { IKernelDebugAdapter, IKernelDebugAdapterConfig, KernelDebugMode } from './debuggingTypes'; import { IKernel } from '../../kernels/types'; +import { IDebugEventMsg } from '@jupyterlab/services/lib/kernel/messages'; export enum IpykernelCheckResult { Unknown, @@ -157,3 +158,7 @@ export async function cellDebugSetup(kernel: IKernel, debugAdapter: IKernelDebug await debugAdapter.dumpAllCells(); } + +export function isDebugEventMsg(msg: unknown): msg is IDebugEventMsg { + return !!(msg as IDebugEventMsg).header && (msg as IDebugEventMsg).header.msg_type === 'debug_event'; +} diff --git a/src/notebooks/debugger/kernelDebugAdapterBase.ts b/src/notebooks/debugger/kernelDebugAdapterBase.ts index 8e7a4c96b61..d30697b5e6b 100644 --- a/src/notebooks/debugger/kernelDebugAdapterBase.ts +++ b/src/notebooks/debugger/kernelDebugAdapterBase.ts @@ -4,7 +4,6 @@ 'use strict'; import { KernelMessage } from '@jupyterlab/services'; -import * as path from '../../platform/vscode-path/path'; import { debug, DebugAdapter, @@ -23,23 +22,30 @@ import { workspace } from 'vscode'; import { DebugProtocol } from 'vscode-debugprotocol'; -import { IKernelConnectionSession, IKernel } from '../../kernels/types'; +import { executeSilently } from '../../kernels/helpers'; +import { IKernel, IKernelConnectionSession } from '../../kernels/types'; +import { IDebugService } from '../../platform/common/application/types'; import { IPlatformService } from '../../platform/common/platform/types'; +import { IDisposable } from '../../platform/common/types'; +import { noop } from '../../platform/common/utils/misc'; +import { traceError, traceInfo, traceInfoIfCI, traceVerbose, traceWarning } from '../../platform/logging'; +import * as path from '../../platform/vscode-path/path'; +import { sendTelemetryEvent } from '../../telemetry'; import { DebuggingTelemetry } from './constants'; import { + IDebuggingDelegate, + IDebugInfoResponse, IKernelDebugAdapter, IKernelDebugAdapterConfig, - IDebuggingDelegate, - KernelDebugMode, - IDebugInfoResponse + KernelDebugMode } from './debuggingTypes'; -import { sendTelemetryEvent } from '../../telemetry'; -import { traceError, traceInfo, traceInfoIfCI, traceVerbose, traceWarning } from '../../platform/logging'; -import { assertIsDebugConfig, isShortNamePath, shortNameMatchesLongName, getMessageSourceAndHookIt } from './helper'; -import { IDisposable } from '../../platform/common/types'; -import { executeSilently } from '../../kernels/helpers'; -import { noop } from '../../platform/common/utils/misc'; -import { IDebugService } from '../../platform/common/application/types'; +import { + assertIsDebugConfig, + getMessageSourceAndHookIt, + isDebugEventMsg, + isShortNamePath, + shortNameMatchesLongName +} from './helper'; /** * For info on the custom requests implemented by jupyter see: @@ -151,12 +157,10 @@ export abstract class KernelDebugAdapterBase implements DebugAdapter, IKernelDeb } async onIOPubMessage(_: unknown, msg: KernelMessage.IIOPubMessage) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const anyMsg = msg as any; traceInfoIfCI(`Debug IO Pub message: ${JSON.stringify(msg)}`); - if (anyMsg.header.msg_type === 'debug_event') { + if (isDebugEventMsg(msg)) { this.trace('event', JSON.stringify(msg)); - if (!(await this.delegate?.willSendEvent(anyMsg))) { + if (!(await this.delegate?.willSendEvent(msg.content))) { this.sendMessage.fire(msg.content); } } diff --git a/src/notebooks/debugger/runByLineController.ts b/src/notebooks/debugger/runByLineController.ts index 6b4583c611e..20464c2d953 100644 --- a/src/notebooks/debugger/runByLineController.ts +++ b/src/notebooks/debugger/runByLineController.ts @@ -1,20 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import * as path from '../../platform/vscode-path/path'; -import { DebugProtocolMessage, NotebookCell } from 'vscode'; +import { NotebookCell } from 'vscode'; import { DebugProtocol } from 'vscode-debugprotocol'; -import { ICommandManager } from '../../platform/common/application/types'; import { IKernel } from '../../kernels/types'; +import { ICommandManager } from '../../platform/common/application/types'; +import { Commands } from '../../platform/common/constants'; import { IConfigurationService } from '../../platform/common/types'; +import { parseForComments } from '../../platform/common/utils'; +import { noop } from '../../platform/common/utils/misc'; +import { traceInfoIfCI, traceVerbose } from '../../platform/logging'; +import * as path from '../../platform/vscode-path/path'; import { sendTelemetryEvent } from '../../telemetry'; import { DebuggingTelemetry } from './constants'; -import { traceInfoIfCI, traceVerbose } from '../../platform/logging'; -import { noop } from '../../platform/common/utils/misc'; -import { Commands } from '../../platform/common/constants'; -import { cellDebugSetup } from './helper'; +import { isJustMyCodeNotification } from './debugCellControllers'; import { IDebuggingDelegate, IKernelDebugAdapter, KernelDebugMode } from './debuggingTypes'; -import { parseForComments } from '../../platform/common/utils'; +import { cellDebugSetup } from './helper'; /** * Listens to event when doing run by line and controls the behavior of the debugger (like auto stepping on moving out of a cell) @@ -54,14 +55,18 @@ export class RunByLineController implements IDebuggingDelegate { return config.__mode; } - public async willSendEvent(msg: DebugProtocolMessage): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const anyMsg = msg as any; - - if (anyMsg.content.event === 'stopped') { - this.lastPausedThreadId = anyMsg.content.body.threadId; + public async willSendEvent(msg: DebugProtocol.Event): Promise { + if (msg.event === 'stopped') { + this.lastPausedThreadId = msg.body.threadId; if (await this.handleStoppedEvent(this.lastPausedThreadId!)) { - this.trace('intercepted', JSON.stringify(anyMsg.content)); + this.trace('intercepted', 'handled stop event'); + return true; + } + } + + if (msg.event === 'output') { + if (isJustMyCodeNotification(msg.body.output)) { + this.trace('intercept', 'justMyCode notification'); return true; } }