提交 f5c3d817 编写于 作者: I isidor

debug: rawDebugSession is no longer an event emitter

上级 9cef05a1
......@@ -7,7 +7,6 @@ import uri from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IActionRunner } from 'vs/base/common/actions';
import Event from 'vs/base/common/event';
import ee = require('vs/base/common/eventEmitter');
import severity from 'vs/base/common/severity';
import { IViewletView } from 'vs/workbench/browser/viewlet';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
......@@ -144,17 +143,6 @@ export interface IExceptionBreakpoint extends IEnablement {
label: string;
}
export var SessionEvents = {
INITIALIZED: 'initialized',
STOPPED: 'stopped',
DEBUGEE_TERMINATED: 'terminated',
SERVER_EXIT: 'exit',
CONTINUED: 'continued',
THREAD: 'thread',
OUTPUT: 'output',
BREAKPOINT: 'breakpoint'
};
// model interfaces
export interface IViewModel extends ITreeElement {
......@@ -246,7 +234,7 @@ export interface IRawAdapter extends IRawEnvAdapter {
linux?: IRawEnvAdapter;
}
export interface IRawDebugSession extends ee.EventEmitter {
export interface IRawDebugSession {
configuration: { type: string, isAttach: boolean, capabilities: DebugProtocol.Capabilites };
disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse>;
......@@ -261,6 +249,11 @@ export interface IRawDebugSession extends ee.EventEmitter {
scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
/**
* Allows to register on each debug session stop event.
*/
onDidStop: Event<DebugProtocol.StoppedEvent>;
}
export interface IConfigurationManager {
......
......@@ -535,10 +535,11 @@ export class RunToCursorAction extends EditorAction {
const lineNumber = this.editor.getPosition().lineNumber;
const uri = this.editor.getModel().getAssociatedResource();
this.debugService.getActiveSession().addOneTimeListener(debug.SessionEvents.STOPPED, () => {
const oneTimeListener = this.debugService.getActiveSession().onDidStop(() => {
const toRemove = this.debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === lineNumber && bp.source.uri.toString() === uri.toString()).pop();
this.debugService.removeBreakpoints(toRemove.getId());
oneTimeListener.dispose();
});
return this.debugService.addBreakpoints([{ uri, lineNumber }]).then(() => {
......
......@@ -228,7 +228,7 @@ export class DebugService implements debug.IDebugService {
private registerSessionListeners(): void {
this.toDisposeOnSessionEnd.push(this.session);
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.INITIALIZED, (event: DebugProtocol.InitializedEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidInitialize(event => {
aria.status(nls.localize('debuggingStarted', "Debugging started."));
this.sendAllBreakpoints().then(() => {
if (this.session.configuration.capabilities.supportsConfigurationDoneRequest) {
......@@ -237,7 +237,7 @@ export class DebugService implements debug.IDebugService {
});
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.STOPPED, (event: DebugProtocol.StoppedEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidStop(event => {
this.setStateAndEmit(debug.State.Stopped);
const threadId = event.body.threadId;
......@@ -266,14 +266,14 @@ export class DebugService implements debug.IDebugService {
}, errors.onUnexpectedError);
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.CONTINUED, () => {
this.toDisposeOnSessionEnd.push(this.session.onDidContinue(() => {
aria.status(nls.localize('debuggingContinued', "Debugging continued."));
this.model.continueThreads();
this.setFocusedStackFrameAndEvaluate(null).done(null, errors.onUnexpectedError);
this.setStateAndEmit(this.configurationManager.configuration.noDebug ? debug.State.RunningNoDebug : debug.State.Running);
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.THREAD, (event: DebugProtocol.ThreadEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidThread(event => {
if (event.body.reason === 'started') {
this.session.threads().done((result) => {
const thread = result.body.threads.filter(thread => thread.id === event.body.threadId).pop();
......@@ -289,7 +289,7 @@ export class DebugService implements debug.IDebugService {
}
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.DEBUGEE_TERMINATED, (event: DebugProtocol.TerminatedEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidTerminateDebugee(event => {
aria.status(nls.localize('debuggingStopped', "Debugging stopped."));
if (this.session && this.session.getId() === (<any>event).sessionId) {
if (event.body && typeof event.body.restart === 'boolean' && event.body.restart) {
......@@ -300,7 +300,7 @@ export class DebugService implements debug.IDebugService {
}
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.OUTPUT, (event: DebugProtocol.OutputEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidOutput(event => {
if (event.body && event.body.category === 'telemetry') {
// only log telemetry events from debug adapter if the adapter provided the telemetry key
if (this.telemetryAdapter) {
......@@ -311,7 +311,7 @@ export class DebugService implements debug.IDebugService {
}
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.BREAKPOINT, (event: DebugProtocol.BreakpointEvent) => {
this.toDisposeOnSessionEnd.push(this.session.onDidBreakpoint(event => {
const id = event.body && event.body.breakpoint ? event.body.breakpoint.id : undefined;
const breakpoint = this.model.getBreakpoints().filter(bp => bp.idFromAdapter === id).pop();
if (breakpoint) {
......@@ -324,12 +324,12 @@ export class DebugService implements debug.IDebugService {
}
}));
this.toDisposeOnSessionEnd.push(this.session.addListener2(debug.SessionEvents.SERVER_EXIT, event => {
this.toDisposeOnSessionEnd.push(this.session.onDidExitAdapter(event => {
// 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905
if (this.session.configuration.type === 'extensionHost' && this._state === debug.State.RunningNoDebug) {
ipc.send('vscode:closeExtensionHostWindow', this.contextService.getWorkspace().resource.fsPath);
}
if (this.session && this.session.getId() === event.sessionId) {
if (this.session && this.session.getId() === (<any>event.body).sessionId) {
this.onSessionEnd();
}
}));
......
......@@ -7,6 +7,7 @@ import nls = require('vs/nls');
import cp = require('child_process');
import fs = require('fs');
import net = require('net');
import Event, { Emitter } from 'vs/base/common/event';
import platform = require('vs/base/common/platform');
import { Action } from 'vs/base/common/actions';
import errors = require('vs/base/common/errors');
......@@ -24,6 +25,9 @@ import { shell } from 'electron';
export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSession {
public restarted: boolean;
public emittedStopped: boolean;
public readyForBreakpoints: boolean;
private flowEventsCount: number;
private serverProcess: cp.ChildProcess;
private socket: net.Socket = null;
......@@ -34,6 +38,15 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
private isAttach: boolean;
private capabilities: DebugProtocol.Capabilites;
private _onDidInitialize: Emitter<DebugProtocol.InitializedEvent>;
private _onDidStop: Emitter<DebugProtocol.StoppedEvent>;
private _onDidTerminateDebugee: Emitter<DebugProtocol.TerminatedEvent>;
private _onDidExitAdapter: Emitter<DebugProtocol.ExitedEvent>;
private _onDidContinue: Emitter<void>;
private _onDidThread: Emitter<DebugProtocol.ThreadEvent>;
private _onDidOutput: Emitter<DebugProtocol.OutputEvent>;
private _onDidBreakpoint: Emitter<DebugProtocol.BreakpointEvent>;
constructor(
private messageService: IMessageService,
private telemetryService: ITelemetryService,
......@@ -42,7 +55,51 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
private telemtryAdapter: AIAdapter
) {
super();
this.flowEventsCount = 0;
this.emittedStopped = false;
this.readyForBreakpoints = false;
this.sentPromises = [];
this._onDidInitialize = new Emitter<DebugProtocol.InitializedEvent>();
this._onDidStop = new Emitter<DebugProtocol.StoppedEvent>();
this._onDidTerminateDebugee = new Emitter<DebugProtocol.TerminatedEvent>();
this._onDidExitAdapter = new Emitter<DebugProtocol.ExitedEvent>();
this._onDidContinue = new Emitter<void>();
this._onDidThread = new Emitter<DebugProtocol.ThreadEvent>();
this._onDidOutput = new Emitter<DebugProtocol.OutputEvent>();
this._onDidBreakpoint = new Emitter<DebugProtocol.BreakpointEvent>();
}
public get onDidInitialize(): Event<DebugProtocol.InitializedEvent> {
return this._onDidInitialize.event;
}
public get onDidStop(): Event<DebugProtocol.StoppedEvent> {
return this._onDidStop.event;
}
public get onDidTerminateDebugee(): Event<DebugProtocol.TerminatedEvent> {
return this._onDidTerminateDebugee.event;
}
public get onDidExitAdapter(): Event<DebugProtocol.ExitedEvent> {
return this._onDidExitAdapter.event;
}
public get onDidContinue(): Event<void> {
return this._onDidContinue.event;
}
public get onDidThread(): Event<DebugProtocol.ThreadEvent> {
return this._onDidThread.event;
}
public get onDidOutput(): Event<DebugProtocol.OutputEvent> {
return this._onDidOutput.event;
}
public get onDidBreakpoint(): Event<DebugProtocol.BreakpointEvent> {
return this._onDidBreakpoint.event;
}
private initServer(): TPromise<void> {
......@@ -88,6 +145,38 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
});
}
protected onEvent(event: DebugProtocol.Event): void {
if (event.body) {
event.body.sessionId = this.getId();
} else {
event.body = { sessionId: this.getId() };
}
if (event.event === 'initialized') {
this.readyForBreakpoints = true;
this._onDidInitialize.fire(event);
} else if (event.event === 'stopped') {
this.emittedStopped = true;
this.flowEventsCount++;
this._onDidStop.fire(<DebugProtocol.StoppedEvent>event);
} else if (event.event === 'thread') {
this._onDidThread.fire(<DebugProtocol.ThreadEvent>event);
} else if (event.event === 'output') {
this._onDidOutput.fire(<DebugProtocol.OutputEvent>event);
} else if (event.event === 'breakpoint') {
this._onDidBreakpoint.fire(<DebugProtocol.BreakpointEvent>event);
} else if (event.event === 'terminated') {
this.flowEventsCount++;
this._onDidTerminateDebugee.fire(event);
} else if (event.event === 'exit') {
this.flowEventsCount++;
this._onDidExitAdapter.fire(<DebugProtocol.ExitedEvent>event);
} else if (event.event === 'continued') {
this.flowEventsCount++;
this._onDidContinue.fire();
}
}
public get configuration(): { type: string, isAttach: boolean, capabilities: DebugProtocol.Capabilites } {
return {
type: this.adapter.type,
......@@ -105,39 +194,39 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
public launch(args: DebugProtocol.LaunchRequestArguments): TPromise<DebugProtocol.LaunchResponse> {
this.isAttach = false;
return this.sendAndLazyEmit('launch', args);
return this.sendAndLazyContinue('launch', args);
}
public attach(args: DebugProtocol.AttachRequestArguments): TPromise<DebugProtocol.AttachResponse> {
this.isAttach = true;
return this.sendAndLazyEmit('attach', args);
return this.sendAndLazyContinue('attach', args);
}
public next(args: DebugProtocol.NextArguments): TPromise<DebugProtocol.NextResponse> {
return this.sendAndLazyEmit('next', args);
return this.sendAndLazyContinue('next', args);
}
public stepIn(args: DebugProtocol.StepInArguments): TPromise<DebugProtocol.StepInResponse> {
return this.sendAndLazyEmit('stepIn', args);
return this.sendAndLazyContinue('stepIn', args);
}
public stepOut(args: DebugProtocol.StepOutArguments): TPromise<DebugProtocol.StepOutResponse> {
return this.sendAndLazyEmit('stepOut', args);
return this.sendAndLazyContinue('stepOut', args);
}
public continue(args: DebugProtocol.ContinueArguments): TPromise<DebugProtocol.ContinueResponse> {
return this.sendAndLazyEmit('continue', args);
return this.sendAndLazyContinue('continue', args);
}
// node sometimes sends "stopped" events earlier than the response for the "step" request.
// due to this we only emit "continued" if we did not miss a stopped event.
// we do not emit straight away to reduce viewlet flickering.
private sendAndLazyEmit(command: string, args: any, eventType = debug.SessionEvents.CONTINUED): TPromise<DebugProtocol.Response> {
private sendAndLazyContinue(command: string, args: any): TPromise<DebugProtocol.Response> {
const count = this.flowEventsCount;
return this.send(command, args).then(response => {
setTimeout(() => {
if (this.flowEventsCount === count) {
this.emit(eventType);
this.onEvent({ event: 'continued', type: 'event', seq: 0 });
}
}, 500);
......@@ -277,7 +366,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
if (this.socket !== null) {
this.socket.end();
this.cachedInitServer = null;
this.emit(debug.SessionEvents.SERVER_EXIT);
this.onEvent({ event: 'exit', type: 'event', seq: 0 });
}
if (!this.serverProcess) {
......@@ -343,7 +432,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
if (!this.stopServerPending) {
this.messageService.show(severity.Error, nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly"));
}
this.emit(debug.SessionEvents.SERVER_EXIT);
this.onEvent({ event: 'exit', type: 'event', seq: 0 });
}
public dispose(): void {
......
......@@ -5,15 +5,10 @@
import stream = require('stream');
import uuid = require('vs/base/common/uuid');
import ee = require('vs/base/common/eventEmitter');
import { TPromise } from 'vs/base/common/winjs.base';
import debug = require('vs/workbench/parts/debug/common/debug');
export abstract class V8Protocol extends ee.EventEmitter {
export abstract class V8Protocol {
public emittedStopped: boolean;
public readyForBreakpoints: boolean;
protected flowEventsCount: number;
private static TWO_CRLF = '\r\n\r\n';
private outputStream: stream.Writable;
......@@ -24,10 +19,6 @@ export abstract class V8Protocol extends ee.EventEmitter {
private contentLength: number;
constructor() {
super();
this.flowEventsCount = 0;
this.emittedStopped = false;
this.readyForBreakpoints = false;
this.sequence = 1;
this.contentLength = -1;
this.pendingRequests = {};
......@@ -35,27 +26,6 @@ export abstract class V8Protocol extends ee.EventEmitter {
this.id = uuid.generateUuid();
}
public emit(eventType: string, data?: any): void {
if (eventType === debug.SessionEvents.STOPPED) {
this.emittedStopped = true;
}
if (eventType === debug.SessionEvents.INITIALIZED) {
this.readyForBreakpoints = true;
}
if (eventType === debug.SessionEvents.CONTINUED || eventType === debug.SessionEvents.STOPPED ||
eventType === debug.SessionEvents.DEBUGEE_TERMINATED || eventType === debug.SessionEvents.SERVER_EXIT) {
this.flowEventsCount++;
}
if (data) {
data.sessionId = this.getId();
} else {
data = { sessionId: this.getId() };
}
super.emit(eventType, data);
}
public getId(): string {
return this.id;
}
......@@ -132,13 +102,13 @@ export abstract class V8Protocol extends ee.EventEmitter {
}
protected abstract onServerError(err: Error): void;
protected abstract onEvent(event: DebugProtocol.Event): void;
private dispatch(body: string): void {
try {
const rawData = JSON.parse(body);
if (typeof rawData.event !== 'undefined') {
const event = <DebugProtocol.Event> rawData;
this.emit(event.event, event);
this.onEvent(rawData);
} else {
const response = <DebugProtocol.Response> rawData;
const clb = this.pendingRequests[response.request_seq];
......
......@@ -119,6 +119,10 @@ class MockRawSession extends ee.EventEmitter implements debug.IRawDebugSession {
};
}
public get onDidStop(): Event<DebugProtocol.StoppedEvent> {
return null;
}
public disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse> {
return TPromise.as(null);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册