diff --git a/package.json b/package.json index b2a6ebf..1843ee3 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "publisher": "webfreak", "icon": "images/icon-plain.svg", "engines": { - "vscode": "^0.10.10" + "vscode": "^1.7.2" }, "main": "./out/src/frontend/extension", "activationEvents": [ diff --git a/src/backend/backend.ts b/src/backend/backend.ts index 675f135..5551487 100644 --- a/src/backend/backend.ts +++ b/src/backend/backend.ts @@ -3,6 +3,7 @@ export interface Breakpoint { line?: number; raw?: string; condition: string; + countCondition?: string; } export interface Stack { diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts index 5d8686d..8785a4f 100644 --- a/src/backend/mi2/mi2.ts +++ b/src/backend/mi2/mi2.ts @@ -16,6 +16,7 @@ export function escape(str: string) { const nonOutput = /^(?:\d*|undefined)[\*\+\=]|[\~\@\&\^]/; const gdbMatch = /(?:\d*|undefined)\(gdb\)/; +const numRegex = /\d+/; function couldBeOutput(line: string) { if (nonOutput.exec(line)) @@ -232,8 +233,7 @@ export class MI2 extends EventEmitter implements IBackend { this.buffer = this.buffer.substr(end + 1); } if (this.buffer.length) { - if (this.onOutputPartial(this.buffer)) - { + if (this.onOutputPartial(this.buffer)) { this.buffer = ""; } } @@ -358,7 +358,7 @@ export class MI2 extends EventEmitter implements IBackend { let to = setTimeout(() => { proc.signal("KILL"); }, 1000); - this.stream.on("exit", function(code) { + this.stream.on("exit", function (code) { clearTimeout(to); }) this.sendRaw("-gdb-exit"); @@ -368,7 +368,7 @@ export class MI2 extends EventEmitter implements IBackend { let to = setTimeout(() => { process.kill(-proc.pid); }, 1000); - this.process.on("exit", function(code) { + this.process.on("exit", function (code) { clearTimeout(to); }); this.sendRaw("-gdb-exit"); @@ -380,7 +380,7 @@ export class MI2 extends EventEmitter implements IBackend { let to = setTimeout(() => { process.kill(-proc.pid); }, 1000); - this.process.on("exit", function(code) { + this.process.on("exit", function (code) { clearTimeout(to); }); this.sendRaw("-target-detach"); @@ -465,10 +465,23 @@ export class MI2 extends EventEmitter implements IBackend { if (this.breakpoints.has(breakpoint)) return resolve(false); let location = ""; + if (breakpoint.countCondition) { + if (breakpoint.countCondition[0] == ">") + location += "-i " + numRegex.exec(breakpoint.countCondition.substr(1))[0] + " "; + else { + let match = numRegex.exec(breakpoint.countCondition)[0]; + if (match.length != breakpoint.countCondition.length) { + this.log("stderr", "Unsupported break count expression: '" + breakpoint.countCondition + "'. Only supports 'X' for breaking once after X times or '>X' for ignoring the first X breaks"); + location += "-t "; + } + else if (parseInt(match) != 0) + location += "-t -i " + parseInt(match) + " "; + } + } if (breakpoint.raw) - location = '"' + escape(breakpoint.raw) + '"'; + location += '"' + escape(breakpoint.raw) + '"'; else - location = '"' + escape(breakpoint.file) + ":" + breakpoint.line + '"'; + location += '"' + escape(breakpoint.file) + ":" + breakpoint.line + '"'; this.sendCommand("break-insert -f " + location).then((result) => { if (result.resultRecords.resultClass == "done") { let bkptNum = parseInt(result.result("bkpt.number")); diff --git a/src/gdb.ts b/src/gdb.ts index ef7181d..c4005bc 100644 --- a/src/gdb.ts +++ b/src/gdb.ts @@ -29,6 +29,7 @@ export interface AttachRequestArguments { class GDBDebugSession extends MI2DebugSession { protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { + response.body.supportsHitConditionalBreakpoints = true; response.body.supportsConfigurationDoneRequest = true; response.body.supportsConditionalBreakpoints = true; response.body.supportsFunctionBreakpoints = true; diff --git a/src/lldb.ts b/src/lldb.ts index 6e3be40..2b3d4dd 100644 --- a/src/lldb.ts +++ b/src/lldb.ts @@ -27,6 +27,7 @@ export interface AttachRequestArguments { class LLDBDebugSession extends MI2DebugSession { protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { + response.body.supportsHitConditionalBreakpoints = true; response.body.supportsConfigurationDoneRequest = true; response.body.supportsConditionalBreakpoints = true; response.body.supportsFunctionBreakpoints = true; diff --git a/src/mago.ts b/src/mago.ts index 9eea6d4..f108b83 100644 --- a/src/mago.ts +++ b/src/mago.ts @@ -30,6 +30,7 @@ class MagoDebugSession extends MI2DebugSession { } protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { + response.body.supportsHitConditionalBreakpoints = true; response.body.supportsConfigurationDoneRequest = true; response.body.supportsConditionalBreakpoints = true; response.body.supportsFunctionBreakpoints = true; diff --git a/src/mibase.ts b/src/mibase.ts index 14a8605..20f44a3 100644 --- a/src/mibase.ts +++ b/src/mibase.ts @@ -135,7 +135,7 @@ export class MI2DebugSession extends DebugSession { this.debugReady = true; let all = []; args.breakpoints.forEach(brk => { - all.push(this.miDebugger.addBreakPoint({ raw: brk.name, condition: brk.condition })); + all.push(this.miDebugger.addBreakPoint({ raw: brk.name, condition: brk.condition, countCondition: brk.hitCondition })); }); Promise.all(all).then(brkpoints => { let finalBrks = []; @@ -168,7 +168,7 @@ export class MI2DebugSession extends DebugSession { } let all = []; args.breakpoints.forEach(brk => { - all.push(this.miDebugger.addBreakPoint({ file: path, line: brk.line, condition: brk.condition })); + all.push(this.miDebugger.addBreakPoint({ file: path, line: brk.line, condition: brk.condition, countCondition: brk.hitCondition })); }); Promise.all(all).then(brkpoints => { let finalBrks = [];