Skip to content

Commit 2b70a25

Browse files
Merge pull request #1514 from PowerShell/andschwa/psreadline
Load only bundled `PSReadLine`
2 parents 52f4184 + 178a317 commit 2b70a25

File tree

6 files changed

+56
-61
lines changed

6 files changed

+56
-61
lines changed

PowerShellEditorServices.Common.props

+1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
<RepositoryType>git</RepositoryType>
1212
<RepositoryUrl>https://github.com/PowerShell/PowerShellEditorServices</RepositoryUrl>
1313
<DebugType>portable</DebugType>
14+
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
1415
</PropertyGroup>
1516
</Project>

PowerShellEditorServices.build.ps1

+5-5
Original file line numberDiff line numberDiff line change
@@ -259,20 +259,20 @@ task TestServer TestServerWinPS,TestServerPS7,TestServerPS72
259259

260260
task TestServerWinPS -If (-not $script:IsNix) {
261261
Set-Location .\test\PowerShellEditorServices.Test\
262-
exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.Desktop (DotNetTestFilter) }
262+
exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.Desktop (DotNetTestFilter) }
263263
}
264264

265265
task TestServerPS7 -If (-not $script:IsRosetta) {
266266
Set-Location .\test\PowerShellEditorServices.Test\
267267
Invoke-WithCreateDefaultHook -NewModulePath $script:PSCoreModulePath {
268-
exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
268+
exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
269269
}
270270
}
271271

272272
task TestServerPS72 {
273273
Set-Location .\test\PowerShellEditorServices.Test\
274274
Invoke-WithCreateDefaultHook -NewModulePath $script:PSCoreModulePath {
275-
exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS72 (DotNetTestFilter) }
275+
exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS72 (DotNetTestFilter) }
276276
}
277277
}
278278

@@ -281,13 +281,13 @@ task TestE2E {
281281

282282
$env:PWSH_EXE_NAME = if ($IsCoreCLR) { "pwsh" } else { "powershell" }
283283
$NetRuntime = if ($IsRosetta) { $script:NetRuntime.PS72 } else { $script:NetRuntime.PS7 }
284-
exec { & $script:dotnetExe test --logger trx -f $NetRuntime (DotNetTestFilter) }
284+
exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $NetRuntime (DotNetTestFilter) }
285285

286286
# Run E2E tests in ConstrainedLanguage mode.
287287
if (!$script:IsNix) {
288288
try {
289289
[System.Environment]::SetEnvironmentVariable("__PSLockdownPolicy", "0x80000007", [System.EnvironmentVariableTarget]::Machine);
290-
exec { & $script:dotnetExe test --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
290+
exec { & $script:dotnetExe test -p:ExtraDefineConstants=TEST --logger trx -f $script:NetRuntime.PS7 (DotNetTestFilter) }
291291
} finally {
292292
[System.Environment]::SetEnvironmentVariable("__PSLockdownPolicy", $null, [System.EnvironmentVariableTarget]::Machine);
293293
}

src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs

-15
Original file line numberDiff line numberDiff line change
@@ -296,21 +296,6 @@ public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode
296296
return runspace;
297297
}
298298

299-
/// <summary>
300-
/// Initializes a new instance of the PowerShellContext class using
301-
/// an existing runspace for the session.
302-
/// </summary>
303-
/// <param name="profilePaths">An object containing the profile paths for the session.</param>
304-
/// <param name="initialRunspace">The initial runspace to use for this instance.</param>
305-
/// <param name="ownsInitialRunspace">If true, the PowerShellContext owns this runspace.</param>
306-
public void Initialize(
307-
ProfilePathInfo profilePaths,
308-
Runspace initialRunspace,
309-
bool ownsInitialRunspace)
310-
{
311-
this.Initialize(profilePaths, initialRunspace, ownsInitialRunspace, consoleHost: null);
312-
}
313-
314299
/// <summary>
315300
/// Initializes a new instance of the PowerShellContext class using
316301
/// an existing runspace for the session.

src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs

+14-24
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,15 @@ internal class PSReadLinePromptContext : IPromptContext
2222
"..",
2323
"..",
2424
"..",
25+
#if TEST
26+
// When using xUnit (dotnet test) the assemblies are deployed to the
27+
// test project folder, invalidating our relative path assumption.
28+
"..",
29+
"..",
30+
"module",
31+
#endif
2532
"PSReadLine");
2633

