Skip to content

Commit 721a9a6

Browse files
committed
Fix bug in SetVariableAsync for strongly typed values
1 parent 06af249 commit 721a9a6

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs

+17-14
Original file line numberDiff line numberDiff line change
@@ -457,22 +457,25 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
457457

458458
if (argTypeConverterAttr is not null)
459459
{
460+
// PSVariable *is* strongly typed, so we have to convert it.
460461
_logger.LogTrace($"Setting variable '{name}' using conversion to value: {expressionResult ?? "<null>"}");
461462

462-
// TODO: This is throwing a 'PSInvalidOperationException' thus causing
463-
// 'DebuggerSetsVariablesWithConversion' to fail.
464-
psVariable.Value = await _executionService.ExecuteDelegateAsync(
465-
"PS debugger argument converter",
466-
ExecutionOptions.Default,
467-
(pwsh, _) =>
468-
{
469-
var engineIntrinsics = (EngineIntrinsics)pwsh.Runspace.SessionStateProxy.GetVariable("ExecutionContext");
470-
471-
// TODO: This is almost (but not quite) the same as LanguagePrimitives.Convert(), which does not require the pipeline thread.
472-
// We should investigate changing it.
473-
return argTypeConverterAttr.Transform(engineIntrinsics, expressionResult);
474-
},
463+
// NOTE: We use 'Get-Variable' here instead of 'SessionStateProxy.GetVariable()'
464+
// because we already have a pipeline running (the debugger) and the latter cannot
465+
// run concurrently (threw 'NoSessionStateProxyWhenPipelineInProgress').
466+
IReadOnlyList<EngineIntrinsics> results = await _executionService.ExecutePSCommandAsync<EngineIntrinsics>(
467+
new PSCommand()
468+
.AddCommand(@"Microsoft.PowerShell.Utility\Get-Variable")
469+
.AddParameter("Name", "ExecutionContext")
470+
.AddParameter("ValueOnly"),
475471
CancellationToken.None).ConfigureAwait(false);
472+
EngineIntrinsics engineIntrinsics = results.Count > 0
473+
? results[0]
474+
: throw new Exception("Couldn't get EngineIntrinsics!");
475+
476+
// TODO: This is almost (but not quite) the same as 'LanguagePrimitives.Convert()',
477+
// which does not require the pipeline thread. We should investigate changing it.
478+
psVariable.Value = argTypeConverterAttr.Transform(engineIntrinsics, expressionResult);
476479
}
477480
else
478481
{
@@ -642,7 +645,7 @@ private Task<VariableContainerDetails> FetchVariableContainerAsync(string scope)
642645

643646
private async Task<VariableContainerDetails> FetchVariableContainerAsync(string scope, bool autoVarsOnly)
644647
{
645-
PSCommand psCommand = new PSCommand().AddCommand("Get-Variable").AddParameter("Scope", scope);
648+
PSCommand psCommand = new PSCommand().AddCommand(@"Microsoft.PowerShell.Utility\Get-Variable").AddParameter("Scope", scope);
646649

647650
var scopeVariableContainer = new VariableContainerDetails(nextVariableId++, "Scope: " + scope);
648651
variables.Add(scopeVariableContainer);

test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ await debugService.SetLineBreakpointsAsync(
613613
Assert.Equal(newGlobalIntValue, intGlobalVar.ValueString);
614614
}
615615

616-
[Fact(Skip = "Variable conversion is broken")]
616+
[Fact]
617617
public async Task DebuggerSetsVariablesWithConversion()
618618
{
619619
await debugService.SetLineBreakpointsAsync(
@@ -628,7 +628,7 @@ await debugService.SetLineBreakpointsAsync(
628628
VariableDetailsBase[] variables = GetVariables(VariableContainerDetails.LocalScopeName);
629629

630630
// Test set of a local string variable (not strongly typed but force conversion)
631-
const string newStrValue = "False";
631+
const string newStrValue = "\"False\"";
632632
const string newStrExpr = "$false";
633633
VariableScope localScope = Array.Find(scopes, s => s.Name == VariableContainerDetails.LocalScopeName);
634634
string setStrValue = await debugService.SetVariableAsync(localScope.Id, "$strVar2", newStrExpr).ConfigureAwait(true);

0 commit comments

Comments
 (0)