diff --git a/src/backend/backend.ts b/src/backend/backend.ts index d85cd267..1a04c7bc 100644 --- a/src/backend/backend.ts +++ b/src/backend/backend.ts @@ -123,3 +123,38 @@ export class VariableObject { return res; } } + +// from https://gist.github.com/justmoon/15511f92e5216fa2624b#gistcomment-1928632 +export interface MIError extends Error { + readonly name: string; + readonly message: string; + readonly source: string; +}; +export interface MIErrorConstructor { + new (message: string, source: string): MIError; + readonly prototype: MIError; +} + +export const MIError: MIErrorConstructor = class MIError { + readonly name: string; + readonly message: string; + readonly source: string; + public constructor(message: string, source: string) { + Object.defineProperty(this, 'name', { + get: () => (this.constructor as any).name, + }); + Object.defineProperty(this, 'message', { + get: () => message, + }); + Object.defineProperty(this, 'source', { + get: () => source, + }); + Error.captureStackTrace(this, this.constructor); + } + + public toString() { + return `${this.message} (from ${this.source})`; + } +}; +Object.setPrototypeOf(MIError as any, Object.create(Error.prototype)); +MIError.prototype.constructor = MIError; diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts index 9a895940..18bd5ca3 100644 --- a/src/backend/mi2/mi2.ts +++ b/src/backend/mi2/mi2.ts @@ -1,4 +1,4 @@ -import { Breakpoint, IBackend, Stack, SSHArguments, Variable, VariableObject } from "../backend" +import { Breakpoint, IBackend, Stack, SSHArguments, Variable, VariableObject, MIError } from "../backend" import * as ChildProcess from "child_process" import { EventEmitter } from "events" import { parseMI, MINode } from '../mi_parse'; @@ -679,7 +679,7 @@ export class MI2 extends EventEmitter implements IBackend { this.log("stderr", "varListChildren"); //TODO: add `from` and `to` arguments 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])); return omg; } @@ -729,11 +729,11 @@ export class MI2 extends EventEmitter implements IBackend { this.handlers[sel] = (node: MINode) => { if (node && node.resultRecords && node.resultRecords.resultClass === "error") { if (suppressFailure) { - this.log("stderr", "WARNING: Error executing command '" + command + "'"); + this.log("stderr", `WARNING: Error executing command '${command}'`); resolve(node); } else - reject((node.result("msg") || "Internal error") + " (from " + command + ")"); + reject(new MIError(node.result("msg") || "Internal error", command)); } else resolve(node); diff --git a/src/mibase.ts b/src/mibase.ts index aaeef587..0b623fd8 100644 --- a/src/mibase.ts +++ b/src/mibase.ts @@ -1,6 +1,6 @@ import { DebugSession, InitializedEvent, TerminatedEvent, StoppedEvent, OutputEvent, Thread, StackFrame, Scope, Source, Handles } from 'vscode-debugadapter'; import { DebugProtocol } from 'vscode-debugprotocol'; -import { Breakpoint, IBackend, Variable, VariableObject, ValuesFormattingMode } from './backend/backend'; +import { Breakpoint, IBackend, Variable, VariableObject, ValuesFormattingMode, MIError } from './backend/backend'; import { MINode } from './backend/mi_parse'; import { expandValue, isExpandable } from './backend/gdb_expansion'; import { MI2 } from './backend/mi2/mi2'; @@ -335,24 +335,30 @@ export class MI2DebugSession extends DebugSession { for (const variable of stack) { if (this.useVarObjects) { try { + let varObjName = `var_${variable.name}`; let varObj: VariableObject; try { - const changes = await this.miDebugger.varUpdate(variable.name); + const changes = await this.miDebugger.varUpdate(varObjName); const changelist = changes.result("changelist"); changelist.forEach((change) => { const name = MINode.valueOf(change, "name"); - const vId = this.variableHandlesReverse[variable.name]; + const vId = this.variableHandlesReverse[varObjName]; const v = this.variableHandles.get(vId) as any; v.applyChanges(change); }); - const varId = this.variableHandlesReverse[variable.name]; + const varId = this.variableHandlesReverse[varObjName]; varObj = this.variableHandles.get(varId) as any; } catch (err) { - varObj = await this.miDebugger.varCreate(variable.name, variable.name); - const varId = findOrCreateVariable(varObj); - varObj.exp = variable.name; - varObj.id = varId; + if (err instanceof MIError && err.message == "Variable object not found") { + varObj = await this.miDebugger.varCreate(variable.name, varObjName); + const varId = findOrCreateVariable(varObj); + varObj.exp = variable.name; + varObj.id = varId; + } + else { + throw err; + } } variables.push(varObj.toProtocolVariable()); }