Skip to content

Commit 03d3818

Browse files
committed
First pass implementation of an Auto variables node that attempts to display just the interesting variables. Starting out with the variables it appears the user has defined.
1 parent 31042aa commit 03d3818

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

src/PowerShellEditorServices/Debugging/DebugService.cs

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,11 @@ public StackFrameDetails[] GetStackFrames()
270270
public VariableScope[] GetVariableScopes(int stackFrameId)
271271
{
272272
int localStackFrameVariableId = this.stackFrameDetails[stackFrameId].LocalVariables.Id;
273+
int autoVariablesId = this.stackFrameDetails[stackFrameId].AutoVariables.Id;
273274

274275
return new VariableScope[]
275276
{
277+
new VariableScope(autoVariablesId, VariableContainerDetails.AutoVariablesName),
276278
new VariableScope(localStackFrameVariableId, VariableContainerDetails.LocalScopeName),
277279
new VariableScope(this.scriptScopeVariables.Id, VariableContainerDetails.ScriptScopeName),
278280
new VariableScope(this.globalScopeVariables.Id, VariableContainerDetails.GlobalScopeName),
@@ -321,11 +323,13 @@ private async Task FetchStackFramesAndVariables()
321323
private async Task FetchGlobalAndScriptVariables()
322324
{
323325
// Retrieve globals first as script variable retrieval needs to search globals.
324-
this.globalScopeVariables = await FetchVariableContainer(VariableContainerDetails.GlobalScopeName);
325-
this.scriptScopeVariables = await FetchVariableContainer(VariableContainerDetails.ScriptScopeName);
326+
this.globalScopeVariables = await FetchVariableContainer(VariableContainerDetails.GlobalScopeName, null);
327+
this.scriptScopeVariables = await FetchVariableContainer(VariableContainerDetails.ScriptScopeName, null);
326328
}
327329

328-
private async Task<VariableContainerDetails> FetchVariableContainer(string scope)
330+
private async Task<VariableContainerDetails> FetchVariableContainer(
331+
string scope,
332+
VariableContainerDetails autoVariables)
329333
{
330334
PSCommand psCommand = new PSCommand();
331335
psCommand.AddCommand("Get-Variable");
@@ -335,52 +339,38 @@ private async Task<VariableContainerDetails> FetchVariableContainer(string scope
335339
new VariableContainerDetails(this.nextVariableId++, "Scope: " + scope);
336340
this.variables.Add(scopeVariableContainer);
337341

338-
339-
// Add a container node to this variable container that will "hide" the built-in,
340-
// automatic variables that we usually aren't interested in. Do this for local and script scope.
341-
VariableContainerDetails automaticVariableContainer = null;
342-
if (scope != VariableContainerDetails.GlobalScopeName)
343-
{
344-
automaticVariableContainer =
345-
new VariableContainerDetails(this.nextVariableId++, "Automatic Variables");
346-
this.variables.Add(automaticVariableContainer);
347-
scopeVariableContainer.Children.Add(automaticVariableContainer.Name, automaticVariableContainer);
348-
}
349-
350342
var results = await this.powerShellContext.ExecuteCommand<PSVariable>(psCommand);
351343
foreach (PSVariable psvariable in results)
352344
{
353345
var variableDetails = new VariableDetails(psvariable) { Id = this.nextVariableId++ };
354346
this.variables.Add(variableDetails);
347+
scopeVariableContainer.Children.Add(variableDetails.Name, variableDetails);
355348

356-
if ((automaticVariableContainer == null) || ShouldAlwaysDisplayVariable(psvariable, scope))
357-
{
358-
scopeVariableContainer.Children.Add(variableDetails.Name, variableDetails);
359-
}
360-
else
349+
if ((autoVariables != null) && AddToAutoVariables(psvariable, scope))
361350
{
362-
automaticVariableContainer.Children.Add(variableDetails.Name, variableDetails);
351+
autoVariables.Children.Add(variableDetails.Name, variableDetails);
363352
}
364353
}
365354

366355
return scopeVariableContainer;
367356
}
368357

369-
private bool ShouldAlwaysDisplayVariable(PSVariable psvariable, string scope)
358+
private bool AddToAutoVariables(PSVariable psvariable, string scope)
370359
{
371-
ScopedItemOptions constantAllScope = ScopedItemOptions.AllScope | ScopedItemOptions.Constant;
372-
ScopedItemOptions readonlyAllScope = ScopedItemOptions.AllScope | ScopedItemOptions.ReadOnly;
373-
374-
if (scope == VariableContainerDetails.GlobalScopeName)
360+
if ((scope == VariableContainerDetails.GlobalScopeName) ||
361+
(scope == VariableContainerDetails.ScriptScopeName))
375362
{
376-
// We don't A) have a good way of distinguishing automatic from user created variabbles
377-
// and B) globalScopeVariables.Children.ContainsKey() doesn't work for automatic variables
363+
// We don't A) have a good way of distinguishing built-in from user created variables
364+
// and B) globalScopeVariables.Children.ContainsKey() doesn't work for built-in variables
378365
// stored in a child variable container within the globals variable container.
379-
return true;
366+
return false;
380367
}
381368

369+
var constantAllScope = ScopedItemOptions.AllScope | ScopedItemOptions.Constant;
370+
var readonlyAllScope = ScopedItemOptions.AllScope | ScopedItemOptions.ReadOnly;
371+
382372
// Some local variables, if they exist, should be displayed by default
383-
if(psvariable.GetType().Name == "LocalVariable")
373+
if (psvariable.GetType().Name == "LocalVariable")
384374
{
385375
if (psvariable.Name.Equals("_"))
386376
{
@@ -428,9 +418,18 @@ private async Task FetchStackFrames()
428418

429419
for (int i = 0; i < callStackFrames.Length; i++)
430420
{
431-
VariableContainerDetails localVariables =
432-
await FetchVariableContainer(i.ToString());
433-
this.stackFrameDetails[i] = StackFrameDetails.Create(callStackFrames[i], localVariables);
421+
VariableContainerDetails autoVariables =
422+
new VariableContainerDetails(
423+
this.nextVariableId++,
424+
VariableContainerDetails.AutoVariablesName);
425+
426+
this.variables.Add(autoVariables);
427+
428+
VariableContainerDetails localVariables =
429+
await FetchVariableContainer(i.ToString(), autoVariables);
430+
431+
this.stackFrameDetails[i] =
432+
StackFrameDetails.Create(callStackFrames[i], autoVariables, localVariables);
434433
}
435434
}
436435

src/PowerShellEditorServices/Debugging/StackFrameDetails.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public class StackFrameDetails
3333
/// </summary>
3434
public int ColumnNumber { get; private set; }
3535

36+
/// <summary>
37+
/// Gets or sets the VariableContainerDetails that contains the auto variables.
38+
/// </summary>
39+
public VariableContainerDetails AutoVariables { get; private set; }
40+
3641
/// <summary>
3742
/// Gets or sets the VariableContainerDetails that contains the local variables.
3843
/// </summary>
@@ -50,6 +55,7 @@ public class StackFrameDetails
5055
/// <returns>A new instance of the StackFrameDetails class.</returns>
5156
static internal StackFrameDetails Create(
5257
CallStackFrame callStackFrame,
58+
VariableContainerDetails autoVariables,
5359
VariableContainerDetails localVariables)
5460
{
5561
return new StackFrameDetails
@@ -58,6 +64,7 @@ static internal StackFrameDetails Create(
5864
FunctionName = callStackFrame.FunctionName,
5965
LineNumber = callStackFrame.Position.StartLineNumber,
6066
ColumnNumber = callStackFrame.Position.StartColumnNumber,
67+
AutoVariables = autoVariables,
6168
LocalVariables = localVariables
6269
};
6370
}

src/PowerShellEditorServices/Debugging/VariableContainerDetails.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,23 @@ public class VariableContainerDetails : VariableDetailsBase
2323
/// <summary>
2424
/// Provides a constant for the name of the Global scope.
2525
/// </summary>
26-
public const string GlobalScopeName = "Global";
26+
public const string AutoVariablesName = "Auto";
2727

2828
/// <summary>
29-
/// Provides a constant for the name of the Script scope.
29+
/// Provides a constant for the name of the Global scope.
3030
/// </summary>
31-
public const string ScriptScopeName = "Script";
31+
public const string GlobalScopeName = "Global";
3232

3333
/// <summary>
3434
/// Provides a constant for the name of the Local scope.
3535
/// </summary>
3636
public const string LocalScopeName = "Local";
3737

38+
/// <summary>
39+
/// Provides a constant for the name of the Script scope.
40+
/// </summary>
41+
public const string ScriptScopeName = "Script";
42+
3843
private readonly Dictionary<string, VariableDetailsBase> children;
3944

4045
/// <summary>

0 commit comments

Comments
 (0)