debug: tighten down debugFocus API proposal (#207006)

* debug: tighten down debugFocus API proposal

Some bug fixes and reworking to align better with our APIs

* fix getter error
This commit is contained in:
Connor Peet 2024-03-06 13:58:09 -08:00 committed by GitHub
parent 25f1b18fbc
commit 5cbe2b9646
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 72 additions and 81 deletions

View file

@ -18,6 +18,7 @@ import { convertToVSCPaths, convertToDAPaths, isSessionAttach } from 'vs/workben
import { ErrorNoTelemetry } from 'vs/base/common/errors';
import { IDebugVisualizerService } from 'vs/workbench/contrib/debug/common/debugVisualizers';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Event } from 'vs/base/common/event';
@extHostNamedCustomer(MainContext.MainThreadDebugService)
export class MainThreadDebugService implements MainThreadDebugServiceShape, IDebugAdapterFactory {
@ -88,28 +89,28 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
this._debugAdapterDescriptorFactories = new Map();
this._extHostKnownSessions = new Set();
this._toDispose.add(this.debugService.getViewModel().onDidFocusThread(({ thread, explicit, session }) => {
if (session) {
const dto: IThreadFocusDto = {
const viewModel = this.debugService.getViewModel();
this._toDispose.add(Event.any(viewModel.onDidFocusStackFrame, viewModel.onDidFocusThread)(() => {
const stackFrame = viewModel.focusedStackFrame;
const thread = viewModel.focusedThread;
if (stackFrame) {
this._proxy.$acceptStackFrameFocus({
kind: 'stackFrame',
threadId: stackFrame.thread.threadId,
frameId: stackFrame.frameId,
sessionId: stackFrame.thread.session.getId(),
} satisfies IStackFrameFocusDto);
} else if (thread) {
this._proxy.$acceptStackFrameFocus({
kind: 'thread',
threadId: thread?.threadId,
sessionId: session.getId(),
};
this._proxy.$acceptStackFrameFocus(dto);
threadId: thread.threadId,
sessionId: thread.session.getId(),
} satisfies IThreadFocusDto);
} else {
this._proxy.$acceptStackFrameFocus(undefined);
}
}));
this._toDispose.add(this.debugService.getViewModel().onDidFocusStackFrame(({ stackFrame, explicit, session }) => {
if (session) {
const dto: IStackFrameFocusDto = {
kind: 'stackFrame',
threadId: stackFrame?.thread.threadId,
frameId: stackFrame?.frameId,
sessionId: session.getId(),
};
this._proxy.$acceptStackFrameFocus(dto);
}
}));
this.sendBreakpointsAndListen();
}

View file

@ -1241,8 +1241,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
get breakpoints() {
return extHostDebugService.breakpoints;
},
get stackFrameFocus() {
return extHostDebugService.stackFrameFocus;
get activeStackItem() {
if (!isProposedApiEnabled(extension, 'debugFocus')) {
return undefined;
}
return extHostDebugService.activeStackItem;
},
registerDebugVisualizationProvider(id, provider) {
checkProposedApiEnabled(extension, 'debugVisualization');
@ -1267,9 +1270,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
onDidChangeBreakpoints(listener, thisArgs?, disposables?) {
return _asExtensionEvent(extHostDebugService.onDidChangeBreakpoints)(listener, thisArgs, disposables);
},
onDidChangeStackFrameFocus(listener, thisArg?, disposables?) {
onDidChangeActiveStackItem(listener, thisArg?, disposables?) {
checkProposedApiEnabled(extension, 'debugFocus');
return _asExtensionEvent(extHostDebugService.onDidChangeStackFrameFocus)(listener, thisArg, disposables);
return _asExtensionEvent(extHostDebugService.onDidChangeActiveStackItem)(listener, thisArg, disposables);
},
registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider, triggerKind?: vscode.DebugConfigurationProviderTriggerKind) {
return extHostDebugService.registerDebugConfigurationProvider(debugType, provider, triggerKind || DebugConfigurationProviderTriggerKind.Initial);
@ -1673,8 +1676,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
InteractiveSessionVoteDirection: extHostTypes.InteractiveSessionVoteDirection,
ChatCopyKind: extHostTypes.ChatCopyKind,
InteractiveEditorResponseFeedbackKind: extHostTypes.InteractiveEditorResponseFeedbackKind,
StackFrameFocus: extHostTypes.StackFrameFocus,
ThreadFocus: extHostTypes.ThreadFocus,
StackFrame: extHostTypes.StackFrame,
Thread: extHostTypes.Thread,
RelatedInformationType: extHostTypes.RelatedInformationType,
SpeechToTextStatus: extHostTypes.SpeechToTextStatus,
PartialAcceptTriggerKind: extHostTypes.PartialAcceptTriggerKind,

View file

@ -2342,14 +2342,14 @@ export type IDebugSessionDto = IDebugSessionFullDto | DebugSessionUUID;
export interface IThreadFocusDto {
kind: 'thread';
sessionId: string;
threadId: number | undefined;
threadId: number;
}
export interface IStackFrameFocusDto {
kind: 'stackFrame';
sessionId: string;
threadId: number | undefined;
frameId: number | undefined;
threadId: number;
frameId: number;
}

View file

@ -15,7 +15,7 @@ import { DebugSessionUUID, ExtHostDebugServiceShape, IBreakpointsDeltaDto, IThre
import { IExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { Breakpoint, DataBreakpoint, DebugAdapterExecutable, DebugAdapterInlineImplementation, DebugAdapterNamedPipeServer, DebugAdapterServer, DebugConsoleMode, Disposable, FunctionBreakpoint, Location, Position, setBreakpointId, SourceBreakpoint, ThreadFocus, StackFrameFocus, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
import { Breakpoint, DataBreakpoint, DebugAdapterExecutable, DebugAdapterInlineImplementation, DebugAdapterNamedPipeServer, DebugAdapterServer, DebugConsoleMode, Disposable, FunctionBreakpoint, Location, Position, setBreakpointId, SourceBreakpoint, Thread, StackFrame, ThemeIcon } from 'vs/workbench/api/common/extHostTypes';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
import { MainThreadDebugVisualization, IAdapterDescriptor, IConfig, IDebugAdapter, IDebugAdapterExecutable, IDebugAdapterNamedPipeServer, IDebugAdapterServer, IDebugVisualization, IDebugVisualizationContext, IDebuggerContribution, DebugVisualizationType, IDebugVisualizationTreeItem } from 'vs/workbench/contrib/debug/common/debug';
@ -44,8 +44,8 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape {
onDidReceiveDebugSessionCustomEvent: Event<vscode.DebugSessionCustomEvent>;
onDidChangeBreakpoints: Event<vscode.BreakpointsChangeEvent>;
breakpoints: vscode.Breakpoint[];
onDidChangeStackFrameFocus: Event<vscode.ThreadFocus | vscode.StackFrameFocus | undefined>;
stackFrameFocus: vscode.ThreadFocus | vscode.StackFrameFocus | undefined;
onDidChangeActiveStackItem: Event<vscode.Thread | vscode.StackFrame | undefined>;
activeStackItem: vscode.Thread | vscode.StackFrame | undefined;
addBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise<void>;
removeBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise<void>;
@ -97,8 +97,8 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
private readonly _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>;
private _stackFrameFocus: vscode.ThreadFocus | vscode.StackFrameFocus | undefined;
private readonly _onDidChangeStackFrameFocus: Emitter<vscode.ThreadFocus | vscode.StackFrameFocus | undefined>;
private _activeStackItem: vscode.Thread | vscode.StackFrame | undefined;
private readonly _onDidChangeActiveStackItem: Emitter<vscode.Thread | vscode.StackFrame | undefined>;
private _debugAdapters: Map<number, IDebugAdapter>;
private _debugAdaptersTrackers: Map<number, vscode.DebugAdapterTracker>;
@ -144,7 +144,7 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
this._onDidChangeBreakpoints = new Emitter<vscode.BreakpointsChangeEvent>();
this._onDidChangeStackFrameFocus = new Emitter<vscode.ThreadFocus | vscode.StackFrameFocus | undefined>();
this._onDidChangeActiveStackItem = new Emitter<vscode.Thread | vscode.StackFrame | undefined>();
this._activeDebugConsole = new ExtHostDebugConsole(this._debugServiceProxy);
@ -278,12 +278,12 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
// extension debug API
get stackFrameFocus(): vscode.ThreadFocus | vscode.StackFrameFocus | undefined {
return this._stackFrameFocus;
get activeStackItem(): vscode.Thread | vscode.StackFrame | undefined {
return this._activeStackItem;
}
get onDidChangeStackFrameFocus(): Event<vscode.ThreadFocus | vscode.StackFrameFocus | undefined> {
return this._onDidChangeStackFrameFocus.event;
get onDidChangeActiveStackItem(): Event<vscode.Thread | vscode.StackFrame | undefined> {
return this._onDidChangeActiveStackItem.event;
}
get onDidChangeBreakpoints(): Event<vscode.BreakpointsChangeEvent> {
@ -768,21 +768,19 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E
this.fireBreakpointChanges(a, r, c);
}
public async $acceptStackFrameFocus(focusDto: IThreadFocusDto | IStackFrameFocusDto): Promise<void> {
let focus: ThreadFocus | StackFrameFocus;
const session = focusDto.sessionId ? await this.getSession(focusDto.sessionId) : undefined;
if (!session) {
throw new Error('no DebugSession found for debug focus context');
public async $acceptStackFrameFocus(focusDto: IThreadFocusDto | IStackFrameFocusDto | undefined): Promise<void> {
let focus: vscode.Thread | vscode.StackFrame | undefined;
if (focusDto) {
const session = await this.getSession(focusDto.sessionId);
if (focusDto.kind === 'thread') {
focus = new Thread(session.api, focusDto.threadId);
} else {
focus = new StackFrame(session.api, focusDto.threadId, focusDto.frameId);
}
}
if (focusDto.kind === 'thread') {
focus = new ThreadFocus(session.api, focusDto.threadId);
} else {
focus = new StackFrameFocus(session.api, focusDto.threadId, focusDto.frameId);
}
this._stackFrameFocus = <vscode.ThreadFocus | vscode.StackFrameFocus>focus;
this._onDidChangeStackFrameFocus.fire(this._stackFrameFocus);
this._activeStackItem = focus;
this._onDidChangeActiveStackItem.fire(this._activeStackItem);
}
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined, token: CancellationToken): Promise<vscode.DebugConfiguration[]> {

View file

@ -3035,23 +3035,20 @@ export class DebugAdapterInlineImplementation implements vscode.DebugAdapterInli
}
@es5ClassCompat
export class StackFrameFocus {
export class StackFrame implements vscode.StackFrame {
constructor(
public readonly session: vscode.DebugSession,
readonly threadId?: number,
readonly frameId?: number) { }
readonly threadId: number,
readonly frameId: number) { }
}
@es5ClassCompat
export class ThreadFocus {
export class Thread implements vscode.Thread {
constructor(
public readonly session: vscode.DebugSession,
readonly threadId?: number) { }
readonly threadId: number) { }
}
@es5ClassCompat
export class EvaluatableExpression implements vscode.EvaluatableExpression {
readonly range: vscode.Range;

View file

@ -7,17 +7,13 @@ declare module 'vscode' {
// See https://github.com/microsoft/vscode/issues/63943
export class ThreadFocus {
export class Thread {
/**
* Create a ThreadFocus
* @param session
* @param threadId
* @param frameId
*/
constructor(
session: DebugSession,
threadId?: number);
constructor(session: DebugSession, threadId: number);
/**
* Debug session for thread.
@ -25,23 +21,19 @@ declare module 'vscode' {
readonly session: DebugSession;
/**
* Id of the associated thread (DAP id). May be undefined if thread has become unselected.
* ID of the associated thread in the debug protocol.
*/
readonly threadId: number | undefined;
readonly threadId: number;
}
export class StackFrameFocus {
export class StackFrame {
/**
* Create a StackFrameFocus
* @param session
* @param threadId
* @param frameId
*/
constructor(
session: DebugSession,
threadId?: number,
frameId?: number);
constructor(session: DebugSession, threadId?: number, frameId?: number);
/**
* Debug session for thread.
@ -49,26 +41,26 @@ declare module 'vscode' {
readonly session: DebugSession;
/**
* Id of the associated thread (DAP id). May be undefined if a frame is unselected.
* Id of the associated thread in the debug protocol.
*/
readonly threadId: number | undefined;
readonly threadId: number;
/**
* Id of the stack frame (DAP id). May be undefined if a frame is unselected.
* Id of the stack frame in the debug protocol.
*/
readonly frameId: number | undefined;
readonly frameId: number;
}
export namespace debug {
/**
* The currently focused thread or stack frame id, or `undefined` if this has not been set. (e.g. not in debug mode).
* The currently focused thread or stack frame, or `undefined` if no
* thread or stack is focused.
*/
export let stackFrameFocus: ThreadFocus | StackFrameFocus | undefined;
export const activeStackItem: Thread | StackFrame | undefined;
/**
* An {@link Event} which fires when the {@link debug.stackFrameFocus} changes. Provides a sessionId. threadId is not undefined
* when a thread of frame has gained focus. frameId is defined when a stackFrame has gained focus.
* An event which fires when the {@link debug.activeStackItem} has changed.
*/
export const onDidChangeStackFrameFocus: Event<ThreadFocus | StackFrameFocus | undefined>;
export const onDidChangeActiveStackItem: Event<Thread | StackFrame | undefined>;
}
}