Skip to content

Commit 39c9ed4

Browse files
Consolidate InterruptCurrentForeground and MustRunInForeground (#1777)
And set them consistently. If the task needs to interrupt or run in the foreground, it really needs to do both.
1 parent 9926944 commit 39c9ed4

File tree

8 files changed

+65
-43
lines changed

8 files changed

+65
-43
lines changed

src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ internal class ConfigurationDoneHandler : IConfigurationDoneHandler
2525
// TODO: We currently set `WriteInputToHost` as true, which writes our debugged commands'
2626
// `GetInvocationText` and that reveals some obscure implementation details we should
2727
// instead hide from the user with pretty strings (or perhaps not write out at all).
28+
//
29+
// This API is mostly used for F5 execution so it requires the foreground.
2830
private static readonly PowerShellExecutionOptions s_debuggerExecutionOptions = new()
2931
{
30-
MustRunInForeground = true,
32+
RequiresForeground = true,
3133
WriteInputToHost = true,
3234
WriteOutputToHost = true,
3335
ThrowOnError = false,

src/PowerShellEditorServices/Services/Extension/ExtensionService.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,16 @@ public Task InvokeCommandAsync(string commandName, EditorContext editorContext,
129129
.AddParameter("ScriptBlock", editorCommand.ScriptBlock)
130130
.AddParameter("ArgumentList", new object[] { editorContext });
131131

132-
// This API is used for editor command execution, so it needs to interrupt the
133-
// current prompt (or other foreground task).
132+
// This API is used for editor command execution so it requires the foreground.
134133
return ExecutionService.ExecutePSCommandAsync(
135134
executeCommand,
136135
cancellationToken,
137136
new PowerShellExecutionOptions
138137
{
138+
RequiresForeground = true,
139139
WriteOutputToHost = !editorCommand.SuppressOutput,
140140
AddToHistory = !editorCommand.SuppressOutput,
141141
ThrowOnError = false,
142-
InterruptCurrentForeground = true
143142
});
144143
}
145144

src/PowerShellEditorServices/Services/PowerShell/Console/PsrlReadLine.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ public PsrlReadLine(
3232
_psrlProxy.OverrideIdleHandler(onIdleAction);
3333
}
3434

35-
public override string ReadLine(CancellationToken cancellationToken) => _psesHost.InvokeDelegate(representation: "ReadLine", new ExecutionOptions { MustRunInForeground = true }, InvokePSReadLine, cancellationToken);
35+
public override string ReadLine(CancellationToken cancellationToken) => _psesHost.InvokeDelegate(
36+
representation: "ReadLine",
37+
new ExecutionOptions { RequiresForeground = true },
38+
InvokePSReadLine,
39+
cancellationToken);
3640

3741
protected override ConsoleKeyInfo ReadKey(CancellationToken cancellationToken) => _psesHost.ReadKey(intercept: true, cancellationToken);
3842

src/PowerShellEditorServices/Services/PowerShell/Execution/BlockingConcurrentDeque.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public bool TryTake(out T item)
6565

6666
public IDisposable BlockConsumers() => PriorityQueueBlockLifetime.StartBlocking(_blockConsumersEvent);
6767

68-
public void Dispose() => ((IDisposable)_blockConsumersEvent).Dispose();
68+
public void Dispose() => _blockConsumersEvent.Dispose();
6969

7070
private class PriorityQueueBlockLifetime : IDisposable
7171
{

src/PowerShellEditorServices/Services/PowerShell/Execution/ExecutionOptions.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,15 @@ public enum ExecutionPriority
1616
public record ExecutionOptions
1717
{
1818
public ExecutionPriority Priority { get; init; } = ExecutionPriority.Normal;
19-
public bool MustRunInForeground { get; init; }
20-
public bool InterruptCurrentForeground { get; init; }
19+
public bool RequiresForeground { get; init; }
2120
}
2221

2322
public record PowerShellExecutionOptions : ExecutionOptions
2423
{
2524
internal static PowerShellExecutionOptions ImmediateInteractive = new()
2625
{
2726
Priority = ExecutionPriority.Next,
28-
MustRunInForeground = true,
29-
InterruptCurrentForeground = true,
27+
RequiresForeground = true,
3028
};
3129

3230
public bool WriteOutputToHost { get; init; }

src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,17 @@ internal class EvaluateHandler : IEvaluateHandler
2121

2222
public async Task<EvaluateResponseBody> Handle(EvaluateRequestArguments request, CancellationToken cancellationToken)
2323
{
24-
// This API is mostly used for F8 execution, so it needs to interrupt the command prompt
25-
// (or other foreground task).
24+
// This API is mostly used for F8 execution so it requires the foreground.
2625
await _executionService.ExecutePSCommandAsync(
2726
new PSCommand().AddScript(request.Expression),
2827
CancellationToken.None,
2928
new PowerShellExecutionOptions
3029
{
30+
RequiresForeground = true,
3131
WriteInputToHost = true,
3232
WriteOutputToHost = true,
3333
AddToHistory = true,
3434
ThrowOnError = false,
35-
InterruptCurrentForeground = true
3635
}).ConfigureAwait(false);
3736

3837
// TODO: Should we return a more informative result?

src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation.
1+
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

44
using System;
@@ -277,7 +277,7 @@ public void SetExit()
277277
public Task<T> InvokeTaskOnPipelineThreadAsync<T>(
278278
SynchronousTask<T> task)
279279
{
280-
if (task.ExecutionOptions.InterruptCurrentForeground)
280+
if (task.ExecutionOptions.RequiresForeground)
281281
{
282282
// When a task must displace the current foreground command,
283283
// we must:
@@ -404,9 +404,14 @@ public void InvokePSDelegate(string representation, ExecutionOptions executionOp
404404

405405
internal Task LoadHostProfilesAsync(CancellationToken cancellationToken)
406406
{
407+
// TODO: Why exactly does loading profiles require the foreground?
407408
return ExecuteDelegateAsync(
408409
"LoadProfiles",
409-
new PowerShellExecutionOptions { MustRunInForeground = true, ThrowOnError = false },
410+
new PowerShellExecutionOptions
411+
{
412+
RequiresForeground = true,
413+
ThrowOnError = false
414+
},
410415
(pwsh, _) => pwsh.LoadProfiles(_hostInfo.ProfilePaths),
411416
cancellationToken);
412417
}
@@ -855,7 +860,15 @@ private string InvokeReadLine(CancellationToken cancellationToken)
855860
private void InvokeInput(string input, CancellationToken cancellationToken)
856861
{
857862
PSCommand command = new PSCommand().AddScript(input, useLocalScope: false);
858-
InvokePSCommand(command, new PowerShellExecutionOptions { AddToHistory = true, ThrowOnError = false, WriteOutputToHost = true }, cancellationToken);
863+
InvokePSCommand(
864+
command,
865+
new PowerShellExecutionOptions
866+
{
867+
AddToHistory = true,
868+
ThrowOnError = false,
869+
WriteOutputToHost = true
870+
},
871+
cancellationToken);
859872
}
860873

861874
private void AddRunspaceEventHandlers(Runspace runspace)
@@ -949,6 +962,7 @@ private Runspace CreateInitialRunspace(InitialSessionState initialSessionState)
949962
return runspace;
950963
}
951964

965+
// NOTE: This token is received from PSReadLine, and it _is_ the ReadKey cancellation token!
952966
private void OnPowerShellIdle(CancellationToken idleCancellationToken)
953967
{
954968
IReadOnlyList<PSEventSubscriber> eventSubscribers = _mainRunspaceEngineIntrinsics.Events.Subscribers;
@@ -981,7 +995,7 @@ private void OnPowerShellIdle(CancellationToken idleCancellationToken)
981995
while (!cancellationScope.CancellationToken.IsCancellationRequested
982996
&& _taskQueue.TryTake(out ISynchronousTask task))
983997
{
984-
if (task.ExecutionOptions.MustRunInForeground)
998+
if (task.ExecutionOptions.RequiresForeground)
985999
{
9861000
// If we have a task that is queued, but cannot be run under readline
9871001
// we place it back at the front of the queue, and cancel the readline task
@@ -1102,27 +1116,27 @@ private void OnDebuggerStopped(object sender, DebuggerStopEventArgs debuggerStop
11021116

11031117
void OnDebuggerStoppedImpl(object sender, DebuggerStopEventArgs debuggerStopEventArgs)
11041118
{
1105-
// If the debug server is NOT active, we need to synchronize state and start it.
1106-
if (!DebugContext.IsDebugServerActive)
1107-
{
1108-
_languageServer?.SendNotification("powerShell/startDebugger");
1109-
}
1119+
// If the debug server is NOT active, we need to synchronize state and start it.
1120+
if (!DebugContext.IsDebugServerActive)
1121+
{
1122+
_languageServer?.SendNotification("powerShell/startDebugger");
1123+
}
11101124

1111-
DebugContext.SetDebuggerStopped(debuggerStopEventArgs);
1125+
DebugContext.SetDebuggerStopped(debuggerStopEventArgs);
11121126

1113-
try
1114-
{
1115-
CurrentPowerShell.WaitForRemoteOutputIfNeeded();
1116-
PowerShellFrameType frameBase = CurrentFrame.FrameType & PowerShellFrameType.Remote;
1117-
PushPowerShellAndRunLoop(
1118-
CreateNestedPowerShell(CurrentRunspace),
1119-
frameBase | PowerShellFrameType.Debug | PowerShellFrameType.Nested | PowerShellFrameType.Repl);
1120-
CurrentPowerShell.ResumeRemoteOutputIfNeeded();
1121-
}
1122-
finally
1123-
{
1124-
DebugContext.SetDebuggerResumed();
1125-
}
1127+
try
1128+
{
1129+
CurrentPowerShell.WaitForRemoteOutputIfNeeded();
1130+
PowerShellFrameType frameBase = CurrentFrame.FrameType & PowerShellFrameType.Remote;
1131+
PushPowerShellAndRunLoop(
1132+
CreateNestedPowerShell(CurrentRunspace),
1133+
frameBase | PowerShellFrameType.Debug | PowerShellFrameType.Nested | PowerShellFrameType.Repl);
1134+
CurrentPowerShell.ResumeRemoteOutputIfNeeded();
1135+
}
1136+
finally
1137+
{
1138+
DebugContext.SetDebuggerResumed();
1139+
}
11261140
}
11271141
}
11281142

@@ -1146,7 +1160,7 @@ private Task PopOrReinitializeRunspaceAsync()
11461160
// we simply run this on its thread, guaranteeing that no other action can occur
11471161
return ExecuteDelegateAsync(
11481162
nameof(PopOrReinitializeRunspaceAsync),
1149-
new ExecutionOptions { InterruptCurrentForeground = true },
1163+
new ExecutionOptions { RequiresForeground = true },
11501164
(_) =>
11511165
{
11521166
while (_psFrameStack.Count > 0

src/PowerShellEditorServices/Services/Template/TemplateService.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,21 @@ public async Task<bool> CreateFromTemplateAsync(
158158
_logger.LogTrace(
159159
$"Invoking Plaster...\n\n TemplatePath: {templatePath}\n DestinationPath: {destinationPath}");
160160

161-
PSCommand command = new();
162-
command.AddCommand("Invoke-Plaster");
163-
command.AddParameter("TemplatePath", templatePath);
164-
command.AddParameter("DestinationPath", destinationPath);
161+
PSCommand command = new PSCommand()
162+
.AddCommand("Invoke-Plaster")
163+
.AddParameter("TemplatePath", templatePath)
164+
.AddParameter("DestinationPath", destinationPath);
165165

166+
// This command is interactive so it requires the foreground.
166167
await _executionService.ExecutePSCommandAsync(
167168
command,
168169
CancellationToken.None,
169-
new PowerShellExecutionOptions { WriteOutputToHost = true, InterruptCurrentForeground = true, ThrowOnError = false }).ConfigureAwait(false);
170+
new PowerShellExecutionOptions
171+
{
172+
RequiresForeground = true,
173+
WriteOutputToHost = true,
174+
ThrowOnError = false
175+
}).ConfigureAwait(false);
170176

171177
// If any errors were written out, creation was not successful
172178
return true;

0 commit comments

Comments
 (0)