Skip to content

Commit 6577794

Browse files
Re-add Stdio option and replace Pester tests with xunit tests. (#1008)
1 parent f25004c commit 6577794

18 files changed

+1163
-2266
lines changed

PowerShellEditorServices.build.ps1

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ $script:IsUnix = $PSVersionTable.PSEdition -and $PSVersionTable.PSEdition -eq "C
2222
$script:TargetPlatform = "netstandard2.0"
2323
$script:TargetFrameworksParam = "/p:TargetFrameworks=`"$script:TargetPlatform`""
2424
$script:RequiredSdkVersion = (Get-Content (Join-Path $PSScriptRoot 'global.json') | ConvertFrom-Json).sdk.version
25-
$script:MinimumPesterVersion = '4.7'
2625
$script:NugetApiUriBase = 'https://www.nuget.org/api/v2/package'
2726
$script:ModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices/bin/"
2827
$script:VSCodeModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices.VSCode/bin/"
@@ -173,7 +172,7 @@ function Invoke-WithCreateDefaultHook {
173172
}
174173
}
175174

176-
task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, PackageNuGet {
175+
task SetupDotNet -Before Clean, Build, TestHost, TestServer, TestProtocol, TestE2E, PackageNuGet {
177176

178177
$dotnetPath = "$PSScriptRoot/.dotnet"
179178
$dotnetExePath = if ($script:IsUnix) { "$dotnetPath/dotnet" } else { "$dotnetPath/dotnet.exe" }
@@ -324,18 +323,13 @@ task Build {
324323
exec { & $script:dotnetExe build -c $Configuration .\src\PowerShellEditorServices.VSCode\PowerShellEditorServices.VSCode.csproj $script:TargetFrameworksParam }
325324
}
326325

327-
task BuildPsesClientModule SetupDotNet,{
328-
Write-Verbose 'Building PsesPsClient testing module'
329-
& $PSScriptRoot/tools/PsesPsClient/build.ps1 -DotnetExe $script:dotnetExe
330-
}
331-
332326
function DotNetTestFilter {
333327
# Reference https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests
334328
if ($TestFilter) { @("--filter",$TestFilter) } else { "" }
335329
}
336330

337-
# task Test TestServer,TestProtocol,TestPester
338-
task Test TestPester
331+
# task Test TestServer,TestProtocol,TestE2E
332+
task Test TestE2E
339333

340334
task TestServer {
341335
Set-Location .\test\PowerShellEditorServices.Test\
@@ -373,26 +367,11 @@ task TestHost {
373367
exec { & $script:dotnetExe test -f $script:TestRuntime.Core (DotNetTestFilter) }
374368
}
375369

376-
task TestPester Build,BuildPsesClientModule,EnsurePesterInstalled,{
377-
$testParams = @{}
378-
if ($env:TF_BUILD)
379-
{
380-
$testParams += @{
381-
OutputFormat = 'NUnitXml'
382-
OutputFile = 'TestResults.xml'
383-
}
384-
}
385-
$result = Invoke-Pester "$PSScriptRoot/test/Pester/" @testParams -PassThru
386-
387-
if ($result.FailedCount -gt 0)
388-
{
389-
throw "$($result.FailedCount) tests failed."
390-
}
391-
}
370+
task TestE2E {
371+
Set-Location .\test\PowerShellEditorServices.Test.E2E\
392372

393-
task EnsurePesterInstalled -If (-not (Get-Module Pester -ListAvailable | Where-Object Version -ge $script:MinimumPesterVersion)) {
394-
Write-Warning "Required Pester version not found, installing Pester to current user scope"
395-
Install-Module -Scope CurrentUser Pester -Force -SkipPublisherCheck
373+
$env:PWSH_EXE_NAME = if ($IsCoreCLR) { "pwsh" } else { "powershell" }
374+
exec { & $script:dotnetExe test --logger trx -f $script:TestRuntime.Core (DotNetTestFilter) }
396375
}
397376

398377
task LayoutModule -After Build {

PowerShellEditorServices.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerShellEditorServices.VS
3030
EndProject
3131
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerShellEditorServices.Engine", "src\PowerShellEditorServices.Engine\PowerShellEditorServices.Engine.csproj", "{29EEDF03-0990-45F4-846E-2616970D1FA2}"
3232
EndProject
33+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerShellEditorServices.Test.E2E", "test\PowerShellEditorServices.Test.E2E\PowerShellEditorServices.Test.E2E.csproj", "{2561F253-8F72-436A-BCC3-AA63AB82EDC0}"
34+
EndProject
3335
Global
3436
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3537
Debug|Any CPU = Debug|Any CPU
@@ -148,6 +150,18 @@ Global
148150
{29EEDF03-0990-45F4-846E-2616970D1FA2}.Release|x64.Build.0 = Release|Any CPU
149151
{29EEDF03-0990-45F4-846E-2616970D1FA2}.Release|x86.ActiveCfg = Release|Any CPU
150152
{29EEDF03-0990-45F4-846E-2616970D1FA2}.Release|x86.Build.0 = Release|Any CPU
153+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
154+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
155+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|x64.ActiveCfg = Debug|Any CPU
156+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|x64.Build.0 = Debug|Any CPU
157+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|x86.ActiveCfg = Debug|Any CPU
158+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Debug|x86.Build.0 = Debug|Any CPU
159+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
160+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|Any CPU.Build.0 = Release|Any CPU
161+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|x64.ActiveCfg = Release|Any CPU
162+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|x64.Build.0 = Release|Any CPU
163+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|x86.ActiveCfg = Release|Any CPU
164+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0}.Release|x86.Build.0 = Release|Any CPU
151165
EndGlobalSection
152166
GlobalSection(SolutionProperties) = preSolution
153167
HideSolutionNode = FALSE
@@ -162,5 +176,6 @@ Global
162176
{E3A5CF5D-6E41-44AC-AE0A-4C227E4BACD4} = {422E561A-8118-4BE7-A54F-9309E4F03AAE}
163177
{3B38E8DA-8BFF-4264-AF16-47929E6398A3} = {F594E7FD-1E72-4E51-A496-B019C2BA3180}
164178
{29EEDF03-0990-45F4-846E-2616970D1FA2} = {F594E7FD-1E72-4E51-A496-B019C2BA3180}
179+
{2561F253-8F72-436A-BCC3-AA63AB82EDC0} = {422E561A-8118-4BE7-A54F-9309E4F03AAE}
165180
EndGlobalSection
166181
EndGlobal

src/PowerShellEditorServices.Engine/Hosting/EditorServicesHost.cs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.Extensions.DependencyInjection;
1919
using Microsoft.Extensions.Logging;
2020
using Microsoft.PowerShell.EditorServices.Extensions;
21+
using Microsoft.PowerShell.EditorServices.Host;
2122
using Serilog;
2223

2324
namespace Microsoft.PowerShell.EditorServices.Engine
@@ -234,13 +235,15 @@ public void StartLanguageService(
234235

235236
_logger.LogInformation($"LSP NamedPipe: {config.InOutPipeName}\nLSP OutPipe: {config.OutPipeName}");
236237

237-
var powerShellContext = GetFullyInitializedPowerShellContext(profilePaths);
238-
239238
_serviceCollection
240239
.AddSingleton<WorkspaceService>()
241240
.AddSingleton<SymbolsService>()
242241
.AddSingleton<ConfigurationService>()
243-
.AddSingleton<PowerShellContextService>(powerShellContext)
242+
.AddSingleton<PowerShellContextService>(
243+
(provider) =>
244+
GetFullyInitializedPowerShellContext(
245+
provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
246+
profilePaths))
244247
.AddSingleton<EditorOperationsService>()
245248
.AddSingleton<ExtensionService>(
246249
(provider) =>
@@ -263,14 +266,29 @@ public void StartLanguageService(
263266
_factory.CreateLogger<AnalysisService>());
264267
});
265268

266-
_languageServer = new OmnisharpLanguageServerBuilder(_serviceCollection)
269+
switch (config.TransportType)
267270
{
268-
NamedPipeName = config.InOutPipeName ?? config.InPipeName,
269-
OutNamedPipeName = config.OutPipeName,
270-
LoggerFactory = _factory,
271-
MinimumLogLevel = LogLevel.Trace,
271+
case EditorServiceTransportType.NamedPipe:
272+
_languageServer = new OmnisharpLanguageServerBuilder(_serviceCollection)
273+
{
274+
NamedPipeName = config.InOutPipeName ?? config.InPipeName,
275+
OutNamedPipeName = config.OutPipeName,
276+
LoggerFactory = _factory,
277+
MinimumLogLevel = LogLevel.Trace,
278+
}
279+
.BuildLanguageServer();
280+
break;
281+
282+
case EditorServiceTransportType.Stdio:
283+
_languageServer = new OmnisharpLanguageServerBuilder(_serviceCollection)
284+
{
285+
Stdio = true,
286+
LoggerFactory = _factory,
287+
MinimumLogLevel = LogLevel.Trace,
288+
}
289+
.BuildLanguageServer();
290+
break;
272291
}
273-
.BuildLanguageServer();
274292

275293
_logger.LogInformation("Starting language server");
276294

@@ -282,21 +300,22 @@ public void StartLanguageService(
282300
config.TransportType, config.Endpoint));
283301
}
284302

285-
private PowerShellContextService GetFullyInitializedPowerShellContext(ProfilePaths profilePaths)
303+
private PowerShellContextService GetFullyInitializedPowerShellContext(
304+
OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer languageServer,
305+
ProfilePaths profilePaths)
286306
{
287307
var logger = _factory.CreateLogger<PowerShellContextService>();
308+
309+
// PSReadLine can only be used when -EnableConsoleRepl is specified otherwise
310+
// issues arise when redirecting stdio.
288311
var powerShellContext = new PowerShellContextService(
289312
logger,
290-
_featureFlags.Contains("PSReadLine"));
313+
_featureFlags.Contains("PSReadLine") && _enableConsoleRepl);
291314

292-
// TODO: Bring this back
293-
//EditorServicesPSHostUserInterface hostUserInterface =
294-
// _enableConsoleRepl
295-
// ? (EditorServicesPSHostUserInterface)new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost)
296-
// : new ProtocolPSHostUserInterface(powerShellContext, messageSender, logger);
297315
EditorServicesPSHostUserInterface hostUserInterface =
298-
new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost);
299-
316+
_enableConsoleRepl
317+
? (EditorServicesPSHostUserInterface) new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost)
318+
: new ProtocolPSHostUserInterface(languageServer, powerShellContext, logger);
300319

301320
EditorServicesPSHost psHost =
302321
new EditorServicesPSHost(

src/PowerShellEditorServices.Engine/LanguageServer/OmnisharpLanguageServer.cs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,28 @@
33
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
44
//
55

6+
using System.IO;
67
using System.IO.Pipes;
78
using System.Reflection;
8-
using System.Threading.Tasks;
9+
using System.Security.AccessControl;
910
using System.Security.Principal;
11+
using System.Threading.Tasks;
12+
1013
using Microsoft.Extensions.DependencyInjection;
1114
using Microsoft.Extensions.Logging;
12-
using OS = OmniSharp.Extensions.LanguageServer.Server;
13-
using System.Security.AccessControl;
15+
using Microsoft.PowerShell.EditorServices.TextDocument;
1416
using OmniSharp.Extensions.LanguageServer.Server;
17+
using OS = OmniSharp.Extensions.LanguageServer.Server;
1518
using PowerShellEditorServices.Engine.Services.Handlers;
16-
using Microsoft.PowerShell.EditorServices.TextDocument;
17-
using System.IO;
1819

1920
namespace Microsoft.PowerShell.EditorServices.Engine
2021
{
2122
public class OmnisharpLanguageServer : ILanguageServer
2223
{
2324
public class Configuration
2425
{
26+
public bool Stdio { get; set; }
27+
2528
public string NamedPipeName { get; set; }
2629

2730
public string OutNamedPipeName { get; set; }
@@ -58,24 +61,33 @@ public OmnisharpLanguageServer(
5861
public async Task StartAsync()
5962
{
6063
_languageServer = await OS.LanguageServer.From(options => {
61-
NamedPipeServerStream namedPipe = CreateNamedPipe(
62-
_configuration.NamedPipeName,
63-
_configuration.OutNamedPipeName,
64-
out NamedPipeServerStream outNamedPipe);
6564

6665
ILogger logger = options.LoggerFactory.CreateLogger("OptionsStartup");
6766

68-
logger.LogInformation("Waiting for connection");
69-
namedPipe.WaitForConnection();
70-
if (outNamedPipe != null)
67+
if (_configuration.Stdio)
7168
{
72-
outNamedPipe.WaitForConnection();
69+
options.WithInput(System.Console.OpenStandardInput());
70+
options.WithOutput(System.Console.OpenStandardOutput());
7371
}
72+
else
73+
{
74+
NamedPipeServerStream namedPipe = CreateNamedPipe(
75+
_configuration.NamedPipeName,
76+
_configuration.OutNamedPipeName,
77+
out NamedPipeServerStream outNamedPipe);
7478

75-
logger.LogInformation("Connected");
79+
logger.LogInformation("Waiting for connection");
80+
namedPipe.WaitForConnection();
81+
if (outNamedPipe != null)
82+
{
83+
outNamedPipe.WaitForConnection();
84+
}
7685

77-
options.Input = namedPipe;
78-
options.Output = outNamedPipe ?? namedPipe;
86+
logger.LogInformation("Connected");
87+
88+
options.Input = namedPipe;
89+
options.Output = outNamedPipe ?? namedPipe;
90+
}
7991

8092
options.LoggerFactory = _configuration.LoggerFactory;
8193
options.MinimumLogLevel = _configuration.MinimumLogLevel;

src/PowerShellEditorServices.Engine/LanguageServer/OmnisharpLanguageServerBuilder.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public OmnisharpLanguageServerBuilder(IServiceCollection serviceCollection)
1010
Services = serviceCollection;
1111
}
1212

13+
public bool Stdio { get; set; }
14+
1315
public string NamedPipeName { get; set; }
1416

1517
public string OutNamedPipeName { get; set; }
@@ -28,7 +30,8 @@ public ILanguageServer BuildLanguageServer()
2830
MinimumLogLevel = MinimumLogLevel,
2931
NamedPipeName = NamedPipeName,
3032
OutNamedPipeName = OutNamedPipeName,
31-
Services = Services
33+
Services = Services,
34+
Stdio = Stdio
3235
};
3336

3437
return new OmnisharpLanguageServer(config);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace Microsoft.PowerShell.EditorServices.Protocol.Messages
7+
{
8+
public class ShowChoicePromptRequest
9+
{
10+
public bool IsMultiChoice { get; set; }
11+
12+
public string Caption { get; set; }
13+
14+
public string Message { get; set; }
15+
16+
public ChoiceDetails[] Choices { get; set; }
17+
18+
public int[] DefaultChoices { get; set; }
19+
}
20+
21+
public class ShowChoicePromptResponse
22+
{
23+
public bool PromptCancelled { get; set; }
24+
25+
public string ResponseText { get; set; }
26+
}
27+
28+
public class ShowInputPromptRequest
29+
{
30+
/// <summary>
31+
/// Gets or sets the name of the field.
32+
/// </summary>
33+
public string Name { get; set; }
34+
35+
/// <summary>
36+
/// Gets or sets the descriptive label for the field.
37+
/// </summary>
38+
public string Label { get; set; }
39+
}
40+
41+
public class ShowInputPromptResponse
42+
{
43+
public bool PromptCancelled { get; set; }
44+
45+
public string ResponseText { get; set; }
46+
}
47+
}
48+

0 commit comments

Comments
 (0)