@@ -27,8 +27,10 @@ public class DebugService
27
27
new Dictionary < string , List < Breakpoint > > ( ) ;
28
28
29
29
private int nextVariableId ;
30
- private List < VariableDetails > currentVariables ;
31
- private StackFrameDetails [ ] callStackFrames ;
30
+ private List < VariableDetailsBase > variables ;
31
+ private VariableContainerDetails globalScopeVariables ;
32
+ private VariableContainerDetails scriptScopeVariables ;
33
+ private StackFrameDetails [ ] stackFrameDetails ;
32
34
33
35
#endregion
34
36
@@ -155,38 +157,28 @@ public void Abort()
155
157
/// </summary>
156
158
/// <param name="variableReferenceId"></param>
157
159
/// <returns>An array of VariableDetails instances which describe the requested variables.</returns>
158
- public VariableDetails [ ] GetVariables ( int variableReferenceId )
160
+ public VariableDetailsBase [ ] GetVariables ( int variableReferenceId )
159
161
{
160
- VariableDetails [ ] childVariables = null ;
162
+ VariableDetailsBase [ ] childVariables ;
161
163
162
- if ( variableReferenceId >= VariableDetails . FirstVariableId )
164
+ VariableDetailsBase parentVariable = this . variables [ variableReferenceId ] ;
165
+ if ( parentVariable . IsExpandable )
163
166
{
164
- int correctedId =
165
- ( variableReferenceId - VariableDetails . FirstVariableId ) ;
167
+ childVariables = parentVariable . GetChildren ( ) ;
166
168
167
- VariableDetails parentVariable =
168
- this . currentVariables [ correctedId ] ;
169
-
170
- if ( parentVariable . IsExpandable )
169
+ foreach ( var child in childVariables )
171
170
{
172
- childVariables = parentVariable . GetChildren ( ) ;
173
-
174
- foreach ( var child in childVariables )
171
+ // Only add child if it hasn't already been added.
172
+ if ( child . Id < 0 )
175
173
{
176
- this . currentVariables . Add ( child ) ;
177
- child . Id = this . nextVariableId ;
178
- this . nextVariableId ++ ;
174
+ child . Id = this . nextVariableId ++ ;
175
+ this . variables . Add ( child ) ;
179
176
}
180
177
}
181
- else
182
- {
183
- childVariables = new VariableDetails [ 0 ] ;
184
- }
185
178
}
186
179
else
187
180
{
188
- // TODO: Get variables for the desired scope ID
189
- childVariables = this . currentVariables . ToArray ( ) ;
181
+ childVariables = new VariableDetailsBase [ 0 ] ;
190
182
}
191
183
192
184
return childVariables ;
@@ -200,13 +192,13 @@ public VariableDetails[] GetVariables(int variableReferenceId)
200
192
/// <param name="variableExpression">The variable expression string to evaluate.</param>
201
193
/// <param name="stackFrameId">The ID of the stack frame in which the expression should be evaluated.</param>
202
194
/// <returns>A VariableDetails object containing the result.</returns>
203
- public VariableDetails GetVariableFromExpression ( string variableExpression , int stackFrameId )
195
+ public VariableDetailsBase GetVariableFromExpression ( string variableExpression , int stackFrameId )
204
196
{
205
197
// Break up the variable path
206
198
string [ ] variablePathParts = variableExpression . Split ( '.' ) ;
207
199
208
- VariableDetails resolvedVariable = null ;
209
- IEnumerable < VariableDetails > variableList = this . currentVariables ;
200
+ VariableDetailsBase resolvedVariable = null ;
201
+ IEnumerable < VariableDetailsBase > variableList = this . variables ;
210
202
211
203
foreach ( var variableName in variablePathParts )
212
204
{
@@ -267,7 +259,7 @@ await this.powerShellContext.ExecuteScriptString(
267
259
/// </returns>
268
260
public StackFrameDetails [ ] GetStackFrames ( )
269
261
{
270
- return this . callStackFrames ;
262
+ return this . stackFrameDetails ;
271
263
}
272
264
273
265
/// <summary>
@@ -278,10 +270,11 @@ public StackFrameDetails[] GetStackFrames()
278
270
/// <returns>The list of VariableScope instances which describe the available variable scopes.</returns>
279
271
public VariableScope [ ] GetVariableScopes ( int stackFrameId )
280
272
{
281
- // TODO: Return different scopes based on PowerShell scoping mechanics
282
273
return new VariableScope [ ]
283
274
{
284
- new VariableScope ( 1 , "Locals" )
275
+ new VariableScope ( this . stackFrameDetails [ stackFrameId ] . LocalVariables . Id , "Local" ) ,
276
+ new VariableScope ( this . scriptScopeVariables . Id , "Script" ) ,
277
+ new VariableScope ( this . globalScopeVariables . Id , "Global" ) ,
285
278
} ;
286
279
}
287
280
@@ -310,25 +303,43 @@ private async Task ClearBreakpointsInFile(ScriptFile scriptFile)
310
303
}
311
304
}
312
305
313
- private async Task FetchVariables ( )
306
+ private async Task FetchStackFramesAndVariables ( )
314
307
{
315
- this . nextVariableId = VariableDetails . FirstVariableId ;
316
- this . currentVariables = new List < VariableDetails > ( ) ;
308
+ this . nextVariableId = VariableDetailsBase . FirstVariableId ;
309
+ this . variables = new List < VariableDetailsBase > ( ) ;
310
+
311
+ // Create a dummy variable for index 0, should never see this.
312
+ this . variables . Add ( new VariableDetails ( "Dummy" , null ) ) ;
317
313
314
+ await FetchGlobalAndScriptVariables ( ) ;
315
+ await FetchStackFrames ( ) ;
316
+
317
+ }
318
+
319
+ private async Task FetchGlobalAndScriptVariables ( )
320
+ {
321
+ this . scriptScopeVariables = await FetchVariableContainer ( "Script" ) ;
322
+ this . globalScopeVariables = await FetchVariableContainer ( "Global" ) ;
323
+ }
324
+
325
+ private async Task < VariableContainerDetails > FetchVariableContainer ( string scope )
326
+ {
318
327
PSCommand psCommand = new PSCommand ( ) ;
319
328
psCommand . AddCommand ( "Get-Variable" ) ;
320
- psCommand . AddParameter ( "Scope" , "Local" ) ;
329
+ psCommand . AddParameter ( "Scope" , scope ) ;
321
330
322
- var results = await this . powerShellContext . ExecuteCommand < PSVariable > ( psCommand ) ;
331
+ var variableContainerDetails = new VariableContainerDetails ( this . nextVariableId ++ , "Scope: " + scope ) ;
332
+ this . variables . Add ( variableContainerDetails ) ;
323
333
324
- foreach ( var variable in results )
334
+ var results = await this . powerShellContext . ExecuteCommand < PSVariable > ( psCommand ) ;
335
+ foreach ( PSVariable variable in results )
325
336
{
326
- var details = new VariableDetails ( variable ) ;
327
- details . Id = this . nextVariableId ;
328
- this . currentVariables . Add ( details ) ;
329
-
330
- this . nextVariableId ++ ;
337
+ var variableDetails = new VariableDetails ( variable ) { Id = this . nextVariableId ++ } ;
338
+ this . variables . Add ( variableDetails ) ;
339
+ variableContainerDetails . Children . Add ( variableDetails ) ;
331
340
}
341
+
342
+ return variableContainerDetails ;
332
343
}
333
344
334
345
private async Task FetchStackFrames ( )
@@ -338,10 +349,14 @@ private async Task FetchStackFrames()
338
349
339
350
var results = await this . powerShellContext . ExecuteCommand < CallStackFrame > ( psCommand ) ;
340
351
341
- this . callStackFrames =
342
- results
343
- . Select ( StackFrameDetails . Create )
344
- . ToArray ( ) ;
352
+ var callStackFrames = results . ToArray ( ) ;
353
+ this . stackFrameDetails = new StackFrameDetails [ callStackFrames . Length ] ;
354
+
355
+ for ( int i = 0 ; i < callStackFrames . Length ; i ++ )
356
+ {
357
+ VariableContainerDetails localVariables = await FetchVariableContainer ( i . ToString ( ) ) ;
358
+ this . stackFrameDetails [ i ] = StackFrameDetails . Create ( callStackFrames [ i ] , localVariables ) ;
359
+ }
345
360
}
346
361
347
362
#endregion
@@ -355,9 +370,8 @@ private async Task FetchStackFrames()
355
370
356
371
private async void OnDebuggerStop ( object sender , DebuggerStopEventArgs e )
357
372
{
358
- // Get the call stack and local variables
359
- await this . FetchStackFrames ( ) ;
360
- await this . FetchVariables ( ) ;
373
+ // Get call stack and variables.
374
+ await this . FetchStackFramesAndVariables ( ) ;
361
375
362
376
// Notify the host that the debugger is stopped
363
377
if ( this . DebuggerStopped != null )
0 commit comments