Enable tslint with basic rules

Add tslint as a plugin to tsc, so that they will show up in vscode or
whatever editor people use.  I only enabled two basic rules that I think
are very useful, prefer-const and no-var-keyword.  Violations of these
rules were fixed with "tslint -p . --fix".  There was one unused
variable (in the isExpandable) function that I removed by hand.
This commit is contained in:
Simon Marchi 2018-07-17 18:19:37 -04:00
commit 1244e4133c
15 changed files with 209 additions and 196 deletions

View file

@ -926,10 +926,12 @@
"ssh2": "^0.5.4" "ssh2": "^0.5.4"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^2.1.6", "@types/mocha": "^2.2.39",
"vscode": "^1.0.3",
"mocha": "^3.2.0",
"@types/node": "^7.0.5", "@types/node": "^7.0.5",
"@types/mocha": "^2.2.39" "mocha": "^3.2.0",
"tslint": "^5.11.0",
"tslint-language-service": "^0.9.9",
"typescript": "^2.1.6",
"vscode": "^1.0.3"
} }
} }

View file

@ -117,7 +117,7 @@ export class VariableObject {
} }
public toProtocolVariable(): DebugProtocol.Variable { public toProtocolVariable(): DebugProtocol.Variable {
let res: DebugProtocol.Variable = { const res: DebugProtocol.Variable = {
name: this.exp, name: this.exp,
evaluateName: this.name, evaluateName: this.name,
value: (this.value === void 0) ? "<unknown>" : this.value, value: (this.value === void 0) ? "<unknown>" : this.value,

View file

@ -12,7 +12,6 @@ const numberRegex = /^\d+(\.\d+)?/;
const pointerCombineChar = "."; const pointerCombineChar = ".";
export function isExpandable(value: string): number { export function isExpandable(value: string): number {
let primitive: any;
let match; let match;
value = value.trim(); value = value.trim();
if (value.length == 0) return 0; if (value.length == 0) return 0;
@ -31,13 +30,13 @@ export function isExpandable(value: string): number {
} }
export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any { export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any {
let parseCString = () => { const parseCString = () => {
value = value.trim(); value = value.trim();
if (value[0] != '"' && value[0] != '\'') if (value[0] != '"' && value[0] != '\'')
return ""; return "";
let stringEnd = 1; let stringEnd = 1;
let inString = true; let inString = true;
let charStr = value[0]; const charStr = value[0];
let remaining = value.substr(1); let remaining = value.substr(1);
let escaped = false; let escaped = false;
while (inString) { while (inString) {
@ -51,16 +50,16 @@ export function expandValue(variableCreate: Function, value: string, root: strin
remaining = remaining.substr(1); remaining = remaining.substr(1);
stringEnd++; stringEnd++;
} }
let str = value.substr(0, stringEnd).trim(); const str = value.substr(0, stringEnd).trim();
value = value.substr(stringEnd).trim(); value = value.substr(stringEnd).trim();
return str; return str;
}; };
let stack = [root]; const stack = [root];
let parseValue, parseCommaResult, parseCommaValue, parseResult, createValue; let parseValue, parseCommaResult, parseCommaValue, parseResult, createValue;
let variable = ""; let variable = "";
let getNamespace = (variable) => { const getNamespace = (variable) => {
let namespace = ""; let namespace = "";
let prefix = ""; let prefix = "";
stack.push(variable); stack.push(variable);
@ -86,11 +85,11 @@ export function expandValue(variableCreate: Function, value: string, root: strin
return prefix + namespace; return prefix + namespace;
}; };
let parseTupleOrList = () => { const parseTupleOrList = () => {
value = value.trim(); value = value.trim();
if (value[0] != '{') if (value[0] != '{')
return undefined; return undefined;
let oldContent = value; const oldContent = value;
value = value.substr(1).trim(); value = value.substr(1).trim();
if (value[0] == '}') { if (value[0] == '}') {
value = value.substr(1).trim(); value = value.substr(1).trim();
@ -103,19 +102,19 @@ export function expandValue(variableCreate: Function, value: string, root: strin
return <any>"<...>"; return <any>"<...>";
} }
} }
let eqPos = value.indexOf("="); const eqPos = value.indexOf("=");
let newValPos1 = value.indexOf("{"); const newValPos1 = value.indexOf("{");
let newValPos2 = value.indexOf(","); const newValPos2 = value.indexOf(",");
let newValPos = newValPos1; let newValPos = newValPos1;
if (newValPos2 != -1 && newValPos2 < newValPos1) if (newValPos2 != -1 && newValPos2 < newValPos1)
newValPos = newValPos2; newValPos = newValPos2;
if (newValPos != -1 && eqPos > newValPos || eqPos == -1) { // is value list if (newValPos != -1 && eqPos > newValPos || eqPos == -1) { // is value list
let values = []; const values = [];
stack.push("[0]"); stack.push("[0]");
let val = parseValue(); let val = parseValue();
stack.pop(); stack.pop();
values.push(createValue("[0]", val)); values.push(createValue("[0]", val));
let remaining = value; const remaining = value;
let i = 0; let i = 0;
while (true) { while (true) {
stack.push("[" + (++i) + "]"); stack.push("[" + (++i) + "]");
@ -132,7 +131,7 @@ export function expandValue(variableCreate: Function, value: string, root: strin
let result = parseResult(true); let result = parseResult(true);
if (result) { if (result) {
let results = []; const results = [];
results.push(result); results.push(result);
while (result = parseCommaResult(true)) while (result = parseCommaResult(true))
results.push(result); results.push(result);
@ -143,7 +142,7 @@ export function expandValue(variableCreate: Function, value: string, root: strin
return undefined; return undefined;
}; };
let parsePrimitive = () => { const parsePrimitive = () => {
let primitive: any; let primitive: any;
let match; let match;
value = value.trim(); value = value.trim();
@ -208,14 +207,14 @@ export function expandValue(variableCreate: Function, value: string, root: strin
parseResult = (pushToStack: boolean = false) => { parseResult = (pushToStack: boolean = false) => {
value = value.trim(); value = value.trim();
let variableMatch = resultRegex.exec(value); const variableMatch = resultRegex.exec(value);
if (!variableMatch) if (!variableMatch)
return undefined; return undefined;
value = value.substr(variableMatch[0].length).trim(); value = value.substr(variableMatch[0].length).trim();
let name = variable = variableMatch[1]; const name = variable = variableMatch[1];
if (pushToStack) if (pushToStack)
stack.push(variable); stack.push(variable);
let val = parseValue(); const val = parseValue();
if (pushToStack) if (pushToStack)
stack.pop(); stack.pop();
return createValue(name, val); return createValue(name, val);

View file

@ -3,13 +3,13 @@ import * as fs from "fs"
export function spawnTerminalEmulator(preferedEmulator: string): Thenable<string> { export function spawnTerminalEmulator(preferedEmulator: string): Thenable<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let ttyFileOutput = "/tmp/vscode-gdb-tty-0" + Math.floor(Math.random() * 100000000).toString(36); const ttyFileOutput = "/tmp/vscode-gdb-tty-0" + Math.floor(Math.random() * 100000000).toString(36);
ChildProcess.spawn(preferedEmulator || "x-terminal-emulator", ["-e", "sh -c \"tty > " + ttyFileOutput + " && sleep 4294967294\""]); ChildProcess.spawn(preferedEmulator || "x-terminal-emulator", ["-e", "sh -c \"tty > " + ttyFileOutput + " && sleep 4294967294\""]);
let it = 0; let it = 0;
let interval = setInterval(() => { const interval = setInterval(() => {
if (fs.existsSync(ttyFileOutput)) { if (fs.existsSync(ttyFileOutput)) {
clearInterval(interval); clearInterval(interval);
let tty = fs.readFileSync(ttyFileOutput).toString("utf8"); const tty = fs.readFileSync(ttyFileOutput).toString("utf8");
fs.unlink(ttyFileOutput); fs.unlink(ttyFileOutput);
return resolve(tty); return resolve(tty);
} }

View file

@ -7,8 +7,8 @@ import * as net from "net"
import * as fs from "fs" import * as fs from "fs"
import { posix } from "path" import { posix } from "path"
import * as nativePath from "path" import * as nativePath from "path"
let path = posix; const path = posix;
var Client = require("ssh2").Client; const Client = require("ssh2").Client;
export function escape(str: string) { export function escape(str: string) {
return str.replace(/\\/g, "\\\\").replace(/"/g, "\\\""); return str.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
@ -31,14 +31,14 @@ export class MI2 extends EventEmitter implements IBackend {
super(); super();
if (procEnv) { if (procEnv) {
var env = {}; const env = {};
// Duplicate process.env so we don't override it // Duplicate process.env so we don't override it
for (var key in process.env) for (const key in process.env)
if (process.env.hasOwnProperty(key)) if (process.env.hasOwnProperty(key))
env[key] = process.env[key]; env[key] = process.env[key];
// Overwrite with user specified variables // Overwrite with user specified variables
for (var key in procEnv) { for (const key in procEnv) {
if (procEnv.hasOwnProperty(key)) { if (procEnv.hasOwnProperty(key)) {
if (procEnv === null) if (procEnv === null)
delete env[key]; delete env[key];
@ -55,13 +55,13 @@ export class MI2 extends EventEmitter implements IBackend {
target = nativePath.join(cwd, target); target = nativePath.join(cwd, target);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.isSSH = false; this.isSSH = false;
let args = this.preargs.concat(this.extraargs || []); const args = this.preargs.concat(this.extraargs || []);
this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv }); this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv });
this.process.stdout.on("data", this.stdout.bind(this)); this.process.stdout.on("data", this.stdout.bind(this));
this.process.stderr.on("data", this.stderr.bind(this)); this.process.stderr.on("data", this.stderr.bind(this));
this.process.on("exit", (() => { this.emit("quit"); }).bind(this)); this.process.on("exit", (() => { this.emit("quit"); }).bind(this));
this.process.on("error", ((err) => { this.emit("launcherror", err); }).bind(this)); this.process.on("error", ((err) => { this.emit("launcherror", err); }).bind(this));
let promises = this.initCommands(target, cwd); const promises = this.initCommands(target, cwd);
if (procArgs && procArgs.length) if (procArgs && procArgs.length)
promises.push(this.sendCommand("exec-arguments " + procArgs)); promises.push(this.sendCommand("exec-arguments " + procArgs));
if (process.platform == "win32") { if (process.platform == "win32") {
@ -103,19 +103,19 @@ export class MI2 extends EventEmitter implements IBackend {
if (args.forwardX11) { if (args.forwardX11) {
this.sshConn.on("x11", (info, accept, reject) => { this.sshConn.on("x11", (info, accept, reject) => {
var xserversock = new net.Socket(); const xserversock = new net.Socket();
xserversock.on("error", (err) => { xserversock.on("error", (err) => {
this.log("stderr", "Could not connect to local X11 server! Did you enable it in your display manager?\n" + err); this.log("stderr", "Could not connect to local X11 server! Did you enable it in your display manager?\n" + err);
}); });
xserversock.on("connect", () => { xserversock.on("connect", () => {
let xclientsock = accept(); const xclientsock = accept();
xclientsock.pipe(xserversock).pipe(xclientsock); xclientsock.pipe(xserversock).pipe(xclientsock);
}); });
xserversock.connect(args.x11port, args.x11host); xserversock.connect(args.x11port, args.x11host);
}); });
} }
let connectionArgs: any = { const connectionArgs: any = {
host: args.host, host: args.host,
port: args.port, port: args.port,
username: args.user username: args.user
@ -138,7 +138,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.sshConn.on("ready", () => { this.sshConn.on("ready", () => {
this.log("stdout", "Running " + this.application + " over ssh..."); this.log("stdout", "Running " + this.application + " over ssh...");
let execArgs: any = {}; const execArgs: any = {};
if (args.forwardX11) { if (args.forwardX11) {
execArgs.x11 = { execArgs.x11 = {
single: false, single: false,
@ -165,7 +165,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.emit("quit"); this.emit("quit");
this.sshConn.end(); this.sshConn.end();
}).bind(this)); }).bind(this));
let promises = this.initCommands(target, cwd, true, attach); const promises = this.initCommands(target, cwd, true, attach);
promises.push(this.sendCommand("environment-cd \"" + escape(cwd) + "\"")); promises.push(this.sendCommand("environment-cd \"" + escape(cwd) + "\""));
if (procArgs && procArgs.length && !attach) if (procArgs && procArgs.length && !attach)
promises.push(this.sendCommand("exec-arguments " + procArgs)); promises.push(this.sendCommand("exec-arguments " + procArgs));
@ -192,7 +192,7 @@ export class MI2 extends EventEmitter implements IBackend {
if (!nativePath.isAbsolute(target)) if (!nativePath.isAbsolute(target))
target = nativePath.join(cwd, target); target = nativePath.join(cwd, target);
} }
var cmds = [ const cmds = [
this.sendCommand("gdb-set target-async on", true), this.sendCommand("gdb-set target-async on", true),
this.sendCommand("environment-directory \"" + escape(cwd) + "\"", true) this.sendCommand("environment-directory \"" + escape(cwd) + "\"", true)
]; ];
@ -211,7 +211,7 @@ export class MI2 extends EventEmitter implements IBackend {
executable = nativePath.join(cwd, executable); executable = nativePath.join(cwd, executable);
if (!executable) if (!executable)
executable = "-p"; executable = "-p";
var isExtendedRemote = false; let isExtendedRemote = false;
if (target.startsWith("extended-remote")) { if (target.startsWith("extended-remote")) {
isExtendedRemote = true; isExtendedRemote = true;
args = this.preargs; args = this.preargs;
@ -222,7 +222,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.process.stderr.on("data", this.stderr.bind(this)); this.process.stderr.on("data", this.stderr.bind(this));
this.process.on("exit", (() => { this.emit("quit"); }).bind(this)); this.process.on("exit", (() => { this.emit("quit"); }).bind(this));
this.process.on("error", ((err) => { this.emit("launcherror", err); }).bind(this)); this.process.on("error", ((err) => { this.emit("launcherror", err); }).bind(this));
var commands = [ const commands = [
this.sendCommand("gdb-set target-async on"), this.sendCommand("gdb-set target-async on"),
this.sendCommand("environment-directory \"" + escape(cwd) + "\"") this.sendCommand("environment-directory \"" + escape(cwd) + "\"")
]; ];
@ -269,7 +269,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.buffer += data; this.buffer += data;
else else
this.buffer += data.toString("utf8"); this.buffer += data.toString("utf8");
let end = this.buffer.lastIndexOf('\n'); const end = this.buffer.lastIndexOf('\n');
if (end != -1) { if (end != -1) {
this.onOutput(this.buffer.substr(0, end)); this.onOutput(this.buffer.substr(0, end));
this.buffer = this.buffer.substr(end + 1); this.buffer = this.buffer.substr(end + 1);
@ -286,7 +286,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.errbuf += data; this.errbuf += data;
else else
this.errbuf += data.toString("utf8"); this.errbuf += data.toString("utf8");
let end = this.errbuf.lastIndexOf('\n'); const end = this.errbuf.lastIndexOf('\n');
if (end != -1) { if (end != -1) {
this.onOutputStderr(this.errbuf.substr(0, end)); this.onOutputStderr(this.errbuf.substr(0, end));
this.errbuf = this.errbuf.substr(end + 1); this.errbuf = this.errbuf.substr(end + 1);
@ -320,7 +320,7 @@ export class MI2 extends EventEmitter implements IBackend {
this.log("stdout", line); this.log("stdout", line);
} }
else { else {
let parsed = parseMI(line); const parsed = parseMI(line);
if (this.debugOutput) if (this.debugOutput)
this.log("log", "GDB -> App: " + JSON.stringify(parsed)); this.log("log", "GDB -> App: " + JSON.stringify(parsed));
let handled = false; let handled = false;
@ -344,7 +344,7 @@ export class MI2 extends EventEmitter implements IBackend {
if (record.asyncClass == "running") if (record.asyncClass == "running")
this.emit("running", parsed); this.emit("running", parsed);
else if (record.asyncClass == "stopped") { else if (record.asyncClass == "stopped") {
let reason = parsed.record("reason"); const reason = parsed.record("reason");
if (trace) if (trace)
this.log("stderr", "stop: " + reason); this.log("stderr", "stop: " + reason);
if (reason == "breakpoint-hit") if (reason == "breakpoint-hit")
@ -402,8 +402,8 @@ export class MI2 extends EventEmitter implements IBackend {
stop() { stop() {
if (this.isSSH) { if (this.isSSH) {
let proc = this.stream; const proc = this.stream;
let to = setTimeout(() => { const to = setTimeout(() => {
proc.signal("KILL"); proc.signal("KILL");
}, 1000); }, 1000);
this.stream.on("exit", function (code) { this.stream.on("exit", function (code) {
@ -412,8 +412,8 @@ export class MI2 extends EventEmitter implements IBackend {
this.sendRaw("-gdb-exit"); this.sendRaw("-gdb-exit");
} }
else { else {
let proc = this.process; const proc = this.process;
let to = setTimeout(() => { const to = setTimeout(() => {
process.kill(-proc.pid); process.kill(-proc.pid);
}, 1000); }, 1000);
this.process.on("exit", function (code) { this.process.on("exit", function (code) {
@ -424,8 +424,8 @@ export class MI2 extends EventEmitter implements IBackend {
} }
detach() { detach() {
let proc = this.process; const proc = this.process;
let to = setTimeout(() => { const to = setTimeout(() => {
process.kill(-proc.pid); process.kill(-proc.pid);
}, 1000); }, 1000);
this.process.on("exit", function (code) { this.process.on("exit", function (code) {
@ -493,7 +493,7 @@ export class MI2 extends EventEmitter implements IBackend {
loadBreakPoints(breakpoints: Breakpoint[]): Thenable<[boolean, Breakpoint][]> { loadBreakPoints(breakpoints: Breakpoint[]): Thenable<[boolean, Breakpoint][]> {
if (trace) if (trace)
this.log("stderr", "loadBreakPoints"); this.log("stderr", "loadBreakPoints");
let promisses = []; const promisses = [];
breakpoints.forEach(breakpoint => { breakpoints.forEach(breakpoint => {
promisses.push(this.addBreakPoint(breakpoint)); promisses.push(this.addBreakPoint(breakpoint));
}); });
@ -517,7 +517,7 @@ export class MI2 extends EventEmitter implements IBackend {
if (breakpoint.countCondition[0] == ">") if (breakpoint.countCondition[0] == ">")
location += "-i " + numRegex.exec(breakpoint.countCondition.substr(1))[0] + " "; location += "-i " + numRegex.exec(breakpoint.countCondition.substr(1))[0] + " ";
else { else {
let match = numRegex.exec(breakpoint.countCondition)[0]; const match = numRegex.exec(breakpoint.countCondition)[0];
if (match.length != breakpoint.countCondition.length) { 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"); 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 "; location += "-t ";
@ -532,8 +532,8 @@ export class MI2 extends EventEmitter implements IBackend {
location += '"' + escape(breakpoint.file) + ":" + breakpoint.line + '"'; location += '"' + escape(breakpoint.file) + ":" + breakpoint.line + '"';
this.sendCommand("break-insert -f " + location).then((result) => { 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")); const bkptNum = parseInt(result.result("bkpt.number"));
let newBrk = { const 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 condition: breakpoint.condition
@ -595,17 +595,17 @@ export class MI2 extends EventEmitter implements IBackend {
async getThreads(): Promise<Thread[]> { async getThreads(): Promise<Thread[]> {
if (trace) this.log("stderr", "getThreads"); if (trace) this.log("stderr", "getThreads");
let command = "thread-info"; const command = "thread-info";
let result = await this.sendCommand(command); const result = await this.sendCommand(command);
let threads = result.result("threads"); const threads = result.result("threads");
let ret: Thread[] = []; const ret: Thread[] = [];
return threads.map(element => { return threads.map(element => {
let ret : Thread = { const ret : Thread = {
id: parseInt(MINode.valueOf(element, "id")), id: parseInt(MINode.valueOf(element, "id")),
targetId: MINode.valueOf(element, "target-id") targetId: MINode.valueOf(element, "target-id")
}; };
let name = MINode.valueOf(element, "name"); const name = MINode.valueOf(element, "name");
if (name) { if (name) {
ret.name = name; ret.name = name;
} }
@ -624,20 +624,20 @@ export class MI2 extends EventEmitter implements IBackend {
if (maxLevels) { if (maxLevels) {
command += " 0 " + maxLevels; command += " 0 " + maxLevels;
} }
let result = await this.sendCommand(command); const result = await this.sendCommand(command);
let stack = result.result("stack"); const stack = result.result("stack");
let ret: Stack[] = []; const ret: Stack[] = [];
return stack.map(element => { return stack.map(element => {
let level = MINode.valueOf(element, "@frame.level"); const level = MINode.valueOf(element, "@frame.level");
let addr = MINode.valueOf(element, "@frame.addr"); const addr = MINode.valueOf(element, "@frame.addr");
let func = MINode.valueOf(element, "@frame.func"); const func = MINode.valueOf(element, "@frame.func");
let filename = MINode.valueOf(element, "@frame.file"); const filename = MINode.valueOf(element, "@frame.file");
let file = MINode.valueOf(element, "@frame.fullname"); const file = MINode.valueOf(element, "@frame.fullname");
let line = 0; let line = 0;
let lnstr = MINode.valueOf(element, "@frame.line"); const lnstr = MINode.valueOf(element, "@frame.line");
if (lnstr) if (lnstr)
line = parseInt(lnstr); line = parseInt(lnstr);
let from = parseInt(MINode.valueOf(element, "@frame.from")); const from = parseInt(MINode.valueOf(element, "@frame.from"));
return { return {
address: addr, address: addr,
fileName: filename, fileName: filename,
@ -655,7 +655,7 @@ export class MI2 extends EventEmitter implements IBackend {
const result = await this.sendCommand(`stack-list-variables --thread ${thread} --frame ${frame} --simple-values`); const result = await this.sendCommand(`stack-list-variables --thread ${thread} --frame ${frame} --simple-values`);
const variables = result.result("variables"); const variables = result.result("variables");
let ret: Variable[] = []; const ret: Variable[] = [];
for (const element of variables) { for (const element of variables) {
const key = MINode.valueOf(element, "name"); const key = MINode.valueOf(element, "name");
const value = MINode.valueOf(element, "value"); const value = MINode.valueOf(element, "value");
@ -712,7 +712,7 @@ export class MI2 extends EventEmitter implements IBackend {
//TODO: add `from` and `to` arguments //TODO: add `from` and `to` arguments
const res = await this.sendCommand(`var-list-children --all-values ${name}`); const res = await this.sendCommand(`var-list-children --all-values ${name}`);
const children = res.result("children") || []; const children = res.result("children") || [];
let omg: VariableObject[] = children.map(child => new VariableObject(child[1])); const omg: VariableObject[] = children.map(child => new VariableObject(child[1]));
return omg; return omg;
} }
@ -764,7 +764,7 @@ export class MI2 extends EventEmitter implements IBackend {
} }
sendCommand(command: string, suppressFailure: boolean = false): Thenable<MINode> { sendCommand(command: string, suppressFailure: boolean = false): Thenable<MINode> {
let sel = this.currentToken++; const sel = this.currentToken++;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.handlers[sel] = (node: MINode) => { this.handlers[sel] = (node: MINode) => {
if (node && node.resultRecords && node.resultRecords.resultClass === "error") { if (node && node.resultRecords && node.resultRecords.resultClass === "error") {

View file

@ -3,7 +3,7 @@ import { Breakpoint } from "../backend"
import * as ChildProcess from "child_process" import * as ChildProcess from "child_process"
import { posix } from "path" import { posix } from "path"
import * as nativePath from "path" import * as nativePath from "path"
let path = posix; const path = posix;
export class MI2_LLDB extends MI2 { export class MI2_LLDB extends MI2 {
protected initCommands(target: string, cwd: string, ssh: boolean = false, attach: boolean = false) { protected initCommands(target: string, cwd: string, ssh: boolean = false, attach: boolean = false) {
@ -15,7 +15,7 @@ export class MI2_LLDB extends MI2 {
if (!nativePath.isAbsolute(target)) if (!nativePath.isAbsolute(target))
target = nativePath.join(cwd, target); target = nativePath.join(cwd, target);
} }
var cmds = [ const cmds = [
this.sendCommand("gdb-set target-async on") this.sendCommand("gdb-set target-async on")
]; ];
if (!attach) if (!attach)
@ -43,7 +43,7 @@ export class MI2_LLDB extends MI2 {
clearBreakPoints(): Thenable<any> { clearBreakPoints(): Thenable<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let promises = []; const promises = [];
this.breakpoints.forEach((k, index) => { this.breakpoints.forEach((k, index) => {
promises.push(this.sendCommand("break-delete " + k).then((result) => { promises.push(this.sendCommand("break-delete " + k).then((result) => {
if (result.resultRecords.resultClass == "done") resolve(true); if (result.resultRecords.resultClass == "done") resolve(true);

View file

@ -5,22 +5,22 @@ import { MINode } from "../mi_parse"
export class MI2_Mago extends MI2_LLDB { export class MI2_Mago extends MI2_LLDB {
getStack(maxLevels: number, thread: number): Promise<Stack[]> { getStack(maxLevels: number, thread: number): Promise<Stack[]> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let command = "stack-list-frames"; const command = "stack-list-frames";
this.sendCommand(command).then((result) => { this.sendCommand(command).then((result) => {
let stack = result.resultRecords.results; const stack = result.resultRecords.results;
let ret: Stack[] = []; const ret: Stack[] = [];
let remaining = []; const remaining = [];
let addToStack = (element) => { const addToStack = (element) => {
let level = MINode.valueOf(element, "frame.level"); const level = MINode.valueOf(element, "frame.level");
let addr = MINode.valueOf(element, "frame.addr"); const addr = MINode.valueOf(element, "frame.addr");
let func = MINode.valueOf(element, "frame.func"); const func = MINode.valueOf(element, "frame.func");
let filename = MINode.valueOf(element, "file"); const filename = MINode.valueOf(element, "file");
let file = MINode.valueOf(element, "fullname"); const file = MINode.valueOf(element, "fullname");
let line = 0; let line = 0;
let lnstr = MINode.valueOf(element, "line"); const lnstr = MINode.valueOf(element, "line");
if (lnstr) if (lnstr)
line = parseInt(lnstr); line = parseInt(lnstr);
let from = parseInt(MINode.valueOf(element, "from")); const from = parseInt(MINode.valueOf(element, "from"));
ret.push({ ret.push({
address: addr, address: addr,
fileName: filename || "", fileName: filename || "",

View file

@ -4,18 +4,18 @@ export interface MIInfo {
resultRecords: { resultClass: string, results: [string, any][] }; resultRecords: { resultClass: string, results: [string, any][] };
} }
var octalMatch = /^[0-7]{3}/; const octalMatch = /^[0-7]{3}/;
function parseString(str: string): string { function parseString(str: string): string {
var ret = new Buffer(str.length * 4); const ret = new Buffer(str.length * 4);
var bufIndex = 0; let bufIndex = 0;
if (str[0] != '"' || str[str.length - 1] != '"') if (str[0] != '"' || str[str.length - 1] != '"')
throw new Error("Not a valid string"); throw new Error("Not a valid string");
str = str.slice(1, -1); str = str.slice(1, -1);
var escaped = false; let escaped = false;
for (var i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
if (escaped) { if (escaped) {
var m; let m;
if (str[i] == '\\') if (str[i] == '\\')
bufIndex += ret.write('\\', bufIndex); bufIndex += ret.write('\\', bufIndex);
else if (str[i] == '"') else if (str[i] == '"')
@ -81,8 +81,8 @@ export class MINode implements MIInfo {
static valueOf(start: any, path: string): any { static valueOf(start: any, path: string): any {
if (!start) if (!start)
return undefined; return undefined;
let pathRegex = /^\.?([a-zA-Z_\-][a-zA-Z0-9_\-]*)/; const pathRegex = /^\.?([a-zA-Z_\-][a-zA-Z0-9_\-]*)/;
let indexRegex = /^\[(\d+)\](?:$|\.)/; const indexRegex = /^\[(\d+)\](?:$|\.)/;
path = path.trim(); path = path.trim();
if (!path) if (!path)
return start; return start;
@ -92,9 +92,9 @@ export class MINode implements MIInfo {
if (target) { if (target) {
path = path.substr(target[0].length); path = path.substr(target[0].length);
if (current.length && typeof current != "string") { if (current.length && typeof current != "string") {
let found = []; const found = [];
for (let i = 0; i < current.length; i++) { for (let i = 0; i < current.length; i++) {
let element = current[i]; const element = current[i];
if (element[0] == target[1]) { if (element[0] == target[1]) {
found.push(element[1]); found.push(element[1]);
} }
@ -114,7 +114,7 @@ export class MINode implements MIInfo {
target = indexRegex.exec(path); target = indexRegex.exec(path);
if (target) { if (target) {
path = path.substr(target[0].length); path = path.substr(target[0].length);
let i = parseInt(target[1]); const i = parseInt(target[1]);
if (current.length && typeof current != "string" && i >= 0 && i < current.length) { if (current.length && typeof current != "string" && i >= 0 && i < current.length) {
current = current[i]; current = current[i];
} else if (i == 0) { } else if (i == 0) {
@ -154,21 +154,21 @@ export function parseMI(output: string): MINode {
*/ */
let token = undefined; let token = undefined;
let outOfBandRecord = []; const outOfBandRecord = [];
let resultRecords = undefined; let resultRecords = undefined;
let asyncRecordType = { const asyncRecordType = {
"*": "exec", "*": "exec",
"+": "status", "+": "status",
"=": "notify" "=": "notify"
}; };
let streamRecordType = { const streamRecordType = {
"~": "console", "~": "console",
"@": "target", "@": "target",
"&": "log" "&": "log"
}; };
let parseCString = () => { const parseCString = () => {
if (output[0] != '"') if (output[0] != '"')
return ""; return "";
let stringEnd = 1; let stringEnd = 1;
@ -199,11 +199,11 @@ export function parseMI(output: string): MINode {
let parseValue, parseCommaResult, parseCommaValue, parseResult; let parseValue, parseCommaResult, parseCommaValue, parseResult;
let parseTupleOrList = () => { const parseTupleOrList = () => {
if (output[0] != '{' && output[0] != '[') if (output[0] != '{' && output[0] != '[')
return undefined; return undefined;
let oldContent = output; const oldContent = output;
let canBeValueList = output[0] == '['; const canBeValueList = output[0] == '[';
output = output.substr(1); output = output.substr(1);
if (output[0] == '}' || output[0] == ']') { if (output[0] == '}' || output[0] == ']') {
output = output.substr(1); // ] or } output = output.substr(1); // ] or }
@ -212,9 +212,9 @@ export function parseMI(output: string): MINode {
if (canBeValueList) { if (canBeValueList) {
let value = parseValue(); let value = parseValue();
if (value) { // is value list if (value) { // is value list
let values = []; const values = [];
values.push(value); values.push(value);
let remaining = output; const remaining = output;
while ((value = parseCommaValue()) !== undefined) while ((value = parseCommaValue()) !== undefined)
values.push(value); values.push(value);
output = output.substr(1); // ] output = output.substr(1); // ]
@ -223,7 +223,7 @@ export function parseMI(output: string): MINode {
} }
let result = parseResult(); let result = parseResult();
if (result) { if (result) {
let results = []; const results = [];
results.push(result); results.push(result);
while (result = parseCommaResult()) while (result = parseCommaResult())
results.push(result); results.push(result);
@ -244,11 +244,11 @@ export function parseMI(output: string): MINode {
}; };
parseResult = () => { parseResult = () => {
let variableMatch = variableRegex.exec(output); const variableMatch = variableRegex.exec(output);
if (!variableMatch) if (!variableMatch)
return undefined; return undefined;
output = output.substr(variableMatch[0].length + 1); output = output.substr(variableMatch[0].length + 1);
let variable = variableMatch[1]; const variable = variableMatch[1];
return [variable, parseValue()]; return [variable, parseValue()];
}; };
@ -275,9 +275,9 @@ export function parseMI(output: string): MINode {
} }
if (match[2]) { if (match[2]) {
let classMatch = asyncClassRegex.exec(output); const classMatch = asyncClassRegex.exec(output);
output = output.substr(classMatch[1].length); output = output.substr(classMatch[1].length);
let asyncRecord = { const asyncRecord = {
isStream: false, isStream: false,
type: asyncRecordType[match[2]], type: asyncRecordType[match[2]],
asyncClass: classMatch[1], asyncClass: classMatch[1],
@ -289,7 +289,7 @@ export function parseMI(output: string): MINode {
outOfBandRecord.push(asyncRecord); outOfBandRecord.push(asyncRecord);
} }
else if (match[3]) { else if (match[3]) {
let streamRecord = { const streamRecord = {
isStream: true, isStream: true,
type: streamRecordType[match[3]], type: streamRecordType[match[3]],
content: parseCString() content: parseCString()

View file

@ -12,8 +12,8 @@ export function activate(context: vscode.ExtensionContext) {
vscode.window.showErrorMessage("No editor with valid file name active"); vscode.window.showErrorMessage("No editor with valid file name active");
return; return;
} }
var fileName = vscode.window.activeTextEditor.document.fileName; const fileName = vscode.window.activeTextEditor.document.fileName;
var ext = path.extname(fileName); const ext = path.extname(fileName);
return fileName.substr(0, fileName.length - ext.length); return fileName.substr(0, fileName.length - ext.length);
})); }));
context.subscriptions.push(vscode.commands.registerCommand("code-debug.getFileBasenameNoExt", () => { context.subscriptions.push(vscode.commands.registerCommand("code-debug.getFileBasenameNoExt", () => {
@ -21,22 +21,22 @@ export function activate(context: vscode.ExtensionContext) {
vscode.window.showErrorMessage("No editor with valid file name active"); vscode.window.showErrorMessage("No editor with valid file name active");
return; return;
} }
var fileName = path.basename(vscode.window.activeTextEditor.document.fileName); const fileName = path.basename(vscode.window.activeTextEditor.document.fileName);
var ext = path.extname(fileName); const ext = path.extname(fileName);
return fileName.substr(0, fileName.length - ext.length); return fileName.substr(0, fileName.length - ext.length);
})); }));
} }
var memoryLocationRegex = /^0x[0-9a-f]+$/; const memoryLocationRegex = /^0x[0-9a-f]+$/;
function getMemoryRange(range: string) { function getMemoryRange(range: string) {
if (!range) if (!range)
return undefined; return undefined;
range = range.replace(/\s+/g, "").toLowerCase(); range = range.replace(/\s+/g, "").toLowerCase();
var index; let index;
if ((index = range.indexOf("+")) != -1) { if ((index = range.indexOf("+")) != -1) {
var from = range.substr(0, index); const from = range.substr(0, index);
var length = range.substr(index + 1); let length = range.substr(index + 1);
if (!memoryLocationRegex.exec(from)) if (!memoryLocationRegex.exec(from))
return undefined; return undefined;
if (memoryLocationRegex.exec(length)) if (memoryLocationRegex.exec(length))
@ -44,8 +44,8 @@ function getMemoryRange(range: string) {
return "from=" + encodeURIComponent(from) + "&length=" + encodeURIComponent(length); return "from=" + encodeURIComponent(from) + "&length=" + encodeURIComponent(length);
} }
else if ((index = range.indexOf("-")) != -1) { else if ((index = range.indexOf("-")) != -1) {
var from = range.substr(0, index); const from = range.substr(0, index);
var to = range.substr(index + 1); const to = range.substr(index + 1);
if (!memoryLocationRegex.exec(from)) if (!memoryLocationRegex.exec(from))
return undefined; return undefined;
if (!memoryLocationRegex.exec(to)) if (!memoryLocationRegex.exec(to))
@ -58,7 +58,7 @@ function getMemoryRange(range: string) {
} }
function examineMemory() { function examineMemory() {
let socketlists = path.join(os.tmpdir(), "code-debug-sockets"); const socketlists = path.join(os.tmpdir(), "code-debug-sockets");
if (!fs.existsSync(socketlists)) { if (!fs.existsSync(socketlists)) {
if (process.platform == "win32") if (process.platform == "win32")
return vscode.window.showErrorMessage("This command is not available on windows"); return vscode.window.showErrorMessage("This command is not available on windows");
@ -72,7 +72,7 @@ function examineMemory() {
else else
return vscode.window.showErrorMessage("No debugging sessions available"); return vscode.window.showErrorMessage("No debugging sessions available");
} }
var pickedFile = (file) => { const pickedFile = (file) => {
vscode.window.showInputBox({ placeHolder: "Memory Location or Range", validateInput: range => getMemoryRange(range) === undefined ? "Range must either be in format 0xF00-0xF01, 0xF100+32 or 0xABC154" : "" }).then(range => { vscode.window.showInputBox({ placeHolder: "Memory Location or Range", validateInput: range => getMemoryRange(range) === undefined ? "Range must either be in format 0xF00-0xF01, 0xF100+32 or 0xABC154" : "" }).then(range => {
vscode.commands.executeCommand("vscode.previewHtml", vscode.Uri.parse("debugmemory://" + file + "#" + getMemoryRange(range))); vscode.commands.executeCommand("vscode.previewHtml", vscode.Uri.parse("debugmemory://" + file + "#" + getMemoryRange(range)));
}); });
@ -91,12 +91,12 @@ function examineMemory() {
class MemoryContentProvider implements vscode.TextDocumentContentProvider { class MemoryContentProvider implements vscode.TextDocumentContentProvider {
provideTextDocumentContent(uri: vscode.Uri, token: vscode.CancellationToken): Thenable<string> { provideTextDocumentContent(uri: vscode.Uri, token: vscode.CancellationToken): Thenable<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var conn = net.connect(path.join(os.tmpdir(), "code-debug-sockets", uri.authority)); const conn = net.connect(path.join(os.tmpdir(), "code-debug-sockets", uri.authority));
var from, to; let from, to;
var highlightAt = -1; let highlightAt = -1;
var splits = uri.fragment.split("&"); const splits = uri.fragment.split("&");
if (splits[0].split("=")[0] == "at") { if (splits[0].split("=")[0] == "at") {
var loc = parseInt(splits[0].split("=")[1].substr(2), 16); const loc = parseInt(splits[0].split("=")[1].substr(2), 16);
highlightAt = 64; highlightAt = 64;
from = Math.max(loc - 64, 0); from = Math.max(loc - 64, 0);
to = Math.max(loc + 768, 0); to = Math.max(loc + 768, 0);
@ -116,14 +116,14 @@ class MemoryContentProvider implements vscode.TextDocumentContentProvider {
return reject("Negative Range"); return reject("Negative Range");
conn.write("examineMemory " + JSON.stringify([from, to - from + 1])); conn.write("examineMemory " + JSON.stringify([from, to - from + 1]));
conn.once("data", data => { conn.once("data", data => {
var formattedCode = ""; let formattedCode = "";
var hexString = data.toString(); const hexString = data.toString();
var x = 0; let x = 0;
var asciiLine = ""; let asciiLine = "";
var byteNo = 0; let byteNo = 0;
for (var i = 0; i < hexString.length; i += 2) { for (let i = 0; i < hexString.length; i += 2) {
var digit = hexString.substr(i, 2); const digit = hexString.substr(i, 2);
var digitNum = parseInt(digit, 16); const digitNum = parseInt(digit, 16);
if (digitNum >= 32 && digitNum <= 126) if (digitNum >= 32 && digitNum <= 126)
asciiLine += String.fromCharCode(digitNum); asciiLine += String.fromCharCode(digitNum);
else else
@ -140,7 +140,7 @@ class MemoryContentProvider implements vscode.TextDocumentContentProvider {
byteNo++; byteNo++;
} }
if (x > 0) { if (x > 0) {
for (var i = 0; i <= 16 - x; i++) { for (let i = 0; i <= 16 - x; i++) {
formattedCode += " "; formattedCode += " ";
} }
formattedCode += asciiLine; formattedCode += asciiLine;

View file

@ -11,8 +11,8 @@ import * as net from "net";
import * as os from "os"; import * as os from "os";
import * as fs from "fs"; import * as fs from "fs";
let resolve = posix.resolve; const resolve = posix.resolve;
let relative = posix.relative; const relative = posix.relative;
class ExtendedVariable { class ExtendedVariable {
constructor(public name, public options) { constructor(public name, public options) {
@ -58,10 +58,10 @@ export class MI2DebugSession extends DebugSession {
try { try {
this.commandServer = net.createServer(c => { this.commandServer = net.createServer(c => {
c.on("data", data => { c.on("data", data => {
var rawCmd = data.toString(); const rawCmd = data.toString();
var spaceIndex = rawCmd.indexOf(" "); const spaceIndex = rawCmd.indexOf(" ");
var func = rawCmd; let func = rawCmd;
var args = []; let args = [];
if (spaceIndex != -1) { if (spaceIndex != -1) {
func = rawCmd.substr(0, spaceIndex); func = rawCmd.substr(0, spaceIndex);
args = JSON.parse(rawCmd.substr(spaceIndex + 1)); args = JSON.parse(rawCmd.substr(spaceIndex + 1));
@ -110,19 +110,19 @@ export class MI2DebugSession extends DebugSession {
} }
protected handleBreakpoint(info: MINode) { protected handleBreakpoint(info: MINode) {
let event = new StoppedEvent("breakpoint", parseInt(info.record("thread-id"))); const event = new StoppedEvent("breakpoint", parseInt(info.record("thread-id")));
(event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all"; (event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all";
this.sendEvent(event); this.sendEvent(event);
} }
protected handleBreak(info: MINode) { protected handleBreak(info: MINode) {
let event = new StoppedEvent("step", parseInt(info.record("thread-id"))); const event = new StoppedEvent("step", parseInt(info.record("thread-id")));
(event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all"; (event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all";
this.sendEvent(event); this.sendEvent(event);
} }
protected handlePause(info: MINode) { protected handlePause(info: MINode) {
let event = new StoppedEvent("user request", parseInt(info.record("thread-id"))); const event = new StoppedEvent("user request", parseInt(info.record("thread-id")));
(event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all"; (event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all";
this.sendEvent(event); this.sendEvent(event);
} }
@ -131,7 +131,7 @@ export class MI2DebugSession extends DebugSession {
if (!this.started) if (!this.started)
this.crashed = true; this.crashed = true;
if (!this.quit) { if (!this.quit) {
let event = new StoppedEvent("exception", parseInt(info.record("thread-id"))); const event = new StoppedEvent("exception", parseInt(info.record("thread-id")));
(event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all"; (event as DebugProtocol.StoppedEvent).body.allThreadsStopped = info.record("stopped-threads") == "all";
this.sendEvent(event); this.sendEvent(event);
} }
@ -175,7 +175,7 @@ export class MI2DebugSession extends DebugSession {
name = `${parent.name}.${name}`; name = `${parent.name}.${name}`;
} }
let res = await this.miDebugger.varAssign(name, args.value); const res = await this.miDebugger.varAssign(name, args.value);
response.body = { response.body = {
value: res.result("value") value: res.result("value")
}; };
@ -194,14 +194,14 @@ export class MI2DebugSession extends DebugSession {
} }
protected setFunctionBreakPointsRequest(response: DebugProtocol.SetFunctionBreakpointsResponse, args: DebugProtocol.SetFunctionBreakpointsArguments): void { protected setFunctionBreakPointsRequest(response: DebugProtocol.SetFunctionBreakpointsResponse, args: DebugProtocol.SetFunctionBreakpointsArguments): void {
let cb = (() => { const cb = (() => {
this.debugReady = true; this.debugReady = true;
let all = []; const all = [];
args.breakpoints.forEach(brk => { args.breakpoints.forEach(brk => {
all.push(this.miDebugger.addBreakPoint({ raw: brk.name, condition: brk.condition, countCondition: brk.hitCondition })); all.push(this.miDebugger.addBreakPoint({ raw: brk.name, condition: brk.condition, countCondition: brk.hitCondition }));
}); });
Promise.all(all).then(brkpoints => { Promise.all(all).then(brkpoints => {
let finalBrks = []; const finalBrks = [];
brkpoints.forEach(brkp => { brkpoints.forEach(brkp => {
if (brkp[0]) if (brkp[0])
finalBrks.push({ line: brkp[1].line }); finalBrks.push({ line: brkp[1].line });
@ -221,7 +221,7 @@ export class MI2DebugSession extends DebugSession {
} }
protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void { protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
let cb = (() => { const cb = (() => {
this.debugReady = true; this.debugReady = true;
this.miDebugger.clearBreakPoints().then(() => { this.miDebugger.clearBreakPoints().then(() => {
let path = args.source.path; let path = args.source.path;
@ -229,11 +229,11 @@ export class MI2DebugSession extends DebugSession {
path = relative(this.trimCWD.replace(/\\/g, "/"), path.replace(/\\/g, "/")); path = relative(this.trimCWD.replace(/\\/g, "/"), path.replace(/\\/g, "/"));
path = resolve(this.switchCWD.replace(/\\/g, "/"), path.replace(/\\/g, "/")); path = resolve(this.switchCWD.replace(/\\/g, "/"), path.replace(/\\/g, "/"));
} }
let all = args.breakpoints.map(brk => { const all = args.breakpoints.map(brk => {
return this.miDebugger.addBreakPoint({ file: path, line: brk.line, condition: brk.condition, countCondition: brk.hitCondition }); return this.miDebugger.addBreakPoint({ file: path, line: brk.line, condition: brk.condition, countCondition: brk.hitCondition });
}); });
Promise.all(all).then(brkpoints => { Promise.all(all).then(brkpoints => {
let finalBrks = []; const finalBrks = [];
brkpoints.forEach(brkp => { brkpoints.forEach(brkp => {
// TODO: Currently all breakpoints returned are marked as verified, // TODO: Currently all breakpoints returned are marked as verified,
// which leads to verified breakpoints on a broken lldb. // which leads to verified breakpoints on a broken lldb.
@ -292,7 +292,7 @@ export class MI2DebugSession extends DebugSession {
protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void { protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void {
this.miDebugger.getStack(args.levels, args.threadId).then(stack => { this.miDebugger.getStack(args.levels, args.threadId).then(stack => {
let ret: StackFrame[] = []; const ret: StackFrame[] = [];
stack.forEach(element => { stack.forEach(element => {
let source = null; let source = null;
let file = element.file; let file = element.file;
@ -358,14 +358,14 @@ export class MI2DebugSession extends DebugSession {
id = this.variableHandles.get(args.variablesReference); id = this.variableHandles.get(args.variablesReference);
} }
let createVariable = (arg, options?) => { const createVariable = (arg, options?) => {
if (options) if (options)
return this.variableHandles.create(new ExtendedVariable(arg, options)); return this.variableHandles.create(new ExtendedVariable(arg, options));
else else
return this.variableHandles.create(arg); return this.variableHandles.create(arg);
}; };
let findOrCreateVariable = (varObj: VariableObject): number => { const findOrCreateVariable = (varObj: VariableObject): number => {
let id: number; let id: number;
if (this.variableHandlesReverse.hasOwnProperty(varObj.name)) { if (this.variableHandlesReverse.hasOwnProperty(varObj.name)) {
id = this.variableHandlesReverse[varObj.name]; id = this.variableHandlesReverse[varObj.name];
@ -380,12 +380,12 @@ export class MI2DebugSession extends DebugSession {
if (typeof id == "number") { if (typeof id == "number") {
let stack: Variable[]; let stack: Variable[];
try { try {
let [threadId, level] = this.frameIdToThreadAndLevel(id); const [threadId, level] = this.frameIdToThreadAndLevel(id);
stack = await this.miDebugger.getStackVariables(threadId, level); stack = await this.miDebugger.getStackVariables(threadId, level);
for (const variable of stack) { for (const variable of stack) {
if (this.useVarObjects) { if (this.useVarObjects) {
try { try {
let varObjName = `var_${id}_${variable.name}`; const varObjName = `var_${id}_${variable.name}`;
let varObj: VariableObject; let varObj: VariableObject;
try { try {
const changes = await this.miDebugger.varUpdate(varObjName); const changes = await this.miDebugger.varUpdate(varObjName);
@ -508,22 +508,22 @@ export class MI2DebugSession extends DebugSession {
} }
} }
else if (id instanceof ExtendedVariable) { else if (id instanceof ExtendedVariable) {
let varReq = id; const varReq = id;
if (varReq.options.arg) { if (varReq.options.arg) {
let strArr = []; const strArr = [];
let argsPart = true; let argsPart = true;
let arrIndex = 0; let arrIndex = 0;
let submit = () => { const submit = () => {
response.body = { response.body = {
variables: strArr variables: strArr
}; };
this.sendResponse(response); this.sendResponse(response);
}; };
let addOne = async () => { const addOne = async () => {
// TODO: this evals on an (effectively) unknown thread for multithreaded programs. // TODO: this evals on an (effectively) unknown thread for multithreaded programs.
const variable = await this.miDebugger.evalExpression(JSON.stringify(`${varReq.name}+${arrIndex})`), 0, 0); const variable = await this.miDebugger.evalExpression(JSON.stringify(`${varReq.name}+${arrIndex})`), 0, 0);
try { try {
let expanded = expandValue(createVariable, variable.result("value"), varReq.name, variable); const expanded = expandValue(createVariable, variable.result("value"), varReq.name, variable);
if (!expanded) { if (!expanded) {
this.sendErrorResponse(response, 15, `Could not expand variable`); this.sendErrorResponse(response, 15, `Could not expand variable`);
} }
@ -641,7 +641,7 @@ export class MI2DebugSession extends DebugSession {
} }
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
let [threadId, level] = this.frameIdToThreadAndLevel(args.frameId); const [threadId, level] = this.frameIdToThreadAndLevel(args.frameId);
if (args.context == "watch" || args.context == "hover") { if (args.context == "watch" || args.context == "hover") {
this.miDebugger.evalExpression(args.expression, threadId, level).then((res) => { this.miDebugger.evalExpression(args.expression, threadId, level).then((res) => {
response.body = { response.body = {

View file

@ -2,7 +2,7 @@ import * as assert from 'assert';
import { expandValue, isExpandable } from '../src/backend/gdb_expansion'; import { expandValue, isExpandable } from '../src/backend/gdb_expansion';
suite("GDB Value Expansion", () => { suite("GDB Value Expansion", () => {
let variableCreate = (variable) => { return { expanded: variable }; }; const variableCreate = (variable) => { return { expanded: variable }; };
test("Various values", () => { test("Various values", () => {
assert.strictEqual(isExpandable(`false`), 0); assert.strictEqual(isExpandable(`false`), 0);
assert.equal(expandValue(variableCreate, `false`), "false"); assert.equal(expandValue(variableCreate, `false`), "false");
@ -104,7 +104,7 @@ suite("GDB Value Expansion", () => {
}); });
test("Simple node", () => { test("Simple node", () => {
assert.strictEqual(isExpandable(`{a = false, b = 5, c = 0x0, d = "foobar"}`), 1); assert.strictEqual(isExpandable(`{a = false, b = 5, c = 0x0, d = "foobar"}`), 1);
let variables = expandValue(variableCreate, `{a = false, b = 5, c = 0x0, d = "foobar"}`); const variables = expandValue(variableCreate, `{a = false, b = 5, c = 0x0, d = "foobar"}`);
assert.equal(variables.length, 4); assert.equal(variables.length, 4);
assert.equal(variables[0].name, "a"); assert.equal(variables[0].name, "a");
assert.equal(variables[0].value, "false"); assert.equal(variables[0].value, "false");
@ -116,9 +116,9 @@ suite("GDB Value Expansion", () => {
assert.equal(variables[3].value, `"foobar"`); assert.equal(variables[3].value, `"foobar"`);
}); });
test("Complex node", () => { test("Complex node", () => {
let node = `{quit = false, _views = {{view = 0x7ffff7ece1e8, renderer = 0x7ffff7eccc50, world = 0x7ffff7ece480}}, deltaTimer = {_flagStarted = false, _timeStart = {length = 0}, _timeMeasured = {length = 0}}, _start = {callbacks = 0x0}, _stop = {callbacks = 0x0}}`; const node = `{quit = false, _views = {{view = 0x7ffff7ece1e8, renderer = 0x7ffff7eccc50, world = 0x7ffff7ece480}}, deltaTimer = {_flagStarted = false, _timeStart = {length = 0}, _timeMeasured = {length = 0}}, _start = {callbacks = 0x0}, _stop = {callbacks = 0x0}}`;
assert.strictEqual(isExpandable(node), 1); assert.strictEqual(isExpandable(node), 1);
let variables = expandValue(variableCreate, node); const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [ assert.deepEqual(variables, [
{ {
name: "quit", name: "quit",
@ -224,9 +224,9 @@ suite("GDB Value Expansion", () => {
]); ]);
}); });
test("Simple node with errors", () => { test("Simple node with errors", () => {
let node = `{_enableMipMaps = false, _minFilter = <incomplete type>, _magFilter = <incomplete type>, _wrapX = <incomplete type>, _wrapY = <incomplete type>, _inMode = 6408, _mode = 6408, _id = 1, _width = 1024, _height = 1024}`; const node = `{_enableMipMaps = false, _minFilter = <incomplete type>, _magFilter = <incomplete type>, _wrapX = <incomplete type>, _wrapY = <incomplete type>, _inMode = 6408, _mode = 6408, _id = 1, _width = 1024, _height = 1024}`;
assert.strictEqual(isExpandable(node), 1); assert.strictEqual(isExpandable(node), 1);
let variables = expandValue(variableCreate, node); const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [ assert.deepEqual(variables, [
{ {
name: "_enableMipMaps", name: "_enableMipMaps",
@ -281,9 +281,9 @@ suite("GDB Value Expansion", () => {
]); ]);
}); });
test("lldb strings", () => { test("lldb strings", () => {
let node = `{ name = {...} }`; const node = `{ name = {...} }`;
assert.strictEqual(isExpandable(node), 1); assert.strictEqual(isExpandable(node), 1);
let variables = expandValue(variableCreate, node); const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [ assert.deepEqual(variables, [
{ {
name: "name", name: "name",
@ -293,8 +293,8 @@ suite("GDB Value Expansion", () => {
]); ]);
}); });
test("float values", () => { test("float values", () => {
let node = `{ intval1 = 123, floatval1 = 123.456, intval2 = 3, floatval2 = 234.45 }`; const node = `{ intval1 = 123, floatval1 = 123.456, intval2 = 3, floatval2 = 234.45 }`;
let variables = expandValue(variableCreate, node); const variables = expandValue(variableCreate, node);
assert.deepEqual(variables, [ assert.deepEqual(variables, [
{ name: "intval1", value: "123", variablesReference: 0 }, { name: "intval1", value: "123", variablesReference: 0 },

View file

@ -10,7 +10,7 @@
// to report the results back to the caller. When the tests are finished, return // to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none. // a possible error to the callback or null if none.
var testRunner = require('vscode/lib/testrunner'); const testRunner = require('vscode/lib/testrunner');
// You can directly control Mocha options by uncommenting the following lines // You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info

View file

@ -3,7 +3,7 @@ import { parseMI, MINode } from '../src/backend/mi_parse';
suite("MI Parse", () => { suite("MI Parse", () => {
test("Simple out of band record", () => { test("Simple out of band record", () => {
let parsed = parseMI(`4=thread-exited,id="3",group-id="i1"`); const parsed = parseMI(`4=thread-exited,id="3",group-id="i1"`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, 4); assert.equal(parsed.token, 4);
assert.equal(parsed.outOfBandRecord.length, 1); assert.equal(parsed.outOfBandRecord.length, 1);
@ -15,7 +15,7 @@ suite("MI Parse", () => {
assert.equal(parsed.resultRecords, undefined); assert.equal(parsed.resultRecords, undefined);
}); });
test("Console stream output with new line", () => { test("Console stream output with new line", () => {
let parsed = parseMI(`~"[Thread 0x7fffe993a700 (LWP 11002) exited]\\n"`); const parsed = parseMI(`~"[Thread 0x7fffe993a700 (LWP 11002) exited]\\n"`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, undefined); assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1); assert.equal(parsed.outOfBandRecord.length, 1);
@ -40,21 +40,21 @@ suite("MI Parse", () => {
assert.equal(parsed.resultRecords, undefined); assert.equal(parsed.resultRecords, undefined);
}); });
test("Empty line", () => { test("Empty line", () => {
let parsed = parseMI(``); const parsed = parseMI(``);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, undefined); assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 0); assert.equal(parsed.outOfBandRecord.length, 0);
assert.equal(parsed.resultRecords, undefined); assert.equal(parsed.resultRecords, undefined);
}); });
test("'(gdb)' line", () => { test("'(gdb)' line", () => {
let parsed = parseMI(`(gdb)`); const parsed = parseMI(`(gdb)`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, undefined); assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 0); assert.equal(parsed.outOfBandRecord.length, 0);
assert.equal(parsed.resultRecords, undefined); assert.equal(parsed.resultRecords, undefined);
}); });
test("Simple result record", () => { test("Simple result record", () => {
let parsed = parseMI(`1^running`); const parsed = parseMI(`1^running`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, 1); assert.equal(parsed.token, 1);
assert.equal(parsed.outOfBandRecord.length, 0); assert.equal(parsed.outOfBandRecord.length, 0);
@ -63,7 +63,7 @@ suite("MI Parse", () => {
assert.equal(parsed.resultRecords.results.length, 0); assert.equal(parsed.resultRecords.results.length, 0);
}); });
test("Advanced out of band record (Breakpoint hit)", () => { test("Advanced out of band record (Breakpoint hit)", () => {
let parsed = parseMI(`*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000004e807f",func="D main",args=[{name="args",value="..."}],file="source/app.d",fullname="/path/to/source/app.d",line="157"},thread-id="1",stopped-threads="all",core="0"`); const parsed = parseMI(`*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000004e807f",func="D main",args=[{name="args",value="..."}],file="source/app.d",fullname="/path/to/source/app.d",line="157"},thread-id="1",stopped-threads="all",core="0"`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, undefined); assert.equal(parsed.token, undefined);
assert.equal(parsed.outOfBandRecord.length, 1); assert.equal(parsed.outOfBandRecord.length, 1);
@ -73,7 +73,7 @@ suite("MI Parse", () => {
assert.deepEqual(parsed.outOfBandRecord[0].output[0], ["reason", "breakpoint-hit"]); assert.deepEqual(parsed.outOfBandRecord[0].output[0], ["reason", "breakpoint-hit"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[1], ["disp", "keep"]); assert.deepEqual(parsed.outOfBandRecord[0].output[1], ["disp", "keep"]);
assert.deepEqual(parsed.outOfBandRecord[0].output[2], ["bkptno", "1"]); assert.deepEqual(parsed.outOfBandRecord[0].output[2], ["bkptno", "1"]);
let frame = [ const frame = [
["addr", "0x00000000004e807f"], ["addr", "0x00000000004e807f"],
["func", "D main"], ["func", "D main"],
["args", [[["name", "args"], ["value", "..."]]]], ["args", [[["name", "args"], ["value", "..."]]]],
@ -88,14 +88,14 @@ suite("MI Parse", () => {
assert.equal(parsed.resultRecords, undefined); assert.equal(parsed.resultRecords, undefined);
}); });
test("Advanced result record", () => { test("Advanced result record", () => {
let parsed = parseMI(`2^done,asm_insns=[src_and_asm_line={line="134",file="source/app.d",fullname="/path/to/source/app.d",line_asm_insn=[{address="0x00000000004e7da4",func-name="_Dmain",offset="0",inst="push %rbp"},{address="0x00000000004e7da5",func-name="_Dmain",offset="1",inst="mov %rsp,%rbp"}]}]`); const parsed = parseMI(`2^done,asm_insns=[src_and_asm_line={line="134",file="source/app.d",fullname="/path/to/source/app.d",line_asm_insn=[{address="0x00000000004e7da4",func-name="_Dmain",offset="0",inst="push %rbp"},{address="0x00000000004e7da5",func-name="_Dmain",offset="1",inst="mov %rsp,%rbp"}]}]`);
assert.ok(parsed); assert.ok(parsed);
assert.equal(parsed.token, 2); assert.equal(parsed.token, 2);
assert.equal(parsed.outOfBandRecord.length, 0); assert.equal(parsed.outOfBandRecord.length, 0);
assert.notEqual(parsed.resultRecords, undefined); assert.notEqual(parsed.resultRecords, undefined);
assert.equal(parsed.resultRecords.resultClass, "done"); assert.equal(parsed.resultRecords.resultClass, "done");
assert.equal(parsed.resultRecords.results.length, 1); assert.equal(parsed.resultRecords.results.length, 1);
let asm_insns = [ const asm_insns = [
"asm_insns", "asm_insns",
[ [
[ [
@ -129,7 +129,7 @@ suite("MI Parse", () => {
assert.equal(parsed.result("asm_insns.src_and_asm_line.line_asm_insn[1].address"), "0x00000000004e7da5"); assert.equal(parsed.result("asm_insns.src_and_asm_line.line_asm_insn[1].address"), "0x00000000004e7da5");
}); });
test("valueof children", () => { test("valueof children", () => {
let obj = [ const obj = [
[ [
"frame", "frame",
[ [
@ -174,17 +174,17 @@ suite("MI Parse", () => {
assert.equal(MINode.valueOf(obj[1], "@frame.line"), undefined); assert.equal(MINode.valueOf(obj[1], "@frame.line"), undefined);
}); });
test("empty string values", () => { test("empty string values", () => {
let parsed = parseMI(`15^done,register-names=["r0","pc","","xpsr","","control"]`); const parsed = parseMI(`15^done,register-names=["r0","pc","","xpsr","","control"]`);
let result = parsed.result('register-names'); const result = parsed.result('register-names');
assert.deepEqual(result, ["r0", "pc", "", "xpsr", "", "control"]); assert.deepEqual(result, ["r0", "pc", "", "xpsr", "", "control"]);
}); });
test("empty array values", () => { test("empty array values", () => {
let parsed = parseMI(`15^done,foo={x=[],y="y"}`); const parsed = parseMI(`15^done,foo={x=[],y="y"}`);
assert.deepEqual(parsed.result('foo.x'), []); assert.deepEqual(parsed.result('foo.x'), []);
assert.equal(parsed.result('foo.y'), "y"); assert.equal(parsed.result('foo.y'), "y");
}); });
test("empty object values", () => { test("empty object values", () => {
let parsed = parseMI(`15^done,foo={x={},y="y"}`); const parsed = parseMI(`15^done,foo={x={},y="y"}`);
assert.deepEqual(parsed.result('foo.x'), {}); assert.deepEqual(parsed.result('foo.x'), {});
assert.equal(parsed.result('foo.y'), "y"); assert.equal(parsed.result('foo.y'), "y");
}); });

View file

@ -7,10 +7,15 @@
"es6" "es6"
], ],
"sourceMap": true, "sourceMap": true,
"rootDir": "." "rootDir": ".",
"plugins": [
{
"name": "tslint-language-service"
}
]
}, },
"exclude": [ "exclude": [
"node_modules", "node_modules",
".vscode-test" ".vscode-test"
] ]
} }

7
tslint.json Normal file
View file

@ -0,0 +1,7 @@
{
"defaultSeverity": "error",
"rules": {
"no-var-keyword": true,
"prefer-const": true
}
}