Added conditional breakpoints
This commit is contained in:
parent
3831f07c2a
commit
97de960df7
4 changed files with 57 additions and 20 deletions
12
package.json
12
package.json
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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[]> {
|
||||||
|
|
|
||||||
28
src/gdb.ts
28
src/gdb.ts
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue