Skip to content

Commit 982ed12

Browse files
committed
Move runspace creation outside of PowerShellContext
This change moves runspace creation outside of PowerShellContext so that the runspace can be configured more easily at the host level. It also changes the relationship between the ConsoleServicePSHost and ConsoleService so that the latter now gets created by the former. This is leading up to a change where the behavior of these two classes will be merged into the PSHost implementation.
1 parent caf9743 commit 982ed12

File tree

13 files changed

+138
-96
lines changed

13 files changed

+138
-96
lines changed

src/PowerShellEditorServices.Host/EditorServicesHost.cs

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

6+
using Microsoft.PowerShell.EditorServices.Console;
67
using Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.Channel;
78
using Microsoft.PowerShell.EditorServices.Protocol.Server;
89
using Microsoft.PowerShell.EditorServices.Session;
910
using Microsoft.PowerShell.EditorServices.Utility;
1011
using System;
1112
using System.Collections.Generic;
1213
using System.Diagnostics;
14+
using System.Management.Automation.Runspaces;
15+
using System.Management.Automation.Host;
1316
using System.Reflection;
1417
using System.Threading;
1518
using Microsoft.PowerShell.EditorServices.Extensions;
@@ -271,9 +274,20 @@ private EditorSession CreateSession(
271274
bool enableConsoleRepl)
272275
{
273276
EditorSession editorSession = new EditorSession();
277+
PowerShellContext powerShellContext = new PowerShellContext();
278+
279+
ConsoleServicePSHost psHost =
280+
new ConsoleServicePSHost(
281+
powerShellContext,
282+
hostDetails,
283+
enableConsoleRepl);
284+
285+
Runspace initialRunspace = PowerShellContext.CreateRunspace(psHost);
286+
powerShellContext.Initialize(profilePaths, initialRunspace, true, psHost.ConsoleService);
287+
274288
editorSession.StartSession(
275-
CreatePowerShellContext(hostDetails, profilePaths, enableConsoleRepl),
276-
enableConsoleRepl);
289+
powerShellContext,
290+
psHost.ConsoleService);
277291

278292
return editorSession;
279293
}
@@ -284,21 +298,25 @@ private EditorSession CreateDebugSession(
284298
IEditorOperations editorOperations)
285299
{
286300
EditorSession editorSession = new EditorSession();
301+
PowerShellContext powerShellContext = new PowerShellContext();
302+
303+
ConsoleServicePSHost psHost =
304+
new ConsoleServicePSHost(
305+
powerShellContext,
306+
hostDetails,
307+
enableConsoleRepl);
308+
309+
Runspace initialRunspace = PowerShellContext.CreateRunspace(psHost);
310+
powerShellContext.Initialize(profilePaths, initialRunspace, true, psHost.ConsoleService);
311+
287312
editorSession.StartDebugSession(
288-
CreatePowerShellContext(hostDetails, profilePaths, enableConsoleRepl),
313+
powerShellContext,
314+
psHost.ConsoleService,
289315
editorOperations);
290316

291317
return editorSession;
292318
}
293319

