提交 b42cf8c2 编写于 作者: I isidor

debug: move notion of session from debug service

上级 f4fa5cc6
...@@ -31,6 +31,7 @@ export const DEBUG_SCHEME = 'debug'; ...@@ -31,6 +31,7 @@ export const DEBUG_SCHEME = 'debug';
export interface IRawModelUpdate { export interface IRawModelUpdate {
threadId: number; threadId: number;
sessionId: string;
thread?: DebugProtocol.Thread; thread?: DebugProtocol.Thread;
callStack?: DebugProtocol.StackFrame[]; callStack?: DebugProtocol.StackFrame[];
stoppedDetails?: IRawStoppedDetails; stoppedDetails?: IRawStoppedDetails;
...@@ -64,6 +65,12 @@ export interface IExpression extends ITreeElement, IExpressionContainer { ...@@ -64,6 +65,12 @@ export interface IExpression extends ITreeElement, IExpressionContainer {
} }
export interface IThread extends ITreeElement { export interface IThread extends ITreeElement {
/**
* Id of the debug session the thread belongs to
*/
sessionId: string;
/** /**
* Id of the thread generated by the debug adapter backend. * Id of the thread generated by the debug adapter backend.
*/ */
...@@ -159,6 +166,7 @@ export interface IExceptionBreakpoint extends IEnablement { ...@@ -159,6 +166,7 @@ export interface IExceptionBreakpoint extends IEnablement {
// model interfaces // model interfaces
export interface IViewModel extends ITreeElement { export interface IViewModel extends ITreeElement {
activeSession: IRawDebugSession;
getFocusedStackFrame(): IStackFrame; getFocusedStackFrame(): IStackFrame;
getSelectedExpression(): IExpression; getSelectedExpression(): IExpression;
getFocusedThreadId(): number; getFocusedThreadId(): number;
......
...@@ -89,7 +89,7 @@ export class Thread implements debug.IThread { ...@@ -89,7 +89,7 @@ export class Thread implements debug.IThread {
public stoppedDetails: debug.IRawStoppedDetails; public stoppedDetails: debug.IRawStoppedDetails;
public stopped: boolean; public stopped: boolean;
constructor(public name: string, public threadId: number) { constructor(public sessionId: string, public name: string, public threadId: number) {
this.promisedCallStack = undefined; this.promisedCallStack = undefined;
this.stoppedDetails = undefined; this.stoppedDetails = undefined;
this.cachedCallStack = undefined; this.cachedCallStack = undefined;
...@@ -97,7 +97,7 @@ export class Thread implements debug.IThread { ...@@ -97,7 +97,7 @@ export class Thread implements debug.IThread {
} }
public getId(): string { public getId(): string {
return `thread:${this.name}:${this.threadId}`; return `thread:${this.sessionId}:${this.name}:${this.threadId}`;
} }
public clearCallStack(): void { public clearCallStack(): void {
...@@ -255,30 +255,31 @@ export abstract class ExpressionContainer implements debug.IExpressionContainer ...@@ -255,30 +255,31 @@ export abstract class ExpressionContainer implements debug.IExpressionContainer
} else { } else {
// Check if object has named variables, fetch them independent from indexed variables #9670 // Check if object has named variables, fetch them independent from indexed variables #9670
this.children = (!!this.namedVariables ? this.fetchVariables(session, undefined, undefined, 'named') : TPromise.as([])).then(childrenArray => { this.children = (!!this.namedVariables ? this.fetchVariables(session, undefined, undefined, 'named')
// Use a dynamic chunk size based on the number of elements #9774 : TPromise.as([])).then(childrenArray => {
let chunkSize = ExpressionContainer.BASE_CHUNK_SIZE; // Use a dynamic chunk size based on the number of elements #9774
while (this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) { let chunkSize = ExpressionContainer.BASE_CHUNK_SIZE;
chunkSize *= ExpressionContainer.BASE_CHUNK_SIZE; while (this.indexedVariables > chunkSize * ExpressionContainer.BASE_CHUNK_SIZE) {
} chunkSize *= ExpressionContainer.BASE_CHUNK_SIZE;
if (this.indexedVariables > chunkSize) {
// There are a lot of children, create fake intermediate values that represent chunks #9537
const numberOfChunks = Math.ceil(this.indexedVariables / chunkSize);
for (let i = 0; i < numberOfChunks; i++) {
const start = this.startOfVariables + i * chunkSize;
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
childrenArray.push(new Variable(this, this.reference, `[${start}..${start + count - 1}]`, '', null, count, null, true, start));
} }
return childrenArray; if (this.indexedVariables > chunkSize) {
} // There are a lot of children, create fake intermediate values that represent chunks #9537
const numberOfChunks = Math.ceil(this.indexedVariables / chunkSize);
for (let i = 0; i < numberOfChunks; i++) {
const start = this.startOfVariables + i * chunkSize;
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
childrenArray.push(new Variable(this, this.reference, `[${start}..${start + count - 1}]`, '', null, count, null, true, start));
}
const start = this.getChildrenInChunks ? this.startOfVariables : undefined; return childrenArray;
const count = this.getChildrenInChunks ? this.indexedVariables : undefined; }
return this.fetchVariables(session, start, count, 'indexed')
.then(variables => arrays.distinct(childrenArray.concat(variables), child => child.name)); const start = this.getChildrenInChunks ? this.startOfVariables : undefined;
}); const count = this.getChildrenInChunks ? this.indexedVariables : undefined;
return this.fetchVariables(session, start, count, 'indexed')
.then(variables => arrays.distinct(childrenArray.concat(variables), child => child.name));
});
} }
} }
...@@ -455,8 +456,13 @@ export class ExceptionBreakpoint implements debug.IExceptionBreakpoint { ...@@ -455,8 +456,13 @@ export class ExceptionBreakpoint implements debug.IExceptionBreakpoint {
} }
} }
class DebugSession {
constructor(public id: string, public raw: debug.IRawDebugSession, public threads: { [reference: number]: debug.IThread; }) { }
}
export class Model implements debug.IModel { export class Model implements debug.IModel {
private sessions: DebugSession[];
private threads: { [reference: number]: debug.IThread; }; private threads: { [reference: number]: debug.IThread; };
private toDispose: lifecycle.IDisposable[]; private toDispose: lifecycle.IDisposable[];
private replElements: debug.ITreeElement[]; private replElements: debug.ITreeElement[];
...@@ -472,9 +478,10 @@ export class Model implements debug.IModel { ...@@ -472,9 +478,10 @@ export class Model implements debug.IModel {
private exceptionBreakpoints: debug.IExceptionBreakpoint[], private exceptionBreakpoints: debug.IExceptionBreakpoint[],
private watchExpressions: Expression[] private watchExpressions: Expression[]
) { ) {
this.threads = {}; this.sessions = [];
this.replElements = []; this.replElements = [];
this.toDispose = []; this.toDispose = [];
this.threads = {};
this._onDidChangeBreakpoints = new Emitter<void>(); this._onDidChangeBreakpoints = new Emitter<void>();
this._onDidChangeCallStack = new Emitter<void>(); this._onDidChangeCallStack = new Emitter<void>();
this._onDidChangeWatchExpressions = new Emitter<debug.IExpression>(); this._onDidChangeWatchExpressions = new Emitter<debug.IExpression>();
...@@ -485,6 +492,15 @@ export class Model implements debug.IModel { ...@@ -485,6 +492,15 @@ export class Model implements debug.IModel {
return 'root'; return 'root';
} }
public getSession(id: string): debug.IRawDebugSession {
return this.sessions.filter(s => s.id === id).map(s => s.raw).pop();
}
public removeSession(id: string): void {
this.sessions = this.sessions.filter(s => s.id !== id);
this._onDidChangeCallStack.fire();
}
public get onDidChangeBreakpoints(): Event<void> { public get onDidChangeBreakpoints(): Event<void> {
return this._onDidChangeBreakpoints.event; return this._onDidChangeBreakpoints.event;
} }
...@@ -787,7 +803,7 @@ export class Model implements debug.IModel { ...@@ -787,7 +803,7 @@ export class Model implements debug.IModel {
public rawUpdate(data: debug.IRawModelUpdate): void { public rawUpdate(data: debug.IRawModelUpdate): void {
if (data.thread && !this.threads[data.threadId]) { if (data.thread && !this.threads[data.threadId]) {
// A new thread came in, initialize it. // A new thread came in, initialize it.
this.threads[data.threadId] = new Thread(data.thread.name, data.thread.id); this.threads[data.threadId] = new Thread(data.sessionId, data.thread.name, data.thread.id);
} }
if (data.stoppedDetails) { if (data.stoppedDetails) {
......
...@@ -12,6 +12,7 @@ export class ViewModel implements debug.IViewModel { ...@@ -12,6 +12,7 @@ export class ViewModel implements debug.IViewModel {
private focusedThread: debug.IThread; private focusedThread: debug.IThread;
private selectedExpression: debug.IExpression; private selectedExpression: debug.IExpression;
private selectedFunctionBreakpoint: debug.IFunctionBreakpoint; private selectedFunctionBreakpoint: debug.IFunctionBreakpoint;
private _activeSession: debug.IRawDebugSession;
private _onDidFocusStackFrame: Emitter<debug.IStackFrame>; private _onDidFocusStackFrame: Emitter<debug.IStackFrame>;
private _onDidSelectExpression: Emitter<debug.IExpression>; private _onDidSelectExpression: Emitter<debug.IExpression>;
private _onDidSelectFunctionBreakpoint: Emitter<debug.IFunctionBreakpoint>; private _onDidSelectFunctionBreakpoint: Emitter<debug.IFunctionBreakpoint>;
...@@ -28,13 +29,18 @@ export class ViewModel implements debug.IViewModel { ...@@ -28,13 +29,18 @@ export class ViewModel implements debug.IViewModel {
return 'root'; return 'root';
} }
public get activeSession(): debug.IRawDebugSession {
return this._activeSession;
}
public getFocusedStackFrame(): debug.IStackFrame { public getFocusedStackFrame(): debug.IStackFrame {
return this.focusedStackFrame; return this.focusedStackFrame;
} }
public setFocusedStackFrame(focusedStackFrame: debug.IStackFrame, focusedThread: debug.IThread): void { public setFocusedStackFrame(focusedStackFrame: debug.IStackFrame, focusedThread: debug.IThread, activeSession: debug.IRawDebugSession): void {
this.focusedStackFrame = focusedStackFrame; this.focusedStackFrame = focusedStackFrame;
this.focusedThread = focusedThread; this.focusedThread = focusedThread;
this._activeSession = activeSession;
this._onDidFocusStackFrame.fire(focusedStackFrame); this._onDidFocusStackFrame.fire(focusedStackFrame);
} }
......
...@@ -154,7 +154,7 @@ export class DebugService implements debug.IDebugService { ...@@ -154,7 +154,7 @@ export class DebugService implements debug.IDebugService {
} }
if (broadcast.channel === EXTENSION_TERMINATE_BROADCAST_CHANNEL) { if (broadcast.channel === EXTENSION_TERMINATE_BROADCAST_CHANNEL) {
this.onSessionEnd(); this.onSessionEnd(this.session);
return; return;
} }
...@@ -259,8 +259,9 @@ export class DebugService implements debug.IDebugService { ...@@ -259,8 +259,9 @@ export class DebugService implements debug.IDebugService {
this.setStateAndEmit(debug.State.Stopped); this.setStateAndEmit(debug.State.Stopped);
const threadId = event.body.threadId; const threadId = event.body.threadId;
this.getThreadData().done(() => { this.getThreadData(session).done(() => {
this.model.rawUpdate({ this.model.rawUpdate({
sessionId: session.getId(),
threadId, threadId,
stoppedDetails: event.body, stoppedDetails: event.body,
allThreadsStopped: event.body.allThreadsStopped allThreadsStopped: event.body.allThreadsStopped
...@@ -285,7 +286,7 @@ export class DebugService implements debug.IDebugService { ...@@ -285,7 +286,7 @@ export class DebugService implements debug.IDebugService {
this.toDisposeOnSessionEnd.push(session.onDidThread(event => { this.toDisposeOnSessionEnd.push(session.onDidThread(event => {
if (event.body.reason === 'started') { if (event.body.reason === 'started') {
this.getThreadData().done(null, errors.onUnexpectedError); this.getThreadData(session).done(null, errors.onUnexpectedError);
} else if (event.body.reason === 'exited') { } else if (event.body.reason === 'exited') {
this.model.clearThreads(true, event.body.threadId); this.model.clearThreads(true, event.body.threadId);
} }
...@@ -337,7 +338,7 @@ export class DebugService implements debug.IDebugService { ...@@ -337,7 +338,7 @@ export class DebugService implements debug.IDebugService {
ipc.send('vscode:closeExtensionHostWindow', this.contextService.getWorkspace().resource.fsPath); ipc.send('vscode:closeExtensionHostWindow', this.contextService.getWorkspace().resource.fsPath);
} }
if (session && session.getId() === event.body.sessionId) { if (session && session.getId() === event.body.sessionId) {
this.onSessionEnd(); this.onSessionEnd(session);
} }
})); }));
} }
...@@ -347,10 +348,10 @@ export class DebugService implements debug.IDebugService { ...@@ -347,10 +348,10 @@ export class DebugService implements debug.IDebugService {
this.appendReplOutput(event.body.output, outputSeverity); this.appendReplOutput(event.body.output, outputSeverity);
} }
private getThreadData(): TPromise<void> { private getThreadData(session: RawDebugSession): TPromise<void> {
return this.session.threads().then(response => { return session.threads().then(response => {
if (response && response.body && response.body.threads) { if (response && response.body && response.body.threads) {
response.body.threads.forEach(thread => this.model.rawUpdate({ threadId: thread.id, thread })); response.body.threads.forEach(thread => this.model.rawUpdate({ sessionId: session.getId(), threadId: thread.id, thread }));
} }
}); });
} }
...@@ -421,8 +422,9 @@ export class DebugService implements debug.IDebugService { ...@@ -421,8 +422,9 @@ export class DebugService implements debug.IDebugService {
if (!thread && focusedStackFrame) { if (!thread && focusedStackFrame) {
thread = this.model.getThreads()[focusedStackFrame.threadId]; thread = this.model.getThreads()[focusedStackFrame.threadId];
} }
const session = this.model.getSession(thread.sessionId);
this.viewModel.setFocusedStackFrame(focusedStackFrame, thread); this.viewModel.setFocusedStackFrame(focusedStackFrame, thread, session);
if (focusedStackFrame) { if (focusedStackFrame) {
return this.model.evaluateWatchExpressions(this.session, focusedStackFrame); return this.model.evaluateWatchExpressions(this.session, focusedStackFrame);
} else { } else {
...@@ -628,10 +630,11 @@ export class DebugService implements debug.IDebugService { ...@@ -628,10 +630,11 @@ export class DebugService implements debug.IDebugService {
this.customTelemetryService = new TelemetryService({ appender }, this.configurationService); this.customTelemetryService = new TelemetryService({ appender }, this.configurationService);
} }
this.session = this.instantiationService.createInstance(RawDebugSession, configuration.debugServer, this.configurationManager.adapter, this.customTelemetryService); const session = this.instantiationService.createInstance(RawDebugSession, configuration.debugServer, this.configurationManager.adapter, this.customTelemetryService);
this.registerSessionListeners(this.session); this.session = session;
this.registerSessionListeners(session);
return this.session.initialize({ return session.initialize({
adapterID: configuration.type, adapterID: configuration.type,
pathFormat: 'path', pathFormat: 'path',
linesStartAt1: true, linesStartAt1: true,
...@@ -644,8 +647,8 @@ export class DebugService implements debug.IDebugService { ...@@ -644,8 +647,8 @@ export class DebugService implements debug.IDebugService {
return TPromise.wrapError(new Error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly"))); return TPromise.wrapError(new Error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly")));
} }
this.model.setExceptionBreakpoints(this.session.configuration.capabilities.exceptionBreakpointFilters); this.model.setExceptionBreakpoints(session.configuration.capabilities.exceptionBreakpointFilters);
return configuration.request === 'attach' ? this.session.attach(configuration) : this.session.launch(configuration); return configuration.request === 'attach' ? session.attach(configuration) : session.launch(configuration);
}).then((result: DebugProtocol.Response) => { }).then((result: DebugProtocol.Response) => {
if (!this.session) { if (!this.session) {
return TPromise.as(null); return TPromise.as(null);
...@@ -775,13 +778,13 @@ export class DebugService implements debug.IDebugService { ...@@ -775,13 +778,13 @@ export class DebugService implements debug.IDebugService {
return this.session; return this.session;
} }
private onSessionEnd(): void { private onSessionEnd(session: RawDebugSession): void {
if (this.session) { if (session) {
const bpsExist = this.model.getBreakpoints().length > 0; const bpsExist = this.model.getBreakpoints().length > 0;
this.telemetryService.publicLog('debugSessionStop', { this.telemetryService.publicLog('debugSessionStop', {
type: this.session.configuration.type, type: session.configuration.type,
success: this.session.emittedStopped || !bpsExist, success: session.emittedStopped || !bpsExist,
sessionLengthInSeconds: this.session.getLengthInSeconds(), sessionLengthInSeconds: session.getLengthInSeconds(),
breakpointCount: this.model.getBreakpoints().length, breakpointCount: this.model.getBreakpoints().length,
watchExpressionsCount: this.model.getWatchExpressions().length watchExpressionsCount: this.model.getWatchExpressions().length
}); });
......
...@@ -22,7 +22,7 @@ suite('Debug - View Model', () => { ...@@ -22,7 +22,7 @@ suite('Debug - View Model', () => {
assert.equal(model.getFocusedStackFrame(), null); assert.equal(model.getFocusedStackFrame(), null);
assert.equal(model.getFocusedThreadId(), 0); assert.equal(model.getFocusedThreadId(), 0);
const frame = new StackFrame(1, 1, null, 'app.js', 1, 1); const frame = new StackFrame(1, 1, null, 'app.js', 1, 1);
model.setFocusedStackFrame(frame, new Thread('myThread', 1)); model.setFocusedStackFrame(frame, new Thread('sessionid', 'myThread', 1), null);
assert.equal(model.getFocusedStackFrame(), frame); assert.equal(model.getFocusedStackFrame(), frame);
assert.equal(model.getFocusedThreadId(), 1); assert.equal(model.getFocusedThreadId(), 1);
......
...@@ -79,6 +79,7 @@ suite('Debug - Model', () => { ...@@ -79,6 +79,7 @@ suite('Debug - Model', () => {
var threadId = 1; var threadId = 1;
var threadName = 'firstThread'; var threadName = 'firstThread';
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: threadId, threadId: threadId,
thread: { thread: {
id: threadId, id: threadId,
...@@ -105,6 +106,7 @@ suite('Debug - Model', () => { ...@@ -105,6 +106,7 @@ suite('Debug - Model', () => {
// Add the threads // Add the threads
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: threadId1, threadId: threadId1,
thread: { thread: {
id: threadId1, id: threadId1,
...@@ -113,6 +115,7 @@ suite('Debug - Model', () => { ...@@ -113,6 +115,7 @@ suite('Debug - Model', () => {
}); });
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: threadId2, threadId: threadId2,
thread: { thread: {
id: threadId2, id: threadId2,
...@@ -122,6 +125,7 @@ suite('Debug - Model', () => { ...@@ -122,6 +125,7 @@ suite('Debug - Model', () => {
// Stopped event with all threads stopped // Stopped event with all threads stopped
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: threadId1, threadId: threadId1,
stoppedDetails: { stoppedDetails: {
reason: stoppedReason, reason: stoppedReason,
...@@ -191,6 +195,7 @@ suite('Debug - Model', () => { ...@@ -191,6 +195,7 @@ suite('Debug - Model', () => {
// Add the threads // Add the threads
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: stoppedThreadId, threadId: stoppedThreadId,
thread: { thread: {
id: stoppedThreadId, id: stoppedThreadId,
...@@ -199,6 +204,7 @@ suite('Debug - Model', () => { ...@@ -199,6 +204,7 @@ suite('Debug - Model', () => {
}); });
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: runningThreadId, threadId: runningThreadId,
thread: { thread: {
id: runningThreadId, id: runningThreadId,
...@@ -208,6 +214,7 @@ suite('Debug - Model', () => { ...@@ -208,6 +214,7 @@ suite('Debug - Model', () => {
// Stopped event with only one thread stopped // Stopped event with only one thread stopped
model.rawUpdate({ model.rawUpdate({
sessionId: 'sessionid',
threadId: stoppedThreadId, threadId: stoppedThreadId,
stoppedDetails: { stoppedDetails: {
reason: stoppedReason, reason: stoppedReason,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册