Added conditional breakpoints

This commit is contained in:
WebFreak001 2016-02-09 15:15:51 +01:00
commit 97de960df7
4 changed files with 57 additions and 20 deletions

View file

@ -2,11 +2,11 @@
"name": "debug", "name": "debug",
"displayName": "Debug", "displayName": "Debug",
"description": "Native debugging for VSCode - Currently in GDB only beta", "description": "Native debugging for VSCode - Currently in GDB only beta",
"version": "0.2.0", "version": "0.3.0",
"publisher": "webfreak", "publisher": "webfreak",
"icon": "images/icon-plain.svg", "icon": "images/icon-plain.svg",
"engines": { "engines": {
"vscode": "^0.10.1" "vscode": "^0.10.8"
}, },
"categories": [ "categories": [
"Debuggers" "Debuggers"
@ -92,11 +92,11 @@
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./" "compile": "node ./node_modules/vscode/bin/compile -watch -p ./"
}, },
"dependencies": { "dependencies": {
"vscode-debugadapter": "^1.0.1", "vscode-debugadapter": "^1.5.0",
"vscode-debugprotocol": "^1.0.1" "vscode-debugprotocol": "^1.5.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^1.6.2", "typescript": "^1.7.5",
"vscode": "0.10.x" "vscode": "0.11.x"
} }
} }

View file

@ -1,6 +1,7 @@
export interface Breakpoint { export interface Breakpoint {
file: string; file: string;
line: number; line: number;
condition: string;
} }
export interface Stack { export interface Stack {

View file

@ -199,12 +199,26 @@ export class MI2 extends EventEmitter implements IBackend {
return resolve(false); return resolve(false);
this.sendCommand("break-insert " + breakpoint.file + ":" + breakpoint.line).then((result) => { this.sendCommand("break-insert " + breakpoint.file + ":" + breakpoint.line).then((result) => {
if (result.resultRecords.resultClass == "done") { if (result.resultRecords.resultClass == "done") {
let bkptNum = parseInt(result.result("bkpt.number"));
let newBrk = { let newBrk = {
file: result.result("bkpt.file"), file: result.result("bkpt.file"),
line: parseInt(result.result("bkpt.line")) line: parseInt(result.result("bkpt.line")),
condition: breakpoint.condition
}; };
this.breakpoints.set(newBrk, parseInt(result.result("bkpt.number"))); if (breakpoint.condition) {
resolve([true, newBrk]); this.sendCommand("break-condition " + bkptNum + " " + breakpoint.condition).then((result) => {
if (result.resultRecords.resultClass == "done") {
this.breakpoints.set(newBrk, bkptNum);
resolve([true, newBrk]);
} else {
resolve([false, null]);
}
});
}
else {
this.breakpoints.set(newBrk, bkptNum);
resolve([true, newBrk]);
}
} }
else { else {
resolve([false, null]); resolve([false, null]);
@ -228,13 +242,15 @@ export class MI2 extends EventEmitter implements IBackend {
} }
clearBreakPoints(): Thenable<any> { clearBreakPoints(): Thenable<any> {
let promisses = []; return new Promise((resolve, reject) => {
let it = this.breakpoints.keys(); this.sendCommand("break-delete").then((result) => {
let value; if (result.resultRecords.resultClass == "done") {
while (!(value = it.next()).done) { this.breakpoints.clear();
promisses.push(this.removeBreakPoint(value.value)); resolve(true);
} }
return Promise.all(promisses); else resolve(false);
});
});
} }
getStack(maxLevels: number): Thenable<Stack[]> { getStack(maxLevels: number): Thenable<Stack[]> {

View file

@ -23,12 +23,16 @@ class MI2DebugSession extends DebugSession {
private variableHandles = new Handles<any>(); private variableHandles = new Handles<any>();
private quit: boolean; private quit: boolean;
private attached: boolean; private attached: boolean;
private needContinue: boolean;
public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) { public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) {
super(debuggerLinesStartAt1, isServer); super(debuggerLinesStartAt1, isServer);
} }
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
response.body.supportsConfigurationDoneRequest = true;
response.body.supportsEvaluateForHovers = true; // Assume working in future releases
response.body.supportsFunctionBreakpoints = true; // TODO: Implement in future release
this.sendResponse(response); this.sendResponse(response);
this.gdbDebugger = new MI2("gdb", ["-q", "--interpreter=mi2"]); this.gdbDebugger = new MI2("gdb", ["-q", "--interpreter=mi2"]);
this.gdbDebugger.on("quit", this.quitEvent.bind(this)); this.gdbDebugger.on("quit", this.quitEvent.bind(this));
@ -65,6 +69,7 @@ class MI2DebugSession extends DebugSession {
protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void { protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
this.quit = false; this.quit = false;
this.attached = false; this.attached = false;
this.needContinue = false;
this.gdbDebugger.load(args.cwd, args.target).then(() => { this.gdbDebugger.load(args.cwd, args.target).then(() => {
this.gdbDebugger.start().then(() => { this.gdbDebugger.start().then(() => {
this.sendResponse(response); this.sendResponse(response);
@ -75,6 +80,7 @@ class MI2DebugSession extends DebugSession {
protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void { protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void {
this.quit = false; this.quit = false;
this.attached = !args.remote; this.attached = !args.remote;
this.needContinue = true;
if (args.remote) { if (args.remote) {
this.gdbDebugger.connect(args.cwd, args.executable, args.target).then(() => { this.gdbDebugger.connect(args.cwd, args.executable, args.target).then(() => {
this.sendResponse(response); this.sendResponse(response);
@ -98,10 +104,9 @@ class MI2DebugSession extends DebugSession {
protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void { protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
this.gdbDebugger.clearBreakPoints().then(() => { this.gdbDebugger.clearBreakPoints().then(() => {
let path = args.source.path; let path = args.source.path;
let lines = args.lines;
let all = []; let all = [];
lines.forEach(line => { args.breakpoints.forEach(brk => {
all.push(this.gdbDebugger.addBreakPoint({ file: path, line: line })); all.push(this.gdbDebugger.addBreakPoint({ file: path, line: brk.line, condition: brk.condition }));
}); });
Promise.all(all).then(brkpoints => { Promise.all(all).then(brkpoints => {
response.body.breakpoints = brkpoints; response.body.breakpoints = brkpoints;
@ -132,6 +137,20 @@ class MI2DebugSession extends DebugSession {
}); });
} }
protected configurationDoneRequest(response: DebugProtocol.ConfigurationDoneResponse, args: DebugProtocol.ConfigurationDoneArguments): void {
// FIXME: Does not seem to get called in january release
if (this.needContinue) {
this.gdbDebugger.continue().then(done => {
this.sendResponse(response);
}, msg => {
this.sendResponse(response);
this.sendEvent(new OutputEvent(`Could not continue: ${msg}\n`, 'stderr'));
});
}
else
this.sendResponse(response);
}
protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void { protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
const scopes = new Array<Scope>(); const scopes = new Array<Scope>();
scopes.push(new Scope("Local", this.variableHandles.create("@frame:" + args.frameId), false)); scopes.push(new Scope("Local", this.variableHandles.create("@frame:" + args.frameId), false));
@ -261,7 +280,8 @@ class MI2DebugSession extends DebugSession {
} }
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
if (args.context == "watch") this.handleMsg("console", "Evaluate (" + args.context + "): " + args.expression + "\n")
if (args.context == "watch" || args.context == "hover")
this.gdbDebugger.evalExpression(args.expression).then((res) => { this.gdbDebugger.evalExpression(args.expression).then((res) => {
response.body = { response.body = {
variablesReference: 0, variablesReference: 0,