Skip to content

Commit

Permalink
Support to start multiple debug sessions from a single launch config
Browse files Browse the repository at this point in the history
  • Loading branch information
isidorn committed Jan 7, 2021
1 parent 80f369b commit 8c3f5dd
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadDebugService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return {
id: sessionID,
type: session.configuration.type,
name: session.configuration.name,
name: session.name,
folderUri: session.root ? session.root.uri : undefined,
configuration: session.configuration
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { SelectBox, ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch, State } from 'vs/workbench/contrib/debug/common/debug';
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { selectBorder, selectBackground } from 'vs/platform/theme/common/colorRegistry';
Expand Down Expand Up @@ -76,7 +76,9 @@ export class StartDebugActionViewItem implements IActionViewItem {

this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.CLICK, () => {
this.start.blur();
this.actionRunner.run(this.action, this.context);
if (this.debugService.state !== State.Initializing) {
this.actionRunner.run(this.action, this.context);
}
}));

this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => {
Expand All @@ -93,7 +95,7 @@ export class StartDebugActionViewItem implements IActionViewItem {

this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Enter)) {
if (event.equals(KeyCode.Enter) && this.debugService.state !== State.Initializing) {
this.actionRunner.run(this.action, this.context);
}
if (event.equals(KeyCode.RightArrow)) {
Expand Down
13 changes: 1 addition & 12 deletions src/vs/workbench/contrib/debug/browser/debugService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import { DebugTelemetry } from 'vs/workbench/contrib/debug/common/debugTelemetry
import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager';
import { ITextModel } from 'vs/editor/common/model';
import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_CONFIGURE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands';
Expand Down Expand Up @@ -95,8 +94,7 @@ export class DebugService implements IDebugService {
@IExtensionHostDebugService private readonly extensionHostDebugService: IExtensionHostDebugService,
@IActivityService private readonly activityService: IActivityService,
@ICommandService private readonly commandService: ICommandService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
this.toDispose = [];

Expand Down Expand Up @@ -296,15 +294,6 @@ export class DebugService implements IDebugService {
if (typeof configOrName === 'string' && launch) {
config = launch.getConfiguration(configOrName);
compound = launch.getCompound(configOrName);

const sessions = this.model.getSessions();
const alreadyRunningMessage = nls.localize('configurationAlreadyRunning', "There is already a debug configuration \"{0}\" running.", configOrName);
if (sessions.some(s => (s.configuration.name === configOrName && s.root === launch.workspace) && (!launch || !launch.workspace || !s.root || this.uriIdentityService.extUri.isEqual(s.root.uri, launch.workspace.uri)))) {
throw new Error(alreadyRunningMessage);
}
if (compound && compound.configurations && sessions.some(p => compound!.configurations.indexOf(p.configuration.name) !== -1)) {
throw new Error(alreadyRunningMessage);
}
} else if (typeof configOrName !== 'string') {
config = configOrName;
}
Expand Down
11 changes: 7 additions & 4 deletions src/vs/workbench/contrib/debug/browser/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class DebugSession implements IDebugSession {

private readonly _onDidChangeREPLElements = new Emitter<void>();

private name: string | undefined;
private _name: string | undefined;
private readonly _onDidChangeName = new Emitter<string>();

constructor(
Expand Down Expand Up @@ -146,15 +146,18 @@ export class DebugSession implements IDebugSession {

getLabel(): string {
const includeRoot = this.workspaceContextService.getWorkspace().folders.length > 1;
const name = this.name || this.configuration.name;
return includeRoot && this.root ? `${name} (${resources.basenameOrAuthority(this.root.uri)})` : name;
return includeRoot && this.root ? `${this.name} (${resources.basenameOrAuthority(this.root.uri)})` : this.name;
}

setName(name: string): void {
this.name = name;
this._name = name;
this._onDidChangeName.fire(name);
}

get name(): string {
return this._name || this.configuration.name;
}

get state(): State {
if (!this.initialized) {
return State.Initializing;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/debug/browser/debugToolBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
}

const actions: IAction[] = [];
const disposable = createAndFillInActionBarActions(this.debugToolBarMenu, undefined, actions, () => false);
const disposable = createAndFillInActionBarActions(this.debugToolBarMenu, { shouldForwardArgs: true }, actions, () => false);
if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id && first.enabled === second.enabled)) {
this.actionBar.clear();
this.actionBar.push(actions, { icon: true, label: false });
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/debug/browser/debugViewlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import 'vs/css!./media/debugViewlet';
import * as nls from 'vs/nls';
import { IAction, IActionViewItem } from 'vs/base/common/actions';
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch } from 'vs/workbench/contrib/debug/common/debug';
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID, CONTEXT_DEBUG_STATE, ILaunch, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
Expand Down Expand Up @@ -183,6 +183,7 @@ MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, {
order: 10,
group: 'navigation',
command: {
precondition: CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Initializing)),
id: DEBUG_START_COMMAND_ID,
title: DEBUG_START_LABEL
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/debug/common/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export interface IDebugSession extends ITreeElement {
readonly subId: string | undefined;
readonly compact: boolean;
readonly compoundRoot: DebugCompoundRoot | undefined;
readonly name: string;

setSubId(subId: string | undefined): void;

Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/contrib/debug/common/debugModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,11 @@ export class DebugModel implements IDebugModel {
return true;
});

let i = 1;
while (this.sessions.some(s => s.getLabel() === session.getLabel())) {
session.setName(`${session.configuration.name} ${++i}`);
}

let index = -1;
if (session.parentSession) {
// Make sure that child sessions are placed after the parent session
Expand Down
12 changes: 10 additions & 2 deletions src/vs/workbench/contrib/debug/test/browser/callStack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ import { generateUuid } from 'vs/base/common/uuid';
import { debugStackframe, debugStackframeFocused } from 'vs/workbench/contrib/debug/browser/debugIcons';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';

const mockWorkspaceContextService = {
getWorkspace: () => {
return {
folders: []
};
}
} as any;

export function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession {
return new DebugSession(generateUuid(), { resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, {
getViewModel(): any {
Expand All @@ -29,7 +37,7 @@ export function createMockSession(model: DebugModel, name = 'mockSession', optio
}
};
}
} as IDebugService, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService, undefined!, undefined!, mockUriIdentityService);
} as IDebugService, undefined!, undefined!, undefined!, undefined!, mockWorkspaceContextService, undefined!, undefined!, NullOpenerService, undefined!, undefined!, mockUriIdentityService);
}

function createTwoStackFrames(session: DebugSession): { firstStackFrame: StackFrame, secondStackFrame: StackFrame } {
Expand Down Expand Up @@ -374,7 +382,7 @@ suite('Debug - CallStack', () => {
get state(): State {
return State.Stopped;
}
}(generateUuid(), { resolved: { name: 'stoppedSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService, undefined!, undefined!, mockUriIdentityService);
}(generateUuid(), { resolved: { name: 'stoppedSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, mockWorkspaceContextService, undefined!, undefined!, NullOpenerService, undefined!, undefined!, mockUriIdentityService);

const runningSession = createMockSession(model);
model.addSession(runningSession);
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/contrib/debug/test/browser/mockDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ export class MockSession implements IDebugSession {
return 'mockname';
}

get name(): string {
return 'mockname';
}

setName(name: string): void {
throw new Error('not implemented');
}
Expand Down

0 comments on commit 8c3f5dd

Please sign in to comment.