From 67432bb17e72ad0ff7cf53f4f3b98f00a5eca652 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 18 Mar 2020 10:47:13 +0100 Subject: [PATCH] debug viewlet show progress fixes #92253 --- .../contrib/debug/browser/debugSession.ts | 8 +++ .../contrib/debug/browser/debugViewlet.ts | 56 +++++++++++++++++-- .../workbench/contrib/debug/common/debug.ts | 1 + .../contrib/debug/test/common/mockDebug.ts | 4 ++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 301e78396da..9636ba66420 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -603,6 +603,14 @@ export class DebugSession implements IDebugSession { }, token); } + async cancel(progressId: string): Promise { + if (!this.raw) { + return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'cancel'))); + } + + return this.raw.cancel({ progressId }); + } + //---- threads getThread(threadId: number): Thread | undefined { diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 2c59ca9f209..e09cd9fdd99 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -5,10 +5,11 @@ import 'vs/css!./media/debugViewlet'; import * as nls from 'vs/nls'; -import { IAction } from 'vs/base/common/actions'; +import { IAction, Action } from 'vs/base/common/actions'; import * as DOM from 'vs/base/browser/dom'; +import { Event } from 'vs/base/common/event'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, DEBUG_PANEL_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, DEBUG_PANEL_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, IDebugSession } from 'vs/workbench/contrib/debug/common/debug'; import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions'; import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -43,6 +44,7 @@ export class DebugViewPaneContainer extends ViewPaneContainer { private paneListeners = new Map(); private debugToolBarMenu: IMenu | undefined; private disposeOnTitleUpdate: IDisposable | undefined; + private progressEvents: { event: DebugProtocol.ProgressStartEvent, session: IDebugSession }[] = []; constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @@ -79,6 +81,34 @@ export class DebugViewPaneContainer extends ViewPaneContainer { this.updateTitleArea(); } })); + + let progressListener: IDisposable; + this._register(this.debugService.getViewModel().onDidFocusSession(session => { + if (progressListener) { + progressListener.dispose(); + } + if (session) { + progressListener = session.onDidProgressStart(async progressStartEvent => { + // Update title area to show the cancel progress action + this.progressEvents.push({ session: session, event: progressStartEvent }); + this.cancelAction.tooltip = nls.localize('cancelProgress', "Cancel {0}", progressStartEvent.body.title); + this.updateTitleArea(); + await this.progressService.withProgress({ location: VIEWLET_ID }, () => { + return new Promise(r => { + // Show progress until a progress end event comes or the session ends + const listener = Event.any(Event.filter(session.onDidProgressEnd, e => e.body.progressId === progressStartEvent.body.progressId), + session.onDidEndAdapter)(() => { + listener.dispose(); + r(); + }); + }); + }); + this.cancelAction.tooltip = nls.localize('cancel', "Cancel"); + this.progressEvents = this.progressEvents.filter(pe => pe.event.body.progressId !== progressStartEvent.body.progressId); + this.updateTitleArea(); + }); + } + })); } create(parent: HTMLElement): void { @@ -111,6 +141,14 @@ export class DebugViewPaneContainer extends ViewPaneContainer { return this._register(this.instantiationService.createInstance(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL)); } + @memoize + private get cancelAction(): Action { + return this._register(new Action('debug.cancelProgress', nls.localize('cancel', "Cancel"), 'debug-action codicon codicon-stop', true, async () => { + let { event, session } = this.progressEvents[this.progressEvents.length - 1]; + await session.cancel(event.body.progressId); + })); + } + @memoize private get selectAndStartAction(): SelectAndStartAction { return this._register(this.instantiationService.createInstance(SelectAndStartAction, SelectAndStartAction.ID, nls.localize('startAdditionalSession', "Start Additional Session"))); @@ -120,6 +158,8 @@ export class DebugViewPaneContainer extends ViewPaneContainer { if (CONTEXT_DEBUG_UX.getValue(this.contextKeyService) === 'simple') { return []; } + + let result: IAction[]; if (!this.showInitialDebugActions) { if (!this.debugToolBarMenu) { @@ -133,14 +173,18 @@ export class DebugViewPaneContainer extends ViewPaneContainer { } this.disposeOnTitleUpdate = disposable; - return actions; + result = actions; + } else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { + result = [this.toggleReplAction]; + } else { + result = [this.startAction, this.configureAction, this.toggleReplAction]; } - if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { - return [this.toggleReplAction]; + if (this.progressEvents.length) { + result.unshift(this.cancelAction); } - return [this.startAction, this.configureAction, this.toggleReplAction]; + return result; } get showInitialDebugActions(): boolean { diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 8cb15795826..a538a757e80 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -223,6 +223,7 @@ export interface IDebugSession extends ITreeElement { variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise; evaluate(expression: string, frameId?: number, context?: string): Promise; customRequest(request: string, args: any): Promise; + cancel(progressId: string): Promise; restartFrame(frameId: number, threadId: number): Promise; next(threadId: number): Promise; diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index cb18399ce4a..ef626b3cde8 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -134,6 +134,10 @@ export class MockDebugService implements IDebugService { export class MockSession implements IDebugSession { + cancel(_progressId: string): Promise { + throw new Error('Method not implemented.'); + } + breakpointsLocations(uri: uri, lineNumber: number): Promise { throw new Error('Method not implemented.'); }