提交 c5429332 编写于 作者: I isidor

debug: editing variable support

fixes #7744
上级 e520a420
...@@ -82,7 +82,8 @@ export function renderVariable(tree: tree.ITree, variable: model.Variable, data: ...@@ -82,7 +82,8 @@ export function renderVariable(tree: tree.ITree, variable: model.Variable, data:
} }
} }
function renderRenameBox(debugService: debug.IDebugService, contextViewService: IContextViewService, tree: tree.ITree, element: any, container: HTMLElement, placeholder: string, ariaLabel: string): void { function renderRenameBox(debugService: debug.IDebugService, contextViewService: IContextViewService, tree: tree.ITree, element: any,
container: HTMLElement, initialValue: string, placeholder: string, ariaLabel: string): void {
let inputBoxContainer = dom.append(container, $('.inputBoxContainer')); let inputBoxContainer = dom.append(container, $('.inputBoxContainer'));
let inputBox = new inputbox.InputBox(inputBoxContainer, contextViewService, { let inputBox = new inputbox.InputBox(inputBoxContainer, contextViewService, {
validationOptions: { validationOptions: {
...@@ -93,7 +94,7 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService: ...@@ -93,7 +94,7 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService:
ariaLabel: ariaLabel ariaLabel: ariaLabel
}); });
inputBox.value = element.name ? element.name : ''; inputBox.value = initialValue ? initialValue : '';
inputBox.focus(); inputBox.focus();
let disposed = false; let disposed = false;
...@@ -110,6 +111,10 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService: ...@@ -110,6 +111,10 @@ function renderRenameBox(debugService: debug.IDebugService, contextViewService:
debugService.renameFunctionBreakpoint(element.getId(), inputBox.value).done(null, errors.onUnexpectedError); debugService.renameFunctionBreakpoint(element.getId(), inputBox.value).done(null, errors.onUnexpectedError);
} else if (element instanceof model.FunctionBreakpoint && !element.name) { } else if (element instanceof model.FunctionBreakpoint && !element.name) {
debugService.removeFunctionBreakpoints(element.getId()).done(null, errors.onUnexpectedError); debugService.removeFunctionBreakpoints(element.getId()).done(null, errors.onUnexpectedError);
} else if (element instanceof model.Variable && renamed) {
debugService.setVariable(element, inputBox.value)
// if everything went fine we need to refresh that tree element since his value updated
.done(() => tree.refresh(element, false), errors.onUnexpectedError);
} }
tree.clearHighlight(); tree.clearHighlight();
...@@ -525,11 +530,13 @@ export class VariablesActionProvider implements renderer.IActionProvider { ...@@ -525,11 +530,13 @@ export class VariablesActionProvider implements renderer.IActionProvider {
public getSecondaryActions(tree: tree.ITree, element: any): TPromise<actions.IAction[]> { public getSecondaryActions(tree: tree.ITree, element: any): TPromise<actions.IAction[]> {
let actions: actions.Action[] = []; let actions: actions.Action[] = [];
const variable = <model.Variable>element; const variable = <model.Variable>element;
actions.push(this.instantiationService.createInstance(debugactions.AddToWatchExpressionsAction, debugactions.AddToWatchExpressionsAction.ID, debugactions.AddToWatchExpressionsAction.LABEL, variable));
if (variable.reference === 0) { if (variable.reference === 0) {
actions.push(this.instantiationService.createInstance(debugactions.SetValueAction, debugactions.SetValueAction.ID, debugactions.SetValueAction.LABEL, variable));
actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable)); actions.push(this.instantiationService.createInstance(debugactions.CopyValueAction, debugactions.CopyValueAction.ID, debugactions.CopyValueAction.LABEL, variable));
actions.push(new actionbar.Separator());
} }
actions.push(this.instantiationService.createInstance(debugactions.AddToWatchExpressionsAction, debugactions.AddToWatchExpressionsAction.ID, debugactions.AddToWatchExpressionsAction.LABEL, variable));
return TPromise.as(actions); return TPromise.as(actions);
} }
...@@ -587,6 +594,13 @@ export class VariablesRenderer implements tree.IRenderer { ...@@ -587,6 +594,13 @@ export class VariablesRenderer implements tree.IRenderer {
private static SCOPE_TEMPLATE_ID = 'scope'; private static SCOPE_TEMPLATE_ID = 'scope';
private static VARIABLE_TEMPLATE_ID = 'variable'; private static VARIABLE_TEMPLATE_ID = 'variable';
constructor(
@debug.IDebugService private debugService: debug.IDebugService,
@IContextViewService private contextViewService: IContextViewService
) {
// noop
}
public getHeight(tree: tree.ITree, element: any): number { public getHeight(tree: tree.ITree, element: any): number {
return 22; return 22;
} }
...@@ -622,7 +636,12 @@ export class VariablesRenderer implements tree.IRenderer { ...@@ -622,7 +636,12 @@ export class VariablesRenderer implements tree.IRenderer {
if (templateId === VariablesRenderer.SCOPE_TEMPLATE_ID) { if (templateId === VariablesRenderer.SCOPE_TEMPLATE_ID) {
this.renderScope(element, templateData); this.renderScope(element, templateData);
} else { } else {
renderVariable(tree, element, templateData, true); if (element === this.debugService.getViewModel().getSelectedExpression()) {
renderRenameBox(this.debugService, this.contextViewService, tree, element, (<IVariableTemplateData>templateData).expression,
(<model.Variable>element).value, null, nls.localize('variableValueAriaLabel', "Type new variable value"));
} else {
renderVariable(tree, element, templateData, true);
}
} }
} }
...@@ -798,7 +817,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer { ...@@ -798,7 +817,7 @@ export class WatchExpressionsRenderer implements tree.IRenderer {
private renderWatchExpression(tree: tree.ITree, watchExpression: debug.IExpression, data: IWatchExpressionTemplateData): void { private renderWatchExpression(tree: tree.ITree, watchExpression: debug.IExpression, data: IWatchExpressionTemplateData): void {
let selectedExpression = this.debugService.getViewModel().getSelectedExpression(); let selectedExpression = this.debugService.getViewModel().getSelectedExpression();
if ((selectedExpression instanceof model.Expression && selectedExpression.getId() === watchExpression.getId()) || (watchExpression instanceof model.Expression && !watchExpression.name)) { if ((selectedExpression instanceof model.Expression && selectedExpression.getId() === watchExpression.getId()) || (watchExpression instanceof model.Expression && !watchExpression.name)) {
renderRenameBox(this.debugService, this.contextViewService, tree, watchExpression, data.expression, nls.localize('watchExpressionPlaceholder', "Expression to watch"), nls.localize('watchExpressionInputAriaLabel', "Type watch expression")); renderRenameBox(this.debugService, this.contextViewService, tree, watchExpression, data.expression, watchExpression.name, nls.localize('watchExpressionPlaceholder', "Expression to watch"), nls.localize('watchExpressionInputAriaLabel', "Type watch expression"));
} }
data.actionBar.context = watchExpression; data.actionBar.context = watchExpression;
...@@ -1071,7 +1090,7 @@ export class BreakpointsRenderer implements tree.IRenderer { ...@@ -1071,7 +1090,7 @@ export class BreakpointsRenderer implements tree.IRenderer {
private renderFunctionBreakpoint(tree: tree.ITree, functionBreakpoint: debug.IFunctionBreakpoint, data: IFunctionBreakpointTemplateData): void { private renderFunctionBreakpoint(tree: tree.ITree, functionBreakpoint: debug.IFunctionBreakpoint, data: IFunctionBreakpointTemplateData): void {
const selected = this.debugService.getViewModel().getSelectedFunctionBreakpoint(); const selected = this.debugService.getViewModel().getSelectedFunctionBreakpoint();
if (!functionBreakpoint.name || (selected && selected.getId() === functionBreakpoint.getId())) { if (!functionBreakpoint.name || (selected && selected.getId() === functionBreakpoint.getId())) {
renderRenameBox(this.debugService, this.contextViewService, tree, functionBreakpoint, data.breakpoint, nls.localize('functionBreakpointPlaceholder', "Function to break on"), nls.localize('functionBreakPointInputAriaLabel', "Type function breakpoint")); renderRenameBox(this.debugService, this.contextViewService, tree, functionBreakpoint, data.breakpoint, functionBreakpoint.name, nls.localize('functionBreakpointPlaceholder', "Function to break on"), nls.localize('functionBreakPointInputAriaLabel', "Type function breakpoint"));
} else { } else {
this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]); this.debugService.getModel().areBreakpointsActivated() ? tree.removeTraits('disabled', [functionBreakpoint]) : tree.addTraits('disabled', [functionBreakpoint]);
data.name.textContent = functionBreakpoint.name; data.name.textContent = functionBreakpoint.name;
......
...@@ -98,6 +98,21 @@ export class VariablesView extends viewlet.CollapsibleViewletView { ...@@ -98,6 +98,21 @@ export class VariablesView extends viewlet.CollapsibleViewletView {
this.telemetryService.publicLog('debug/variables/selected'); this.telemetryService.publicLog('debug/variables/selected');
} }
})); }));
this.toDispose.push(this.debugService.getViewModel().onDidSelectExpression(expression => {
if (!expression || !(expression instanceof Variable)) {
return;
}
this.tree.refresh(expression, false).then(() => {
this.tree.setHighlight(expression);
this.tree.addOneTimeDisposableListener(events.EventType.HIGHLIGHT, (e: tree.IHighlightEvent) => {
if (!e.highlight) {
this.debugService.getViewModel().setSelectedExpression(null);
}
});
}).done(null, errors.onUnexpectedError);
}));
} }
private onFocusStackFrame(stackFrame: debug.IStackFrame): void { private onFocusStackFrame(stackFrame: debug.IStackFrame): void {
......
...@@ -358,6 +358,11 @@ export interface IDebugService { ...@@ -358,6 +358,11 @@ export interface IDebugService {
*/ */
appendReplOutput(value: string, severity?: severity): void; appendReplOutput(value: string, severity?: severity): void;
/**
* Sets the value for the variable against the debug adapter.
*/
setVariable(variable: IExpression, value: string): TPromise<void>;
/** /**
* Adds a new watch expression and evaluates it against the debug adapter. * Adds a new watch expression and evaluates it against the debug adapter.
*/ */
......
...@@ -543,6 +543,28 @@ export class EditorConditionalBreakpointAction extends EditorAction { ...@@ -543,6 +543,28 @@ export class EditorConditionalBreakpointAction extends EditorAction {
} }
} }
export class SetValueAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.setValue';
static LABEL = nls.localize('setValue', "Set Value");
constructor(id: string, label: string, private variable: model.Variable, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, null, debugService, keybindingService);
}
public run(): TPromise<any> {
if (this.variable instanceof model.Variable) {
this.debugService.getViewModel().setSelectedExpression(this.variable);
}
return TPromise.as(null);
}
protected isEnabled(state: debug.State): boolean {
const session = this.debugService.getActiveSession();
return super.isEnabled(state) && state === debug.State.Stopped && session && session.configuration.capabilities.supportsSetVariable;
}
}
export class CopyValueAction extends AbstractDebugAction { export class CopyValueAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.copyValue'; static ID = 'workbench.debug.viewlet.action.copyValue';
static LABEL = nls.localize('copyValue', "Copy Value"); static LABEL = nls.localize('copyValue', "Copy Value");
......
...@@ -483,6 +483,18 @@ export class DebugService implements debug.IDebugService { ...@@ -483,6 +483,18 @@ export class DebugService implements debug.IDebugService {
this.model.removeReplExpressions(); this.model.removeReplExpressions();
} }
public setVariable(variable: debug.IExpression, value: string): TPromise<any> {
if (!this.session || !(variable instanceof model.Variable)) {
return TPromise.as(null);
}
return this.session.setVarialbe({
name: variable.name,
value,
variablesReference: (<model.Variable>variable).parent.reference
}).then(() => variable.value = value);
}
public addWatchExpression(name: string): TPromise<void> { public addWatchExpression(name: string): TPromise<void> {
return this.model.addWatchExpression(this.session, this.viewModel.getFocusedStackFrame(), name); return this.model.addWatchExpression(this.session, this.viewModel.getFocusedStackFrame(), name);
} }
......
...@@ -246,6 +246,10 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes ...@@ -246,6 +246,10 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes
return this.send('pause', args); return this.send('pause', args);
} }
public setVarialbe(args: DebugProtocol.SetVariableArguments): TPromise<DebugProtocol.SetVariableResponse> {
return this.send('setVariable', args);
}
public disconnect(restart = false, force = false): TPromise<DebugProtocol.DisconnectResponse> { public disconnect(restart = false, force = false): TPromise<DebugProtocol.DisconnectResponse> {
if (this.stopServerPending && force) { if (this.stopServerPending && force) {
return this.stopServer(); return this.stopServer();
......
...@@ -126,6 +126,10 @@ export class MockDebugService implements debug.IDebugService { ...@@ -126,6 +126,10 @@ export class MockDebugService implements debug.IDebugService {
public pause(threadId: number): TPromise<any> { public pause(threadId: number): TPromise<any> {
return TPromise.as(null); return TPromise.as(null);
} }
public setVariable(variable: debug.IExpression, value: string): TPromise<any> {
return TPromise.as(null);
}
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册