提交 e4d4b43f 编写于 作者: D Dmitry Gozman

Allow debug session to share repl with its parent; fixes #62419

Introduced DebugSessionOptions passed to debug.startDebugging which
encapsulated DebugConsoleMode to control this behavior.
上级 bbb56dba
...@@ -616,6 +616,56 @@ declare module 'vscode' { ...@@ -616,6 +616,56 @@ declare module 'vscode' {
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>; debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
} }
/**
* Debug console mode used by debug session, see [options](#DebugSessionOptions).
*/
export enum DebugConsoleMode {
/**
* Debug session should have a separate debug console.
*/
Separate = 0,
/**
* Debug session should share debug console with its parent session.
* This value has no effect for sessions which do not have a parent session.
*/
MergeWithParent = 1
}
/**
* Options for [starting a debug session](#debug.startDebugging).
*/
export interface DebugSessionOptions {
/**
* When specified the newly created debug session is registered as a "child" session of this
* "parent" debug session.
*/
parentSession?: DebugSession;
/**
* Controls whether this session should have a separate debug console or share it
* with the parent session. Has no effect for sessions which do not have a parent session.
* Defaults to Separate.
*/
consoleMode?: DebugConsoleMode;
}
export namespace debug {
/**
* Start debugging by using either a named launch or named compound configuration,
* or by directly passing a [DebugConfiguration](#DebugConfiguration).
* The named configurations are looked up in '.vscode/launch.json' found in the given folder.
* Before debugging starts, all unsaved files are saved and the launch configurations are brought up-to-date.
* Folder specific variables used in the configuration (e.g. '${workspaceFolder}') are resolved against the given folder.
* @param folder The [workspace folder](#WorkspaceFolder) for looking up named configurations and resolving variables or `undefined` for a non-folder setup.
* @param nameOrConfiguration Either the name of a debug or compound configuration or a [DebugConfiguration](#DebugConfiguration) object.
* @param parentSessionOrOptions Debug sesison options. When passed a parent [debug session](#DebugSession), assumes options with just this parent session.
* @return A thenable that resolves when debugging could be successfully started.
*/
export function startDebugging(folder: WorkspaceFolder | undefined, nameOrConfiguration: string | DebugConfiguration, parentSessionOrOptions?: DebugSession | DebugSessionOptions): Thenable<boolean>;
}
//#endregion //#endregion
//#region Rob, Matt: logging //#region Rob, Matt: logging
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
import { DisposableStore } from 'vs/base/common/lifecycle'; import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI as uri } from 'vs/base/common/uri'; import { URI as uri } from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto, IDataBreakpointDto, IStartDebuggingOptions
} from 'vs/workbench/api/common/extHost.protocol'; } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import severity from 'vs/base/common/severity'; import severity from 'vs/base/common/severity';
...@@ -218,10 +218,15 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb ...@@ -218,10 +218,15 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return undefined; return undefined;
} }
public $startDebugging(_folderUri: uri | undefined, nameOrConfiguration: string | IConfig, parentSessionID: DebugSessionUUID | undefined): Promise<boolean> { public $startDebugging(options: IStartDebuggingOptions): Promise<boolean> {
const folderUri = _folderUri ? uri.revive(_folderUri) : undefined; const folderUri = options.folder ? uri.revive(options.folder) : undefined;
const launch = this.debugService.getConfigurationManager().getLaunch(folderUri); const launch = this.debugService.getConfigurationManager().getLaunch(folderUri);
return this.debugService.startDebugging(launch, nameOrConfiguration, false, this.getSession(parentSessionID)).then(success => { const debugOptions: IDebugSessionOptions = {
noDebug: false,
parentSession: this.getSession(options.parentSessionID),
repl: options.repl
};
return this.debugService.startDebugging(launch, options.nameOrConfig, debugOptions).then(success => {
return success; return success;
}, err => { }, err => {
return Promise.reject(new Error(err && err.message ? err.message : 'cannot start debugging')); return Promise.reject(new Error(err && err.message ? err.message : 'cannot start debugging'));
......
...@@ -754,8 +754,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ...@@ -754,8 +754,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerDebugAdapterTrackerFactory(debugType: string, factory: vscode.DebugAdapterTrackerFactory) { registerDebugAdapterTrackerFactory(debugType: string, factory: vscode.DebugAdapterTrackerFactory) {
return extHostDebugService.registerDebugAdapterTrackerFactory(debugType, factory); return extHostDebugService.registerDebugAdapterTrackerFactory(debugType, factory);
}, },
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession) { startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSessionOrOptions?: vscode.DebugSession | vscode.DebugSessionOptions) {
return extHostDebugService.startDebugging(folder, nameOrConfig, parentSession); if (!parentSessionOrOptions || (typeof parentSessionOrOptions === 'object' && 'configuration' in parentSessionOrOptions)) {
return extHostDebugService.startDebugging(folder, nameOrConfig, { parentSession: parentSessionOrOptions });
}
checkProposedApiEnabled(extension);
return extHostDebugService.startDebugging(folder, nameOrConfig, parentSessionOrOptions || {});
}, },
addBreakpoints(breakpoints: vscode.Breakpoint[]) { addBreakpoints(breakpoints: vscode.Breakpoint[]) {
return extHostDebugService.addBreakpoints(breakpoints); return extHostDebugService.addBreakpoints(breakpoints);
...@@ -900,6 +904,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ...@@ -900,6 +904,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall, CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall,
CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall, CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall,
CallHierarchyItem: extHostTypes.CallHierarchyItem, CallHierarchyItem: extHostTypes.CallHierarchyItem,
DebugConsoleMode: extHostTypes.DebugConsoleMode,
Decoration: extHostTypes.Decoration, Decoration: extHostTypes.Decoration,
WebviewEditorState: extHostTypes.WebviewEditorState, WebviewEditorState: extHostTypes.WebviewEditorState,
UIKind: UIKind UIKind: UIKind
......
...@@ -39,7 +39,7 @@ import { ThemeColor } from 'vs/platform/theme/common/themeService'; ...@@ -39,7 +39,7 @@ import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import * as tasks from 'vs/workbench/api/common/shared/tasks'; import * as tasks from 'vs/workbench/api/common/shared/tasks';
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views'; import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
import { IAdapterDescriptor, IConfig } from 'vs/workbench/contrib/debug/common/debug'; import { IAdapterDescriptor, IConfig, IDebugSessionReplMode } from 'vs/workbench/contrib/debug/common/debug';
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder'; import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/terminal/common/terminal';
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
...@@ -712,6 +712,13 @@ export interface IDebugConfiguration { ...@@ -712,6 +712,13 @@ export interface IDebugConfiguration {
[key: string]: any; [key: string]: any;
} }
export interface IStartDebuggingOptions {
folder: UriComponents | undefined;
nameOrConfig: string | IDebugConfiguration;
parentSessionID?: DebugSessionUUID;
repl?: IDebugSessionReplMode;
}
export interface MainThreadDebugServiceShape extends IDisposable { export interface MainThreadDebugServiceShape extends IDisposable {
$registerDebugTypes(debugTypes: string[]): void; $registerDebugTypes(debugTypes: string[]): void;
$sessionCached(sessionID: string): void; $sessionCached(sessionID: string): void;
...@@ -722,7 +729,7 @@ export interface MainThreadDebugServiceShape extends IDisposable { ...@@ -722,7 +729,7 @@ export interface MainThreadDebugServiceShape extends IDisposable {
$registerDebugAdapterDescriptorFactory(type: string, handle: number): Promise<void>; $registerDebugAdapterDescriptorFactory(type: string, handle: number): Promise<void>;
$unregisterDebugConfigurationProvider(handle: number): void; $unregisterDebugConfigurationProvider(handle: number): void;
$unregisterDebugAdapterDescriptorFactory(handle: number): void; $unregisterDebugAdapterDescriptorFactory(handle: number): void;
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | IDebugConfiguration, parentSessionID: string | undefined): Promise<boolean>; $startDebugging(options: IStartDebuggingOptions): Promise<boolean>;
$setDebugSessionName(id: DebugSessionUUID, name: string): void; $setDebugSessionName(id: DebugSessionUUID, name: string): void;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Promise<any>; $customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Promise<any>;
$appendDebugConsole(value: string): void; $appendDebugConsole(value: string): void;
......
...@@ -26,7 +26,7 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape { ...@@ -26,7 +26,7 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape {
addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>; addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>; removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void>;
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession): Promise<boolean>; startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean>;
registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable; registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable;
registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable; registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable;
registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable; registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable;
......
...@@ -2352,6 +2352,22 @@ export enum CommentMode { ...@@ -2352,6 +2352,22 @@ export enum CommentMode {
//#endregion //#endregion
//#region debug
export enum DebugConsoleMode {
/**
* Debug session should have a separate debug console.
*/
Separate = 0,
/**
* Debug session should share debug console with its parent session.
* This value has no effect for sessions which do not have a parent session.
*/
MergeWithParent = 1
}
//#endregion
@es5ClassCompat @es5ClassCompat
export class QuickInputButtons { export class QuickInputButtons {
......
...@@ -14,7 +14,7 @@ import { ...@@ -14,7 +14,7 @@ import {
IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
} from 'vs/workbench/api/common/extHost.protocol'; } from 'vs/workbench/api/common/extHost.protocol';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable, DataBreakpoint } from 'vs/workbench/api/common/extHostTypes'; import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable, DataBreakpoint, DebugConsoleMode } from 'vs/workbench/api/common/extHostTypes';
import { ExecutableDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; import { ExecutableDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter'; import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
...@@ -252,8 +252,13 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe ...@@ -252,8 +252,13 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe
return this._debugServiceProxy.$unregisterBreakpoints(ids, fids, dids); return this._debugServiceProxy.$unregisterBreakpoints(ids, fids, dids);
} }
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, parentSession?: vscode.DebugSession): Promise<boolean> { public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise<boolean> {
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig, parentSession ? parentSession.id : undefined); return this._debugServiceProxy.$startDebugging({
folder: folder ? folder.uri : undefined,
nameOrConfig,
parentSessionID: options.parentSession ? options.parentSession.id : undefined,
repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate'
});
} }
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable { public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable {
......
...@@ -202,7 +202,7 @@ export class FocusSessionActionViewItem extends SelectActionViewItem { ...@@ -202,7 +202,7 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
this._register(attachSelectBoxStyler(this.selectBox, themeService)); this._register(attachSelectBoxStyler(this.selectBox, themeService));
this._register(this.debugService.getViewModel().onDidFocusSession(() => { this._register(this.debugService.getViewModel().onDidFocusSession(() => {
const session = this.debugService.getViewModel().focusedSession; const session = this.getSelectedSession();
if (session) { if (session) {
const index = this.getSessions().indexOf(session); const index = this.getSessions().indexOf(session);
this.select(index); this.select(index);
...@@ -222,11 +222,11 @@ export class FocusSessionActionViewItem extends SelectActionViewItem { ...@@ -222,11 +222,11 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
} }
protected getActionContext(_: string, index: number): any { protected getActionContext(_: string, index: number): any {
return this.debugService.getModel().getSessions()[index]; return this.getSessions()[index];
} }
private update() { private update() {
const session = this.debugService.getViewModel().focusedSession; const session = this.getSelectedSession();
const sessions = this.getSessions(); const sessions = this.getSessions();
const names = sessions.map(s => { const names = sessions.map(s => {
const label = s.getLabel(); const label = s.getLabel();
...@@ -240,10 +240,23 @@ export class FocusSessionActionViewItem extends SelectActionViewItem { ...@@ -240,10 +240,23 @@ export class FocusSessionActionViewItem extends SelectActionViewItem {
this.setOptions(names.map(data => <ISelectOptionItem>{ text: data }), session ? sessions.indexOf(session) : undefined); this.setOptions(names.map(data => <ISelectOptionItem>{ text: data }), session ? sessions.indexOf(session) : undefined);
} }
private getSelectedSession(): IDebugSession | undefined {
const session = this.debugService.getViewModel().focusedSession;
return session ? this.mapFocusedSessionToSelected(session) : undefined;
}
protected getSessions(): ReadonlyArray<IDebugSession> { protected getSessions(): ReadonlyArray<IDebugSession> {
const showSubSessions = this.configurationService.getValue<IDebugConfiguration>('debug').showSubSessionsInToolBar; const showSubSessions = this.configurationService.getValue<IDebugConfiguration>('debug').showSubSessionsInToolBar;
const sessions = this.debugService.getModel().getSessions(); const sessions = this.debugService.getModel().getSessions();
return showSubSessions ? sessions : sessions.filter(s => !s.parentSession); return showSubSessions ? sessions : sessions.filter(s => !s.parentSession);
} }
protected mapFocusedSessionToSelected(focusedSession: IDebugSession): IDebugSession {
const showSubSessions = this.configurationService.getValue<IDebugConfiguration>('debug').showSubSessionsInToolBar;
while (focusedSession.parentSession && !showSubSessions) {
focusedSession = focusedSession.parentSession;
}
return focusedSession;
}
} }
...@@ -41,7 +41,7 @@ import { IAction } from 'vs/base/common/actions'; ...@@ -41,7 +41,7 @@ import { IAction } from 'vs/base/common/actions';
import { deepClone, equals } from 'vs/base/common/objects'; import { deepClone, equals } from 'vs/base/common/objects';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession'; import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel } from 'vs/workbench/contrib/debug/common/debug'; import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils'; import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
import { isErrorWithActions, createErrorWithActions } from 'vs/base/common/errorsWithActions'; import { isErrorWithActions, createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { RunOnceScheduler } from 'vs/base/common/async'; import { RunOnceScheduler } from 'vs/base/common/async';
...@@ -255,7 +255,7 @@ export class DebugService implements IDebugService { ...@@ -255,7 +255,7 @@ export class DebugService implements IDebugService {
* main entry point * main entry point
* properly manages compounds, checks for errors and handles the initializing state. * properly manages compounds, checks for errors and handles the initializing state.
*/ */
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, noDebug = false, parentSession?: IDebugSession): Promise<boolean> { startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean> {
this.startInitializingState(); this.startInitializingState();
// make sure to save all files and that the configuration is up to date // make sure to save all files and that the configuration is up to date
...@@ -318,7 +318,7 @@ export class DebugService implements IDebugService { ...@@ -318,7 +318,7 @@ export class DebugService implements IDebugService {
} }
} }
return this.createSession(launchForName, launchForName!.getConfiguration(name), noDebug, parentSession); return this.createSession(launchForName, launchForName!.getConfiguration(name), options);
})).then(values => values.every(success => !!success)); // Compound launch is a success only if each configuration launched successfully })).then(values => values.every(success => !!success)); // Compound launch is a success only if each configuration launched successfully
} }
...@@ -328,7 +328,7 @@ export class DebugService implements IDebugService { ...@@ -328,7 +328,7 @@ export class DebugService implements IDebugService {
return Promise.reject(new Error(message)); return Promise.reject(new Error(message));
} }
return this.createSession(launch, config, noDebug, parentSession); return this.createSession(launch, config, options);
}); });
})); }));
}).then(success => { }).then(success => {
...@@ -344,7 +344,7 @@ export class DebugService implements IDebugService { ...@@ -344,7 +344,7 @@ export class DebugService implements IDebugService {
/** /**
* gets the debugger for the type, resolves configurations by providers, substitutes variables and runs prelaunch tasks * gets the debugger for the type, resolves configurations by providers, substitutes variables and runs prelaunch tasks
*/ */
private createSession(launch: ILaunch | undefined, config: IConfig | undefined, noDebug: boolean, parentSession?: IDebugSession): Promise<boolean> { private createSession(launch: ILaunch | undefined, config: IConfig | undefined, options?: IDebugSessionOptions): Promise<boolean> {
// We keep the debug type in a separate variable 'type' so that a no-folder config has no attributes. // We keep the debug type in a separate variable 'type' so that a no-folder config has no attributes.
// Storing the type in the config would break extensions that assume that the no-folder case is indicated by an empty config. // Storing the type in the config would break extensions that assume that the no-folder case is indicated by an empty config.
let type: string | undefined; let type: string | undefined;
...@@ -356,7 +356,7 @@ export class DebugService implements IDebugService { ...@@ -356,7 +356,7 @@ export class DebugService implements IDebugService {
} }
const unresolvedConfig = deepClone(config); const unresolvedConfig = deepClone(config);
if (noDebug) { if (options && options.noDebug) {
config!.noDebug = true; config!.noDebug = true;
} }
...@@ -390,7 +390,7 @@ export class DebugService implements IDebugService { ...@@ -390,7 +390,7 @@ export class DebugService implements IDebugService {
const workspace = launch ? launch.workspace : undefined; const workspace = launch ? launch.workspace : undefined;
return this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask).then(result => { return this.runTaskAndCheckErrors(workspace, resolvedConfig.preLaunchTask).then(result => {
if (result === TaskRunResult.Success) { if (result === TaskRunResult.Success) {
return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, parentSession); return this.doCreateSession(workspace, { resolved: resolvedConfig, unresolved: unresolvedConfig }, options);
} }
return false; return false;
}); });
...@@ -419,9 +419,9 @@ export class DebugService implements IDebugService { ...@@ -419,9 +419,9 @@ export class DebugService implements IDebugService {
/** /**
* instantiates the new session, initializes the session, registers session listeners and reports telemetry * instantiates the new session, initializes the session, registers session listeners and reports telemetry
*/ */
private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, parentSession?: IDebugSession): Promise<boolean> { private doCreateSession(root: IWorkspaceFolder | undefined, configuration: { resolved: IConfig, unresolved: IConfig | undefined }, options?: IDebugSessionOptions): Promise<boolean> {
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, parentSession); const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model, options);
this.model.addSession(session); this.model.addSession(session);
// register listeners as the very first thing! // register listeners as the very first thing!
this.registerSessionListeners(session); this.registerSessionListeners(session);
......
...@@ -12,7 +12,7 @@ import { Event, Emitter } from 'vs/base/common/event'; ...@@ -12,7 +12,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes'; import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes';
import { Position, IPosition } from 'vs/editor/common/core/position'; import { Position, IPosition } from 'vs/editor/common/core/position';
import * as aria from 'vs/base/browser/ui/aria/aria'; import * as aria from 'vs/base/browser/ui/aria/aria';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource'; import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel'; import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
...@@ -43,6 +43,7 @@ export class DebugSession implements IDebugSession { ...@@ -43,6 +43,7 @@ export class DebugSession implements IDebugSession {
private _subId: string | undefined; private _subId: string | undefined;
private raw: RawDebugSession | undefined; private raw: RawDebugSession | undefined;
private initialized = false; private initialized = false;
private _options: IDebugSessionOptions;
private sources = new Map<string, Source>(); private sources = new Map<string, Source>();
private threads = new Map<number, Thread>(); private threads = new Map<number, Thread>();
...@@ -66,7 +67,7 @@ export class DebugSession implements IDebugSession { ...@@ -66,7 +67,7 @@ export class DebugSession implements IDebugSession {
private _configuration: { resolved: IConfig, unresolved: IConfig | undefined }, private _configuration: { resolved: IConfig, unresolved: IConfig | undefined },
public root: IWorkspaceFolder, public root: IWorkspaceFolder,
private model: DebugModel, private model: DebugModel,
private _parentSession: IDebugSession | undefined, options: IDebugSessionOptions | undefined,
@IDebugService private readonly debugService: IDebugService, @IDebugService private readonly debugService: IDebugService,
@ITelemetryService private readonly telemetryService: ITelemetryService, @ITelemetryService private readonly telemetryService: ITelemetryService,
@IWindowService private readonly windowService: IWindowService, @IWindowService private readonly windowService: IWindowService,
...@@ -79,7 +80,12 @@ export class DebugSession implements IDebugSession { ...@@ -79,7 +80,12 @@ export class DebugSession implements IDebugSession {
@IOpenerService private readonly openerService: IOpenerService @IOpenerService private readonly openerService: IOpenerService
) { ) {
this.id = generateUuid(); this.id = generateUuid();
this.repl = new ReplModel(this); this._options = options || {};
if (this.hasSeparateRepl()) {
this.repl = new ReplModel();
} else {
this.repl = (this.parentSession as DebugSession).repl;
}
} }
getId(): string { getId(): string {
...@@ -103,7 +109,7 @@ export class DebugSession implements IDebugSession { ...@@ -103,7 +109,7 @@ export class DebugSession implements IDebugSession {
} }
get parentSession(): IDebugSession | undefined { get parentSession(): IDebugSession | undefined {
return this._parentSession; return this._options.parentSession;
} }
setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig | undefined }) { setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig | undefined }) {
...@@ -954,13 +960,17 @@ export class DebugSession implements IDebugSession { ...@@ -954,13 +960,17 @@ export class DebugSession implements IDebugSession {
return this.repl.getReplElements(); return this.repl.getReplElements();
} }
hasSeparateRepl(): boolean {
return !this.parentSession || this._options.repl !== 'mergeWithParent';
}
removeReplExpressions(): void { removeReplExpressions(): void {
this.repl.removeReplExpressions(); this.repl.removeReplExpressions();
this._onDidChangeREPLElements.fire(); this._onDidChangeREPLElements.fire();
} }
async addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> { async addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> {
const expressionEvaluated = this.repl.addReplExpression(stackFrame, name); const expressionEvaluated = this.repl.addReplExpression(this, stackFrame, name);
this._onDidChangeREPLElements.fire(); this._onDidChangeREPLElements.fire();
await expressionEvaluated; await expressionEvaluated;
this._onDidChangeREPLElements.fire(); this._onDidChangeREPLElements.fire();
...@@ -974,7 +984,7 @@ export class DebugSession implements IDebugSession { ...@@ -974,7 +984,7 @@ export class DebugSession implements IDebugSession {
} }
logToRepl(sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) { logToRepl(sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) {
this.repl.logToRepl(sev, args, frame); this.repl.logToRepl(this, sev, args, frame);
this._onDidChangeREPLElements.fire(); this._onDidChangeREPLElements.fire();
} }
} }
...@@ -356,7 +356,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati ...@@ -356,7 +356,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
getActions(): IAction[] { getActions(): IAction[] {
const result: IAction[] = []; const result: IAction[] = [];
if (this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s)).length > 1) { if (this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s)).length > 1) {
result.push(this.selectReplAction); result.push(this.selectReplAction);
} }
result.push(this.clearReplAction); result.push(this.clearReplAction);
...@@ -968,12 +968,15 @@ registerEditorAction(FilterReplAction); ...@@ -968,12 +968,15 @@ registerEditorAction(FilterReplAction);
class SelectReplActionViewItem extends FocusSessionActionViewItem { class SelectReplActionViewItem extends FocusSessionActionViewItem {
protected getActionContext(_: string, index: number): any { protected getSessions(): ReadonlyArray<IDebugSession> {
return this.debugService.getModel().getSessions(true)[index]; return this.debugService.getModel().getSessions(true).filter(s => s.hasSeparateRepl() && !sessionsToIgnore.has(s));
} }
protected getSessions(): ReadonlyArray<IDebugSession> { protected mapFocusedSessionToSelected(focusedSession: IDebugSession): IDebugSession {
return this.debugService.getModel().getSessions(true).filter(s => !sessionsToIgnore.has(s)); while (focusedSession.parentSession && !focusedSession.hasSeparateRepl()) {
focusedSession = focusedSession.parentSession;
}
return focusedSession;
} }
} }
......
...@@ -147,6 +147,14 @@ export interface LoadedSourceEvent { ...@@ -147,6 +147,14 @@ export interface LoadedSourceEvent {
source: Source; source: Source;
} }
export type IDebugSessionReplMode = 'separate' | 'mergeWithParent';
export interface IDebugSessionOptions {
noDebug?: boolean;
parentSession?: IDebugSession;
repl?: IDebugSessionReplMode;
}
export interface IDebugSession extends ITreeElement { export interface IDebugSession extends ITreeElement {
readonly configuration: IConfig; readonly configuration: IConfig;
...@@ -173,7 +181,7 @@ export interface IDebugSession extends ITreeElement { ...@@ -173,7 +181,7 @@ export interface IDebugSession extends ITreeElement {
clearThreads(removeThreads: boolean, reference?: number): void; clearThreads(removeThreads: boolean, reference?: number): void;
getReplElements(): IReplElement[]; getReplElements(): IReplElement[];
hasSeparateRepl(): boolean;
removeReplExpressions(): void; removeReplExpressions(): void;
addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void>; addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void>;
appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void; appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void;
...@@ -815,7 +823,7 @@ export interface IDebugService { ...@@ -815,7 +823,7 @@ export interface IDebugService {
* Returns true if the start debugging was successfull. For compound launches, all configurations have to start successfuly for it to return success. * Returns true if the start debugging was successfull. For compound launches, all configurations have to start successfuly for it to return success.
* On errors the startDebugging will throw an error, however some error and cancelations are handled and in that case will simply return false. * On errors the startDebugging will throw an error, however some error and cancelations are handled and in that case will simply return false.
*/ */
startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, noDebug?: boolean, parentSession?: IDebugSession): Promise<boolean>; startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean>;
/** /**
* Restarts a session or creates a new one if there is no active session. * Restarts a session or creates a new one if there is no active session.
......
...@@ -27,7 +27,7 @@ export function startDebugging(debugService: IDebugService, historyService: IHis ...@@ -27,7 +27,7 @@ export function startDebugging(debugService: IDebugService, historyService: IHis
configurationManager.selectConfiguration(launch); configurationManager.selectConfiguration(launch);
} }
return debugService.startDebugging(launch, undefined, noDebug); return debugService.startDebugging(launch, undefined, { noDebug });
} }
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string { export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
......
...@@ -108,16 +108,14 @@ export class ReplEvaluationResult extends ExpressionContainer implements IReplEl ...@@ -108,16 +108,14 @@ export class ReplEvaluationResult extends ExpressionContainer implements IReplEl
export class ReplModel { export class ReplModel {
private replElements: IReplElement[] = []; private replElements: IReplElement[] = [];
constructor(private session: IDebugSession) { }
getReplElements(): IReplElement[] { getReplElements(): IReplElement[] {
return this.replElements; return this.replElements;
} }
async addReplExpression(stackFrame: IStackFrame | undefined, name: string): Promise<void> { async addReplExpression(session: IDebugSession, stackFrame: IStackFrame | undefined, name: string): Promise<void> {
this.addReplElement(new ReplEvaluationInput(name)); this.addReplElement(new ReplEvaluationInput(name));
const result = new ReplEvaluationResult(); const result = new ReplEvaluationResult();
await result.evaluateExpression(name, this.session, stackFrame, 'repl'); await result.evaluateExpression(name, session, stackFrame, 'repl');
this.addReplElement(result); this.addReplElement(result);
} }
...@@ -153,14 +151,14 @@ export class ReplModel { ...@@ -153,14 +151,14 @@ export class ReplModel {
} }
} }
logToRepl(sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) { logToRepl(session: IDebugSession, sev: severity, args: any[], frame?: { uri: URI, line: number, column: number }) {
let source: IReplElementSource | undefined; let source: IReplElementSource | undefined;
if (frame) { if (frame) {
source = { source = {
column: frame.column, column: frame.column,
lineNumber: frame.line, lineNumber: frame.line,
source: this.session.getSource({ source: session.getSource({
name: basenameOrAuthority(frame.uri), name: basenameOrAuthority(frame.uri),
path: frame.uri.fsPath path: frame.uri.fsPath
}) })
......
...@@ -12,11 +12,11 @@ import { MockRawSession } from 'vs/workbench/contrib/debug/test/common/mockDebug ...@@ -12,11 +12,11 @@ import { MockRawSession } from 'vs/workbench/contrib/debug/test/common/mockDebug
import { Source } from 'vs/workbench/contrib/debug/common/debugSource'; import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession'; import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { SimpleReplElement, RawObjectReplElement, ReplEvaluationInput, ReplModel } from 'vs/workbench/contrib/debug/common/replModel'; import { SimpleReplElement, RawObjectReplElement, ReplEvaluationInput, ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
import { IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug'; import { IBreakpointUpdateData, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { NullOpenerService } from 'vs/platform/opener/common/opener'; import { NullOpenerService } from 'vs/platform/opener/common/opener';
function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession { function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession {
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService);
} }
suite('Debug - Model', () => { suite('Debug - Model', () => {
...@@ -341,10 +341,10 @@ suite('Debug - Model', () => { ...@@ -341,10 +341,10 @@ suite('Debug - Model', () => {
session['raw'] = <any>rawSession; session['raw'] = <any>rawSession;
const thread = new Thread(session, 'mockthread', 1); const thread = new Thread(session, 'mockthread', 1);
const stackFrame = new StackFrame(thread, 1, <any>undefined, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 10 }, 1); const stackFrame = new StackFrame(thread, 1, <any>undefined, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 10 }, 1);
const replModel = new ReplModel(session); const replModel = new ReplModel();
replModel.addReplExpression(stackFrame, 'myVariable').then(); replModel.addReplExpression(session, stackFrame, 'myVariable').then();
replModel.addReplExpression(stackFrame, 'myVariable').then(); replModel.addReplExpression(session, stackFrame, 'myVariable').then();
replModel.addReplExpression(stackFrame, 'myVariable').then(); replModel.addReplExpression(session, stackFrame, 'myVariable').then();
assert.equal(replModel.getReplElements().length, 3); assert.equal(replModel.getReplElements().length, 3);
replModel.getReplElements().forEach(re => { replModel.getReplElements().forEach(re => {
...@@ -405,13 +405,13 @@ suite('Debug - Model', () => { ...@@ -405,13 +405,13 @@ suite('Debug - Model', () => {
model.addSession(session); model.addSession(session);
const secondSession = createMockSession(model, 'mockSession2'); const secondSession = createMockSession(model, 'mockSession2');
model.addSession(secondSession); model.addSession(secondSession);
const firstChild = createMockSession(model, 'firstChild', session); const firstChild = createMockSession(model, 'firstChild', { parentSession: session });
model.addSession(firstChild); model.addSession(firstChild);
const secondChild = createMockSession(model, 'secondChild', session); const secondChild = createMockSession(model, 'secondChild', { parentSession: session });
model.addSession(secondChild); model.addSession(secondChild);
const thirdSession = createMockSession(model, 'mockSession3'); const thirdSession = createMockSession(model, 'mockSession3');
model.addSession(thirdSession); model.addSession(thirdSession);
const anotherChild = createMockSession(model, 'secondChild', secondSession); const anotherChild = createMockSession(model, 'secondChild', { parentSession: secondSession });
model.addSession(anotherChild); model.addSession(anotherChild);
const sessions = model.getSessions(); const sessions = model.getSessions();
...@@ -426,8 +426,7 @@ suite('Debug - Model', () => { ...@@ -426,8 +426,7 @@ suite('Debug - Model', () => {
// Repl output // Repl output
test('repl output', () => { test('repl output', () => {
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); const repl = new ReplModel();
const repl = new ReplModel(session);
repl.appendToRepl('first line\n', severity.Error); repl.appendToRepl('first line\n', severity.Error);
repl.appendToRepl('second line ', severity.Error); repl.appendToRepl('second line ', severity.Error);
repl.appendToRepl('third line ', severity.Error); repl.appendToRepl('third line ', severity.Error);
...@@ -466,4 +465,41 @@ suite('Debug - Model', () => { ...@@ -466,4 +465,41 @@ suite('Debug - Model', () => {
assert.equal(elements[1], '23\n45\n'); assert.equal(elements[1], '23\n45\n');
assert.equal(elements[2], '6'); assert.equal(elements[2], '6');
}); });
test('repl merging', () => {
// 'mergeWithParent' should be ignored when there is no parent.
const parent = createMockSession(model, 'parent', { repl: 'mergeWithParent' });
const child1 = createMockSession(model, 'child1', { parentSession: parent, repl: 'separate' });
const child2 = createMockSession(model, 'child2', { parentSession: parent, repl: 'mergeWithParent' });
const grandChild = createMockSession(model, 'grandChild', { parentSession: child2, repl: 'mergeWithParent' });
const child3 = createMockSession(model, 'child3', { parentSession: parent });
parent.appendToRepl('1\n', severity.Info);
assert.equal(parent.getReplElements().length, 1);
assert.equal(child1.getReplElements().length, 0);
assert.equal(child2.getReplElements().length, 1);
assert.equal(grandChild.getReplElements().length, 1);
assert.equal(child3.getReplElements().length, 0);
grandChild.appendToRepl('1\n', severity.Info);
assert.equal(parent.getReplElements().length, 2);
assert.equal(child1.getReplElements().length, 0);
assert.equal(child2.getReplElements().length, 2);
assert.equal(grandChild.getReplElements().length, 2);
assert.equal(child3.getReplElements().length, 0);
child3.appendToRepl('1\n', severity.Info);
assert.equal(parent.getReplElements().length, 2);
assert.equal(child1.getReplElements().length, 0);
assert.equal(child2.getReplElements().length, 2);
assert.equal(grandChild.getReplElements().length, 2);
assert.equal(child3.getReplElements().length, 1);
child1.appendToRepl('1\n', severity.Info);
assert.equal(parent.getReplElements().length, 2);
assert.equal(child1.getReplElements().length, 1);
assert.equal(child2.getReplElements().length, 2);
assert.equal(grandChild.getReplElements().length, 2);
assert.equal(child3.getReplElements().length, 1);
});
}); });
...@@ -7,7 +7,7 @@ import { URI as uri } from 'vs/base/common/uri'; ...@@ -7,7 +7,7 @@ import { URI as uri } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Position, IPosition } from 'vs/editor/common/core/position'; import { Position, IPosition } from 'vs/editor/common/core/position';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug'; import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IDebugModel, IViewModel, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate, IFunctionBreakpoint, IExceptionBreakpoint, IDebugger, IExceptionInfo, AdapterEndEvent, IReplElement, IExpression, IReplElementSource, IDataBreakpoint, IDebugSessionOptions } from 'vs/workbench/contrib/debug/common/debug';
import { Source } from 'vs/workbench/contrib/debug/common/debugSource'; import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
import { CompletionItem } from 'vs/editor/common/modes'; import { CompletionItem } from 'vs/editor/common/modes';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
...@@ -102,7 +102,7 @@ export class MockDebugService implements IDebugService { ...@@ -102,7 +102,7 @@ export class MockDebugService implements IDebugService {
public removeWatchExpressions(id?: string): void { } public removeWatchExpressions(id?: string): void { }
public startDebugging(launch: ILaunch, configOrName?: IConfig | string, noDebug?: boolean): Promise<boolean> { public startDebugging(launch: ILaunch, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean> {
return Promise.resolve(true); return Promise.resolve(true);
} }
...@@ -159,6 +159,10 @@ export class MockSession implements IDebugSession { ...@@ -159,6 +159,10 @@ export class MockSession implements IDebugSession {
return []; return [];
} }
hasSeparateRepl(): boolean {
return true;
}
removeReplExpressions(): void { } removeReplExpressions(): void { }
get onDidChangeReplElements(): Event<void> { get onDidChangeReplElements(): Event<void> {
throw new Error('not implemented'); throw new Error('not implemented');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册