Added function breakpoints (fix #45)
This commit is contained in:
parent
4cbb822d39
commit
50fb4798b7
7 changed files with 71 additions and 23 deletions
|
|
@ -349,8 +349,8 @@
|
||||||
"test": "node ./node_modules/vscode/bin/test"
|
"test": "node ./node_modules/vscode/bin/test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-debugadapter": "^1.5.0",
|
"vscode-debugadapter": "^1.7.0-pre.1",
|
||||||
"vscode-debugprotocol": "^1.5.0",
|
"vscode-debugprotocol": "^1.7.0-pre.1",
|
||||||
"ssh2": "^0.4.13"
|
"ssh2": "^0.4.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export interface Breakpoint {
|
export interface Breakpoint {
|
||||||
file: string;
|
file?: string;
|
||||||
line: number;
|
line?: number;
|
||||||
|
raw?: string;
|
||||||
condition: string;
|
condition: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ export function escape(str: string) {
|
||||||
return str.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
return str.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
const nonOutput = /^[0-9]*[\*\+\=]|[\~\@\&\^]/;
|
const nonOutput = /^(?:\d*|undefined)[\*\+\=]|[\~\@\&\^]/;
|
||||||
const gdbMatch = /(undefined|\d*)\(gdb\)/;
|
const gdbMatch = /(?:\d*|undefined)\(gdb\)/;
|
||||||
|
|
||||||
function couldBeOutput(line: string) {
|
function couldBeOutput(line: string) {
|
||||||
if (nonOutput.exec(line))
|
if (nonOutput.exec(line))
|
||||||
|
|
@ -409,7 +409,12 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (this.breakpoints.has(breakpoint))
|
if (this.breakpoints.has(breakpoint))
|
||||||
return resolve(false);
|
return resolve(false);
|
||||||
this.sendCommand("break-insert -f " + breakpoint.file + ":" + breakpoint.line).then((result) => {
|
let location = "";
|
||||||
|
if (breakpoint.raw)
|
||||||
|
location = '"' + escape(breakpoint.raw) + '"';
|
||||||
|
else
|
||||||
|
location = breakpoint.file + ":" + breakpoint.line;
|
||||||
|
this.sendCommand("break-insert -f " + location).then((result) => {
|
||||||
if (result.resultRecords.resultClass == "done") {
|
if (result.resultRecords.resultClass == "done") {
|
||||||
let bkptNum = parseInt(result.result("bkpt.number"));
|
let bkptNum = parseInt(result.result("bkpt.number"));
|
||||||
let newBrk = {
|
let newBrk = {
|
||||||
|
|
@ -425,7 +430,7 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
} else {
|
} else {
|
||||||
resolve([false, null]);
|
resolve([false, null]);
|
||||||
}
|
}
|
||||||
});
|
}, reject);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.breakpoints.set(newBrk, bkptNum);
|
this.breakpoints.set(newBrk, bkptNum);
|
||||||
|
|
@ -433,9 +438,9 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resolve([false, null]);
|
reject(result);
|
||||||
}
|
}
|
||||||
});
|
}, reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,6 +466,8 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
else resolve(false);
|
else resolve(false);
|
||||||
|
}, () => {
|
||||||
|
resolve(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,9 @@ export class MINode implements MIInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenRegex = /^[0-9]+/;
|
const tokenRegex = /^\d+/;
|
||||||
const outOfBandRecordRegex = /^(?:([0-9]*)([\*\+\=])|([\~\@\&]))/;
|
const outOfBandRecordRegex = /^(?:(\d*|undefined)([\*\+\=])|([\~\@\&]))/;
|
||||||
const resultRecordRegex = /^([0-9]*)\^(done|running|connected|error|exit)/;
|
const resultRecordRegex = /^(\d*)\^(done|running|connected|error|exit)/;
|
||||||
const newlineRegex = /^\r\n?/;
|
const newlineRegex = /^\r\n?/;
|
||||||
const endRegex = /^\(gdb\)\r\n?/;
|
const endRegex = /^\(gdb\)\r\n?/;
|
||||||
const variableRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*)/;
|
const variableRegex = /^([a-zA-Z_\-][a-zA-Z0-9_\-]*)/;
|
||||||
|
|
@ -212,7 +212,7 @@ export function parseMI(output: string): MINode {
|
||||||
|
|
||||||
while (match = outOfBandRecordRegex.exec(output)) {
|
while (match = outOfBandRecordRegex.exec(output)) {
|
||||||
output = output.substr(match[0].length);
|
output = output.substr(match[0].length);
|
||||||
if (match[1] && token === undefined) {
|
if (match[1] && token === undefined && match[1] !== "undefined") {
|
||||||
token = parseInt(match[1]);
|
token = parseInt(match[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,9 @@ export interface AttachRequestArguments {
|
||||||
class GDBDebugSession extends MI2DebugSession {
|
class GDBDebugSession extends MI2DebugSession {
|
||||||
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
||||||
response.body.supportsConfigurationDoneRequest = true;
|
response.body.supportsConfigurationDoneRequest = true;
|
||||||
response.body.supportsEvaluateForHovers = true; // Assume working in future releases
|
response.body.supportsConditionalBreakpoints = true;
|
||||||
response.body.supportsFunctionBreakpoints = true; // TODO: Implement in future release
|
response.body.supportsFunctionBreakpoints = true;
|
||||||
|
response.body.supportsEvaluateForHovers = true;
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
this.miDebugger = new MI2("gdb", ["-q", "--interpreter=mi2"]);
|
this.miDebugger = new MI2("gdb", ["-q", "--interpreter=mi2"]);
|
||||||
this.initDebugger();
|
this.initDebugger();
|
||||||
|
|
@ -40,6 +41,7 @@ class GDBDebugSession extends MI2DebugSession {
|
||||||
this.isSSH = false;
|
this.isSSH = false;
|
||||||
this.started = false;
|
this.started = false;
|
||||||
this.crashed = false;
|
this.crashed = false;
|
||||||
|
this.debugReady = false;
|
||||||
this.miDebugger.printCalls = !!args.printCalls;
|
this.miDebugger.printCalls = !!args.printCalls;
|
||||||
if (args.ssh !== undefined) {
|
if (args.ssh !== undefined) {
|
||||||
if (args.ssh.forwardX11 === undefined)
|
if (args.ssh.forwardX11 === undefined)
|
||||||
|
|
@ -95,6 +97,7 @@ class GDBDebugSession extends MI2DebugSession {
|
||||||
this.attached = !args.remote;
|
this.attached = !args.remote;
|
||||||
this.needContinue = true;
|
this.needContinue = true;
|
||||||
this.isSSH = false;
|
this.isSSH = false;
|
||||||
|
this.debugReady = false;
|
||||||
this.miDebugger.printCalls = !!args.printCalls;
|
this.miDebugger.printCalls = !!args.printCalls;
|
||||||
if (args.remote) {
|
if (args.remote) {
|
||||||
this.miDebugger.connect(args.cwd, args.executable, args.target).then(() => {
|
this.miDebugger.connect(args.cwd, args.executable, args.target).then(() => {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,9 @@ export interface AttachRequestArguments {
|
||||||
class LLDBDebugSession extends MI2DebugSession {
|
class LLDBDebugSession extends MI2DebugSession {
|
||||||
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
||||||
response.body.supportsConfigurationDoneRequest = true;
|
response.body.supportsConfigurationDoneRequest = true;
|
||||||
response.body.supportsEvaluateForHovers = true; // Assume working in future releases
|
response.body.supportsConditionalBreakpoints = true;
|
||||||
response.body.supportsFunctionBreakpoints = true; // TODO: Implement in future release
|
response.body.supportsFunctionBreakpoints = true;
|
||||||
|
response.body.supportsEvaluateForHovers = true;
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
this.miDebugger = new MI2_LLDB("lldb-mi", []);
|
this.miDebugger = new MI2_LLDB("lldb-mi", []);
|
||||||
this.initDebugger();
|
this.initDebugger();
|
||||||
|
|
@ -38,6 +39,7 @@ class LLDBDebugSession extends MI2DebugSession {
|
||||||
this.isSSH = false;
|
this.isSSH = false;
|
||||||
this.started = false;
|
this.started = false;
|
||||||
this.crashed = false;
|
this.crashed = false;
|
||||||
|
this.debugReady = false;
|
||||||
this.miDebugger.printCalls = !!args.printCalls;
|
this.miDebugger.printCalls = !!args.printCalls;
|
||||||
if (args.ssh !== undefined) {
|
if (args.ssh !== undefined) {
|
||||||
if (args.ssh.forwardX11 === undefined)
|
if (args.ssh.forwardX11 === undefined)
|
||||||
|
|
@ -93,6 +95,7 @@ class LLDBDebugSession extends MI2DebugSession {
|
||||||
this.attached = true;
|
this.attached = true;
|
||||||
this.needContinue = true;
|
this.needContinue = true;
|
||||||
this.isSSH = false;
|
this.isSSH = false;
|
||||||
|
this.debugReady = false;
|
||||||
this.miDebugger.printCalls = !!args.printCalls;
|
this.miDebugger.printCalls = !!args.printCalls;
|
||||||
this.miDebugger.attach(args.cwd, args.executable, args.target).then(() => {
|
this.miDebugger.attach(args.cwd, args.executable, args.target).then(() => {
|
||||||
if (args.autorun)
|
if (args.autorun)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export class MI2DebugSession extends DebugSession {
|
||||||
protected switchCWD: string;
|
protected switchCWD: string;
|
||||||
protected started: boolean;
|
protected started: boolean;
|
||||||
protected crashed: boolean;
|
protected crashed: boolean;
|
||||||
|
protected debugReady: boolean;
|
||||||
protected miDebugger: MI2;
|
protected miDebugger: MI2;
|
||||||
|
|
||||||
public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) {
|
public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) {
|
||||||
|
|
@ -79,8 +80,36 @@ export class MI2DebugSession extends DebugSession {
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected setFunctionBreakPointsRequest(response: DebugProtocol.SetFunctionBreakpointsResponse, args: DebugProtocol.SetFunctionBreakpointsArguments): void {
|
||||||
|
let cb = (() => {
|
||||||
|
this.debugReady = true;
|
||||||
|
let all = [];
|
||||||
|
args.breakpoints.forEach(brk => {
|
||||||
|
all.push(this.miDebugger.addBreakPoint({ raw: brk.name, condition: brk.condition }));
|
||||||
|
});
|
||||||
|
Promise.all(all).then(brkpoints => {
|
||||||
|
let finalBrks = [];
|
||||||
|
brkpoints.forEach(brkp => {
|
||||||
|
if (brkp[0])
|
||||||
|
finalBrks.push({ line: brkp[1].line });
|
||||||
|
});
|
||||||
|
response.body = {
|
||||||
|
breakpoints: finalBrks
|
||||||
|
};
|
||||||
|
this.sendResponse(response);
|
||||||
|
}, msg => {
|
||||||
|
this.sendErrorResponse(response, 10, msg.toString());
|
||||||
|
});
|
||||||
|
}).bind(this);
|
||||||
|
if (this.debugReady)
|
||||||
|
cb();
|
||||||
|
else
|
||||||
|
this.miDebugger.once("debug-ready", cb);
|
||||||
|
}
|
||||||
|
|
||||||
protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
|
protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
|
||||||
this.miDebugger.once("debug-ready", (() => {
|
let cb = (() => {
|
||||||
|
this.debugReady = true;
|
||||||
this.miDebugger.clearBreakPoints().then(() => {
|
this.miDebugger.clearBreakPoints().then(() => {
|
||||||
let path = args.source.path;
|
let path = args.source.path;
|
||||||
if (this.isSSH) {
|
if (this.isSSH) {
|
||||||
|
|
@ -100,13 +129,18 @@ export class MI2DebugSession extends DebugSession {
|
||||||
response.body = {
|
response.body = {
|
||||||
breakpoints: finalBrks
|
breakpoints: finalBrks
|
||||||
};
|
};
|
||||||
setTimeout(() => {
|
|
||||||
this.miDebugger.emit("ui-break-done");
|
|
||||||
}, 50);
|
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
|
}, msg => {
|
||||||
|
this.sendErrorResponse(response, 9, msg.toString());
|
||||||
});
|
});
|
||||||
|
}, msg => {
|
||||||
|
this.sendErrorResponse(response, 9, msg.toString());
|
||||||
});
|
});
|
||||||
}).bind(this));
|
}).bind(this);
|
||||||
|
if (this.debugReady)
|
||||||
|
cb();
|
||||||
|
else
|
||||||
|
this.miDebugger.once("debug-ready", cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected threadsRequest(response: DebugProtocol.ThreadsResponse): void {
|
protected threadsRequest(response: DebugProtocol.ThreadsResponse): void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue