Skip to content

Commit

Permalink
[vscode] Implement stubbed API for activeStackFrame API
Browse files Browse the repository at this point in the history
fixes eclipse-theia#13846

contributed on behalf of STMicroelectronics
  • Loading branch information
rschnekenbu committed Jul 9, 2024
1 parent 10b156c commit e3fa0f5
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

<!-- ## not yet released
- [debug] implement activeStackItem and related change event in debug namespace [#13900](https://github.com/eclipse-theia/theia/pull/13900) - contributed on behalf of STMicroelectronics
<a name="breaking_changes_not_yet_released">[Breaking Changes:](#breaking_changes_not_yet_released)</a>
-->
Expand Down
15 changes: 8 additions & 7 deletions packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ export interface DidChangeBreakpointsEvent {
uri: URI
}

export interface DidFocusStackFrameEvent {
session: DebugSession;
frame: DebugStackFrame | undefined;
}

export interface DebugSessionCustomEvent {
readonly body?: any // eslint-disable-line @typescript-eslint/no-explicit-any
readonly event: string
Expand Down Expand Up @@ -94,9 +89,12 @@ export class DebugSessionManager {
protected readonly onDidReceiveDebugSessionCustomEventEmitter = new Emitter<DebugSessionCustomEvent>();
readonly onDidReceiveDebugSessionCustomEvent: Event<DebugSessionCustomEvent> = this.onDidReceiveDebugSessionCustomEventEmitter.event;

protected readonly onDidFocusStackFrameEmitter = new Emitter<DidFocusStackFrameEvent>();
protected readonly onDidFocusStackFrameEmitter = new Emitter<DebugStackFrame | undefined>();
readonly onDidFocusStackFrame = this.onDidFocusStackFrameEmitter.event;

protected readonly onDidFocusThreadEmitter = new Emitter<DebugThread | undefined>();
readonly onDidFocusThread = this.onDidFocusThreadEmitter.event;

protected readonly onDidChangeBreakpointsEmitter = new Emitter<DidChangeBreakpointsEvent>();
readonly onDidChangeBreakpoints = this.onDidChangeBreakpointsEmitter.event;
protected fireDidChangeBreakpoints(event: DidChangeBreakpointsEvent): void {
Expand Down Expand Up @@ -518,7 +516,10 @@ export class DebugSessionManager {
}
this.fireDidChange(current);
}));
this.disposeOnCurrentSessionChanged.push(current.onDidFocusStackFrame(frame => this.onDidFocusStackFrameEmitter.fire({ session: current, frame })));
this.disposeOnCurrentSessionChanged.push(current.onDidFocusStackFrame(frame => this.onDidFocusStackFrameEmitter.fire(frame)));
this.disposeOnCurrentSessionChanged.push(current.onDidFocusThread(thread => this.onDidFocusThreadEmitter.fire(thread)));
const { currentThread } = current;
this.onDidFocusThreadEmitter.fire(currentThread);
}
this.updateBreakpoints(previous, current);
this.open();
Expand Down
9 changes: 9 additions & 0 deletions packages/debug/src/browser/debug-session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ export class DebugSession implements CompositeTreeElement {
return this.onDidFocusStackFrameEmitter.event;
}

protected readonly onDidFocusThreadEmitter = new Emitter<DebugThread | undefined>();
get onDidFocusThread(): Event<DebugThread | undefined> {
return this.onDidFocusThreadEmitter.event;
}

protected readonly onDidChangeBreakpointsEmitter = new Emitter<URI>();
readonly onDidChangeBreakpoints: Event<URI> = this.onDidChangeBreakpointsEmitter.event;
protected fireDidChangeBreakpoints(uri: URI): void {
Expand Down Expand Up @@ -254,8 +259,12 @@ export class DebugSession implements CompositeTreeElement {
return this._currentThread;
}
set currentThread(thread: DebugThread | undefined) {
if (this._currentThread === thread) {
return;
}
this.toDisposeOnCurrentThread.dispose();
this._currentThread = thread;
this.onDidFocusThreadEmitter.fire(thread);
this.fireDidChange();
if (thread) {
this.toDisposeOnCurrentThread.push(thread.onDidChanged(() => this.fireDidChange()));
Expand Down
7 changes: 7 additions & 0 deletions packages/debug/src/browser/model/debug-stack-frame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ export class DebugStackFrame extends DebugStackFrameData implements TreeElement
return this.session.id + ':' + this.thread.id + ':' + this.raw.id;
}

/**
* Returns the frame identifier from the debug protocol.
*/
get frameId(): number {
return this.raw.id;
}

protected _source: DebugSource | undefined;
get source(): DebugSource | undefined {
return this._source;
Expand Down
7 changes: 7 additions & 0 deletions packages/debug/src/browser/model/debug-thread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,18 @@ export class DebugThread extends DebugThreadData implements TreeElement {
return this.session.id + ':' + this.raw.id;
}

get threadId(): number {
return this.raw.id;
}

protected _currentFrame: DebugStackFrame | undefined;
get currentFrame(): DebugStackFrame | undefined {
return this._currentFrame;
}
set currentFrame(frame: DebugStackFrame | undefined) {
if (this._currentFrame === frame) {
return;
}
this._currentFrame = frame;
this.onDidChangedEmitter.fire(undefined);
this.onDidFocusStackFrameEmitter.fire(frame);
Expand Down
1 change: 1 addition & 0 deletions packages/debug/src/browser/view/debug-threads-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export class DebugThreadsWidget extends SourceTreeWidget {
this.viewModel.currentSession = node.element;
this.debugCallStackItemTypeKey.set('session');
} else if (node.element instanceof DebugThread) {
this.viewModel.currentSession = node.element.session;
node.element.session.currentThread = node.element;
this.debugCallStackItemTypeKey.set('thread');
}
Expand Down
10 changes: 10 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -895,3 +895,13 @@ export interface InlineCompletionsProvider<T extends InlineCompletions = InlineC
freeInlineCompletions(completions: T): void;
}

export interface DebugStackFrameDTO {
readonly sessionId: string,
readonly frameId: number,
readonly threadId: number
}

export interface DebugThreadDTO {
readonly sessionId: string,
readonly threadId: number
}
6 changes: 5 additions & 1 deletion packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ import {
InlineCompletionContext,
DocumentDropEdit,
DataTransferDTO,
DocumentDropEditProviderMetadata
DocumentDropEditProviderMetadata,
DebugStackFrameDTO,
DebugThreadDTO
} from './plugin-api-rpc-model';
import { ExtPluginApi } from './plugin-ext-api-contribution';
import { KeysToAnyValues, KeysToKeysToAnyValue } from './types';
Expand Down Expand Up @@ -1981,6 +1983,8 @@ export interface DebugExt {
debugConfiguration: DebugConfiguration
): Promise<theia.DebugConfiguration | undefined | null>;

$onDidChangeActiveFrame(frame: DebugStackFrameDTO | undefined): void;
$onDidChangeActiveThread(thread: DebugThreadDTO | undefined): void;
$createDebugSession(debugConfiguration: DebugConfiguration, workspaceFolder: string | undefined): Promise<string>;
$terminateDebugSession(sessionId: string): Promise<void>;
$getTerminalCreationOptions(debugType: string): Promise<TerminalOptionsExt | undefined>;
Expand Down
23 changes: 21 additions & 2 deletions packages/plugin-ext/src/main/browser/debug/debug-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
MAIN_RPC_CONTEXT
} from '../../../common/plugin-api-rpc';
import { DebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
import { Breakpoint, WorkspaceFolder } from '../../../common/plugin-api-rpc-model';
import { Breakpoint, DebugStackFrameDTO, DebugThreadDTO, WorkspaceFolder } from '../../../common/plugin-api-rpc-model';
import { LabelProvider } from '@theia/core/lib/browser';
import { EditorManager } from '@theia/editor/lib/browser';
import { BreakpointManager, BreakpointsChangeEvent } from '@theia/debug/lib/browser/breakpoint/breakpoint-manager';
Expand Down Expand Up @@ -56,6 +56,8 @@ import { DebugContribution } from '@theia/debug/lib/browser/debug-contribution';
import { ConnectionImpl } from '../../../common/connection';
import { WorkspaceService } from '@theia/workspace/lib/browser';
import { DebugSessionOptions as TheiaDebugSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
import { DebugStackFrame } from '@theia/debug/lib/browser/model/debug-stack-frame';
import { DebugThread } from '@theia/debug/lib/browser/model/debug-thread';

export class DebugMainImpl implements DebugMain, Disposable {
private readonly debugExt: DebugExt;
Expand Down Expand Up @@ -117,7 +119,9 @@ export class DebugMainImpl implements DebugMain, Disposable {
this.sessionManager.onDidStartDebugSession(debugSession => this.debugExt.$sessionDidStart(debugSession.id)),
this.sessionManager.onDidDestroyDebugSession(debugSession => this.debugExt.$sessionDidDestroy(debugSession.id)),
this.sessionManager.onDidChangeActiveDebugSession(event => this.debugExt.$sessionDidChange(event.current && event.current.id)),
this.sessionManager.onDidReceiveDebugSessionCustomEvent(event => this.debugExt.$onSessionCustomEvent(event.session.id, event.event, event.body))
this.sessionManager.onDidReceiveDebugSessionCustomEvent(event => this.debugExt.$onSessionCustomEvent(event.session.id, event.event, event.body)),
this.sessionManager.onDidFocusStackFrame(stackFrame => this.debugExt.$onDidChangeActiveFrame(this.toDebugStackFrameDTO(stackFrame))),
this.sessionManager.onDidFocusThread(debugThread => this.debugExt.$onDidChangeActiveThread(this.toDebugThreadDTO(debugThread))),
]);
}

Expand Down Expand Up @@ -340,6 +344,21 @@ export class DebugMainImpl implements DebugMain, Disposable {
}
}

private toDebugStackFrameDTO(stackFrame: DebugStackFrame | undefined): DebugStackFrameDTO | undefined {
return stackFrame ? {
sessionId: stackFrame.session.id,
frameId: stackFrame.frameId,
threadId: stackFrame.thread.threadId
} : undefined;
}

private toDebugThreadDTO(debugThread: DebugThread | undefined): DebugThreadDTO | undefined {
return debugThread ? {
sessionId: debugThread.session.id,
threadId: debugThread.threadId
} : undefined;
}

private toTheiaPluginApiBreakpoints(breakpoints: (SourceBreakpoint | FunctionBreakpoint)[]): Breakpoint[] {
return breakpoints.map(b => this.toTheiaPluginApiBreakpoint(b));
}
Expand Down
42 changes: 40 additions & 2 deletions packages/plugin-ext/src/plugin/debug/debug-ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import { Emitter } from '@theia/core/lib/common/event';
import { Path } from '@theia/core/lib/common/path';
import * as theia from '@theia/plugin';
import { URI } from '@theia/core/shared/vscode-uri';
import { Breakpoint } from '../../common/plugin-api-rpc-model';
import { Breakpoint, DebugStackFrameDTO, DebugThreadDTO } from '../../common/plugin-api-rpc-model';
import { DebugConfigurationProviderTriggerKind, DebugExt, DebugMain, PLUGIN_RPC_CONTEXT as Ext, TerminalOptionsExt } from '../../common/plugin-api-rpc';
import { PluginPackageDebuggersContribution } from '../../common/plugin-protocol';
import { RPCProtocol } from '../../common/rpc-protocol';
import { CommandRegistryImpl } from '../command-registry';
import { ConnectionImpl } from '../../common/connection';
import { DEBUG_SCHEME, SCHEME_PATTERN } from '@theia/debug/lib/common/debug-uri-utils';
import { Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range, URI as URIImpl } from '../types-impl';
import { Disposable, Breakpoint as BreakpointExt, SourceBreakpoint, FunctionBreakpoint, Location, Range, URI as URIImpl, DebugStackFrame, DebugThread } from '../types-impl';
import { PluginDebugAdapterSession } from './plugin-debug-adapter-session';
import { PluginDebugAdapterTracker } from './plugin-debug-adapter-tracker';
import { generateUuid } from '@theia/core/lib/common/uuid';
Expand Down Expand Up @@ -79,6 +79,9 @@ export class DebugExtImpl implements DebugExt {
activeDebugSession: theia.DebugSession | undefined;
activeDebugConsole: theia.DebugConsole;

_activeStackItem: theia.DebugStackFrame | theia.DebugThread | undefined;
private readonly onDidChangeActiveStackItemEmitter = new Emitter<theia.DebugStackFrame | theia.DebugThread | undefined>();

private readonly _breakpoints = new Map<string, theia.Breakpoint>();

private frontendAdapterCreator = new PluginDebugAdapterCreator();
Expand Down Expand Up @@ -149,6 +152,10 @@ export class DebugExtImpl implements DebugExt {
return this.onDidStartDebugSessionEmitter.event;
}

get onDidChangeActiveStackItem(): theia.Event<theia.DebugStackFrame | theia.DebugThread | undefined> {
return this.onDidChangeActiveStackItemEmitter.event;
}

get onDidChangeBreakpoints(): theia.Event<theia.BreakpointsChangeEvent> {
return this.onDidChangeBreakpointsEmitter.event;
}
Expand Down Expand Up @@ -262,6 +269,37 @@ export class DebugExtImpl implements DebugExt {
});
}

set activeStackItem(stackItem: theia.DebugStackFrame | theia.DebugThread | undefined) {
this._activeStackItem = stackItem;
this.onDidChangeActiveStackItemEmitter.fire(this.activeStackItem);
}

get activeStackItem(): theia.DebugStackFrame | theia.DebugThread | undefined {
return this._activeStackItem;
}

async $onDidChangeActiveThread(debugThread: DebugThreadDTO | undefined): Promise<void> {
if (!debugThread) {
this.activeStackItem = undefined;
return;
}
const session = this.sessions.get(debugThread.sessionId);
if (session) {
this.activeStackItem = new DebugThread(session, debugThread.threadId);
}
}

async $onDidChangeActiveFrame(debugFrame: DebugStackFrameDTO | undefined): Promise<void> {
if (!debugFrame) {
this.activeStackItem = undefined;
return;
}
const session = this.sessions.get(debugFrame!.sessionId);
if (session) {
this.activeStackItem = new DebugStackFrame(session, debugFrame.threadId, debugFrame.frameId);
}
}

async $onSessionCustomEvent(sessionId: string, event: string, body?: any): Promise<void> {
const session = this.sessions.get(sessionId);
if (session) {
Expand Down
6 changes: 2 additions & 4 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1092,13 +1092,11 @@ export function createAPIFactory(
get onDidChangeBreakpoints(): theia.Event<theia.BreakpointsChangeEvent> {
return debugExt.onDidChangeBreakpoints;
},
/** @stubbed */
get activeStackItem(): DebugThread | DebugStackFrame | undefined {
return undefined;
return debugExt.activeStackItem;
},
/** @stubbed */
get onDidChangeActiveStackItem(): theia.Event<DebugThread | DebugStackFrame | undefined> {
return Event.None;
return debugExt.onDidChangeActiveStackItem;
},
registerDebugAdapterDescriptorFactory(debugType: string, factory: theia.DebugAdapterDescriptorFactory): Disposable {
return debugExt.registerDebugAdapterDescriptorFactory(debugType, factory);
Expand Down
8 changes: 4 additions & 4 deletions packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3031,12 +3031,12 @@ export class FunctionBreakpoint extends Breakpoint {
}
}

export class DebugThread {
private constructor(readonly session: theia.DebugSession, readonly threadId: number) { }
export class DebugThread implements theia.DebugThread {
constructor(readonly session: theia.DebugSession, readonly threadId: number) { }
}

export class DebugStackFrame {
private constructor(readonly session: theia.DebugSession, readonly threadId: number, readonly frameId: number) { }
export class DebugStackFrame implements theia.DebugStackFrame {
constructor(readonly session: theia.DebugSession, readonly threadId: number, readonly frameId: number) { }
}

@es5ClassCompat
Expand Down
2 changes: 0 additions & 2 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12546,13 +12546,11 @@ export module '@theia/plugin' {
* thread or stack is focused. A thread can be focused any time there is
* an active debug session, while a stack frame can only be focused when
* a session is paused and the call stack has been retrieved.
* @stubbed
*/
export const activeStackItem: DebugThread | DebugStackFrame | undefined;

/**
* An event which fires when the {@link debug.activeStackItem} has changed.
* @stubbed
*/
export const onDidChangeActiveStackItem: Event<DebugThread | DebugStackFrame | undefined>;

Expand Down

0 comments on commit e3fa0f5

Please sign in to comment.