diff --git a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts index 3d9510afb956773d3ac3c51c0d2014a57dfee4c2..c6237974b7a15c911f383484d4c3f98d3ff6bc3d 100644 --- a/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts +++ b/src/vs/workbench/parts/debug/browser/debugEditorModelManager.ts @@ -200,11 +200,12 @@ export class DebugEditorModelManager implements IWorkbenchContribution { const data: IRawBreakpoint[] = []; - const enabledAndConditions: { [key: number]: { enabled: boolean, condition: string } } = {}; + const lineToBreakpointDataMap: { [key: number]: { enabled: boolean, condition: string, hitCondition: string } } = {}; this.debugService.getModel().getBreakpoints().filter(bp => bp.source.uri.toString() === modelUrlStr).forEach(bp => { - enabledAndConditions[bp.lineNumber] = { + lineToBreakpointDataMap[bp.lineNumber] = { enabled: bp.enabled, - condition: bp.condition + condition: bp.condition, + hitCondition: bp.hitCondition }; }); @@ -217,8 +218,9 @@ export class DebugEditorModelManager implements IWorkbenchContribution { data.push({ uri: modelUrl, lineNumber: decorationRange.startLineNumber, - enabled: enabledAndConditions[modelData.breakpointLines[i]].enabled, - condition: enabledAndConditions[modelData.breakpointLines[i]].condition + enabled: lineToBreakpointDataMap[modelData.breakpointLines[i]].enabled, + condition: lineToBreakpointDataMap[modelData.breakpointLines[i]].condition, + hitCondition: lineToBreakpointDataMap[modelData.breakpointLines[i]].hitCondition }); } } @@ -280,7 +282,7 @@ export class DebugEditorModelManager implements IWorkbenchContribution { let result = (!breakpoint.enabled || !activated) ? DebugEditorModelManager.BREAKPOINT_DISABLED_DECORATION : debugActive && modelData && modelData.dirty && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_DIRTY_DECORATION : debugActive && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_UNVERIFIED_DECORATION : - !breakpoint.condition ? DebugEditorModelManager.BREAKPOINT_DECORATION : null; + !breakpoint.condition && !breakpoint.hitCondition ? DebugEditorModelManager.BREAKPOINT_DECORATION : null; if (result && breakpoint.message) { result = objects.clone(result); @@ -291,19 +293,20 @@ export class DebugEditorModelManager implements IWorkbenchContribution { return result; } - if (!session || session.configuration.capabilities.supportsConditionalBreakpoints) { - const mode = modelData ? modelData.model.getMode() : null; - const modeId = mode ? mode.getId() : ''; - const glyphMarginHoverMessage = `\`\`\`${modeId}\n${ breakpoint.condition }\`\`\``; - - return { - glyphMarginClassName: 'debug-breakpoint-conditional-glyph', - glyphMarginHoverMessage, - stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges - }; + if (session && !session.configuration.capabilities.supportsConditionalBreakpoints) { + return DebugEditorModelManager.BREAKPOINT_UNSUPPORTED_DECORATION; } - - return DebugEditorModelManager.BREAKPOINT_UNSUPPORTED_DECORATION; + + const mode = modelData ? modelData.model.getMode() : null; + const modeId = mode ? mode.getId() : ''; + const condition = breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition; + const glyphMarginHoverMessage = `\`\`\`${modeId}\n${ condition }\`\`\``; + + return { + glyphMarginClassName: 'debug-breakpoint-conditional-glyph', + glyphMarginHoverMessage, + stickiness: editorcommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges + }; } // editor decorations diff --git a/src/vs/workbench/parts/debug/common/debug.ts b/src/vs/workbench/parts/debug/common/debug.ts index 4e87d10c03aff87958df218a8cc2d766a0843865..4e2719cd7d8d423bfa4dba9aaa8b902c408b5d64 100644 --- a/src/vs/workbench/parts/debug/common/debug.ts +++ b/src/vs/workbench/parts/debug/common/debug.ts @@ -130,6 +130,7 @@ export interface IRawBreakpoint { lineNumber: number; enabled?: boolean; condition?: string; + hitCondition?: string; } export interface IBreakpoint extends IEnablement { @@ -137,6 +138,7 @@ export interface IBreakpoint extends IEnablement { lineNumber: number; desiredLineNumber: number; condition: string; + hitCondition: string; verified: boolean; idFromAdapter: number; message: string; @@ -146,6 +148,7 @@ export interface IFunctionBreakpoint extends IEnablement { name: string; verified: boolean; idFromAdapter: number; + hitCondition: string; } export interface IExceptionBreakpoint extends IEnablement { diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index b4cac7501a470e940ba28f4e75c94cbb058920be..9f55504dd9d5af1d9dfbfec38a2f47fb3f16e6e8 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -410,7 +410,8 @@ export class Breakpoint implements debug.IBreakpoint { public source: Source, public desiredLineNumber: number, public enabled: boolean, - public condition: string + public condition: string, + public hitCondition: string ) { if (enabled === undefined) { this.enabled = true; @@ -431,7 +432,7 @@ export class FunctionBreakpoint implements debug.IFunctionBreakpoint { public verified: boolean; public idFromAdapter: number; - constructor(public name: string, public enabled: boolean) { + constructor(public name: string, public enabled: boolean, public hitCondition: string) { this.verified = false; this.id = uuid.generateUuid(); } @@ -563,7 +564,7 @@ export class Model implements debug.IModel { public addBreakpoints(rawData: debug.IRawBreakpoint[]): void { this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => - new Breakpoint(new Source(Source.toRawSource(rawBp.uri, this)), rawBp.lineNumber, rawBp.enabled, rawBp.condition))); + new Breakpoint(new Source(Source.toRawSource(rawBp.uri, this)), rawBp.lineNumber, rawBp.enabled, rawBp.condition, rawBp.hitCondition))); this.breakpointsActivated = true; this._onDidChangeBreakpoints.fire(); } @@ -612,17 +613,18 @@ export class Model implements debug.IModel { } public addFunctionBreakpoint(functionName: string): void { - this.functionBreakpoints.push(new FunctionBreakpoint(functionName, true)); + this.functionBreakpoints.push(new FunctionBreakpoint(functionName, true, null)); this._onDidChangeBreakpoints.fire(); } - public updateFunctionBreakpoints(data: { [id: string]: { name?: string, verified?: boolean; id?: number } }): void { + public updateFunctionBreakpoints(data: { [id: string]: { name?: string, verified?: boolean; id?: number; hitCondition?: string } }): void { this.functionBreakpoints.forEach(fbp => { const fbpData = data[fbp.getId()]; if (fbpData) { fbp.name = fbpData.name || fbp.name; fbp.verified = fbpData.verified; fbp.idFromAdapter = fbpData.id; + fbp.hitCondition = fbpData.hitCondition; } }); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d1d67e57b1aa6c269ddeebca6bd0a7edb2070ee8..ae9288f41476aa3e665a91a967ebed5e70eb57c1 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -359,7 +359,7 @@ export class DebugService implements debug.IDebugService { try { result = JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => { return new model.Breakpoint(new Source(breakpoint.source.raw ? breakpoint.source.raw : { path: uri.parse(breakpoint.source.uri).fsPath, name: breakpoint.source.name }), - breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition); + breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition, breakpoint.hitCondition); }); } catch (e) { } @@ -370,7 +370,7 @@ export class DebugService implements debug.IDebugService { let result: debug.IFunctionBreakpoint[]; try { result = JSON.parse(this.storageService.get(DEBUG_FUNCTION_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((fb: any) => { - return new model.FunctionBreakpoint(fb.name, fb.enabled); + return new model.FunctionBreakpoint(fb.name, fb.enabled, fb.hitCondition); }); } catch (e) { } @@ -1045,7 +1045,7 @@ export class DebugService implements debug.IDebugService { return this.session.setBreakpoints({ source: rawSource, lines: breakpointsToSend.map(bp => bp.desiredLineNumber), - breakpoints: breakpointsToSend.map(bp => ({ line: bp.desiredLineNumber, condition: bp.condition })), + breakpoints: breakpointsToSend.map(bp => ({ line: bp.desiredLineNumber, condition: bp.condition, hitCondition: bp.hitCondition })), sourceModified }).then(response => { if (!response || !response.body) { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts index 6f43336463f9af2d0996a6111e9e82930d539790..34ba1a8f8bcb6f13430e276a140300db12b05286 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugViewer.ts @@ -1190,8 +1190,8 @@ export class BreakpointsRenderer implements tree.IRenderer { if (breakpoint.message) { data.breakpoint.title = breakpoint.message; } - } else if (breakpoint.condition) { - data.breakpoint.title = breakpoint.condition; + } else if (breakpoint.condition || breakpoint.hitCondition) { + data.breakpoint.title = breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition; } }