提交 6ce07caa 编写于 作者: I isidor

debug: respect variable.evaluateName

fixes #10210
上级 be90e836
......@@ -768,9 +768,8 @@ export class AddToWatchExpressionsAction extends AbstractDebugAction {
}
public run(): TPromise<any> {
const process = this.debugService.getViewModel().focusedProcess;
const type = process ? process.session.configuration.type : null;
return this.debugService.addWatchExpression(model.getFullExpressionName(this.expression, type));
const name = this.expression instanceof model.Variable ? this.expression.evaluateName : this.expression.name;
return this.debugService.addWatchExpression(name);
}
}
......
......@@ -57,35 +57,6 @@ export function evaluateExpression(stackFrame: debug.IStackFrame, expression: Ex
});
}
const notPropertySyntax = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
const arrayElementSyntax = /\[.*\]$/;
export function getFullExpressionName(expression: debug.IExpression, sessionType: string): string {
let names = [expression.name];
if (expression instanceof Variable) {
let v = (<Variable>expression).parent;
while (v instanceof Variable || v instanceof Expression) {
names.push((<Variable>v).name);
v = (<Variable>v).parent;
}
}
names = names.reverse();
let result = null;
names.forEach(name => {
if (!result) {
result = name;
} else if (arrayElementSyntax.test(name) || (sessionType === 'node' && !notPropertySyntax.test(name))) {
// use safe way to access node properties a['property_name']. Also handles array elements.
result = name && name.indexOf('[') === 0 ? `${result}${name}` : `${result}['${name}']`;
} else {
result = `${result}.${name}`;
}
});
return result;
}
export class OutputElement implements debug.ITreeElement {
private static ID_COUNTER = 0;
......@@ -203,7 +174,7 @@ export abstract class ExpressionContainer implements debug.IExpressionContainer
for (let i = 0; i < numberOfChunks; i++) {
const start = this.startOfVariables + i * chunkSize;
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
childrenArray.push(new Variable(this.stackFrame, this, this.reference, `[${start}..${start + count - 1}]`, '', null, count, null, true, start));
childrenArray.push(new Variable(this.stackFrame, this, this.reference, `[${start}..${start + count - 1}]`, '', '', null, count, null, true, start));
}
return childrenArray;
......@@ -236,9 +207,9 @@ export abstract class ExpressionContainer implements debug.IExpressionContainer
filter
}).then(response => {
return response && response.body && response.body.variables ? arrays.distinct(response.body.variables.filter(v => !!v), v => v.name).map(
v => new Variable(this.stackFrame, this, v.variablesReference, v.name, v.value, v.namedVariables, v.indexedVariables, v.type)
v => new Variable(this.stackFrame, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.type)
) : [];
}, (e: Error) => [new Variable(this.stackFrame, this, 0, null, e.message, 0, 0, null, false)]);
}, (e: Error) => [new Variable(this.stackFrame, this, 0, null, e.message, '', 0, 0, null, false)]);
}
// The adapter explicitly sents the children count of an expression only if there are lots of children which should be chunked.
......@@ -271,12 +242,15 @@ export class Variable extends ExpressionContainer implements debug.IExpression {
// Used to show the error message coming from the adapter when setting the value #7807
public errorMessage: string;
private static NOT_PROPERTY_SYNTAX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
private static ARRAY_ELEMENT_SYNTAX = /\[.*\]$/;
constructor(
stackFrame: debug.IStackFrame,
public parent: debug.IExpressionContainer,
reference: number,
public name: string,
private _evaluateName: string,
value: string,
namedVariables: number,
indexedVariables: number,
......@@ -288,6 +262,34 @@ export class Variable extends ExpressionContainer implements debug.IExpression {
this.value = massageValue(value);
}
public get evaluateName(): string {
if (this._evaluateName) {
return this._evaluateName;
}
let names = [this.name];
let v = this.parent;
while (v instanceof Variable || v instanceof Expression) {
names.push((<Variable>v).name);
v = (<Variable>v).parent;
}
names = names.reverse();
let result = null;
names.forEach(name => {
if (!result) {
result = name;
} else if (Variable.ARRAY_ELEMENT_SYNTAX.test(name) || (this.stackFrame.thread.process.session.configuration.type === 'node' && !Variable.NOT_PROPERTY_SYNTAX.test(name))) {
// use safe way to access node properties a['property_name']. Also handles array elements.
result = name && name.indexOf('[') === 0 ? `${result}${name}` : `${result}['${name}']`;
} else {
result = `${result}.${name}`;
}
});
return result;
}
public setVariable(value: string): TPromise<any> {
return this.stackFrame.thread.process.session.setVariable({
name: this.name,
......
......@@ -7,7 +7,7 @@ import nls = require('vs/nls');
import actions = require('vs/base/common/actions');
import { TPromise } from 'vs/base/common/winjs.base';
import { clipboard } from 'electron';
import { Variable, getFullExpressionName } from 'vs/workbench/parts/debug/common/debugModel';
import { Variable } from 'vs/workbench/parts/debug/common/debugModel';
import { IDebugService } from 'vs/workbench/parts/debug/common/debug';
export class CopyValueAction extends actions.Action {
......@@ -22,7 +22,7 @@ export class CopyValueAction extends actions.Action {
if (this.value instanceof Variable) {
const frameId = this.debugService.getViewModel().focusedStackFrame.frameId;
const process = this.debugService.getViewModel().focusedProcess;
return process.session.evaluate({ expression: getFullExpressionName(this.value, process.session.configuration.type), frameId }).then(result => {
return process.session.evaluate({ expression: this.value.evaluateName, frameId }).then(result => {
clipboard.writeText(result.body.result);
}, err => clipboard.writeText(this.value.value));
}
......
......@@ -364,22 +364,4 @@ suite('Debug - Model', () => {
model.removeReplExpressions();
assert.equal(model.getReplElements().length, 0);
});
// Utils
test('full expression name', () => {
const type = 'node';
assert.equal(debugmodel.getFullExpressionName(new debugmodel.Expression(null, false), type), null);
assert.equal(debugmodel.getFullExpressionName(new debugmodel.Expression('son', false), type), 'son');
const process = new debugmodel.Process('mockProcess', rawSession);
const thread = new debugmodel.Thread(process, 'mockthread', 1);
const stackFrame = new debugmodel.StackFrame(thread, 1, null, 'app.js', 1, 1);
const scope = new debugmodel.Scope(stackFrame, 'myscope', 1, false, 1, 0);
const son = new debugmodel.Variable(stackFrame, new debugmodel.Variable(stackFrame, new debugmodel.Variable(stackFrame, scope, 0, 'grandfather', '75', 1, 0), 0, 'father', '45', 1, 0), 0, 'son', '20', 1, 0);
assert.equal(debugmodel.getFullExpressionName(son, type), 'grandfather.father.son');
const grandson = new debugmodel.Variable(stackFrame, son, 0, '/weird_name', '1', 0, 0);
assert.equal(debugmodel.getFullExpressionName(grandson, type), 'grandfather.father.son[\'/weird_name\']');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册