294-
private PowerShellContext CreatePowerShellContext(
295-
HostDetails hostDetails,
296-
ProfilePaths profilePaths,
297-
bool enableConsoleRepl)
298-
{
299-
return new PowerShellContext(hostDetails, profilePaths, enableConsoleRepl);
300-
}
301-
302320
#if !CoreCLR
303321
static void CurrentDomain_UnhandledException(
304322
object sender,

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,9 @@ public LanguageServer(
7070
this.editorSession.StartDebugService(this.editorOperations);
7171
this.editorSession.DebugService.DebuggerStopped += DebugService_DebuggerStopped;
7272

73-
if (this.editorSession.UsesConsoleHost)
74-
{
75-
this.editorSession.ConsoleService.EnableConsoleRepl = true;
76-
}
77-
else
73+
if (!this.editorSession.ConsoleService.EnableConsoleRepl)
7874
{
75+
// TODO: This should be handled in ProtocolPSHost
7976
this.editorSession.ConsoleService.OutputWritten += this.powerShellContext_OutputWritten;
8077

8178
// Always send console prompts through the UI in the language service
@@ -144,6 +141,7 @@ protected override void Initialize()
144141
protected override async Task Shutdown()
145142
{
146143
// Stop the interactive terminal
144+
// TODO: This can happen at the host level
147145
this.editorSession.ConsoleService.CancelReadLoop();
148146

149147
// Make sure remaining output is flushed before exiting
@@ -578,6 +576,7 @@ protected async Task HandleDidChangeConfigurationNotification(
578576
if (!this.consoleReplStarted)
579577
{
580578
// Start the interactive terminal
579+
// TODO: This can happen at the host level
581580
this.editorSession.ConsoleService.StartReadLoop();
582581
this.consoleReplStarted = true;
583582
}
@@ -1160,6 +1159,7 @@ protected Task HandleEvaluateRequest(
11601159
(task) =>
11611160
{
11621161
// Start the command loop again
1162+
// TODO: This can happen inside the PSHost
11631163
this.editorSession.ConsoleService.StartReadLoop();
11641164

11651165
// Return an empty result since the result value is irrelevant

src/PowerShellEditorServices/Analysis/AnalysisService.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,8 @@ public string SettingsPath
102102
/// <summary>
103103
/// Creates an instance of the AnalysisService class.
104104
/// </summary>
105-
/// <param name="consoleHost">An object that implements IConsoleHost in which to write errors/warnings
106-
/// from analyzer.</param>
107105
/// <param name="settingsPath">Path to a PSScriptAnalyzer settings file.</param>
108-
public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
106+
public AnalysisService(string settingsPath = null)
109107
{
110108
try
111109
{

src/PowerShellEditorServices/Console/ConsoleService.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ public ConsoleService(
7676
{
7777
// Register this instance as the IConsoleHost for the PowerShellContext
7878
this.powerShellContext = powerShellContext;
79-
this.powerShellContext.ConsoleHost = this;
8079
this.powerShellContext.DebuggerStop += PowerShellContext_DebuggerStop;
8180
this.powerShellContext.DebuggerResumed += PowerShellContext_DebuggerResumed;
8281
this.powerShellContext.ExecutionStatusChanged += PowerShellContext_ExecutionStatusChanged;

src/PowerShellEditorServices/Session/EditorSession.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ public class EditorSession
8484
/// </param>
8585
public void StartSession(
8686
PowerShellContext powerShellContext,
87-
bool enableConsoleRepl)
87+
ConsoleService consoleService)
8888
{
8989
// Initialize all services
9090
this.PowerShellContext = powerShellContext;
91+
this.ConsoleService = consoleService;
92+
this.UsesConsoleHost = this.ConsoleService.EnableConsoleRepl;
93+
9194
this.LanguageService = new LanguageService(this.PowerShellContext);
92-
this.ConsoleService = new ConsoleService(this.PowerShellContext);
9395
this.ExtensionService = new ExtensionService(this.PowerShellContext);
9496
this.TemplateService = new TemplateService(this.PowerShellContext);
95-
this.UsesConsoleHost = enableConsoleRepl;
9697

9798
this.InstantiateAnalysisService();
9899

@@ -109,11 +110,13 @@ public void StartSession(
109110
/// </param>
110111
public void StartDebugSession(
111112
PowerShellContext powerShellContext,
113+
ConsoleService consoleService,
112114
IEditorOperations editorOperations)
113115
{
114116
// Initialize all services
115117
this.PowerShellContext = powerShellContext;
116-
this.ConsoleService = new ConsoleService(this.PowerShellContext);
118+
this.ConsoleService = consoleService;
119+
117120
this.RemoteFileManager = new RemoteFileManager(this.PowerShellContext, editorOperations);
118121
this.DebugService = new DebugService(this.PowerShellContext, this.RemoteFileManager);
119122

@@ -142,7 +145,7 @@ internal void InstantiateAnalysisService(string settingsPath = null)
142145
// Script Analyzer binaries are not included.
143146
try
144147
{
145-
this.AnalysisService = new AnalysisService(this.PowerShellContext.ConsoleHost, settingsPath);
148+
this.AnalysisService = new AnalysisService(settingsPath);
146149
}
147150
catch (FileNotFoundException)
148151
{

src/PowerShellEditorServices/Session/PowerShellContext.cs

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ public class PowerShellContext : IDisposable, IHostSupportsInteractiveSession
3838
private RunspaceDetails initialRunspace;
3939
private SessionDetails mostRecentSessionDetails;
4040

41-
private IConsoleHost consoleHost;
4241
private ProfilePaths profilePaths;
43-
private ConsoleServicePSHost psHost;
4442

4543
private IVersionSpecificOperations versionSpecificOperations;
4644

@@ -94,15 +92,7 @@ public PowerShellVersionDetails LocalPowerShellVersion
9492
/// Gets or sets an IConsoleHost implementation for use in
9593
/// writing output to the console.
9694
/// </summary>
97-
internal IConsoleHost ConsoleHost
98-
{
99-
get { return this.consoleHost; }
100-
set
101-
{
102-
this.consoleHost = value;
103-
this.psHost.ConsoleHost = value;
104-
}
105-
}
95+
private IConsoleHost ConsoleHost { get; set; }
10696

10797
/// <summary>
10898
/// Gets details pertaining to the current runspace.
@@ -125,42 +115,18 @@ public string PromptString
125115

126116
#region Constructors
127117

128-
/// <summary>
129-
/// Initializes a new instance of the PowerShellContext class and
130-
/// opens a runspace to be used for the session.
131-
/// </summary>
132-
public PowerShellContext() : this((HostDetails)null, null)
133-
{
134-
}
135-
136-
/// <summary>
137-
/// Initializes a new instance of the PowerShellContext class and
138-
/// opens a runspace to be used for the session.
139-
/// </summary>
140-
/// <param name="hostDetails">Provides details about the host application.</param>
141-
/// <param name="profilePaths">An object containing the profile paths for the session.</param>
142-
public PowerShellContext(HostDetails hostDetails, ProfilePaths profilePaths)
143-
: this(hostDetails, profilePaths, false)
144-
{
145-
}
146-
147-
/// <summary>
148-
/// Initializes a new instance of the PowerShellContext class and
149-
/// opens a runspace to be used for the session.
150-
/// </summary>
151-
/// <param name="hostDetails">Provides details about the host application.</param>
152-
/// <param name="profilePaths">An object containing the profile paths for the session.</param>
153-
/// <param name="enableConsoleRepl">
154-
/// Enables a terminal-based REPL for this session.
155-
/// </param>
156-
public PowerShellContext(
118+
public static Runspace CreateRunspace(
157119
HostDetails hostDetails,
158-
ProfilePaths profilePaths,
120+
PowerShellContext powerShellContext,
159121
bool enableConsoleRepl)
160122
{
161-
hostDetails = hostDetails ?? HostDetails.Default;
123+
var psHost = new ConsoleServicePSHost(powerShellContext, hostDetails, enableConsoleRepl);
124+
powerShellContext.ConsoleHost = psHost.ConsoleService;
125+
return CreateRunspace(psHost);
126+
}
162127

163-
this.psHost = new ConsoleServicePSHost(hostDetails, this, enableConsoleRepl);
128+
public static Runspace CreateRunspace(PSHost psHost)
129+
{
164130
var initialSessionState = InitialSessionState.CreateDefault2();
165131

166132
Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState);
@@ -170,9 +136,7 @@ public PowerShellContext(
170136
runspace.ThreadOptions = PSThreadOptions.ReuseThread;
171137
runspace.Open();
172138

173-
this.ownsInitialRunspace = true;
174-
175-
this.Initialize(profilePaths, runspace);
139+
return runspace;
176140
}
177141

178142
/// <summary>
@@ -181,16 +145,34 @@ public PowerShellContext(
181145
/// </summary>
182146
/// <param name="profilePaths">An object containing the profile paths for the session.</param>
183147
/// <param name="initialRunspace">The initial runspace to use for this instance.</param>
184-
public PowerShellContext(ProfilePaths profilePaths, Runspace initialRunspace)
148+
/// <param name="ownsInitialRunspace">If true, the PowerShellContext owns this runspace.</param>
149+
public void Initialize(
150+
ProfilePaths profilePaths,
151+
Runspace initialRunspace,
152+
bool ownsInitialRunspace)
185153
{
186-
this.Initialize(profilePaths, initialRunspace);
154+
this.Initialize(profilePaths, initialRunspace, ownsInitialRunspace, null);
187155
}
188156

189-
private void Initialize(ProfilePaths profilePaths, Runspace initialRunspace)
157+
/// <summary>
158+
/// Initializes a new instance of the PowerShellContext class using
159+
/// an existing runspace for the session.
160+
/// </summary>
161+
/// <param name="profilePaths">An object containing the profile paths for the session.</param>
162+
/// <param name="initialRunspace">The initial runspace to use for this instance.</param>
163+
/// <param name="ownsInitialRunspace">If true, the PowerShellContext owns this runspace.</param>
164+
/// <param name="consoleHost">An IConsoleHost implementation. Optional.</param>
165+
public void Initialize(
166+
ProfilePaths profilePaths,
167+
Runspace initialRunspace,
168+
bool ownsInitialRunspace,
169+
IConsoleHost consoleHost)
190170
{
191171
Validate.IsNotNull("initialRunspace", initialRunspace);
192172

173+
this.ownsInitialRunspace = ownsInitialRunspace;
193174
this.SessionState = PowerShellContextState.NotStarted;
175+
this.ConsoleHost = consoleHost;
194176

195177
// Get the PowerShell runtime version
196178
this.LocalPowerShellVersion =

src/PowerShellEditorServices/Session/SessionPSHost.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Microsoft.PowerShell.EditorServices
1717
/// ConsoleService and routes its calls to an IConsoleHost
1818
/// implementation.
1919
/// </summary>
20-
internal class ConsoleServicePSHost : PSHost, IHostSupportsInteractiveSession
20+
public class ConsoleServicePSHost : PSHost, IHostSupportsInteractiveSession
2121
{
2222
#region Private Fields
2323

@@ -42,6 +42,8 @@ internal IConsoleHost ConsoleHost
4242
}
4343
}
4444

45+
public ConsoleService ConsoleService { get; private set; }
46+
4547
#endregion
4648

4749
#region Constructors
@@ -50,23 +52,27 @@ internal IConsoleHost ConsoleHost
5052
/// Creates a new instance of the ConsoleServicePSHost class
5153
/// with the given IConsoleHost implementation.
5254
/// </summary>
55+
/// <param name="powerShellContext">
56+
/// An implementation of IHostSupportsInteractiveSession for runspace management.
57+
/// </param>
5358
/// <param name="hostDetails">
5459
/// Provides details about the host application.
5560
/// </param>
56-
/// <param name="hostSupportsInteractiveSession">
57-
/// An implementation of IHostSupportsInteractiveSession for runspace management.
58-
/// </param>
5961
/// <param name="enableConsoleRepl">
6062
/// Enables a terminal-based REPL for this session.
6163
/// </param>
6264
public ConsoleServicePSHost(
65+
PowerShellContext powerShellContext,
6366
HostDetails hostDetails,
64-
IHostSupportsInteractiveSession hostSupportsInteractiveSession,
6567
bool enableConsoleRepl)
6668
{
6769
this.hostDetails = hostDetails;
6870
this.hostUserInterface = new ConsoleServicePSHostUserInterface(enableConsoleRepl);
69-
this.hostSupportsInteractiveSession = hostSupportsInteractiveSession;
71+
this.hostSupportsInteractiveSession = powerShellContext;
72+
73+
this.ConsoleService = new ConsoleService(powerShellContext);
74+
this.ConsoleService.EnableConsoleRepl = enableConsoleRepl;
75+
this.ConsoleHost = this.ConsoleService;
7076

7177
System.Console.CancelKeyPress +=
7278
(obj, args) =>

0 commit comments

Comments
 (0)