diff --git a/src/vs/workbench/parts/debug/browser/debugActions.ts b/src/vs/workbench/parts/debug/browser/debugActions.ts index a8285926ec9ed4caa5eec4a83b42b6bc18418454..b46f4ae96843d3c38734c0af40205901a81be594 100644 --- a/src/vs/workbench/parts/debug/browser/debugActions.ts +++ b/src/vs/workbench/parts/debug/browser/debugActions.ts @@ -266,7 +266,7 @@ export class RemoveBreakpointAction extends AbstractDebugAction { } public run(breakpoint: debug.IBreakpoint): Promise { - return breakpoint instanceof model.Breakpoint ? this.debugService.toggleBreakpoint(breakpoint.source.uri, breakpoint.lineNumber) + return breakpoint instanceof model.Breakpoint ? this.debugService.toggleBreakpoint({ uri: breakpoint.source.uri, lineNumber: breakpoint.lineNumber }) : this.debugService.removeFunctionBreakpoints(breakpoint.getId()); } } @@ -281,7 +281,7 @@ export class RemoveAllBreakpointsAction extends AbstractDebugAction { } public run(): Promise { - return Promise.join([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints()]); + return Promise.join([this.debugService.removeAllBreakpoints(), this.debugService.removeFunctionBreakpoints()]); } protected isEnabled(): boolean { @@ -406,7 +406,7 @@ export class ToggleBreakpointAction extends EditorAction { var lineNumber = this.editor.getPosition().lineNumber; var modelUrl = this.editor.getModel().getAssociatedResource(); if (this.debugService.canSetBreakpointsIn(this.editor.getModel(), lineNumber)) { - return this.debugService.toggleBreakpoint(modelUrl, lineNumber); + return this.debugService.toggleBreakpoint({ uri: modelUrl, lineNumber: lineNumber }); } } @@ -451,10 +451,10 @@ export class RunToCursorAction extends EditorAction { var uri = this.editor.getModel().getAssociatedResource(); this.debugService.getActiveSession().addOneTimeListener(debug.SessionEvents.STOPPED, () => { - this.debugService.toggleBreakpoint(uri, lineNumber); + this.debugService.toggleBreakpoint({ uri, lineNumber }); }); - return this.debugService.toggleBreakpoint(uri, lineNumber).then(() => { + return this.debugService.toggleBreakpoint({ uri, lineNumber }).then(() => { return this.debugService.getActiveSession().continue({ threadId: this.debugService.getViewModel().getFocusedThreadId() }).then(response => { return response.success; }); diff --git a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts index c324a3d08372b921d99bbaa927ba9f05c2673e24..1f9d9a0af64af7f44ef09f4f7b2c53f9cea501cf 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorContribution.ts @@ -52,7 +52,7 @@ export class DebugEditorContribution implements editorcommon.IEditorContribution nls.localize('addBreakpoint', "Add Breakpoint"), null, true, - () => this.debugService.toggleBreakpoint(uri, lineNumber) + () => this.debugService.toggleBreakpoint({ uri, lineNumber }) )); } @@ -81,7 +81,7 @@ export class DebugEditorContribution implements editorcommon.IEditorContribution getActionsContext: () => breakpoint }); } else { - this.debugService.toggleBreakpoint(uri, lineNumber); + this.debugService.toggleBreakpoint({ uri, lineNumber }); } })); diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 30570b2e1322e164107ba172b6c1485ba47ec247..50027c9466b129e5504b0eeebc87d9823855b7c0 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -6,7 +6,7 @@ import lifecycle = require('vs/base/common/lifecycle'); import editorcommon = require('vs/editor/common/editorCommon'); import wbext = require('vs/workbench/common/contributions'); -import { IDebugService, ModelEvents, ViewModelEvents, IBreakpoint } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, ModelEvents, ViewModelEvents, IBreakpoint, IRawBreakpoint } from 'vs/workbench/parts/debug/common/debug'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -197,7 +197,7 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { } const model = modelData.model; - const data: { lineNumber: number; enabled: boolean; condition: string }[] = []; + const data: IRawBreakpoint[] = []; const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.source.uri.toString() === modelUrlStr); const enabledAndConditions: { [key: number]: { enabled: boolean, condition: string } } = {}; @@ -208,12 +208,15 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { }; } + const modelUrl = model.getAssociatedResource(); + for (var i = 0, len = modelData.breakpointDecorationIds.length; i < len; i++) { var decorationRange = model.getDecorationRange(modelData.breakpointDecorationIds[i]); // Check if the line got deleted. if (decorationRange.endColumn - decorationRange.startColumn > 0) { // Since we know it is collapsed, it cannot grow to multiple lines data.push({ + uri: modelUrl, lineNumber: decorationRange.startLineNumber, enabled: enabledAndConditions[modelData.breakpointLines[i]].enabled, condition: enabledAndConditions[modelData.breakpointLines[i]].condition @@ -221,7 +224,7 @@ export class DebugEditorModelManager implements wbext.IWorkbenchContribution { } } - this.debugService.setBreakpointsForModel(model.getAssociatedResource(), data); + this.debugService.setBreakpointsForModel(modelUrl, data); } private onModelRemoved(model: editorcommon.IModel): void { diff --git a/src/vs/workbench/parts/debug/browser/debugViewer.ts b/src/vs/workbench/parts/debug/browser/debugViewer.ts index 038ef827bdb4a975be36397c761182315a446f12..5c8c8292796f4bdf822c798ddcb1cce962153f4d 100644 --- a/src/vs/workbench/parts/debug/browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/browser/debugViewer.ts @@ -901,7 +901,7 @@ export class BreakpointsController extends BaseDebugController { const element = tree.getFocus(); if (element instanceof model.Breakpoint) { const bp = element; - this.debugService.toggleBreakpoint(bp.source.uri, bp.lineNumber).done(null, errors.onUnexpectedError); + this.debugService.toggleBreakpoint({ uri: bp.source.uri, lineNumber: bp.lineNumber }).done(null, errors.onUnexpectedError); return true; } else if (element instanceof model.FunctionBreakpoint) { diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index c62d75573c2c250953cca8bfc57774a06fb54570..03b47194b7f1822f2e223da3d075dee7f51a9131 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -67,6 +67,13 @@ export interface IEnablement extends ITreeElement { enabled: boolean; } +export interface IRawBreakpoint { + uri: uri; + lineNumber: number; + enabled: boolean; + condition?: string; +} + export interface IBreakpoint extends IEnablement { source: Source; lineNumber: number; @@ -216,12 +223,12 @@ export interface IDebugService extends ee.IEventEmitter { setFocusedStackFrameAndEvaluate(focusedStackFrame: IStackFrame): void; - setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition: string }[]): Promise; - toggleBreakpoint(modelUri: uri, lineNumber: number, condition?: string): Promise; + setBreakpointsForModel(modelUri: uri, data: IRawBreakpoint[]): Promise; + toggleBreakpoint(IRawBreakpoint): Promise; enableOrDisableAllBreakpoints(enabled: boolean): Promise; toggleEnablement(element: IEnablement): Promise; - removeBreakpoints(modelUri?: uri): Promise; toggleBreakpointsActivated(): Promise; + removeAllBreakpoints(): Promise; sendAllBreakpoints(): Promise; addFunctionBreakpoint(functionName?: string): Promise; diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index f4506116599a9e52d89d92c7371b6a077608315b..baa734af72dd75b6e90fedcad9adf44f5d66dca9 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -258,6 +258,9 @@ export class Breakpoint implements debug.IBreakpoint { private id: string; constructor(public source: Source, public desiredLineNumber: number, public enabled: boolean, public condition: string) { + if (enabled === undefined) { + this.enabled = true; + } this.lineNumber = this.desiredLineNumber; this.id = uuid.generateUuid(); } @@ -361,14 +364,14 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } - public addBreakpoint(modelUri: uri, lineNumber: number, condition: string): void { - this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), lineNumber, true, condition)); + public addBreakpoints(rawData: debug.IRawBreakpoint[]): void { + this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => new Breakpoint(Source.fromUri(rawBp.uri), rawBp.lineNumber, rawBp.enabled, rawBp.condition))); this.breakpointsActivated = true; this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } - public removeBreakpoint(id: string): void { - this.breakpoints = this.breakpoints.filter(bp => bp.getId() !== id); + public removeBreakpoints(toRemove: debug.IBreakpoint[]): void { + this.breakpoints = this.breakpoints.filter(bp => !toRemove.some(toRemove => toRemove.getId() === bp.getId())); this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } @@ -403,19 +406,6 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } - public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition?: string; }[]): void { - this.removeBreakpoints(modelUri); - for (var i = 0, len = data.length; i < len; i++) { - this.breakpoints.push(new Breakpoint(Source.fromUri(modelUri), data[i].lineNumber, data[i].enabled, data[i].condition)); - } - this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); - } - - public removeBreakpoints(modelUri: uri): void { - this.breakpoints = this.breakpoints.filter(bp => modelUri && modelUri.toString() !== bp.source.uri.toString()); - this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); - } - public addFunctionBreakpoint(functionName: string): void { this.functionBreakpoints.push(new FunctionBreakpoint(functionName, true)); this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); @@ -578,12 +568,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { } public clearWatchExpressions(id: string = null): void { - if (id) { - this.watchExpressions = this.watchExpressions.filter(we => we.getId() !== id); - } else { - this.watchExpressions = []; - } - + this.watchExpressions = id ? this.watchExpressions.filter(we => we.getId() !== id) : []; this.emit(debug.ModelEvents.WATCH_EXPRESSIONS_UPDATED); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 37973ff3335b7b87a98eeeb0ed291cea8ffcbbfb..3396f4c205218d9f194cae31ac59f69b059df6d3 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -369,20 +369,23 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } } - public setBreakpointsForModel(modelUri: uri, data: { lineNumber: number; enabled: boolean; condition: string; }[]): Promise { - this.model.setBreakpointsForModel(modelUri, data); + public setBreakpointsForModel(modelUri: uri, rawData: debug.IRawBreakpoint[]): Promise { + this.model.removeBreakpoints( + this.model.getBreakpoints().filter(bp => bp.source.uri.toString() === modelUri.toString())); + this.model.addBreakpoints(rawData); + return this.sendBreakpoints(modelUri); } - public toggleBreakpoint(modelUri: uri, lineNumber: number, condition: string = null): Promise { - const breakpoint = this.model.getBreakpoints().filter(bp => bp.lineNumber === lineNumber && bp.source.uri.toString() === modelUri.toString()).pop(); + public toggleBreakpoint(rawBreakpoint: debug.IRawBreakpoint): Promise { + const breakpoint = this.model.getBreakpoints().filter(bp => bp.lineNumber === rawBreakpoint.lineNumber && bp.source.uri.toString() === rawBreakpoint.uri.toString()).pop(); if (breakpoint) { - this.model.removeBreakpoint(breakpoint.getId()); + this.model.removeBreakpoints([breakpoint]); } else { - this.model.addBreakpoint(modelUri, lineNumber, condition); + this.model.addBreakpoints([rawBreakpoint]); } - return this.sendBreakpoints(modelUri); + return this.sendBreakpoints(rawBreakpoint.uri); } public enableOrDisableAllBreakpoints(enabled: boolean): Promise { @@ -402,9 +405,9 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService return this.sendExceptionBreakpoints(); } - public removeBreakpoints(modelUri: uri = null): Promise { - var urisToClear = modelUri ? [modelUri] : arrays.distinct(this.model.getBreakpoints(), bp => bp.source.uri.toString()).map(bp => bp.source.uri); - this.model.removeBreakpoints(modelUri); + public removeAllBreakpoints(): Promise { + const urisToClear = arrays.distinct(this.model.getBreakpoints(), bp => bp.source.uri.toString()).map(bp => bp.source.uri); + this.model.removeBreakpoints(this.model.getBreakpoints()); return Promise.join(urisToClear.map(uri => this.sendBreakpoints(uri))); } @@ -762,16 +765,8 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService } private onFileChanges(fileChangesEvent: FileChangesEvent): void { - var breakpoints = this.model.getBreakpoints(); - var clearedUris: { [key: string]: boolean } = {}; - for (var i = 0; i < breakpoints.length; i++) { - var uri = breakpoints[i].source.uri; - var uriStr = uri.toString(); - if (!clearedUris[uriStr] && fileChangesEvent.contains(uri, FileChangeType.DELETED)) { - this.removeBreakpoints(uri); - clearedUris[uriStr] = true; - } - } + this.model.removeBreakpoints(this.model.getBreakpoints().filter(bp => + fileChangesEvent.contains(bp.source.uri, FileChangeType.DELETED))); } private store(): void { diff --git a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts index 739b770a0f585669ef7b73515a1ea40df6f321f4..e3ea29f80a6598218509bef70ab627a2bf8c09d1 100644 --- a/src/vs/workbench/parts/debug/test/common/debugModel.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugModel.test.ts @@ -24,20 +24,20 @@ suite('Debug - Model', () => { test('breakpoints simple', () => { var modelUri = uri.file('/myfolder/myfile.js'); - model.setBreakpointsForModel(modelUri, [{ lineNumber: 5, enabled: true }, { lineNumber: 10, enabled: false }]); + model.addBreakpoints([{ uri: modelUri, lineNumber: 5, enabled: true }, { uri: modelUri, lineNumber: 10, enabled: false }]); assert.equal(model.areBreakpointsActivated(), true); assert.equal(model.getBreakpoints().length, 2); - model.removeBreakpoints(modelUri); + model.removeBreakpoints(model.getBreakpoints()); assert.equal(model.getBreakpoints().length, 0); }); test('breakpoints toggling', () => { var modelUri = uri.file('/myfolder/myfile.js'); - model.setBreakpointsForModel(modelUri, [{ lineNumber: 5, enabled: true }, { lineNumber: 10, enabled: false }]); - model.addBreakpoint(modelUri, 12, 'fake condition'); + model.addBreakpoints([{ uri: modelUri, lineNumber: 5, enabled: true }, { uri: modelUri, lineNumber: 10, enabled: false }]); + model.addBreakpoints([{ uri: modelUri, lineNumber: 12, enabled: true, condition: 'fake condition'}]); assert.equal(model.getBreakpoints().length, 3); - model.removeBreakpoint(model.getBreakpoints().pop().getId()); + model.removeBreakpoints([model.getBreakpoints().pop()]); assert.equal(model.getBreakpoints().length, 2); model.toggleBreakpointsActivated(); @@ -49,8 +49,8 @@ suite('Debug - Model', () => { test('breakpoints two files', () => { var modelUri1 = uri.file('/myfolder/my file first.js'); var modelUri2 = uri.file('/secondfolder/second/second file.js') - model.setBreakpointsForModel(modelUri1, [{ lineNumber: 5, enabled: true }, { lineNumber: 10, enabled: false }]); - model.setBreakpointsForModel(modelUri2, [{ lineNumber: 1, enabled: true }, { lineNumber: 2, enabled: true }, { lineNumber: 3, enabled: false }]); + model.addBreakpoints([{ uri: modelUri1, lineNumber: 5, enabled: true }, { uri: modelUri1, lineNumber: 10, enabled: false }]); + model.addBreakpoints([{ uri: modelUri2, lineNumber: 1, enabled: true }, { uri: modelUri2, lineNumber: 2, enabled: true }, { uri: modelUri2, lineNumber: 3, enabled: false }]); assert.equal(model.getBreakpoints().length, 5); var bp = model.getBreakpoints()[0]; @@ -66,7 +66,7 @@ suite('Debug - Model', () => { model.toggleEnablement(bp); assert.equal(bp.enabled, true); - model.removeBreakpoints(modelUri1); + model.removeBreakpoints(model.getBreakpoints().filter(bp => bp.source.uri.toString() === modelUri1.toString())); assert.equal(model.getBreakpoints().length, 3); });