Reuse variable objects, utilize var-update

Same variables now have same ids in each VariablesResponse.
This allows vscode to keep track of changes properly and prevents
collapsing of all variables after every step.
This commit is contained in:
gentoo90 2017-05-25 23:49:19 +03:00
commit 2551dba725
3 changed files with 137 additions and 54 deletions

View file

@ -1,3 +1,6 @@
import { MINode } from "./mi_parse";
import { DebugProtocol } from "vscode-debugprotocol/lib/debugProtocol";
export interface Breakpoint {
file?: string;
line?: number;
@ -59,4 +62,62 @@ export interface IBackend {
isReady(): boolean;
changeVariable(name: string, rawValue: string): Thenable<any>;
examineMemory(from: number, to: number): Thenable<any>;
}
}
export class VariableObject {
name: string;
exp: string;
numchild: number;
type: string;
value: string;
threadId: string;
frozen: boolean;
dynamic: boolean;
displayhint: string;
has_more: boolean;
id: number;
constructor(node: any) {
this.name = MINode.valueOf(node, "name");
this.exp = MINode.valueOf(node, "exp");
this.numchild = parseInt(MINode.valueOf(node, "numchild"));
this.type = MINode.valueOf(node, "type");
this.value = MINode.valueOf(node, "value");
this.threadId = MINode.valueOf(node, "thread-id");
this.frozen = !!MINode.valueOf(node, "frozen");
this.dynamic = !!MINode.valueOf(node, "dynamic");
this.displayhint = MINode.valueOf(node, "displayhint");
// TODO: use has_more when it's > 0
this.has_more = !!MINode.valueOf(node, "has_more");
}
public applyChanges(node: MINode) {
this.value = MINode.valueOf(node, "value");
if (!!MINode.valueOf(node, "type_changed")) {
this.type = MINode.valueOf(node, "new_type");
}
this.dynamic = !!MINode.valueOf(node, "dynamic");
this.displayhint = MINode.valueOf(node, "displayhint");
this.has_more = !!MINode.valueOf(node, "has_more");
}
public isCompound(): boolean {
return this.numchild > 0 ||
this.value === "{...}" ||
(this.dynamic && (this.displayhint === "array" || this.displayhint === "map"));
}
public toProtocolVariable(): DebugProtocol.Variable {
let res: DebugProtocol.Variable = {
name: this.exp,
evaluateName: this.name,
value: (this.value === void 0) ? "<unknown>" : this.value,
type: this.type,
// kind: this.displayhint,
variablesReference: this.id
};
if (this.displayhint) {
res.kind = this.displayhint;
}
return res;
}
}

View file

@ -1,4 +1,4 @@
import { Breakpoint, IBackend, Stack, SSHArguments, Variable } from "../backend"
import { Breakpoint, IBackend, Stack, SSHArguments, Variable, VariableObject } from "../backend"
import * as ChildProcess from "child_process"
import { EventEmitter } from "events"
import { parseMI, MINode } from '../mi_parse';
@ -661,17 +661,33 @@ export class MI2 extends EventEmitter implements IBackend {
});
}
async varCreate(expression: string): Promise<MINode> {
async varCreate(expression: string, name: string = "-"): Promise<VariableObject> {
if (trace)
this.log("stderr", "varCreate");
return this.sendCommand(`var-create - * "${expression}"`);
const res = await this.sendCommand(`var-create ${name} @ "${expression}"`);
return new VariableObject(res.result(""));
}
async varListChildren(name: string): Promise<MINode> {
async varEvalExpression(name: string): Promise < MINode > {
if (trace)
this.log("stderr", "varEvalExpression");
return this.sendCommand(`var-evaluate-expression ${name}`);
}
async varListChildren(name: string): Promise<VariableObject[]> {
if (trace)
this.log("stderr", "varListChildren");
//TODO: add `from` and `to` arguments
return this.sendCommand(`var-list-children --simple-values ${name}`);
const res = await this.sendCommand(`var-list-children --all-values ${name}`);
const children = res.result("children");
let omg: VariableObject[] = children.map(child => new VariableObject(child[1]));
return omg;
}
async varUpdate(name: string = "*"): Promise<MINode> {
if (trace)
this.log("stderr", "varUpdate");
return this.sendCommand(`var-update --all-values ${name}`)
}
logNoNewLine(type: string, msg: string) {