27-
private static readonly string ReadLineInitScript = $@"
28-
[System.Diagnostics.DebuggerHidden()]
29-
[System.Diagnostics.DebuggerStepThrough()]
30-
param()
31-
end {{
32-
$module = Get-Module -ListAvailable PSReadLine |
33-
Where-Object {{ $_.Version -ge '2.0.2' }} |
34-
Sort-Object -Descending Version |
35-
Select-Object -First 1
36-
if (-not $module) {{
37-
Import-Module '{_psReadLineModulePath.Replace("'", "''")}'
38-
return [Microsoft.PowerShell.PSConsoleReadLine]
39-
}}
40-
41-
Import-Module -ModuleInfo $module
42-
return [Microsoft.PowerShell.PSConsoleReadLine]
43-
}}";
44-
4534
private static readonly Lazy<CmdletInfo> s_lazyInvokeReadLineForEditorServicesCmdletInfo = new Lazy<CmdletInfo>(() =>
4635
{
4736
var type = Type.GetType("Microsoft.PowerShell.EditorServices.Commands.InvokeReadLineForEditorServicesCommand, Microsoft.PowerShell.EditorServices.Hosting");
@@ -97,14 +86,15 @@ internal static bool TryGetPSReadLineProxy(
9786
using (var pwsh = PowerShell.Create())
9887
{
9988
pwsh.Runspace = runspace;
100-
var psReadLineType = pwsh
101-
.AddScript(ReadLineInitScript, useLocalScope: true)
102-
.Invoke<Type>()
103-
.FirstOrDefault();
89+
pwsh.AddCommand("Microsoft.PowerShell.Core\\Import-Module")
90+
.AddParameter("Name", _psReadLineModulePath)
91+
.Invoke();
92+
93+
var psReadLineType = Type.GetType("Microsoft.PowerShell.PSConsoleReadLine, Microsoft.PowerShell.PSReadLine2");
10494

10595
if (psReadLineType == null)
10696
{
107-
logger.LogWarning("PSReadLine unable to be loaded: {Reason}", pwsh.HadErrors ? pwsh.Streams.Error[0].ToString() : "<Unknown reason>");
97+
logger.LogWarning("PSConsoleReadline type not found: {Reason}", pwsh.HadErrors ? pwsh.Streams.Error[0].ToString() : "<Unknown reason>");
10898
return false;
10999
}
110100

@@ -117,7 +107,7 @@ internal static bool TryGetPSReadLineProxy(
117107
// The Type we got back from PowerShell doesn't have the members we expected.
118108
// Could be an older version, a custom build, or something a newer version with
119109
// breaking changes.
120-
logger.LogWarning("PSReadLine unable to be loaded: {Reason}", e);
110+
logger.LogWarning("PSReadLineProxy unable to be initialized: {Reason}", e);
121111
return false;
122112
}
123113
}

test/PowerShellEditorServices.Test/PowerShellContextFactory.cs

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
using Microsoft.Extensions.Logging;
5-
using Microsoft.Extensions.Logging.Abstractions;
6-
using Microsoft.PowerShell.EditorServices.Hosting;
7-
using Microsoft.PowerShell.EditorServices.Services;
8-
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
9-
using Microsoft.PowerShell.EditorServices.Test.Shared;
104
using System;
115
using System.Collections.Generic;
126
using System.IO;
137
using System.Management.Automation;
148
using System.Threading;
159
using System.Threading.Tasks;
10+
using Microsoft.Extensions.Logging;
11+
using Microsoft.Extensions.Logging.Abstractions;
12+
using Microsoft.PowerShell.EditorServices.Hosting;
13+
using Microsoft.PowerShell.EditorServices.Services;
14+
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
15+
using Microsoft.PowerShell.EditorServices.Test.Shared;
1616

1717
namespace Microsoft.PowerShell.EditorServices.Test
1818
{
@@ -32,6 +32,8 @@ internal static class PowerShellContextFactory
3232
Path.GetFullPath(
3333
TestUtilities.NormalizePath("../../../../PowerShellEditorServices.Test.Shared/ProfileTest.ps1")));
3434

35+
public static System.Management.Automation.Runspaces.Runspace initialRunspace;
36+
3537
public static PowerShellContextService Create(ILogger logger)
3638
{
3739
PowerShellContextService powerShellContext = new PowerShellContextService(logger, null, isPSReadLineEnabled: false);
@@ -50,15 +52,17 @@ public static PowerShellContextService Create(ILogger logger)
5052
consoleReplEnabled: false,
5153
usesLegacyReadLine: false);
5254

53-
54-
powerShellContext.Initialize(
55-
TestProfilePaths,
56-
PowerShellContextService.CreateRunspace(
55+
initialRunspace = PowerShellContextService.CreateRunspace(
5756
testHostDetails,
5857
powerShellContext,
5958
new TestPSHostUserInterface(powerShellContext, logger),
60-
logger),
61-
true);
59+
logger);
60+
61+
powerShellContext.Initialize(
62+
TestProfilePaths,
63+
initialRunspace,
64+
ownsInitialRunspace: true,
65+
consoleHost: null);
6266

6367
return powerShellContext;
6468
}

test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
using Microsoft.Extensions.Logging.Abstractions;
5-
using Microsoft.PowerShell.EditorServices.Services;
6-
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
7-
using Microsoft.PowerShell.EditorServices.Test.Shared;
8-
using Microsoft.PowerShell.EditorServices.Utility;
94
using System;
105
using System.Collections.Generic;
116
using System.IO;
127
using System.Linq;
138
using System.Management.Automation;
9+
using System.Runtime.InteropServices;
1410
using System.Threading.Tasks;
11+
using Microsoft.Extensions.Logging.Abstractions;
12+
using Microsoft.PowerShell.EditorServices.Services;
13+
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
14+
using Microsoft.PowerShell.EditorServices.Test.Shared;
15+
using Microsoft.PowerShell.EditorServices.Utility;
1516
using Xunit;
1617

1718
namespace Microsoft.PowerShell.EditorServices.Test.Console
1819
{
1920
public class PowerShellContextTests : IDisposable
2021
{
22+
// Borrowed from `VersionUtils` which can't be used here due to an initialization problem.
23+
private static bool IsWindows { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
24+
2125
private PowerShellContextService powerShellContext;
2226
private AsyncQueue<SessionStateChangedEventArgs> stateChangeQueue;
2327

@@ -143,6 +147,17 @@ await this.powerShellContext.ExecuteCommandAsync<string>(
143147
Assert.Equal(expectedString, result.FirstOrDefault(), true);
144148
}
145149

150+
[Trait("Category", "PSReadLine")]
151+
[SkippableFact]
152+
public async Task CanGetPSReadLineProxy()
153+
{
154+
Skip.If(IsWindows, "This test doesn't work on Windows for some reason.");
155+
Assert.True(PSReadLinePromptContext.TryGetPSReadLineProxy(
156+
NullLogger.Instance,
157+
PowerShellContextFactory.initialRunspace,
158+
out PSReadLineProxy proxy));
159+
}
160+
146161
#region Helper Methods
147162

148163
private async Task AssertStateChange(PowerShellContextState expectedState)

0 commit comments

Comments
 (0)