diff --git a/.vsts-ci/azure-pipelines-ci.yml b/.vsts-ci/azure-pipelines-ci.yml
index 25706f2c0..dc2f2d461 100644
--- a/.vsts-ci/azure-pipelines-ci.yml
+++ b/.vsts-ci/azure-pipelines-ci.yml
@@ -8,14 +8,6 @@ variables:
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: 'true'
-trigger:
- branches:
- include:
- - master
-
-pr:
-- master
-
jobs:
- job: PS51_Win2016
displayName: PowerShell 5.1 - Windows Server 2016
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec126a985..77e7761b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,80 @@
# PowerShell Editor Services Release History
+## v3.0.0
+### Thursday, October 28, 2021
+
+This preview release includes a complete overhaul of the core PowerShell engine
+of PowerShell Editor Services.
+This represents over a year's work,
+tracked in [PSES #1295](https://github.com/PowerShell/PowerShellEditorServices/issues/1295)
+and implemented in [PSES #1459](https://github.com/PowerShell/PowerShellEditorServices/pull/1459),
+and is our answer to many, many issues
+opened by users over the last few years.
+We're hoping you'll see a marked improvement
+in the reliability, performance and footprint
+of the extension as a result.
+
+Previously the Integrated Console was run
+by setting threadpool tasks on a shared main runspace,
+and where LSP servicing was done with PowerShell idle events.
+This lead to overhead, threading issues
+and a complex implementation intended to work around
+the asymmetry between PowerShell as a synchronous,
+single-threaded runtime and a language server
+as an asynchronous, multi-threaded service.
+
+Now, PowerShell Editor Services maintains its own dedicated pipeline thread,
+which is able to service requests similar to JavaScript's event loop,
+meaning we can run everything synchronously on the correct thread.
+We also get more efficiency because we can directly call
+PowerShell APIs and code written in C# from this thread,
+without the overhead of a PowerShell pipeline.
+
+This change has overhauled how we service LSP requests,
+how the Integrated Console works,
+how PSReadLine is integrated,
+how debugging is implemented,
+how remoting is handled,
+and a long tail of other features in PowerShell Editor Services.
+
+Also, in making it, while 6,000 lines of code were added,
+we removed 12,000,
+for a more maintainable, more efficient
+and easier to understand extension backend.
+
+While most of our testing has been re-enabled
+(and we're working on adding more),
+there are bound to be issues with this new implementation.
+Please give this a try and let us know if you run into anything.
+
+We also want to thank [@SeeminglyScience](https://github.com/SeeminglyScience)
+for his help and knowledge as we've made this migration.
+
+Finally, a crude breakdown of the work from the commits:
+
+- An initial dedicated pipeline thread consumer implementation
+- Implement the console REPL
+- Implement PSRL idle handling
+- Implement completions
+- Move to invoking PSRL as a C# delegate
+- Implement cancellation and Ctrl+C
+- Make F8 work again
+- Ensure execution policy is set correctly
+- Implement $PROFILE support
+- Make nested prompts work
+- Implement REPL debugging
+- Implement remote debugging in the REPL
+- Hook up the debugging UI
+- Implement a new concurrent priority queue for PowerShell tasks
+- Reimplement the REPL synchronously rather than on its own thread
+- Really get debugging working...
+- Implement DSC breakpoint support
+- Reimplement legacy readline support
+- Ensure stdio is still supported as an LSP transport
+- Remove PowerShellContextService and other defunct code
+- Get integration tests working again (and improve diagnosis of PSES failures)
+- Get unit testing working again (except debug service tests)
+
## v2.5.2
### Monday, October 18, 2021
diff --git a/PowerShellEditorServices.Common.props b/PowerShellEditorServices.Common.props
index d2371b014..0e8d135fe 100644
--- a/PowerShellEditorServices.Common.props
+++ b/PowerShellEditorServices.Common.props
@@ -1,6 +1,6 @@
- 2.5.2
+ 3.0.0
Microsoft
© Microsoft Corporation.
diff --git a/module/PowerShellEditorServices/PowerShellEditorServices.psd1 b/module/PowerShellEditorServices/PowerShellEditorServices.psd1
index 071a37c8e..ff89a1890 100644
--- a/module/PowerShellEditorServices/PowerShellEditorServices.psd1
+++ b/module/PowerShellEditorServices/PowerShellEditorServices.psd1
@@ -19,7 +19,7 @@ RootModule = if ($PSEdition -eq 'Core')
}
# Version number of this module.
-ModuleVersion = '2.5.2'
+ModuleVersion = '3.0.0'
# ID used to uniquely identify this module
GUID = '9ca15887-53a2-479a-9cda-48d26bcb6c47'
diff --git a/modules.json b/modules.json
index 5b1559a21..c879da4a9 100644
--- a/modules.json
+++ b/modules.json
@@ -6,6 +6,7 @@
"Version": "1.1.3"
},
"PSReadLine": {
- "Version": "2.1.0"
+ "Version": "2.2.0-beta4",
+ "AllowPrerelease": true
}
}
diff --git a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs
deleted file mode 100644
index 58038d13e..000000000
--- a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineConstructorCommand.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Management.Automation;
-using System.Runtime.CompilerServices;
-
-namespace Microsoft.PowerShell.EditorServices.Commands
-{
- ///
- /// The Start-EditorServices command, the conventional entrypoint for PowerShell Editor Services.
- ///
- public sealed class InvokeReadLineConstructorCommand : PSCmdlet
- {
- protected override void EndProcessing()
- {
- Type type = Type.GetType("Microsoft.PowerShell.PSConsoleReadLine, Microsoft.PowerShell.PSReadLine2");
- RuntimeHelpers.RunClassConstructor(type.TypeHandle);
- }
- }
-}
diff --git a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs
deleted file mode 100644
index b0adf6fc8..000000000
--- a/src/PowerShellEditorServices.Hosting/Commands/InvokeReadLineForEditorServicesCommand.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Reflection;
-using System.Threading;
-
-namespace Microsoft.PowerShell.EditorServices.Commands
-{
- ///
- /// The Start-EditorServices command, the conventional entrypoint for PowerShell Editor Services.
- ///
- public sealed class InvokeReadLineForEditorServicesCommand : PSCmdlet
- {
- private delegate string ReadLineInvoker(
- Runspace runspace,
- EngineIntrinsics engineIntrinsics,
- CancellationToken cancellationToken);
-
- private static Lazy s_readLine = new Lazy(() =>
- {
- Type type = Type.GetType("Microsoft.PowerShell.PSConsoleReadLine, Microsoft.PowerShell.PSReadLine2");
- MethodInfo method = type?.GetMethod(
- "ReadLine",
- new[] { typeof(Runspace), typeof(EngineIntrinsics), typeof(CancellationToken) });
-
- // TODO: Handle method being null here. This shouldn't ever happen.
-
- return (ReadLineInvoker)method.CreateDelegate(typeof(ReadLineInvoker));
- });
-
- ///
- /// The ID to give to the host's profile.
- ///
- [Parameter(Mandatory = true)]
- [ValidateNotNullOrEmpty]
- public CancellationToken CancellationToken { get; set; }
-
- protected override void EndProcessing()
- {
- // This returns a string.
- object result = s_readLine.Value(
- Runspace.DefaultRunspace,
- SessionState.PSVariable.Get("ExecutionContext").Value as EngineIntrinsics,
- CancellationToken
- );
-
- WriteObject(result);
- }
- }
-}
diff --git a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
index 10b7281af..7b48b9c3d 100644
--- a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
+++ b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
@@ -120,6 +120,11 @@ public static EditorServicesLoader Create(
{
AppDomain.CurrentDomain.AssemblyLoad += (object sender, AssemblyLoadEventArgs args) =>
{
+ if (args.LoadedAssembly.IsDynamic)
+ {
+ return;
+ }
+
logger.Log(
PsesLogLevel.Diagnostic,
$"Loaded '{args.LoadedAssembly.GetName()}' from '{args.LoadedAssembly.Location}'");
diff --git a/src/PowerShellEditorServices/Extensions/Api/EditorContextService.cs b/src/PowerShellEditorServices/Extensions/Api/EditorContextService.cs
index 2b880c805..9229f7071 100644
--- a/src/PowerShellEditorServices/Extensions/Api/EditorContextService.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/EditorContextService.cs
@@ -4,7 +4,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.PowerShell.EditorServices.Handlers;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
namespace Microsoft.PowerShell.EditorServices.Extensions.Services
diff --git a/src/PowerShellEditorServices/Extensions/Api/EditorExtensionServiceProvider.cs b/src/PowerShellEditorServices/Extensions/Api/EditorExtensionServiceProvider.cs
index 8d25db01d..73e8e209e 100644
--- a/src/PowerShellEditorServices/Extensions/Api/EditorExtensionServiceProvider.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/EditorExtensionServiceProvider.cs
@@ -5,7 +5,7 @@
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.PowerShell.EditorServices.Services;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
diff --git a/src/PowerShellEditorServices/Extensions/Api/EditorUIService.cs b/src/PowerShellEditorServices/Extensions/Api/EditorUIService.cs
index f83dd7d20..1fcafabcf 100644
--- a/src/PowerShellEditorServices/Extensions/Api/EditorUIService.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/EditorUIService.cs
@@ -6,7 +6,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
namespace Microsoft.PowerShell.EditorServices.Extensions.Services
@@ -116,7 +116,9 @@ public async Task PromptInputAsync(string message)
new ShowInputPromptRequest
{
Name = message,
- }).Returning(CancellationToken.None).ConfigureAwait(false);
+ })
+ .Returning(CancellationToken.None)
+ .ConfigureAwait(false);
if (response.PromptCancelled)
{
@@ -142,7 +144,9 @@ public async Task> PromptMultipleSelectionAsync(string mes
Message = message,
Choices = choiceDetails,
DefaultChoices = defaultChoiceIndexes?.ToArray(),
- }).Returning(CancellationToken.None).ConfigureAwait(false);
+ })
+ .Returning(CancellationToken.None)
+ .ConfigureAwait(false);
if (response.PromptCancelled)
{
@@ -168,7 +172,9 @@ public async Task PromptSelectionAsync(string message, IReadOnlyList -1 ? new[] { defaultChoiceIndex } : null,
- }).Returning(CancellationToken.None).ConfigureAwait(false);
+ })
+ .Returning(CancellationToken.None)
+ .ConfigureAwait(false);
if (response.PromptCancelled)
{
diff --git a/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs b/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs
index 229dc0e9b..64435154f 100644
--- a/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/ExtensionCommandService.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Microsoft.PowerShell.EditorServices.Services;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
diff --git a/src/PowerShellEditorServices/Extensions/Api/LanguageServerService.cs b/src/PowerShellEditorServices/Extensions/Api/LanguageServerService.cs
index 466e6b106..1a5254319 100644
--- a/src/PowerShellEditorServices/Extensions/Api/LanguageServerService.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/LanguageServerService.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using MediatR;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
using System.Threading;
using System.Threading.Tasks;
diff --git a/src/PowerShellEditorServices/Extensions/Api/WorkspaceService.cs b/src/PowerShellEditorServices/Extensions/Api/WorkspaceService.cs
index 98eb9f06e..dc1300e00 100644
--- a/src/PowerShellEditorServices/Extensions/Api/WorkspaceService.cs
+++ b/src/PowerShellEditorServices/Extensions/Api/WorkspaceService.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Management.Automation.Language;
-using System.Threading.Tasks;
namespace Microsoft.PowerShell.EditorServices.Extensions.Services
{
diff --git a/src/PowerShellEditorServices/Extensions/EditorContext.cs b/src/PowerShellEditorServices/Extensions/EditorContext.cs
index f8e65f472..a844febe3 100644
--- a/src/PowerShellEditorServices/Extensions/EditorContext.cs
+++ b/src/PowerShellEditorServices/Extensions/EditorContext.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
namespace Microsoft.PowerShell.EditorServices.Extensions
diff --git a/src/PowerShellEditorServices/Extensions/EditorFileRanges.cs b/src/PowerShellEditorServices/Extensions/EditorFileRanges.cs
index f3d84e963..c7a7d5b38 100644
--- a/src/PowerShellEditorServices/Extensions/EditorFileRanges.cs
+++ b/src/PowerShellEditorServices/Extensions/EditorFileRanges.cs
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Microsoft.PowerShell.EditorServices.Handlers;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
using Microsoft.PowerShell.EditorServices.Services.TextDocument;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using System;
diff --git a/src/PowerShellEditorServices/Extensions/EditorObject.cs b/src/PowerShellEditorServices/Extensions/EditorObject.cs
index b88f41f84..68747ac27 100644
--- a/src/PowerShellEditorServices/Extensions/EditorObject.cs
+++ b/src/PowerShellEditorServices/Extensions/EditorObject.cs
@@ -5,7 +5,7 @@
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.PowerShell.EditorServices.Extensions.Services;
-using Microsoft.PowerShell.EditorServices.Services;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
namespace Microsoft.PowerShell.EditorServices.Extensions
{
diff --git a/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs b/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs
index 02d0be68f..6a5c07bc2 100644
--- a/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs
+++ b/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Threading.Tasks;
-
namespace Microsoft.PowerShell.EditorServices.Extensions
{
///
diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs b/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs
index 82fe5214a..ff827646e 100644
--- a/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs
+++ b/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs
@@ -8,10 +8,10 @@
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell.EditorServices.Logging;
using Microsoft.PowerShell.EditorServices.Server;
-using Microsoft.PowerShell.EditorServices.Services;
using Serilog;
using Serilog.Events;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
+using Microsoft.PowerShell.EditorServices.Services.Extension;
#if DEBUG
using Serilog.Debugging;
diff --git a/src/PowerShellEditorServices/Logging/HostLoggerAdapter.cs b/src/PowerShellEditorServices/Logging/HostLoggerAdapter.cs
index 802d6c762..41026a5f1 100644
--- a/src/PowerShellEditorServices/Logging/HostLoggerAdapter.cs
+++ b/src/PowerShellEditorServices/Logging/HostLoggerAdapter.cs
@@ -3,8 +3,6 @@
using Microsoft.Extensions.Logging;
using System;
-using System.Collections.Generic;
-using System.Text;
namespace Microsoft.PowerShell.EditorServices.Logging
{
diff --git a/src/PowerShellEditorServices/PowerShellEditorServices.csproj b/src/PowerShellEditorServices/PowerShellEditorServices.csproj
index 55802fc82..6fdc36b3c 100644
--- a/src/PowerShellEditorServices/PowerShellEditorServices.csproj
+++ b/src/PowerShellEditorServices/PowerShellEditorServices.csproj
@@ -42,6 +42,9 @@
-
+
+
+
+
diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs
index e4327cfbe..0b1bf209b 100644
--- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs
+++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs
@@ -3,18 +3,15 @@
using System;
using System.IO;
-using System.Management.Automation;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell.EditorServices.Handlers;
using Microsoft.PowerShell.EditorServices.Services;
-using Microsoft.PowerShell.EditorServices.Utility;
-using OmniSharp.Extensions.DebugAdapter.Protocol;
-using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization;
+using Microsoft.PowerShell.EditorServices.Services.PowerShell.Debugging;
+using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
using OmniSharp.Extensions.DebugAdapter.Server;
-using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Server;
namespace Microsoft.PowerShell.EditorServices.Server
@@ -24,17 +21,6 @@ namespace Microsoft.PowerShell.EditorServices.Server
///
internal class PsesDebugServer : IDisposable
{
- ///
- /// This is a bool but must be an int, since Interlocked.Exchange can't handle a bool
- ///
- private static int s_hasRunPsrlStaticCtor = 0;
-
- private static readonly Lazy s_lazyInvokeReadLineConstructorCmdletInfo = new Lazy(() =>
- {
- var type = Type.GetType("Microsoft.PowerShell.EditorServices.Commands.InvokeReadLineConstructorCommand, Microsoft.PowerShell.EditorServices.Hosting");
- return new CmdletInfo("__Invoke-ReadLineConstructor", type);
- });
-
private readonly Stream _inputStream;
private readonly Stream _outputStream;
private readonly bool _useTempSession;
@@ -42,7 +28,10 @@ internal class PsesDebugServer : IDisposable
private readonly TaskCompletionSource _serverStopped;
private DebugAdapterServer _debugAdapterServer;
- private PowerShellContextService _powerShellContextService;
+
+ private PsesInternalHost _psesHost;
+
+ private bool _startedPses;
protected readonly ILoggerFactory _loggerFactory;
@@ -75,30 +64,17 @@ public async Task StartAsync()
{
// We need to let the PowerShell Context Service know that we are in a debug session
// so that it doesn't send the powerShell/startDebugger message.
- _powerShellContextService = ServiceProvider.GetService();
- _powerShellContextService.IsDebugServerActive = true;
-
- // Needed to make sure PSReadLine's static properties are initialized in the pipeline thread.
- // This is only needed for Temp sessions who only have a debug server.
- if (_usePSReadLine && _useTempSession && Interlocked.Exchange(ref s_hasRunPsrlStaticCtor, 1) == 0)
- {
- var command = new PSCommand()
- .AddCommand(s_lazyInvokeReadLineConstructorCmdletInfo.Value);
-
- // This must be run synchronously to ensure debugging works
- _powerShellContextService
- .ExecuteCommandAsync