@@ -8,19 +8,19 @@ import { RunOnceScheduler } from 'vs/base/common/async';
88import * as dom from 'vs/base/browser/dom' ;
99import { CollapseAction } from 'vs/workbench/browser/viewlet' ;
1010import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet' ;
11- import { IDebugService , IExpression , IScope , CONTEXT_VARIABLES_FOCUSED , IStackFrame , CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT } from 'vs/workbench/contrib/debug/common/debug' ;
11+ import { IDebugService , IExpression , IScope , CONTEXT_VARIABLES_FOCUSED , IStackFrame , CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT , IDataBreakpointInfoResponse , CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED , CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT } from 'vs/workbench/contrib/debug/common/debug' ;
1212import { Variable , Scope , ErrorScope , StackFrame } from 'vs/workbench/contrib/debug/common/debugModel' ;
1313import { IContextMenuService } from 'vs/platform/contextview/browser/contextView' ;
1414import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding' ;
1515import { renderViewTree , renderVariable , IInputBoxOptions , AbstractExpressionsRenderer , IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView' ;
16- import { IAction , Action , Separator } from 'vs/base/common/actions' ;
16+ import { IAction } from 'vs/base/common/actions' ;
1717import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions' ;
1818import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
1919import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer' ;
2020import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget' ;
2121import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list' ;
2222import { ITreeRenderer , ITreeNode , ITreeMouseEvent , ITreeContextMenuEvent , IAsyncDataSource } from 'vs/base/browser/ui/tree/tree' ;
23- import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
23+ import { IInstantiationService , ServicesAccessor } from 'vs/platform/instantiation/common/instantiation' ;
2424import { Emitter } from 'vs/base/common/event' ;
2525import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService' ;
2626import { IAsyncDataTreeViewState } from 'vs/base/browser/ui/tree/asyncDataTree' ;
@@ -36,11 +36,19 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
3636import { withUndefinedAsNull } from 'vs/base/common/types' ;
3737import { IMenuService , IMenu , MenuId } from 'vs/platform/actions/common/actions' ;
3838import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem' ;
39+ import { CommandsRegistry } from 'vs/platform/commands/common/commands' ;
3940
4041const $ = dom . $ ;
4142let forgetScopes = true ;
4243
4344export const variableSetEmitter = new Emitter < void > ( ) ;
45+ let variableInternalContext : Variable | undefined ;
46+ let dataBreakpointInfoResponse : IDataBreakpointInfoResponse | undefined ;
47+
48+ interface IVariablesContext {
49+ container : DebugProtocol . Variable | DebugProtocol . Scope ;
50+ variable : DebugProtocol . Variable ;
51+ }
4452
4553export class VariablesView extends ViewPane {
4654
@@ -51,6 +59,8 @@ export class VariablesView extends ViewPane {
5159 private autoExpandedScopes = new Set < string > ( ) ;
5260 private menu : IMenu ;
5361 private debugProtocolVariableMenuContext : IContextKey < string > ;
62+ private breakWhenValueChangesSupported : IContextKey < boolean > ;
63+ private variableEvaluateName : IContextKey < boolean > ;
5464
5565 constructor (
5666 options : IViewletViewOptions ,
@@ -60,7 +70,6 @@ export class VariablesView extends ViewPane {
6070 @IConfigurationService configurationService : IConfigurationService ,
6171 @IInstantiationService instantiationService : IInstantiationService ,
6272 @IViewDescriptorService viewDescriptorService : IViewDescriptorService ,
63- @IClipboardService private readonly clipboardService : IClipboardService ,
6473 @IContextKeyService contextKeyService : IContextKeyService ,
6574 @IOpenerService openerService : IOpenerService ,
6675 @IThemeService themeService : IThemeService ,
@@ -72,6 +81,8 @@ export class VariablesView extends ViewPane {
7281 this . menu = menuService . createMenu ( MenuId . DebugVariablesContext , contextKeyService ) ;
7382 this . _register ( this . menu ) ;
7483 this . debugProtocolVariableMenuContext = CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT . bindTo ( contextKeyService ) ;
84+ this . breakWhenValueChangesSupported = CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED . bindTo ( contextKeyService ) ;
85+ this . variableEvaluateName = CONTEXT_VARIABLE_EVALUATE_NAME_PRESENT . bindTo ( contextKeyService ) ;
7586
7687 // Use scheduler to prevent unnecessary flashing
7788 this . onFocusStackFrameScheduler = new RunOnceScheduler ( async ( ) => {
@@ -193,45 +204,25 @@ export class VariablesView extends ViewPane {
193204 const variable = e . element ;
194205 if ( variable instanceof Variable && ! ! variable . value ) {
195206 this . debugProtocolVariableMenuContext . set ( variable . variableMenuContext || '' ) ;
196-
197- const actions : IAction [ ] = [ ] ;
207+ variableInternalContext = variable ;
198208 const session = this . debugService . getViewModel ( ) . focusedSession ;
199- if ( session && session . capabilities . supportsSetVariable ) {
200- actions . push ( new Action ( 'workbench.setValue' , nls . localize ( 'setValue' , "Set Value" ) , undefined , true , async ( ) => {
201- this . debugService . getViewModel ( ) . setSelectedExpression ( variable ) ;
202- } ) ) ;
203- }
204- actions . push ( this . instantiationService . createInstance ( CopyValueAction , CopyValueAction . ID , CopyValueAction . LABEL , variable , 'variables' ) ) ;
205- if ( variable . evaluateName ) {
206- actions . push ( new Action ( 'debug.copyEvaluatePath' , nls . localize ( 'copyAsExpression' , "Copy as Expression" ) , undefined , true , async ( ) => {
207- await this . clipboardService . writeText ( variable . evaluateName ! ) ;
208- } ) ) ;
209- actions . push ( new Separator ( ) ) ;
210- actions . push ( new Action ( 'debug.addToWatchExpressions' , nls . localize ( 'addToWatchExpressions' , "Add to Watch" ) , undefined , true , async ( ) => {
211- this . debugService . addWatchExpression ( variable . evaluateName ) ;
212- } ) ) ;
213- }
209+ this . variableEvaluateName . set ( ! ! variable . evaluateName ) ;
210+ this . breakWhenValueChangesSupported . reset ( ) ;
214211 if ( session && session . capabilities . supportsDataBreakpoints ) {
215212 const response = await session . dataBreakpointInfo ( variable . name , variable . parent . reference ) ;
216- const dataid = response ?. dataId ;
217- if ( response && dataid ) {
218- actions . push ( new Separator ( ) ) ;
219- actions . push ( new Action ( 'debug.breakWhenValueChanges' , nls . localize ( 'breakWhenValueChanges' , "Break When Value Changes" ) , undefined , true , async ( ) => {
220- await this . debugService . addDataBreakpoint ( response . description , dataid , ! ! response . canPersist , response . accessTypes ) ;
221- } ) ) ;
222- }
213+ const dataBreakpointId = response ?. dataId ;
214+ this . breakWhenValueChangesSupported . set ( ! ! dataBreakpointId ) ;
223215 }
224216
225- const context = {
217+ const context : IVariablesContext = {
226218 container : ( variable . parent as ( Variable | Scope ) ) . toDebugProtocolObject ( ) ,
227219 variable : variable . toDebugProtocolObject ( )
228220 } ;
221+ const actions : IAction [ ] = [ ] ;
229222 const actionsDisposable = createAndFillInContextMenuActions ( this . menu , { arg : context , shouldForwardArgs : false } , actions , this . contextMenuService ) ;
230-
231223 this . contextMenuService . showContextMenu ( {
232224 getAnchor : ( ) => e . anchor ,
233225 getActions : ( ) => actions ,
234- getActionsContext : ( ) => variable ,
235226 onHide : ( ) => dispose ( actionsDisposable )
236227 } ) ;
237228 }
@@ -392,3 +383,54 @@ class VariablesAccessibilityProvider implements IListAccessibilityProvider<IExpr
392383 return null ;
393384 }
394385}
386+
387+ export const SET_VARIABLE_ID = 'debug.setVariable' ;
388+ CommandsRegistry . registerCommand ( {
389+ id : SET_VARIABLE_ID ,
390+ handler : ( accessor : ServicesAccessor ) => {
391+ const debugService = accessor . get ( IDebugService ) ;
392+ debugService . getViewModel ( ) . setSelectedExpression ( variableInternalContext ) ;
393+ }
394+ } ) ;
395+
396+ export const COPY_VALUE_ID = 'debug.copyValue' ;
397+ CommandsRegistry . registerCommand ( {
398+ id : COPY_VALUE_ID ,
399+ handler : async ( accessor : ServicesAccessor ) => {
400+ const instantiationService = accessor . get ( IInstantiationService ) ;
401+ if ( variableInternalContext ) {
402+ const action = instantiationService . createInstance ( CopyValueAction , CopyValueAction . ID , CopyValueAction . LABEL , variableInternalContext , 'variables' ) ;
403+ await action . run ( ) ;
404+ }
405+ }
406+ } ) ;
407+
408+ export const BREAK_WHEN_VALUE_CHANGES_ID = 'debug.breakWhenValueChanges' ;
409+ CommandsRegistry . registerCommand ( {
410+ id : BREAK_WHEN_VALUE_CHANGES_ID ,
411+ handler : async ( accessor : ServicesAccessor ) => {
412+ const debugService = accessor . get ( IDebugService ) ;
413+ if ( dataBreakpointInfoResponse ) {
414+ await debugService . addDataBreakpoint ( dataBreakpointInfoResponse . description , dataBreakpointInfoResponse . dataId ! , ! ! dataBreakpointInfoResponse . canPersist , dataBreakpointInfoResponse . accessTypes ) ;
415+ }
416+ }
417+ } ) ;
418+
419+ export const COPY_EVALUATE_PATH_ID = 'debug.copyEvaluatePath' ;
420+ CommandsRegistry . registerCommand ( {
421+ id : COPY_EVALUATE_PATH_ID ,
422+ handler : async ( accessor : ServicesAccessor , context : IVariablesContext ) => {
423+ const clipboardService = accessor . get ( IClipboardService ) ;
424+ await clipboardService . writeText ( context . variable . evaluateName ! ) ;
425+ }
426+ } ) ;
427+
428+ export const ADD_TO_WATCH_ID = 'debug.addToWatchExpressions' ;
429+ CommandsRegistry . registerCommand ( {
430+ id : ADD_TO_WATCH_ID ,
431+ handler : async ( accessor : ServicesAccessor , context : IVariablesContext ) => {
432+ const debugService = accessor . get ( IDebugService ) ;
433+ debugService . addWatchExpression ( context . variable . evaluateName ) ;
434+ }
435+ } ) ;
436+
0 commit comments