提交 b42cf8c2 编写于 作者: I isidor

debug: move notion of session from debug service

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