Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug: adopt external changes #190602

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/debug/browser/debugService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class DebugService implements IDebugService {
this.disposables.add(this.adapterManager);
this.configurationManager = this.instantiationService.createInstance(ConfigurationManager, this.adapterManager);
this.disposables.add(this.configurationManager);
this.debugStorage = this.instantiationService.createInstance(DebugStorage);
this.debugStorage = this.disposables.add(this.instantiationService.createInstance(DebugStorage));

this.chosenEnvironments = this.debugStorage.loadChosenEnvironments();

Expand Down
52 changes: 27 additions & 25 deletions src/vs/workbench/contrib/debug/browser/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';

export class DebugSession implements IDebugSession {
export class DebugSession implements IDebugSession, IDisposable {
parentSession: IDebugSession | undefined;

private _subId: string | undefined;
Expand All @@ -52,7 +52,7 @@ export class DebugSession implements IDebugSession {
private threads = new Map<number, Thread>();
private threadIds: number[] = [];
private cancellationMap = new Map<number, CancellationTokenSource[]>();
private rawListeners: IDisposable[] = [];
private rawListeners = new DisposableStore();
private fetchThreadsScheduler: RunOnceScheduler | undefined;
private passFocusScheduler: RunOnceScheduler;
private lastContinuedThreadId: number | undefined;
Expand Down Expand Up @@ -103,14 +103,11 @@ export class DebugSession implements IDebugSession {
this.repl = (this.parentSession as DebugSession).repl;
}

const toDispose = new DisposableStore();
const toDispose = this.rawListeners.add(new DisposableStore());
const replListener = toDispose.add(new MutableDisposable());
replListener.value = this.repl.onDidChangeElements(() => this._onDidChangeREPLElements.fire());
if (lifecycleService) {
toDispose.add(lifecycleService.onWillShutdown(() => {
this.shutdown();
dispose(toDispose);
}));
toDispose.add(lifecycleService.onWillShutdown(() => this.shutdown()));
}

const compoundRoot = this._options.compoundRoot;
Expand Down Expand Up @@ -950,7 +947,7 @@ export class DebugSession implements IDebugSession {
return;
}

this.rawListeners.push(this.raw.onDidInitialize(async () => {
this.rawListeners.add(this.raw.onDidInitialize(async () => {
aria.status(localize('debuggingStarted', "Debugging started."));
const sendConfigurationDone = async () => {
if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) {
Expand All @@ -976,7 +973,7 @@ export class DebugSession implements IDebugSession {
}));

const statusQueue = new Queue<void>();
this.rawListeners.push(this.raw.onDidStop(async event => {
this.rawListeners.add(this.raw.onDidStop(async event => {
statusQueue.queue(async () => {
this.passFocusScheduler.cancel();
this.stoppedDetails.push(event.body);
Expand Down Expand Up @@ -1026,15 +1023,15 @@ export class DebugSession implements IDebugSession {
});
}));

this.rawListeners.push(this.raw.onDidThread(event => {
this.rawListeners.add(this.raw.onDidThread(event => {
statusQueue.queue(async () => {
if (event.body.reason === 'started') {
// debounce to reduce threadsRequest frequency and improve performance
if (!this.fetchThreadsScheduler) {
this.fetchThreadsScheduler = new RunOnceScheduler(() => {
this.fetchThreads();
}, 100);
this.rawListeners.push(this.fetchThreadsScheduler);
this.rawListeners.add(this.fetchThreadsScheduler);
}
if (!this.fetchThreadsScheduler.isScheduled()) {
this.fetchThreadsScheduler.schedule();
Expand All @@ -1052,7 +1049,7 @@ export class DebugSession implements IDebugSession {
});
}));

this.rawListeners.push(this.raw.onDidTerminateDebugee(async event => {
this.rawListeners.add(this.raw.onDidTerminateDebugee(async event => {
aria.status(localize('debuggingStopped', "Debugging stopped."));
if (event.body && event.body.restart) {
await this.debugService.restartSession(this, event.body.restart);
Expand All @@ -1061,14 +1058,14 @@ export class DebugSession implements IDebugSession {
}
}));

this.rawListeners.push(this.raw.onDidContinued(event => {
this.rawListeners.add(this.raw.onDidContinued(event => {
statusQueue.queue(async () => {
const threadId = event.body.allThreadsContinued !== false ? undefined : event.body.threadId;
if (typeof threadId === 'number') {
this.stoppedDetails = this.stoppedDetails.filter(sd => sd.threadId !== threadId);
const tokens = this.cancellationMap.get(threadId);
this.cancellationMap.delete(threadId);
tokens?.forEach(t => t.cancel());
tokens?.forEach(t => t.dispose(true));
} else {
this.stoppedDetails = [];
this.cancelAllRequests();
Expand All @@ -1082,7 +1079,7 @@ export class DebugSession implements IDebugSession {
}));

const outputQueue = new Queue<void>();
this.rawListeners.push(this.raw.onDidOutput(async event => {
this.rawListeners.add(this.raw.onDidOutput(async event => {
const outputSeverity = event.body.category === 'stderr' ? Severity.Error : event.body.category === 'console' ? Severity.Warning : Severity.Info;

// When a variables event is received, execute immediately to obtain the variables value #126967
Expand Down Expand Up @@ -1161,7 +1158,7 @@ export class DebugSession implements IDebugSession {
});
}));

this.rawListeners.push(this.raw.onDidBreakpoint(event => {
this.rawListeners.add(this.raw.onDidBreakpoint(event => {
const id = event.body && event.body.breakpoint ? event.body.breakpoint.id : undefined;
const breakpoint = this.model.getBreakpoints().find(bp => bp.getIdFromAdapter(this.getId()) === id);
const functionBreakpoint = this.model.getFunctionBreakpoints().find(bp => bp.getIdFromAdapter(this.getId()) === id);
Expand Down Expand Up @@ -1216,30 +1213,30 @@ export class DebugSession implements IDebugSession {
}
}));

this.rawListeners.push(this.raw.onDidLoadedSource(event => {
this.rawListeners.add(this.raw.onDidLoadedSource(event => {
this._onDidLoadedSource.fire({
reason: event.body.reason,
source: this.getSource(event.body.source)
});
}));

this.rawListeners.push(this.raw.onDidCustomEvent(event => {
this.rawListeners.add(this.raw.onDidCustomEvent(event => {
this._onDidCustomEvent.fire(event);
}));

this.rawListeners.push(this.raw.onDidProgressStart(event => {
this.rawListeners.add(this.raw.onDidProgressStart(event => {
this._onDidProgressStart.fire(event);
}));
this.rawListeners.push(this.raw.onDidProgressUpdate(event => {
this.rawListeners.add(this.raw.onDidProgressUpdate(event => {
this._onDidProgressUpdate.fire(event);
}));
this.rawListeners.push(this.raw.onDidProgressEnd(event => {
this.rawListeners.add(this.raw.onDidProgressEnd(event => {
this._onDidProgressEnd.fire(event);
}));
this.rawListeners.push(this.raw.onDidInvalidateMemory(event => {
this.rawListeners.add(this.raw.onDidInvalidateMemory(event => {
this._onDidInvalidMemory.fire(event);
}));
this.rawListeners.push(this.raw.onDidInvalidated(async event => {
this.rawListeners.add(this.raw.onDidInvalidated(async event => {
if (!(event.body.areas && event.body.areas.length === 1 && (event.body.areas[0] === 'variables' || event.body.areas[0] === 'watch'))) {
// If invalidated event only requires to update variables or watch, do that, otherwise refatch threads https://github.com/microsoft/vscode/issues/106745
this.cancelAllRequests();
Expand All @@ -1253,7 +1250,7 @@ export class DebugSession implements IDebugSession {
}
}));

this.rawListeners.push(this.raw.onDidExitAdapter(event => this.onDidExitAdapter(event)));
this.rawListeners.add(this.raw.onDidExitAdapter(event => this.onDidExitAdapter(event)));
}

private onDidExitAdapter(event?: AdapterEndEvent): void {
Expand All @@ -1280,6 +1277,11 @@ export class DebugSession implements IDebugSession {
this._onDidChangeState.fire();
}

public dispose() {
this.cancelAllRequests();
dispose(this.rawListeners);
}

//---- sources

getSourceForUri(uri: URI): Source | undefined {
Expand Down Expand Up @@ -1325,7 +1327,7 @@ export class DebugSession implements IDebugSession {
}

private cancelAllRequests(): void {
this.cancellationMap.forEach(tokens => tokens.forEach(t => t.cancel()));
this.cancellationMap.forEach(tokens => tokens.forEach(t => t.dispose(true)));
this.cancellationMap.clear();
}

Expand Down
39 changes: 25 additions & 14 deletions src/vs/workbench/contrib/debug/common/debugModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { DisassemblyViewInput } from 'vs/workbench/contrib/debug/common/disassem
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ILogService } from 'vs/platform/log/common/log';
import { autorun } from 'vs/base/common/observable';

interface IDebugProtocolVariableWithContext extends DebugProtocol.Variable {
__vscodeVariableMenuContext?: string;
Expand Down Expand Up @@ -1173,19 +1174,19 @@ export class ThreadAndSessionIds implements ITreeElement {
}
}

export class DebugModel implements IDebugModel {
export class DebugModel extends Disposable implements IDebugModel {

private sessions: IDebugSession[];
private schedulers = new Map<string, { scheduler: RunOnceScheduler; completeDeferred: DeferredPromise<void> }>();
private breakpointsActivated = true;
private readonly _onDidChangeBreakpoints = new Emitter<IBreakpointsChangeEvent | undefined>();
private readonly _onDidChangeCallStack = new Emitter<void>();
private readonly _onDidChangeWatchExpressions = new Emitter<IExpression | undefined>();
private breakpoints: Breakpoint[];
private functionBreakpoints: FunctionBreakpoint[];
private exceptionBreakpoints: ExceptionBreakpoint[];
private dataBreakpoints: DataBreakpoint[];
private watchExpressions: Expression[];
private readonly _onDidChangeBreakpoints = this._register(new Emitter<IBreakpointsChangeEvent | undefined>());
private readonly _onDidChangeCallStack = this._register(new Emitter<void>());
private readonly _onDidChangeWatchExpressions = this._register(new Emitter<IExpression | undefined>());
private breakpoints!: Breakpoint[];
private functionBreakpoints!: FunctionBreakpoint[];
private exceptionBreakpoints!: ExceptionBreakpoint[];
private dataBreakpoints!: DataBreakpoint[];
private watchExpressions!: Expression[];
private instructionBreakpoints: InstructionBreakpoint[];

constructor(
Expand All @@ -1194,11 +1195,21 @@ export class DebugModel implements IDebugModel {
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
@ILogService private readonly logService: ILogService
) {
this.breakpoints = debugStorage.loadBreakpoints();
this.functionBreakpoints = debugStorage.loadFunctionBreakpoints();
this.exceptionBreakpoints = debugStorage.loadExceptionBreakpoints();
this.dataBreakpoints = debugStorage.loadDataBreakpoints();
this.watchExpressions = debugStorage.loadWatchExpressions();
super();

this._register(autorun(reader => {
this.breakpoints = debugStorage.breakpoints.read(reader);
this.functionBreakpoints = debugStorage.functionBreakpoints.read(reader);
this.exceptionBreakpoints = debugStorage.exceptionBreakpoints.read(reader);
this.dataBreakpoints = debugStorage.dataBreakpoints.read(reader);
this._onDidChangeBreakpoints.fire(undefined);
}));

this._register(autorun(reader => {
this.watchExpressions = debugStorage.watchExpressions.read(reader);
this._onDidChangeWatchExpressions.fire(undefined);
}));

this.instructionBreakpoints = [];
this.sessions = [];
}
Expand Down
41 changes: 34 additions & 7 deletions src/vs/workbench/contrib/debug/common/debugStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { IEvaluate, IExpression, IDebugModel } from 'vs/workbench/contrib/debug/
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { ILogService } from 'vs/platform/log/common/log';
import { observableValue } from 'vs/base/common/observable';
import { Disposable } from 'vs/base/common/lifecycle';

const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint';
const DEBUG_FUNCTION_BREAKPOINTS_KEY = 'debug.functionbreakpoint';
Expand All @@ -19,13 +21,38 @@ const DEBUG_WATCH_EXPRESSIONS_KEY = 'debug.watchexpressions';
const DEBUG_CHOSEN_ENVIRONMENTS_KEY = 'debug.chosenenvironment';
const DEBUG_UX_STATE_KEY = 'debug.uxstate';

export class DebugStorage {
export class DebugStorage extends Disposable {
public readonly breakpoints = observableValue('debugBreakpoints', this.loadBreakpoints());
public readonly functionBreakpoints = observableValue('debugFunctionBreakpoints', this.loadFunctionBreakpoints());
public readonly exceptionBreakpoints = observableValue('debugExceptionBreakpoints', this.loadExceptionBreakpoints());
public readonly dataBreakpoints = observableValue('debugDataBreakpoints', this.loadDataBreakpoints());
public readonly watchExpressions = observableValue('debugWatchExpressions', this.loadWatchExpressions());

constructor(
@IStorageService private readonly storageService: IStorageService,
@ITextFileService private readonly textFileService: ITextFileService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
@ILogService private readonly logService: ILogService
) { }
) {
super();

this._register(storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, this._store)(e => {
if (e.external) {
switch (e.key) {
case DEBUG_BREAKPOINTS_KEY:
return this.breakpoints.set(this.loadBreakpoints(), undefined);
case DEBUG_FUNCTION_BREAKPOINTS_KEY:
return this.functionBreakpoints.set(this.loadFunctionBreakpoints(), undefined);
case DEBUG_EXCEPTION_BREAKPOINTS_KEY:
return this.exceptionBreakpoints.set(this.loadExceptionBreakpoints(), undefined);
case DEBUG_DATA_BREAKPOINTS_KEY:
return this.dataBreakpoints.set(this.loadDataBreakpoints(), undefined);
case DEBUG_WATCH_EXPRESSIONS_KEY:
return this.watchExpressions.set(this.loadWatchExpressions(), undefined);
}
}
}));
}

loadDebugUxState(): 'simple' | 'default' {
return this.storageService.get(DEBUG_UX_STATE_KEY, StorageScope.WORKSPACE, 'default') as 'simple' | 'default';
Expand All @@ -35,7 +62,7 @@ export class DebugStorage {
this.storageService.store(DEBUG_UX_STATE_KEY, value, StorageScope.WORKSPACE, StorageTarget.MACHINE);
}

loadBreakpoints(): Breakpoint[] {
private loadBreakpoints(): Breakpoint[] {
let result: Breakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => {
Expand All @@ -46,7 +73,7 @@ export class DebugStorage {
return result || [];
}

loadFunctionBreakpoints(): FunctionBreakpoint[] {
private loadFunctionBreakpoints(): FunctionBreakpoint[] {
let result: FunctionBreakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => {
Expand All @@ -57,7 +84,7 @@ export class DebugStorage {
return result || [];
}

loadExceptionBreakpoints(): ExceptionBreakpoint[] {
private loadExceptionBreakpoints(): ExceptionBreakpoint[] {
let result: ExceptionBreakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_EXCEPTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((exBreakpoint: any) => {
Expand All @@ -68,7 +95,7 @@ export class DebugStorage {
return result || [];
}

loadDataBreakpoints(): DataBreakpoint[] {
private loadDataBreakpoints(): DataBreakpoint[] {
let result: DataBreakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_DATA_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((dbp: any) => {
Expand All @@ -79,7 +106,7 @@ export class DebugStorage {
return result || [];
}

loadWatchExpressions(): Expression[] {
private loadWatchExpressions(): Expression[] {
let result: Expression[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_WATCH_EXPRESSIONS_KEY, StorageScope.WORKSPACE, '[]')).map((watchStoredData: { name: string; id: string }) => {
Expand Down
Loading
Loading