diff --git a/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs b/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs index 64435154f..10ddc55a7 100644 --- a/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs +++ b/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs @@ -4,6 +4,7 @@ using Microsoft.PowerShell.EditorServices.Services.Extension; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.PowerShell.EditorServices.Extensions.Services @@ -78,7 +79,7 @@ public ExtensionCommandService(ExtensionService extensionService) public IReadOnlyList GetCommands() => _extensionService.GetCommands(); - public Task InvokeCommandAsync(string commandName, EditorContext editorContext) => _extensionService.InvokeCommandAsync(commandName, editorContext); + public Task InvokeCommandAsync(string commandName, EditorContext editorContext) => _extensionService.InvokeCommandAsync(commandName, editorContext, CancellationToken.None); public bool RegisterCommand(EditorCommand editorCommand) => _extensionService.RegisterCommand(editorCommand); diff --git a/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs b/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs index 116273734..6882abbbc 100644 --- a/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs +++ b/src/PowerShellEditorServices/Services/Extension/ExtensionService.cs @@ -119,7 +119,7 @@ internal Task InitializeAsync() /// The context in which the command is being invoked. /// A Task that can be awaited for completion. /// The command being invoked was not registered. - public async Task InvokeCommandAsync(string commandName, EditorContext editorContext) + public Task InvokeCommandAsync(string commandName, EditorContext editorContext, CancellationToken cancellationToken) { if (editorCommands.TryGetValue(commandName, out EditorCommand editorCommand)) { @@ -128,20 +128,21 @@ public async Task InvokeCommandAsync(string commandName, EditorContext editorCon .AddParameter("ScriptBlock", editorCommand.ScriptBlock) .AddParameter("ArgumentList", new object[] { editorContext }); - await ExecutionService.ExecutePSCommandAsync( + // This API is used for editor command execution, so it needs to interrupt the + // current prompt (or other foreground task). + return ExecutionService.ExecutePSCommandAsync( executeCommand, - CancellationToken.None, + cancellationToken, new PowerShellExecutionOptions { WriteOutputToHost = !editorCommand.SuppressOutput, + AddToHistory = !editorCommand.SuppressOutput, ThrowOnError = false, - AddToHistory = !editorCommand.SuppressOutput - }).ConfigureAwait(false); - } - else - { - throw new KeyNotFoundException($"Editor command not found: '{commandName}'"); + InterruptCurrentForeground = true + }); } + + throw new KeyNotFoundException($"Editor command not found: '{commandName}'"); } /// diff --git a/src/PowerShellEditorServices/Services/Extension/Handlers/InvokeExtensionCommandHandler.cs b/src/PowerShellEditorServices/Services/Extension/Handlers/InvokeExtensionCommandHandler.cs index 1a50779cc..705572697 100644 --- a/src/PowerShellEditorServices/Services/Extension/Handlers/InvokeExtensionCommandHandler.cs +++ b/src/PowerShellEditorServices/Services/Extension/Handlers/InvokeExtensionCommandHandler.cs @@ -4,40 +4,28 @@ using System.Threading; using System.Threading.Tasks; using MediatR; -using Microsoft.Extensions.Logging; using Microsoft.PowerShell.EditorServices.Extensions; namespace Microsoft.PowerShell.EditorServices.Services.Extension { internal class InvokeExtensionCommandHandler : IInvokeExtensionCommandHandler { - private readonly ILogger _logger; private readonly ExtensionService _extensionService; private readonly EditorOperationsService _editorOperationsService; public InvokeExtensionCommandHandler( - ILoggerFactory factory, ExtensionService extensionService, - EditorOperationsService editorOperationsService - ) + EditorOperationsService editorOperationsService) { - _logger = factory.CreateLogger(); _extensionService = extensionService; _editorOperationsService = editorOperationsService; } public async Task Handle(InvokeExtensionCommandParams request, CancellationToken cancellationToken) { - // We can now await here because we handle asynchronous message handling. - EditorContext editorContext = - _editorOperationsService.ConvertClientEditorContext( - request.Context); - - await _extensionService.InvokeCommandAsync( - request.Name, - editorContext).ConfigureAwait(false); - - return await Unit.Task.ConfigureAwait(false); + EditorContext editorContext = _editorOperationsService.ConvertClientEditorContext(request.Context); + await _extensionService.InvokeCommandAsync(request.Name, editorContext, cancellationToken).ConfigureAwait(false); + return Unit.Value; } } } diff --git a/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs b/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs index faf0e6142..97fd00f5e 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs @@ -30,15 +30,21 @@ public EvaluateHandler( public async Task Handle(EvaluateRequestArguments request, CancellationToken cancellationToken) { - // TODO: Understand why we currently handle this asynchronously and why we return a dummy result value - // instead of awaiting the execution and returing a real result of some kind - - // This API is mostly used for F8 execution, so needs to interrupt the command prompt + // This API is mostly used for F8 execution, so it needs to interrupt the command prompt + // (or other foreground task). await _executionService.ExecutePSCommandAsync( new PSCommand().AddScript(request.Expression), CancellationToken.None, - new PowerShellExecutionOptions { WriteInputToHost = true, WriteOutputToHost = true, AddToHistory = true, ThrowOnError = false, InterruptCurrentForeground = true }).ConfigureAwait(false); + new PowerShellExecutionOptions + { + WriteInputToHost = true, + WriteOutputToHost = true, + AddToHistory = true, + ThrowOnError = false, + InterruptCurrentForeground = true + }).ConfigureAwait(false); + // TODO: Should we return a more informative result? return new EvaluateResponseBody { Result = "",