@@ -8,8 +8,8 @@ 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 , IViewModel } from 'vs/workbench/contrib/debug/common/debug' ;
12- import { Variable , Scope , ErrorScope } from 'vs/workbench/contrib/debug/common/debugModel' ;
11+ import { IDebugService , IExpression , IScope , CONTEXT_VARIABLES_FOCUSED , IStackFrame } from 'vs/workbench/contrib/debug/common/debug' ;
12+ import { 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' ;
@@ -34,6 +34,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views';
3434import { IOpenerService } from 'vs/platform/opener/common/opener' ;
3535import { IThemeService } from 'vs/platform/theme/common/themeService' ;
3636import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry' ;
37+ import { withUndefinedAsNull } from 'vs/base/common/types' ;
3738
3839const $ = dom . $ ;
3940let forgetScopes = true ;
@@ -44,8 +45,8 @@ export class VariablesView extends ViewPane {
4445
4546 private onFocusStackFrameScheduler : RunOnceScheduler ;
4647 private needsRefresh = false ;
47- private tree ! : WorkbenchAsyncDataTree < IViewModel | IExpression | IScope , IExpression | IScope , FuzzyScore > ;
48- private savedViewState : IAsyncDataTreeViewState | undefined ;
48+ private tree ! : WorkbenchAsyncDataTree < IStackFrame | null , IExpression | IScope , FuzzyScore > ;
49+ private savedViewState = new Map < string , IAsyncDataTreeViewState > ( ) ;
4950
5051 constructor (
5152 options : IViewletViewOptions ,
@@ -68,26 +69,23 @@ export class VariablesView extends ViewPane {
6869 const stackFrame = this . debugService . getViewModel ( ) . focusedStackFrame ;
6970
7071 this . needsRefresh = false ;
71- if ( stackFrame && this . savedViewState ) {
72- await this . tree . setInput ( this . debugService . getViewModel ( ) , this . savedViewState ) ;
73- this . savedViewState = undefined ;
74- } else {
75- if ( ! stackFrame ) {
76- // We have no stackFrame, save tree state before it is cleared
77- this . savedViewState = this . tree . getViewState ( ) ;
78- }
79- await this . tree . updateChildren ( ) ;
80- if ( stackFrame ) {
81- const scopes = await stackFrame . getScopes ( ) ;
82- // Expand the first scope if it is not expensive and if there is no expansion state (all are collapsed)
83- if ( scopes . every ( s => this . tree . getNode ( s ) . collapsed ) && scopes . length > 0 ) {
84- const toExpand = scopes . find ( s => ! s . expensive ) ;
85- if ( toExpand ) {
86- this . tree . expand ( toExpand ) ;
87- }
88- }
89- }
72+ const input = this . tree . getInput ( ) ;
73+ if ( input ) {
74+ this . savedViewState . set ( input . getId ( ) , this . tree . getViewState ( ) ) ;
75+ }
76+ if ( ! stackFrame ) {
77+ await this . tree . setInput ( null ) ;
78+ return ;
79+ }
80+
81+ const viewState = this . savedViewState . get ( stackFrame . getId ( ) ) ;
82+ await this . tree . setInput ( stackFrame , viewState ) ;
9083
84+ // Automatically expand the first scope if it is not expensive and if all scopes are collapsed
85+ const scopes = await stackFrame . getScopes ( ) ;
86+ const toExpand = scopes . find ( s => ! s . expensive ) ;
87+ if ( toExpand && scopes . every ( s => this . tree . isCollapsed ( s ) ) ) {
88+ await this . tree . expand ( toExpand ) ;
9189 }
9290 } , 400 ) ;
9391 }
@@ -99,7 +97,7 @@ export class VariablesView extends ViewPane {
9997 dom . addClass ( container , 'debug-variables' ) ;
10098 const treeContainer = renderViewTree ( container ) ;
10199
102- this . tree = < WorkbenchAsyncDataTree < IViewModel | IExpression | IScope , IExpression | IScope , FuzzyScore > > this . instantiationService . createInstance ( WorkbenchAsyncDataTree , 'VariablesView' , treeContainer , new VariablesDelegate ( ) ,
100+ this . tree = < WorkbenchAsyncDataTree < IStackFrame | null , IExpression | IScope , FuzzyScore > > this . instantiationService . createInstance ( WorkbenchAsyncDataTree , 'VariablesView' , treeContainer , new VariablesDelegate ( ) ,
103101 [ this . instantiationService . createInstance ( VariablesRenderer ) , new ScopesRenderer ( ) , new ScopeErrorRenderer ( ) ] ,
104102 new VariablesDataSource ( ) , {
105103 accessibilityProvider : new VariablesAccessibilityProvider ( ) ,
@@ -110,12 +108,10 @@ export class VariablesView extends ViewPane {
110108 }
111109 } ) ;
112110
113- this . tree . setInput ( this . debugService . getViewModel ( ) ) ;
111+ this . tree . setInput ( withUndefinedAsNull ( this . debugService . getViewModel ( ) . focusedStackFrame ) ) ;
114112
115113 CONTEXT_VARIABLES_FOCUSED . bindTo ( this . tree . contextKeyService ) ;
116114
117- this . tree . updateChildren ( ) ;
118-
119115 this . _register ( this . debugService . getViewModel ( ) . onDidFocusStackFrame ( sf => {
120116 if ( ! this . isBodyVisible ( ) ) {
121117 this . needsRefresh = true ;
@@ -148,6 +144,7 @@ export class VariablesView extends ViewPane {
148144 this . tree . rerender ( e ) ;
149145 }
150146 } ) ) ;
147+ this . _register ( this . debugService . onDidEndSession ( ( ) => this . savedViewState . clear ( ) ) ) ;
151148 }
152149
153150 getActions ( ) : IAction [ ] {
@@ -213,24 +210,26 @@ export class VariablesView extends ViewPane {
213210 }
214211}
215212
216- function isViewModel ( obj : any ) : obj is IViewModel {
217- return typeof obj . getSelectedExpression === 'function' ;
213+ function isStackFrame ( obj : any ) : obj is IStackFrame {
214+ return obj instanceof StackFrame ;
218215}
219216
220- export class VariablesDataSource implements IAsyncDataSource < IViewModel , IExpression | IScope > {
217+ export class VariablesDataSource implements IAsyncDataSource < IStackFrame | null , IExpression | IScope > {
221218
222- hasChildren ( element : IViewModel | IExpression | IScope ) : boolean {
223- if ( isViewModel ( element ) ) {
219+ hasChildren ( element : IStackFrame | null | IExpression | IScope ) : boolean {
220+ if ( ! element ) {
221+ return false ;
222+ }
223+ if ( isStackFrame ( element ) ) {
224224 return true ;
225225 }
226226
227227 return element . hasChildren ;
228228 }
229229
230- getChildren ( element : IViewModel | IExpression | IScope ) : Promise < ( IExpression | IScope ) [ ] > {
231- if ( isViewModel ( element ) ) {
232- const stackFrame = element . focusedStackFrame ;
233- return stackFrame ? stackFrame . getScopes ( ) : Promise . resolve ( [ ] ) ;
230+ getChildren ( element : IStackFrame | IExpression | IScope ) : Promise < ( IExpression | IScope ) [ ] > {
231+ if ( isStackFrame ( element ) ) {
232+ return element . getScopes ( ) ;
234233 }
235234
236235 return element . getChildren ( ) ;
0 commit comments