提交 8da82215 编写于 作者: A Andre Weinand

debt: improve debug abstraction naming

上级 33693bcd
......@@ -12,7 +12,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
import { IDebugService, State, ISession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID }
import { IDebugService, State, IDebugSession, IThread, IEnablement, IBreakpoint, IStackFrame, REPL_ID }
from 'vs/workbench/parts/debug/common/debug';
import { Variable, Expression, Thread, Breakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { IPartService } from 'vs/workbench/services/part/common/partService';
......@@ -225,11 +225,11 @@ export class RestartAction extends AbstractDebugAction {
return new StartAction(StartAction.ID, StartAction.LABEL, this.debugService, this.keybindingService, this.contextService, this.historyService);
}
private setLabel(session: ISession): void {
private setLabel(session: IDebugSession): void {
this.updateLabel(session && session.configuration.request === 'attach' ? RestartAction.RECONNECT_LABEL : RestartAction.LABEL);
}
public run(session: ISession): TPromise<any> {
public run(session: IDebugSession): TPromise<any> {
if (!session || !session.getId) {
session = this.debugService.getViewModel().focusedSession;
}
......@@ -324,7 +324,7 @@ export class StopAction extends AbstractDebugAction {
super(id, label, 'debug-action stop', debugService, keybindingService, 80);
}
public run(session: ISession): TPromise<any> {
public run(session: IDebugSession): TPromise<any> {
if (!session || !session.getId) {
session = this.debugService.getViewModel().focusedSession;
}
......
......@@ -12,7 +12,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { DEBUG_SCHEME, IDebugService, ISession } from 'vs/workbench/parts/debug/common/debug';
import { DEBUG_SCHEME, IDebugService, IDebugSession } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
/**
......@@ -41,7 +41,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
public provideTextContent(resource: uri): TPromise<ITextModel> {
let session: ISession;
let session: IDebugSession;
let sourceRef: number;
if (resource.query) {
......
......@@ -16,7 +16,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { WorkbenchTree, TreeResourceNavigator } from 'vs/platform/list/browser/listService';
import { renderViewTree, twistiePixels } from 'vs/workbench/parts/debug/browser/baseDebugView';
import { IAccessibilityProvider, ITree, IRenderer, IDataSource } from 'vs/base/parts/tree/browser/tree';
import { ISession, IDebugService, IModel, CONTEXT_LOADED_SCRIPTS_ITEM_TYPE } from 'vs/workbench/parts/debug/common/debug';
import { IDebugSession, IDebugService, IModel, CONTEXT_LOADED_SCRIPTS_ITEM_TYPE } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -47,7 +47,7 @@ class BaseTreeItem {
this._showedMoreThanOne = false;
}
setSource(session: ISession, source: Source): void {
setSource(session: IDebugSession, source: Source): void {
this._source = source;
}
......@@ -188,7 +188,7 @@ class RootTreeItem extends BaseTreeItem {
});
}
add(session: ISession): SessionTreeItem {
add(session: IDebugSession): SessionTreeItem {
return this.createIfNeeded(session.getId(), () => new SessionTreeItem(this, session, this._environmentService, this._contextService));
}
}
......@@ -197,10 +197,10 @@ class SessionTreeItem extends BaseTreeItem {
private static URL_REGEXP = /^(https?:\/\/[^/]+)(\/.*)$/;
private _session: ISession;
private _session: IDebugSession;
private _initialized: boolean;
constructor(parent: BaseTreeItem, session: ISession, private _environmentService: IEnvironmentService, private rootProvider: IWorkspaceContextService) {
constructor(parent: BaseTreeItem, session: IDebugSession, private _environmentService: IEnvironmentService, private rootProvider: IWorkspaceContextService) {
super(parent, session.getName(true));
this._initialized = false;
this._session = session;
......@@ -387,7 +387,7 @@ export class LoadedScriptsView extends TreeViewsViewletPanel {
const root = new RootTreeItem(this.debugService.getModel(), this.environmentService, this.contextService);
this.tree.setInput(root);
const registerLoadedSourceListener = (session: ISession) => {
const registerLoadedSourceListener = (session: IDebugSession) => {
this.disposables.push(session.onDidLoadedSource(event => {
const sessionRoot = root.add(session);
sessionRoot.addPath(event.source);
......
......@@ -108,15 +108,28 @@ export interface IExpression extends IReplElement, IExpressionContainer {
readonly type?: string;
}
export interface IRawSession {
export interface IRawDebugSession {
capabilities: DebugProtocol.Capabilities;
disconnected: boolean;
readyForBreakpoints: boolean;
emittedStopped: boolean;
sessionLengthInSeconds: number;
launch(args: DebugProtocol.LaunchRequestArguments): TPromise<DebugProtocol.LaunchResponse>;
attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse>;
terminate(restart?: boolean): TPromise<DebugProtocol.TerminateResponse>;
disconnect(restart?: boolean): TPromise<any>;
setBreakpoints(args: DebugProtocol.SetBreakpointsArguments): TPromise<DebugProtocol.SetBreakpointsResponse>;
setFunctionBreakpoints(args: DebugProtocol.SetFunctionBreakpointsArguments): TPromise<DebugProtocol.SetFunctionBreakpointsResponse>;
setExceptionBreakpoints(args: DebugProtocol.SetExceptionBreakpointsArguments): TPromise<DebugProtocol.SetExceptionBreakpointsResponse>;
stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse>;
scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
disconnect(restart?: boolean): TPromise<any>;
terminate(restart?: boolean): TPromise<DebugProtocol.TerminateResponse>;
custom(request: string, args: any): TPromise<DebugProtocol.Response>;
restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): TPromise<DebugProtocol.RestartFrameResponse>;
......@@ -133,12 +146,12 @@ export interface IRawSession {
setVariable(args: DebugProtocol.SetVariableArguments): TPromise<DebugProtocol.SetVariableResponse>;
source(args: DebugProtocol.SourceArguments): TPromise<DebugProtocol.SourceResponse>;
loadedSources(args: DebugProtocol.LoadedSourcesArguments): TPromise<DebugProtocol.LoadedSourcesResponse>;
}
export interface ISession extends ITreeElement, IDisposable {
export interface IDebugSession extends ITreeElement, IDisposable {
readonly configuration: IConfig;
readonly raw: IRawSession;
readonly raw: IRawDebugSession;
readonly state: State;
readonly root: IWorkspaceFolder;
readonly capabilities: DebugProtocol.Capabilities;
......@@ -175,7 +188,7 @@ export interface IThread extends ITreeElement {
/**
* Process the thread belongs to
*/
readonly session: ISession;
readonly session: IDebugSession;
/**
* Id of the thread generated by the debug adapter backend.
......@@ -307,7 +320,7 @@ export interface IViewModel extends ITreeElement {
/**
* Returns the focused debug session or null if no session is stopped.
*/
readonly focusedSession: ISession;
readonly focusedSession: IDebugSession;
/**
* Returns the focused thread or null if no thread is stopped.
......@@ -326,13 +339,13 @@ export interface IViewModel extends ITreeElement {
isMultiSessionView(): boolean;
onDidFocusSession: Event<ISession | undefined>;
onDidFocusSession: Event<IDebugSession | undefined>;
onDidFocusStackFrame: Event<{ stackFrame: IStackFrame, explicit: boolean }>;
onDidSelectExpression: Event<IExpression>;
}
export interface IModel extends ITreeElement {
getSessions(): ReadonlyArray<ISession>;
getSessions(): ReadonlyArray<IDebugSession>;
getBreakpoints(filter?: { uri?: uri, lineNumber?: number, column?: number, enabledOnly?: boolean }): ReadonlyArray<IBreakpoint>;
areBreakpointsActivated(): boolean;
getFunctionBreakpoints(): ReadonlyArray<IFunctionBreakpoint>;
......@@ -606,17 +619,17 @@ export interface IDebugService {
/**
* Allows to register on new session events.
*/
onDidNewSession: Event<ISession>;
onDidNewSession: Event<IDebugSession>;
/**
* Allows to register on sessions about to be created (not yet fully initialised)
*/
onWillNewSession: Event<ISession>;
onWillNewSession: Event<IDebugSession>;
/**
* Allows to register on end session events.
*/
onDidEndSession: Event<ISession>;
onDidEndSession: Event<IDebugSession>;
/**
* Gets the current configuration manager.
......@@ -626,7 +639,7 @@ export interface IDebugService {
/**
* Sets the focused stack frame and evaluates all expressions against the newly focused stack frame,
*/
focusStackFrame(focusedStackFrame: IStackFrame, thread?: IThread, session?: ISession, explicit?: boolean): void;
focusStackFrame(focusedStackFrame: IStackFrame, thread?: IThread, session?: IDebugSession, explicit?: boolean): void;
/**
* Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes.
......@@ -677,7 +690,7 @@ export interface IDebugService {
* Sends all breakpoints to the passed session.
* If session is not passed, sends all breakpoints to each session.
*/
sendAllBreakpoints(session?: ISession): TPromise<any>;
sendAllBreakpoints(session?: IDebugSession): TPromise<any>;
/**
* Adds a new expression to the repl.
......@@ -724,12 +737,12 @@ export interface IDebugService {
/**
* Restarts a session or creates a new one if there is no active session.
*/
restartSession(session: ISession, restartData?: any): TPromise<any>;
restartSession(session: IDebugSession, restartData?: any): TPromise<any>;
/**
* Stops the session. If the session does not exist then stops all sessions.
*/
stopSession(session: ISession): TPromise<any>;
stopSession(session: IDebugSession): TPromise<any>;
/**
* Makes unavailable all sources with the passed uri. Source will appear as grayed out in callstack view.
......@@ -739,7 +752,7 @@ export interface IDebugService {
/**
* returns Session with the given ID (or undefined if ID is not found)
*/
getSession(sessionId: string): ISession;
getSession(sessionId: string): IDebugSession;
/**
* Gets the current debug model.
......
......@@ -16,7 +16,7 @@ import { isObject, isString, isUndefinedOrNull } from 'vs/base/common/types';
import { distinct } from 'vs/base/common/arrays';
import { Range, IRange } from 'vs/editor/common/core/range';
import {
ITreeElement, IExpression, IExpressionContainer, ISession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel, IReplElementSource,
ITreeElement, IExpression, IExpressionContainer, IDebugSession, IStackFrame, IExceptionBreakpoint, IBreakpoint, IFunctionBreakpoint, IModel, IReplElementSource,
IThread, IRawModelUpdate, IScope, IRawStoppedDetails, IEnablement, IBreakpointData, IExceptionInfo, IReplElement, IBreakpointsChangeEvent, IBreakpointUpdateData, IBaseBreakpoint
} from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
......@@ -112,7 +112,7 @@ export class ExpressionContainer implements IExpressionContainer {
protected children: TPromise<IExpression[]>;
constructor(
protected session: ISession,
protected session: IDebugSession,
private _reference: number,
private id: string,
public namedVariables = 0,
......@@ -230,7 +230,7 @@ export class Expression extends ExpressionContainer implements IExpression {
}
}
public evaluate(session: ISession, stackFrame: IStackFrame, context: string): TPromise<void> {
public evaluate(session: IDebugSession, stackFrame: IStackFrame, context: string): TPromise<void> {
if (!session || (!stackFrame && context !== 'repl')) {
this.value = context === 'repl' ? nls.localize('startDebugFirst', "Please start a debug session to evaluate") : Expression.DEFAULT_VALUE;
this.available = false;
......@@ -271,7 +271,7 @@ export class Variable extends ExpressionContainer implements IExpression {
public errorMessage: string;
constructor(
session: ISession,
session: IDebugSession,
public parent: IExpressionContainer,
reference: number,
public name: string,
......@@ -409,7 +409,7 @@ export class Thread implements IThread {
public stoppedDetails: IRawStoppedDetails;
public stopped: boolean;
constructor(public session: ISession, public name: string, public threadId: number) {
constructor(public session: IDebugSession, public name: string, public threadId: number) {
this.stoppedDetails = null;
this.callStack = [];
this.staleCallStack = [];
......@@ -750,7 +750,7 @@ export class ThreadAndSessionIds implements ITreeElement {
export class Model implements IModel {
private sessions: ISession[];
private sessions: IDebugSession[];
private toDispose: lifecycle.IDisposable[];
private replElements: IReplElement[];
private schedulers = new Map<string, RunOnceScheduler>();
......@@ -781,11 +781,11 @@ export class Model implements IModel {
return 'root';
}
public getSessions(): ISession[] {
public getSessions(): IDebugSession[] {
return this.sessions;
}
public addSession(session: ISession): void {
public addSession(session: IDebugSession): void {
this.sessions.push(session);
}
......@@ -1043,7 +1043,7 @@ export class Model implements IModel {
return this.replElements;
}
public addReplExpression(session: ISession, stackFrame: IStackFrame, name: string): TPromise<void> {
public addReplExpression(session: IDebugSession, stackFrame: IStackFrame, name: string): TPromise<void> {
const expression = new Expression(name);
this.addReplElements([expression]);
return expression.evaluate(session, stackFrame, 'repl')
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, ISession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED } from 'vs/workbench/parts/debug/common/debug';
import { CONTEXT_EXPRESSION_SELECTED, IViewModel, IStackFrame, IDebugSession, IThread, IExpression, IFunctionBreakpoint, CONTEXT_BREAKPOINT_SELECTED, CONTEXT_LOADED_SCRIPTS_SUPPORTED } from 'vs/workbench/parts/debug/common/debug';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
export class ViewModel implements IViewModel {
......@@ -12,11 +12,11 @@ export class ViewModel implements IViewModel {
firstSessionStart = true;
private _focusedStackFrame: IStackFrame;
private _focusedSession: ISession;
private _focusedSession: IDebugSession;
private _focusedThread: IThread;
private selectedExpression: IExpression;
private selectedFunctionBreakpoint: IFunctionBreakpoint;
private readonly _onDidFocusSession: Emitter<ISession | undefined>;
private readonly _onDidFocusSession: Emitter<IDebugSession | undefined>;
private readonly _onDidFocusStackFrame: Emitter<{ stackFrame: IStackFrame, explicit: boolean }>;
private readonly _onDidSelectExpression: Emitter<IExpression>;
private multiSessionView: boolean;
......@@ -25,7 +25,7 @@ export class ViewModel implements IViewModel {
private loadedScriptsSupportedContextKey: IContextKey<boolean>;
constructor(contextKeyService: IContextKeyService) {
this._onDidFocusSession = new Emitter<ISession | undefined>();
this._onDidFocusSession = new Emitter<IDebugSession | undefined>();
this._onDidFocusStackFrame = new Emitter<{ stackFrame: IStackFrame, explicit: boolean }>();
this._onDidSelectExpression = new Emitter<IExpression>();
this.multiSessionView = false;
......@@ -38,7 +38,7 @@ export class ViewModel implements IViewModel {
return 'root';
}
get focusedSession(): ISession {
get focusedSession(): IDebugSession {
return this._focusedSession;
}
......@@ -60,7 +60,7 @@ export class ViewModel implements IViewModel {
return this._focusedStackFrame;
}
setFocus(stackFrame: IStackFrame, thread: IThread, session: ISession, explicit: boolean): void {
setFocus(stackFrame: IStackFrame, thread: IThread, session: IDebugSession, explicit: boolean): void {
const shouldEmit = this._focusedSession !== session || this._focusedThread !== thread || this._focusedStackFrame !== stackFrame;
this._focusedStackFrame = stackFrame;
......@@ -77,7 +77,7 @@ export class ViewModel implements IViewModel {
}
}
get onDidFocusSession(): Event<ISession> {
get onDidFocusSession(): Event<IDebugSession> {
return this._onDidFocusSession.event;
}
......
......@@ -8,7 +8,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import * as dom from 'vs/base/browser/dom';
import { TPromise } from 'vs/base/common/winjs.base';
import { TreeViewsViewletPanel, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IDebugService, State, IStackFrame, ISession, IThread, CONTEXT_CALLSTACK_ITEM_TYPE } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, State, IStackFrame, IDebugSession, IThread, CONTEXT_CALLSTACK_ITEM_TYPE } from 'vs/workbench/parts/debug/common/debug';
import { Thread, StackFrame, ThreadAndSessionIds, Model } from 'vs/workbench/parts/debug/common/debugModel';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -27,7 +27,7 @@ import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
import { ILabelService } from 'vs/platform/label/common/label';
import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession';
import { DebugSession } from 'vs/workbench/parts/debug/electron-browser/debugSession';
const $ = dom.$;
......@@ -126,7 +126,7 @@ export class CallStackView extends TreeViewsViewletPanel {
if (element instanceof Thread) {
this.debugService.focusStackFrame(undefined, element, element.session, true);
}
if (element instanceof Session) {
if (element instanceof DebugSession) {
this.debugService.focusStackFrame(undefined, undefined, element, true);
}
if (element instanceof ThreadAndSessionIds) {
......@@ -144,7 +144,7 @@ export class CallStackView extends TreeViewsViewletPanel {
this.callStackItemType.set('stackFrame');
} else if (focus instanceof Thread) {
this.callStackItemType.set('thread');
} else if (focus instanceof Session) {
} else if (focus instanceof DebugSession) {
this.callStackItemType.set('session');
} else {
this.callStackItemType.reset();
......@@ -192,7 +192,7 @@ export class CallStackView extends TreeViewsViewletPanel {
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
const thread = this.debugService.getViewModel().focusedThread;
const session = this.debugService.getViewModel().focusedSession;
const updateSelection = (element: IStackFrame | ISession) => {
const updateSelection = (element: IStackFrame | IDebugSession) => {
this.ignoreSelectionChangedEvent = true;
try {
this.tree.setSelection([element]);
......@@ -271,7 +271,7 @@ class CallStackActionProvider implements IActionProvider {
public getSecondaryActions(tree: ITree, element: any): TPromise<IAction[]> {
const actions: IAction[] = [];
if (element instanceof Session) {
if (element instanceof DebugSession) {
actions.push(this.instantiationService.createInstance(RestartAction, RestartAction.ID, RestartAction.LABEL));
actions.push(new StopAction(StopAction.ID, StopAction.LABEL, this.debugService, this.keybindingService));
} else if (element instanceof Thread) {
......@@ -313,7 +313,7 @@ class CallStackDataSource implements IDataSource {
}
public hasChildren(tree: ITree, element: any): boolean {
return element instanceof Model || element instanceof Session || (element instanceof Thread && (<Thread>element).stopped);
return element instanceof Model || element instanceof DebugSession || (element instanceof Thread && (<Thread>element).stopped);
}
public getChildren(tree: ITree, element: any): TPromise<any> {
......@@ -324,7 +324,7 @@ class CallStackDataSource implements IDataSource {
return TPromise.as(element.getSessions());
}
const session = <ISession>element;
const session = <IDebugSession>element;
return TPromise.as(session.getAllThreads());
}
......@@ -408,7 +408,7 @@ class CallStackRenderer implements IRenderer {
}
public getTemplateId(tree: ITree, element: any): string {
if (element instanceof Session) {
if (element instanceof DebugSession) {
return CallStackRenderer.SESSION_TEMPLATE_ID;
}
if (element instanceof Thread) {
......@@ -482,7 +482,7 @@ class CallStackRenderer implements IRenderer {
}
}
private renderSession(session: ISession, data: ISessionTemplateData): void {
private renderSession(session: IDebugSession, data: ISessionTemplateData): void {
data.session.title = nls.localize({ key: 'session', comment: ['Session is a noun'] }, "Session");
data.name.textContent = session.getName(this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE);
const stoppedThread = session.getAllThreads().filter(t => t.stopped).pop();
......
......@@ -22,7 +22,6 @@ import { FileChangesEvent, FileChangeType, IFileService } from 'vs/platform/file
import { IWindowService } from 'vs/platform/windows/common/windows';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { RawDebugSession } from 'vs/workbench/parts/debug/electron-browser/rawDebugSession';
import { Model, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression, RawObjectReplElement } from 'vs/workbench/parts/debug/common/debugModel';
import { ViewModel } from 'vs/workbench/parts/debug/common/debugViewModel';
import * as debugactions from 'vs/workbench/parts/debug/browser/debugActions';
......@@ -48,10 +47,10 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IAction, Action } from 'vs/base/common/actions';
import { normalizeDriveLetter } from 'vs/base/common/labels';
import { deepClone, equals } from 'vs/base/common/objects';
import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession';
import { DebugSession } from 'vs/workbench/parts/debug/electron-browser/debugSession';
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, State, ISession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IModel, IReplElementSource, IEnablement, IBreakpoint, IBreakpointData, IExpression, ICompound, IGlobalConfig, IStackFrame } from 'vs/workbench/parts/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, IModel, IReplElementSource, IEnablement, IBreakpoint, IBreakpointData, IExpression, ICompound, IGlobalConfig, IStackFrame } from 'vs/workbench/parts/debug/common/debug';
const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint';
const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated';
......@@ -63,13 +62,13 @@ export class DebugService implements IDebugService {
_serviceBrand: any;
private readonly _onDidChangeState: Emitter<State>;
private readonly _onDidNewSession: Emitter<ISession>;
private readonly _onWillNewSession: Emitter<ISession>;
private readonly _onDidEndSession: Emitter<ISession>;
private readonly _onDidNewSession: Emitter<IDebugSession>;
private readonly _onWillNewSession: Emitter<IDebugSession>;
private readonly _onDidEndSession: Emitter<IDebugSession>;
private model: Model;
private viewModel: ViewModel;
private configurationManager: ConfigurationManager;
private allSessions = new Map<string, ISession>();
private allSessions = new Map<string, IDebugSession>();
private toDispose: IDisposable[];
private debugType: IContextKey<string>;
private debugState: IContextKey<string>;
......@@ -106,9 +105,9 @@ export class DebugService implements IDebugService {
this.breakpointsToSendOnResourceSaved = new Set<string>();
this._onDidChangeState = new Emitter<State>();
this._onDidNewSession = new Emitter<ISession>();
this._onWillNewSession = new Emitter<ISession>();
this._onDidEndSession = new Emitter<ISession>();
this._onDidNewSession = new Emitter<IDebugSession>();
this._onWillNewSession = new Emitter<IDebugSession>();
this._onDidEndSession = new Emitter<IDebugSession>();
this.configurationManager = this.instantiationService.createInstance(ConfigurationManager);
this.toDispose.push(this.configurationManager);
......@@ -128,7 +127,7 @@ export class DebugService implements IDebugService {
this.lifecycleService.onShutdown(this.dispose, this);
this.toDispose.push(this.broadcastService.onBroadcast(broadcast => {
const session = <Session>this.getSession(broadcast.payload.debugId);
const session = <DebugSession>this.getSession(broadcast.payload.debugId);
if (session) {
switch (broadcast.channel) {
......@@ -159,7 +158,7 @@ export class DebugService implements IDebugService {
}));
}
getSession(sessionId: string): ISession {
getSession(sessionId: string): IDebugSession {
return this.allSessions.get(sessionId);
}
......@@ -225,15 +224,15 @@ export class DebugService implements IDebugService {
return this._onDidChangeState.event;
}
get onDidNewSession(): Event<ISession> {
get onDidNewSession(): Event<IDebugSession> {
return this._onDidNewSession.event;
}
get onWillNewSession(): Event<ISession> {
get onWillNewSession(): Event<IDebugSession> {
return this._onWillNewSession.event;
}
get onDidEndSession(): Event<ISession> {
get onDidEndSession(): Event<IDebugSession> {
return this._onDidEndSession.event;
}
......@@ -404,14 +403,14 @@ export class DebugService implements IDebugService {
return equalsIgnoreCase(config.type, 'extensionhost');
}
private attachExtensionHost(session: Session, port: number): TPromise<void> {
private attachExtensionHost(session: DebugSession, port: number): TPromise<void> {
session.configuration.request = 'attach';
session.configuration.port = port;
const dbgr = this.configurationManager.getDebugger(session.configuration.type);
return session.initialize(dbgr).then(() => {
(<RawDebugSession>session.raw).attach(session.configuration).then(result => {
session.raw.attach(session.configuration).then(result => {
this.focusStackFrame(undefined, undefined, session);
});
});
......@@ -419,7 +418,7 @@ export class DebugService implements IDebugService {
private doCreateSession(root: IWorkspaceFolder, configuration: { resolved: IConfig, unresolved: IConfig }): TPromise<any> {
const session = this.instantiationService.createInstance(Session, configuration, root, this.model);
const session = this.instantiationService.createInstance(DebugSession, configuration, root, this.model);
this.allSessions.set(session.getId(), session);
// register listeners as the very first thing!
......@@ -434,7 +433,7 @@ export class DebugService implements IDebugService {
return session.initialize(dbgr).then(() => {
const raw = <RawDebugSession>session.raw;
const raw = session.raw;
// pass the sessionID for EH debugging
if (this.isExtensionHostDebugging(resolved)) {
......@@ -511,7 +510,7 @@ export class DebugService implements IDebugService {
});
}
private registerSessionListeners(session: Session): void {
private registerSessionListeners(session: DebugSession): void {
this.toDispose.push(session.onDidChangeState((state) => {
if (state === State.Running && this.viewModel.focusedSession && this.viewModel.focusedSession.getId() === session.getId()) {
......@@ -561,9 +560,9 @@ export class DebugService implements IDebugService {
}));
}
restartSession(session: ISession, restartData?: any): TPromise<any> {
restartSession(session: IDebugSession, restartData?: any): TPromise<any> {
return this.textFileService.saveAll().then(() => {
const unresolvedConfiguration = (<Session>session).unresolvedConfiguration;
const unresolvedConfiguration = (<DebugSession>session).unresolvedConfiguration;
if (session.capabilities.supportsRestartRequest) {
return this.runTask(session.root, session.configuration.postDebugTask, session.configuration, unresolvedConfiguration)
.then(success => success ? this.runTask(session.root, session.configuration.preLaunchTask, session.configuration, unresolvedConfiguration)
......@@ -617,7 +616,7 @@ export class DebugService implements IDebugService {
});
}
stopSession(session: ISession): TPromise<any> {
stopSession(session: IDebugSession): TPromise<any> {
if (session) {
return session.raw.terminate();
......@@ -783,7 +782,7 @@ export class DebugService implements IDebugService {
return stackFrameToFocus.openInEditor(this.editorService, true);
}
focusStackFrame(stackFrame: IStackFrame, thread?: IThread, session?: ISession, explicit?: boolean): void {
focusStackFrame(stackFrame: IStackFrame, thread?: IThread, session?: IDebugSession, explicit?: boolean): void {
if (!session) {
if (stackFrame || thread) {
session = stackFrame ? stackFrame.thread.session : thread.session;
......@@ -824,7 +823,7 @@ export class DebugService implements IDebugService {
this.model.removeReplExpressions();
}
private addToRepl(session: ISession, extensionOutput: IRemoteConsoleLog) {
private addToRepl(session: IDebugSession, extensionOutput: IRemoteConsoleLog) {
let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info;
......@@ -998,17 +997,17 @@ export class DebugService implements IDebugService {
return this.sendFunctionBreakpoints();
}
sendAllBreakpoints(session?: ISession): TPromise<any> {
sendAllBreakpoints(session?: IDebugSession): TPromise<any> {
return TPromise.join(distinct(this.model.getBreakpoints(), bp => bp.uri.toString()).map(bp => this.sendBreakpoints(bp.uri, false, session)))
.then(() => this.sendFunctionBreakpoints(session))
// send exception breakpoints at the end since some debug adapters rely on the order
.then(() => this.sendExceptionBreakpoints(session));
}
private sendBreakpoints(modelUri: uri, sourceModified = false, session?: ISession): TPromise<void> {
private sendBreakpoints(modelUri: uri, sourceModified = false, session?: IDebugSession): TPromise<void> {
const sendBreakpointsToSession = (session: ISession): TPromise<void> => {
const raw = <RawDebugSession>session.raw;
const sendBreakpointsToSession = (session: IDebugSession): TPromise<void> => {
const raw = session.raw;
if (!raw.readyForBreakpoints) {
return TPromise.as(null);
}
......@@ -1051,9 +1050,9 @@ export class DebugService implements IDebugService {
return this.sendToOneOrAllSessions(session, sendBreakpointsToSession);
}
private sendFunctionBreakpoints(session?: ISession): TPromise<void> {
const sendFunctionBreakpointsToSession = (session: ISession): TPromise<void> => {
const raw = <RawDebugSession>session.raw;
private sendFunctionBreakpoints(session?: IDebugSession): TPromise<void> {
const sendFunctionBreakpointsToSession = (session: IDebugSession): TPromise<void> => {
const raw = session.raw;
if (!raw.readyForBreakpoints || !raw.capabilities.supportsFunctionBreakpoints) {
return TPromise.as(null);
}
......@@ -1075,9 +1074,9 @@ export class DebugService implements IDebugService {
return this.sendToOneOrAllSessions(session, sendFunctionBreakpointsToSession);
}
private sendExceptionBreakpoints(session?: ISession): TPromise<void> {
const sendExceptionBreakpointsToSession = (session: ISession): TPromise<any> => {
const raw = <RawDebugSession>session.raw;
private sendExceptionBreakpoints(session?: IDebugSession): TPromise<void> {
const sendExceptionBreakpointsToSession = (session: IDebugSession): TPromise<any> => {
const raw = session.raw;
if (!raw.readyForBreakpoints || this.model.getExceptionBreakpoints().length === 0) {
return TPromise.as(null);
}
......@@ -1089,7 +1088,7 @@ export class DebugService implements IDebugService {
return this.sendToOneOrAllSessions(session, sendExceptionBreakpointsToSession);
}
private sendToOneOrAllSessions(session: ISession, send: (session: ISession) => TPromise<void>): TPromise<void> {
private sendToOneOrAllSessions(session: IDebugSession, send: (session: IDebugSession) => TPromise<void>): TPromise<void> {
if (session) {
return send(session);
}
......@@ -1217,7 +1216,7 @@ export class DebugService implements IDebugService {
});
}
private telemetryDebugSessionStop(session: ISession): TPromise<any> {
private telemetryDebugSessionStop(session: IDebugSession): TPromise<any> {
const breakpoints = this.model.getBreakpoints();
......@@ -1232,8 +1231,8 @@ export class DebugService implements IDebugService {
*/
return this.telemetryService.publicLog('debugSessionStop', {
type: session && session.configuration.type,
success: (<RawDebugSession>session.raw).emittedStopped || breakpoints.length === 0,
sessionLengthInSeconds: (<RawDebugSession>session.raw).getLengthInSeconds(),
success: session.raw.emittedStopped || breakpoints.length === 0,
sessionLengthInSeconds: session.raw.sessionLengthInSeconds,
breakpointCount: breakpoints.length,
watchExpressionsCount: this.model.getWatchExpressions().length
});
......
......@@ -13,7 +13,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ISuggestion } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position';
import * as aria from 'vs/base/browser/ui/aria/aria';
import { ISession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, IRawSession, LoadedSourceEvent } from 'vs/workbench/parts/debug/common/debug';
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, IRawDebugSession, LoadedSourceEvent } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { mixin } from 'vs/base/common/objects';
import { Thread, ExpressionContainer, Model } from 'vs/workbench/parts/debug/common/debugModel';
......@@ -28,7 +28,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { generateUuid } from 'vs/base/common/uuid';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
export class Session implements ISession {
export class DebugSession implements IDebugSession {
private id: string;
......@@ -60,7 +60,7 @@ export class Session implements ISession {
return this.id;
}
get raw(): IRawSession {
get raw(): IRawDebugSession {
return this._raw;
}
......
......@@ -15,24 +15,24 @@ import { IOutputService } from 'vs/workbench/parts/output/common/output';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { formatPII } from 'vs/workbench/parts/debug/common/debugUtils';
import { SocketDebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter';
import { IRawSession, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug';
import { IRawDebugSession, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
export class RawDebugSession implements IRawSession {
public emittedStopped: boolean;
public readyForBreakpoints: boolean;
public disconnected: boolean;
export class RawDebugSession implements IRawDebugSession {
private debugAdapter: IDebugAdapter;
private cachedInitDebugAdapterP: TPromise<void>;
private startTime: number;
private terminated: boolean;
private cancellationTokens: CancellationTokenSource[];
private _capabilities: DebugProtocol.Capabilities;
private allThreadsContinued: boolean;
private isAttached: boolean;
private _emittedStopped: boolean;
private _readyForBreakpoints: boolean;
private _disconnected: boolean;
private _capabilities: DebugProtocol.Capabilities;
// DAP events
private readonly _onDidInitialize: Emitter<DebugProtocol.InitializedEvent>;
private readonly _onDidStop: Emitter<DebugProtocol.StoppedEvent>;
......@@ -57,8 +57,8 @@ export class RawDebugSession implements IRawSession {
@ITelemetryService private telemetryService: ITelemetryService,
@IOutputService private outputService: IOutputService
) {
this.emittedStopped = false;
this.readyForBreakpoints = false;
this._emittedStopped = false;
this._readyForBreakpoints = false;
this.allThreadsContinued = true;
this.cancellationTokens = [];
......@@ -77,7 +77,31 @@ export class RawDebugSession implements IRawSession {
this._onDidExitAdapter = new Emitter<Error>();
}
// DAP events
public get onDidExitAdapter(): Event<Error> {
return this._onDidExitAdapter.event;
}
public get sessionLengthInSeconds(): number {
return (new Date().getTime() - this.startTime) / 1000;
}
public get capabilities(): DebugProtocol.Capabilities {
return this._capabilities || {};
}
public get readyForBreakpoints(): boolean {
return this._readyForBreakpoints;
}
public get emittedStopped(): boolean {
return this._emittedStopped;
}
public get disconnected(): boolean {
return this._disconnected;
}
//---- DAP events
public get onDidInitialize(): Event<DebugProtocol.InitializedEvent> {
return this._onDidInitialize.event;
......@@ -123,164 +147,12 @@ export class RawDebugSession implements IRawSession {
return this._onDidEvent.event;
}
// DA event
public get onDidExitAdapter(): Event<Error> {
return this._onDidExitAdapter.event;
}
private startAdapter(): TPromise<void> {
if (!this.cachedInitDebugAdapterP) {
const startSessionP = this._debugger.createDebugAdapter(this.root, this.outputService, this.debugServerPort).then(debugAdapter => {
this.debugAdapter = debugAdapter;
this.debugAdapter.onError(err => this.onDebugAdapterError(err));
this.debugAdapter.onEvent(event => this.onDapEvent(event));
this.debugAdapter.onRequest(request => this.dispatchRequest(request));
this.debugAdapter.onExit(code => this.onDebugAdapterExit(code));
return this.debugAdapter.startSession();
});
this.cachedInitDebugAdapterP = startSessionP.then(() => {
this.startTime = new Date().getTime();
}, err => {
this.cachedInitDebugAdapterP = null;
return TPromise.wrapError(err);
});
}
return this.cachedInitDebugAdapterP;
}
private send<R extends DebugProtocol.Response>(command: string, args: any, cancelOnDisconnect = true): TPromise<R> {
return this.startAdapter().then(() => {
const cancellationSource = new CancellationTokenSource();
const promise = this.internalSend<R>(command, args, cancellationSource.token).then(response => {
return response;
},
(errorResponse: DebugProtocol.ErrorResponse) => {
const error = errorResponse && errorResponse.body ? errorResponse.body.error : null;
const errorMessage = errorResponse ? errorResponse.message : '';
const telemetryMessage = error ? formatPII(error.format, true, error.variables) : errorMessage;
if (error && error.sendTelemetry) {
/* __GDPR__
"debugProtocolErrorResponse" : {
"error" : { "classification": "CallstackOrException", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
if (this.customTelemetryService) {
/* __GDPR__TODO__
The message is sent in the name of the adapter but the adapter doesn't know about it.
However, since adapters are an open-ended set, we can not declared the events statically either.
*/
this.customTelemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
}
}
const userMessage = error ? formatPII(error.format, false, error.variables) : errorMessage;
if (error && error.url) {
const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info");
return TPromise.wrapError<R>(errors.create(userMessage, {
actions: [new Action('debug.moreInfo', label, null, true, () => {
window.open(error.url);
return TPromise.as(null);
})]
}));
}
if (errors.isPromiseCanceledError(errorResponse)) {
return TPromise.wrapError<R>(<any>errorResponse);
}
return TPromise.wrapError<R>(new Error(userMessage));
});
if (cancelOnDisconnect) {
this.cancellationTokens.push(cancellationSource);
}
return promise;
});
}
private internalSend<R extends DebugProtocol.Response>(command: string, args: any, cancelationToken: CancellationToken): TPromise<R> {
return new TPromise<R>((completeDispatch, errorDispatch) => {
cancelationToken.onCancellationRequested(() => errorDispatch(errors.canceled()));
this.debugAdapter.sendRequest(command, args, (result: R) => {
if (result.success) {
completeDispatch(result);
} else {
errorDispatch(result);
}
});
});
}
private onDapEvent(event: DebugProtocol.Event): void {
switch (event.event) {
case 'initialized':
this.readyForBreakpoints = true;
this._onDidInitialize.fire(event);
break;
case 'loadedSource':
this._onDidLoadedSource.fire(<DebugProtocol.LoadedSourceEvent>event);
break;
case 'capabilities':
if (event.body) {
const capabilites = (<DebugProtocol.CapabilitiesEvent>event).body.capabilities;
this._capabilities = objects.mixin(this._capabilities, capabilites);
}
break;
case 'stopped':
this.emittedStopped = true;
this._onDidStop.fire(<DebugProtocol.StoppedEvent>event);
break;
case 'continued':
this.allThreadsContinued = (<DebugProtocol.ContinuedEvent>event).body.allThreadsContinued === false ? false : true;
this._onDidContinued.fire(<DebugProtocol.ContinuedEvent>event);
break;
case 'thread':
this._onDidThread.fire(<DebugProtocol.ThreadEvent>event);
break;
case 'output':
this._onDidOutput.fire(<DebugProtocol.OutputEvent>event);
break;
case 'breakpoint':
this._onDidBreakpoint.fire(<DebugProtocol.BreakpointEvent>event);
break;
case 'terminated':
this._onDidTerminateDebugee.fire(<DebugProtocol.TerminatedEvent>event);
break;
case 'exit':
this._onDidExitDebugee.fire(<DebugProtocol.ExitedEvent>event);
break;
default:
this._onDidCustomEvent.fire(event);
break;
}
this._onDidEvent.fire(event);
}
public get capabilities(): DebugProtocol.Capabilities {
return this._capabilities || {};
}
//---- DAP requests
public initialize(args: DebugProtocol.InitializeRequestArguments): TPromise<DebugProtocol.InitializeResponse> {
return this.send('initialize', args).then(response => this.readCapabilities(response));
}
private readCapabilities(response: DebugProtocol.Response): DebugProtocol.Response {
if (response) {
this._capabilities = objects.mixin(this._capabilities, response.body);
}
return response;
}
public launch(args: DebugProtocol.LaunchRequestArguments): TPromise<DebugProtocol.LaunchResponse> {
return this.send('launch', args).then(response => this.readCapabilities(response));
}
......@@ -423,11 +295,118 @@ export class RawDebugSession implements IRawSession {
return this.send(request, args);
}
public getLengthInSeconds(): number {
return (new Date().getTime() - this.startTime) / 1000;
public disconnect(restart = false): TPromise<any> {
if (this.disconnected) {
return this.stopAdapter();
}
// Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666.
// Give a 1s timeout to give a chance for some promises to complete.
setTimeout(() => {
this.cancellationTokens.forEach(token => token.cancel());
this.cancellationTokens = [];
}, 1000);
if (this.debugAdapter && !this.disconnected) {
// point of no return: from now on don't report any errors
this._disconnected = true;
return this.send('disconnect', { restart }, false).then(() => this.stopAdapter(), () => this.stopAdapter());
}
return TPromise.as(null);
}
//---- private
private startAdapter(): TPromise<void> {
if (!this.cachedInitDebugAdapterP) {
const startSessionP = this._debugger.createDebugAdapter(this.root, this.outputService, this.debugServerPort).then(debugAdapter => {
this.debugAdapter = debugAdapter;
this.debugAdapter.onError(err => {
// TODO: don't stop server on this layer
this.stopAdapter(err);
});
this.debugAdapter.onEvent(event => this.onDapEvent(event));
this.debugAdapter.onExit(code => this.onDebugAdapterExit(code));
this.debugAdapter.onRequest(request => this.dispatchRequest(request));
return this.debugAdapter.startSession();
});
this.cachedInitDebugAdapterP = startSessionP.then(() => {
this.startTime = new Date().getTime();
}, err => {
this.cachedInitDebugAdapterP = null;
return TPromise.wrapError(err);
});
}
return this.cachedInitDebugAdapterP;
}
private onDapEvent(event: DebugProtocol.Event): void {
switch (event.event) {
case 'initialized':
this._readyForBreakpoints = true;
this._onDidInitialize.fire(event);
break;
case 'loadedSource':
this._onDidLoadedSource.fire(<DebugProtocol.LoadedSourceEvent>event);
break;
case 'capabilities':
if (event.body) {
const capabilites = (<DebugProtocol.CapabilitiesEvent>event).body.capabilities;
this._capabilities = objects.mixin(this._capabilities, capabilites);
}
break;
case 'stopped':
this._emittedStopped = true;
this._onDidStop.fire(<DebugProtocol.StoppedEvent>event);
break;
case 'continued':
this.allThreadsContinued = (<DebugProtocol.ContinuedEvent>event).body.allThreadsContinued === false ? false : true;
this._onDidContinued.fire(<DebugProtocol.ContinuedEvent>event);
break;
case 'thread':
this._onDidThread.fire(<DebugProtocol.ThreadEvent>event);
break;
case 'output':
this._onDidOutput.fire(<DebugProtocol.OutputEvent>event);
break;
case 'breakpoint':
this._onDidBreakpoint.fire(<DebugProtocol.BreakpointEvent>event);
break;
case 'terminated':
this._onDidTerminateDebugee.fire(<DebugProtocol.TerminatedEvent>event);
break;
case 'exit':
this._onDidExitDebugee.fire(<DebugProtocol.ExitedEvent>event);
break;
default:
this._onDidCustomEvent.fire(event);
break;
}
this._onDidEvent.fire(event);
}
private onDebugAdapterExit(code: number): void {
this.debugAdapter = null;
this.cachedInitDebugAdapterP = null;
if (!this.disconnected && code !== 0) {
this._onDidExitAdapter.fire(new Error(`exit code: ${code}`));
} else {
// normal exit
this._onDidExitAdapter.fire();
}
}
private dispatchRequest(request: DebugProtocol.Request): void {
const response: DebugProtocol.Response = {
type: 'response',
seq: 0,
......@@ -435,38 +414,107 @@ export class RawDebugSession implements IRawSession {
request_seq: request.seq,
success: true
};
const sendResponse = (response) => this.debugAdapter && this.debugAdapter.sendResponse(response);
if (request.command === 'runInTerminal') {
const sendResponse = (response) => this.debugAdapter && this.debugAdapter.sendResponse(response);
this._debugger.runInTerminal(<DebugProtocol.RunInTerminalRequestArguments>request.arguments).then(_ => {
response.body = {};
sendResponse(response);
}, err => {
switch (request.command) {
case 'runInTerminal':
this._debugger.runInTerminal(<DebugProtocol.RunInTerminalRequestArguments>request.arguments).then(_ => {
response.body = {};
sendResponse(response);
}, err => {
response.success = false;
response.message = err.message;
sendResponse(response);
});
break;
case 'handshake':
try {
const vsda = <any>require.__$__nodeRequire('vsda');
const obj = new vsda.signer();
const sig = obj.sign(request.arguments.value);
response.body = {
signature: sig
};
sendResponse(response);
} catch (e) {
response.success = false;
response.message = e.message;
sendResponse(response);
}
break;
default:
response.success = false;
response.message = err.message;
response.message = `unknown request '${request.command}'`;
sendResponse(response);
});
break;
}
}
} else if (request.command === 'handshake') {
try {
const vsda = <any>require.__$__nodeRequire('vsda');
const obj = new vsda.signer();
const sig = obj.sign(request.arguments.value);
response.body = {
signature: sig
};
sendResponse(response);
} catch (e) {
response.success = false;
response.message = e.message;
sendResponse(response);
private send<R extends DebugProtocol.Response>(command: string, args: any, cancelOnDisconnect = true): TPromise<R> {
return this.startAdapter().then(() => {
const cancellationSource = new CancellationTokenSource();
const promise = this.internalSend<R>(command, args, cancellationSource.token).then(
response => {
return response;
},
(errorResponse: DebugProtocol.ErrorResponse) => {
if (errors.isPromiseCanceledError(errorResponse)) {
return TPromise.wrapError<R>(<any>errorResponse);
}
const error = errorResponse && errorResponse.body ? errorResponse.body.error : null;
const errorMessage = errorResponse ? errorResponse.message : '';
if (error && error.sendTelemetry) {
const telemetryMessage = error ? formatPII(error.format, true, error.variables) : errorMessage;
this.telemetryDebugProtocolErrorResponse(telemetryMessage);
}
const userMessage = error ? formatPII(error.format, false, error.variables) : errorMessage;
if (error && error.url) {
const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info");
return TPromise.wrapError<R>(errors.create(userMessage, {
actions: [new Action('debug.moreInfo', label, null, true, () => {
window.open(error.url);
return TPromise.as(null);
})]
}));
}
return TPromise.wrapError<R>(new Error(userMessage));
}
);
if (cancelOnDisconnect) {
this.cancellationTokens.push(cancellationSource);
}
} else {
response.success = false;
response.message = `unknown request '${request.command}'`;
sendResponse(response);
return promise;
});
}
private internalSend<R extends DebugProtocol.Response>(command: string, args: any, cancelationToken: CancellationToken): TPromise<R> {
return new TPromise<R>((completeDispatch, errorDispatch) => {
cancelationToken.onCancellationRequested(() => errorDispatch(errors.canceled()));
this.debugAdapter.sendRequest(command, args, (result: R) => {
if (result.success) {
completeDispatch(result);
} else {
errorDispatch(result);
}
});
});
}
private readCapabilities(response: DebugProtocol.Response): DebugProtocol.Response {
if (response) {
this._capabilities = objects.mixin(this._capabilities, response.body);
}
return response;
}
private fireFakeContinued(threadId: number, allThreadsContinued = false): void {
......@@ -481,28 +529,7 @@ export class RawDebugSession implements IRawSession {
});
}
public disconnect(restart = false): TPromise<any> {
if (this.disconnected) {
return this.stopServer();
}
// Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666.
// Give a 1s timeout to give a chance for some promises to complete.
setTimeout(() => {
this.cancellationTokens.forEach(token => token.cancel());
this.cancellationTokens = [];
}, 1000);
if (this.debugAdapter && !this.disconnected) {
// point of no return: from now on don't report any errors
this.disconnected = true;
return this.send('disconnect', { restart }, false).then(() => this.stopServer(), () => this.stopServer());
}
return TPromise.as(null);
}
private stopServer(error?: Error): TPromise<any> {
private stopAdapter(error?: Error): TPromise<any> {
if (/* this.socket !== null */ this.debugAdapter instanceof SocketDebugAdapter) {
this.debugAdapter.stopSession();
......@@ -510,25 +537,27 @@ export class RawDebugSession implements IRawSession {
}
this._onDidExitAdapter.fire(error);
this.disconnected = true;
this._disconnected = true;
if (!this.debugAdapter || this.debugAdapter instanceof SocketDebugAdapter) {
return TPromise.as(null);
}
return this.debugAdapter.stopSession();
}
private onDebugAdapterError(err: Error): void {
this.stopServer(err);
}
private onDebugAdapterExit(code: number): void {
this.debugAdapter = null;
this.cachedInitDebugAdapterP = null;
if (!this.disconnected && code !== 0) {
this._onDidExitAdapter.fire(new Error(`exit code: ${code}`));
} else {
// normal exit
this._onDidExitAdapter.fire();
private telemetryDebugProtocolErrorResponse(telemetryMessage: string) {
/* __GDPR__
"debugProtocolErrorResponse" : {
"error" : { "classification": "CallstackOrException", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
if (this.customTelemetryService) {
/* __GDPR__TODO__
The message is sent in the name of the adapter but the adapter doesn't know about it.
However, since adapters are an open-ended set, we can not declared the events statically either.
*/
this.customTelemetryService.publicLog('debugProtocolErrorResponse', { error: telemetryMessage });
}
}
}
......@@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Position } from 'vs/editor/common/core/position';
import { ILaunch, IDebugService, State, ISession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawSession, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate } from 'vs/workbench/parts/debug/common/debug';
import { ILaunch, IDebugService, State, IDebugSession, IConfigurationManager, IStackFrame, IBreakpointData, IBreakpointUpdateData, IConfig, IModel, IViewModel, IRawDebugSession, IBreakpoint, LoadedSourceEvent, IThread, IRawModelUpdate } from 'vs/workbench/parts/debug/common/debug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { ISuggestion } from 'vs/editor/common/modes';
......@@ -16,7 +16,7 @@ export class MockDebugService implements IDebugService {
public _serviceBrand: any;
getSession(sessionId: string): ISession {
getSession(sessionId: string): IDebugSession {
return undefined;
}
......@@ -24,15 +24,15 @@ export class MockDebugService implements IDebugService {
return null;
}
public get onWillNewSession(): Event<ISession> {
public get onWillNewSession(): Event<IDebugSession> {
return null;
}
public get onDidNewSession(): Event<ISession> {
public get onDidNewSession(): Event<IDebugSession> {
return null;
}
public get onDidEndSession(): Event<ISession> {
public get onDidEndSession(): Event<IDebugSession> {
return null;
}
......@@ -47,7 +47,7 @@ export class MockDebugService implements IDebugService {
public focusStackFrame(focusedStackFrame: IStackFrame): void {
}
sendAllBreakpoints(session?: ISession): TPromise<any> {
sendAllBreakpoints(session?: IDebugSession): TPromise<any> {
return TPromise.as(null);
}
......@@ -126,10 +126,10 @@ export class MockDebugService implements IDebugService {
}
}
export class MockSession implements ISession {
export class MockSession implements IDebugSession {
configuration: IConfig = { type: 'mock', request: 'launch' };
raw: IRawSession = new MockRawSession();
raw: IRawDebugSession = new MockRawSession();
state = State.Stopped;
root: IWorkspaceFolder;
......@@ -188,7 +188,11 @@ export class MockSession implements ISession {
dispose(): void { }
}
export class MockRawSession implements IRawSession {
export class MockRawSession implements IRawDebugSession {
capabilities: DebugProtocol.Capabilities;
disconnected: boolean;
sessionLengthInSeconds: number;
public readyForBreakpoints = true;
public emittedStopped = true;
......@@ -219,6 +223,10 @@ export class MockRawSession implements IRawSession {
return TPromise.as(null);
}
public launch(args: DebugProtocol.LaunchRequestArguments): TPromise<DebugProtocol.LaunchResponse> {
return TPromise.as(null);
}
public attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse> {
return TPromise.as(null);
}
......
......@@ -10,7 +10,7 @@ import { SimpleReplElement, Model, Expression, RawObjectReplElement, StackFrame,
import * as sinon from 'sinon';
import { MockRawSession } from 'vs/workbench/parts/debug/test/common/mockDebug';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { Session } from 'vs/workbench/parts/debug/electron-browser/debugSession';
import { DebugSession } from 'vs/workbench/parts/debug/electron-browser/debugSession';
suite('Debug - Model', () => {
let model: Model;
......@@ -109,7 +109,7 @@ suite('Debug - Model', () => {
test('threads simple', () => {
const threadId = 1;
const threadName = 'firstThread';
const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
model.addSession(session);
assert.equal(model.getSessions().length, 1);
......@@ -141,7 +141,7 @@ suite('Debug - Model', () => {
const stoppedReason = 'breakpoint';
// Add the threads
const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
model.addSession(session);
session['_raw'] = <any>rawSession;
......@@ -234,7 +234,7 @@ suite('Debug - Model', () => {
const runningThreadId = 2;
const runningThreadName = 'runningThread';
const stoppedReason = 'breakpoint';
const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
model.addSession(session);
session['_raw'] = <any>rawSession;
......@@ -348,7 +348,7 @@ suite('Debug - Model', () => {
test('repl expressions', () => {
assert.equal(model.getReplElements().length, 0);
const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
model.addSession(session);
session['_raw'] = <any>rawSession;
......@@ -370,7 +370,7 @@ suite('Debug - Model', () => {
});
test('stack frame get specific source name', () => {
const session = new Session({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined, model, undefined, undefined, undefined, undefined);
model.addSession(session);
let firstStackFrame: StackFrame;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册