Skip to content

Commit 0ef094e

Browse files
committed
Revert to expanding public instance and static properties
After fixing the bug where we'd stop retrieving values when one value failed, that seemed to fix the overall bug where lots of expected properties failed to show up. While investigating, I also found many properties duplicated, seemingly due to being retrieved both off the PSObject and off the .NET object, so now when we do the latter we check (by name) that it hasn't already been added.
1 parent 5913cab commit 0ef094e

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

src/PowerShellEditorServices/Services/DebugAdapter/Debugging/VariableDetails.cs

+13-17
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ private static object SafeGetValue(PSPropertyInfo psProperty)
123123
{
124124
// Sometimes we can't get the value, like ExitCode, for reasons beyond our control,
125125
// so just return the message from the exception that arises.
126-
return ex.Message;
126+
return new UnableToRetrievePropertyMessage { Name = psProperty.Name, Message = ex.Message };
127127
}
128128
}
129129

@@ -345,11 +345,8 @@ protected static void AddDotNetProperties(object obj, List<VariableDetails> chil
345345
return;
346346
}
347347

348-
// We include NonPublic properties because the C# extension seems to as well, and this
349-
// isn't an inline local because we're often debugging it.
350-
PropertyInfo[] properties = objectType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
351-
352-
foreach (PropertyInfo property in properties)
348+
// Search all the public instance or static properties and add those missing.
349+
foreach (PropertyInfo property in objectType.GetProperties())
353350
{
354351
// Don't display indexer properties, it causes an exception anyway.
355352
if (property.GetIndexParameters().Length > 0)
@@ -359,10 +356,11 @@ protected static void AddDotNetProperties(object obj, List<VariableDetails> chil
359356

360357
try
361358
{
362-
childVariables.Add(
363-
new VariableDetails(
364-
property.Name,
365-
property.GetValue(obj)));
359+
// Only add unique properties because we may have already added some.
360+
if (!childVariables.Exists(p => p.Name == property.Name))
361+
{
362+
childVariables.Add(new VariableDetails(property.Name, property.GetValue(obj)));
363+
}
366364
}
367365
catch (Exception ex)
368366
{
@@ -376,21 +374,19 @@ protected static void AddDotNetProperties(object obj, List<VariableDetails> chil
376374
childVariables.Add(
377375
new VariableDetails(
378376
property.Name,
379-
new UnableToRetrievePropertyMessage(
380-
"Error retrieving property - " + ex.GetType().Name)));
377+
new UnableToRetrievePropertyMessage { Name = property.Name, Message = ex.Message }));
381378
}
382379
}
383380
}
384381

385382
#endregion
386383

387-
private readonly struct UnableToRetrievePropertyMessage
384+
private record UnableToRetrievePropertyMessage
388385
{
389-
public UnableToRetrievePropertyMessage(string message) => Message = message;
390-
391-
public string Message { get; }
386+
public string Name { get; init; }
387+
public string Message { get; init; }
392388

393-
public override string ToString() => "<" + Message + ">";
389+
public override string ToString() => $"Error retrieving property '${Name}': ${Message}";
394390
}
395391
}
396392

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

+27-13
Original file line numberDiff line numberDiff line change
@@ -919,18 +919,14 @@ await GetVariables(VariableContainerDetails.ScriptScopeName).ConfigureAwait(true
919919
Assert.NotNull(rawDetailsView);
920920
Assert.Empty(rawDetailsView.Type);
921921
Assert.Empty(rawDetailsView.ValueString);
922-
Assert.Collection(rawDetailsView.GetChildren(NullLogger.Instance),
922+
VariableDetailsBase[] rawViewChildren = rawDetailsView.GetChildren(NullLogger.Instance);
923+
Assert.Collection(rawViewChildren,
923924
(i) =>
924925
{
925926
Assert.Equal("Length", i.Name);
926927
Assert.Equal("4", i.ValueString);
927928
},
928929
(i) =>
929-
{
930-
Assert.Equal("NativeLength", i.Name);
931-
Assert.Equal("4", i.ValueString);
932-
},
933-
(i) =>
934930
{
935931
Assert.Equal("LongLength", i.Name);
936932
Assert.Equal("4", i.ValueString);
@@ -980,10 +976,8 @@ await GetVariables(VariableContainerDetails.ScriptScopeName).ConfigureAwait(true
980976
Assert.NotNull(rawDetailsView);
981977
Assert.Empty(rawDetailsView.Type);
982978
Assert.Empty(rawDetailsView.ValueString);
983-
Assert.Collection(rawDetailsView.GetChildren(NullLogger.Instance),
984-
(i) => Assert.Equal("hcp", i.Name),
985-
(i) => Assert.Equal("comparer", i.Name),
986-
(i) => Assert.Equal("EqualityComparer", i.Name),
979+
VariableDetailsBase[] rawDetailsChildren = rawDetailsView.GetChildren(NullLogger.Instance);
980+
Assert.Collection(rawDetailsChildren,
987981
(i) =>
988982
{
989983
Assert.Equal("IsReadOnly", i.Name);
@@ -1045,8 +1039,28 @@ await GetVariables(VariableContainerDetails.ScriptScopeName).ConfigureAwait(true
10451039
Assert.Empty(rawDetailsView.Type);
10461040
Assert.Empty(rawDetailsView.ValueString);
10471041
VariableDetailsBase[] rawViewChildren = rawDetailsView.GetChildren(NullLogger.Instance);
1048-
Assert.Equal(15, rawViewChildren.Length);
1049-
Assert.NotNull(Array.Find(rawViewChildren, v => v.Name == "Comparer"));
1042+
Assert.Collection(rawViewChildren,
1043+
(i) =>
1044+
{
1045+
Assert.Equal("Count", i.Name);
1046+
Assert.Equal("4", i.ValueString);
1047+
},
1048+
(i) =>
1049+
{
1050+
Assert.Equal("Comparer", i.Name);
1051+
Assert.Equal("[GenericComparer`1]", i.ValueString);
1052+
},
1053+
(i) =>
1054+
{
1055+
Assert.Equal("Keys", i.Name);
1056+
Assert.Equal("[KeyCollection: 4]", i.ValueString);
1057+
},
1058+
(i) =>
1059+
{
1060+
Assert.Equal("Values", i.Name);
1061+
Assert.Equal("[ValueCollection: 4]", i.ValueString);
1062+
}
1063+
);
10501064
}
10511065

10521066
[Fact]
@@ -1098,7 +1112,7 @@ await debugService.SetLineBreakpointsAsync(
10981112
Assert.True(var.IsExpandable);
10991113

11001114
VariableDetailsBase[] childVars = await debugService.GetVariables(var.Id, CancellationToken.None).ConfigureAwait(true);
1101-
Assert.Contains(childVars, i => i.Name is "Name" && i.ValueString is "\"dotnet\"");
1115+
Assert.Contains(childVars, i => i.Name is "Name");
11021116
Assert.Contains(childVars, i => i.Name is "Handles");
11031117
Assert.Contains(childVars, i => i.Name is "CommandLine");
11041118
Assert.Contains(childVars, i => i.Name is "ExitCode");

0 commit comments

Comments
 (0)