Skip to content

Commit a7057e3

Browse files
Add powershellcontext (PowerShell#1005)
* Add powershellcontext * using file sink now instead * all the newlines
1 parent 9e67baa commit a7057e3

File tree

75 files changed

+13728
-57
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+13728
-57
lines changed

PowerShellEditorServices.build.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ $script:RequiredBuildAssets = @{
8383
'publish/OmniSharp.Extensions.LanguageServer.dll',
8484
'publish/Serilog.dll',
8585
'publish/Serilog.Extensions.Logging.dll',
86-
'publish/Serilog.Sinks.Console.dll',
86+
'publish/Serilog.Sinks.File.dll',
8787
'publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll',
8888
'publish/Microsoft.Extensions.DependencyInjection.dll',
8989
'publish/Microsoft.Extensions.Logging.Abstractions.dll',

src/PowerShellEditorServices.Engine/Hosting/EditorServicesHost.cs

+90-35
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
//
55

66
using System;
7+
using System.Collections.Generic;
78
using System.Diagnostics;
9+
using System.IO;
810
using System.Linq;
911
using System.Management.Automation;
1012
using System.Management.Automation.Host;
13+
using System.Management.Automation.Runspaces;
1114
using System.Reflection;
1215
using System.Runtime.InteropServices;
1316
using System.Threading;
@@ -60,11 +63,19 @@ public class EditorServicesHost
6063

6164
private readonly HostDetails _hostDetails;
6265

66+
private readonly PSHost _internalHost;
67+
68+
private readonly bool _enableConsoleRepl;
69+
70+
private readonly HashSet<string> _featureFlags;
71+
72+
private readonly string[] _additionalModules;
73+
6374
private ILanguageServer _languageServer;
6475

65-
private readonly Extensions.Logging.ILogger _logger;
76+
private Microsoft.Extensions.Logging.ILogger _logger;
6677

67-
private readonly ILoggerFactory _factory;
78+
private ILoggerFactory _factory;
6879

6980
#endregion
7081

@@ -126,24 +137,15 @@ public EditorServicesHost(
126137
Validate.IsNotNull(nameof(internalHost), internalHost);
127138

128139
_serviceCollection = new ServiceCollection();
129-
130-
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext()
131-
.WriteTo.Console()
132-
.CreateLogger();
133-
_factory = new LoggerFactory().AddSerilog(Log.Logger);
134-
_logger = _factory.CreateLogger<EditorServicesHost>();
135-
136140
_hostDetails = hostDetails;
137141

138-
/*
139-
this.hostDetails = hostDetails;
140-
this.enableConsoleRepl = enableConsoleRepl;
141-
this.bundledModulesPath = bundledModulesPath;
142-
this.additionalModules = additionalModules ?? Array.Empty<string>();
143-
this.featureFlags = new HashSet<string>(featureFlags ?? Array.Empty<string>();
144-
this.serverCompletedTask = new TaskCompletionSource<bool>();
145-
this.internalHost = internalHost;
146-
*/
142+
//this._hostDetails = hostDetails;
143+
this._enableConsoleRepl = enableConsoleRepl;
144+
//this.bundledModulesPath = bundledModulesPath;
145+
this._additionalModules = additionalModules ?? Array.Empty<string>();
146+
this._featureFlags = new HashSet<string>(featureFlags ?? Array.Empty<string>());
147+
//this.serverCompletedTask = new TaskCompletionSource<bool>();
148+
this._internalHost = internalHost;
147149

148150
#if DEBUG
149151
if (waitForDebugger)
@@ -174,6 +176,12 @@ public EditorServicesHost(
174176
/// <param name="logLevel">The minimum level of log messages to be written.</param>
175177
public void StartLogging(string logFilePath, PsesLogLevel logLevel)
176178
{
179+
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext()
180+
.WriteTo.File(logFilePath)
181+
.CreateLogger();
182+
_factory = new LoggerFactory().AddSerilog(Log.Logger);
183+
_logger = _factory.CreateLogger<EditorServicesHost>();
184+
177185
FileVersionInfo fileVersionInfo =
178186
FileVersionInfo.GetVersionInfo(this.GetType().GetTypeInfo().Assembly.Location);
179187

@@ -184,7 +192,7 @@ public void StartLogging(string logFilePath, PsesLogLevel logLevel)
184192
string buildTime = BuildInfo.BuildTime?.ToString("s", System.Globalization.CultureInfo.InvariantCulture) ?? "<unspecified>";
185193

186194
string logHeader = $@"
187-
PowerShell Editor Services Host v{fileVersionInfo.FileVersion} starting (PID {Process.GetCurrentProcess().Id}
195+
PowerShell Editor Services Host v{fileVersionInfo.FileVersion} starting (PID {Process.GetCurrentProcess().Id})
188196
189197
Host application details:
190198
@@ -219,23 +227,69 @@ public void StartLanguageService(
219227
{
220228
while (System.Diagnostics.Debugger.IsAttached)
221229
{
222-
Console.WriteLine($"{Process.GetCurrentProcess().Id}");
230+
System.Console.WriteLine($"{Process.GetCurrentProcess().Id}");
223231
Thread.Sleep(2000);
224232
}
225233

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

228-
_serviceCollection.AddSingleton<WorkspaceService>();
229-
_serviceCollection.AddSingleton<SymbolsService>();
230-
_serviceCollection.AddSingleton<ConfigurationService>();
231-
_serviceCollection.AddSingleton<AnalysisService>(
232-
(provider) => {
233-
return AnalysisService.Create(
234-
provider.GetService<ConfigurationService>(),
235-
provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
236-
_factory.CreateLogger<AnalysisService>());
237-
}
238-
);
236+
var logger = _factory.CreateLogger<PowerShellContextService>();
237+
var powerShellContext = new PowerShellContextService(
238+
logger,
239+
_featureFlags.Contains("PSReadLine"));
240+
241+
// TODO: Bring this back
242+
//EditorServicesPSHostUserInterface hostUserInterface =
243+
// _enableConsoleRepl
244+
// ? (EditorServicesPSHostUserInterface)new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost)
245+
// : new ProtocolPSHostUserInterface(powerShellContext, messageSender, logger);
246+
EditorServicesPSHostUserInterface hostUserInterface =
247+
(EditorServicesPSHostUserInterface)new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost);
248+
249+
250+
EditorServicesPSHost psHost =
251+
new EditorServicesPSHost(
252+
powerShellContext,
253+
_hostDetails,
254+
hostUserInterface,
255+
logger);
256+
257+
Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost);
258+
powerShellContext.Initialize(profilePaths, initialRunspace, true, hostUserInterface);
259+
260+
powerShellContext.ImportCommandsModuleAsync(
261+
Path.Combine(
262+
Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location),
263+
@"..\Commands"));
264+
265+
// TODO: This can be moved to the point after the $psEditor object
266+
// gets initialized when that is done earlier than LanguageServer.Initialize
267+
foreach (string module in this._additionalModules)
268+
{
269+
var command =
270+
new System.Management.Automation.PSCommand()
271+
.AddCommand("Microsoft.PowerShell.Core\\Import-Module")
272+
.AddParameter("Name", module);
273+
274+
powerShellContext.ExecuteCommandAsync<System.Management.Automation.PSObject>(
275+
command,
276+
sendOutputToHost: false,
277+
sendErrorToHost: true);
278+
}
279+
280+
_serviceCollection
281+
.AddSingleton<WorkspaceService>()
282+
.AddSingleton<SymbolsService>()
283+
.AddSingleton<ConfigurationService>()
284+
.AddSingleton<PowerShellContextService>(powerShellContext)
285+
.AddSingleton<AnalysisService>(
286+
(provider) => {
287+
return AnalysisService.Create(
288+
provider.GetService<ConfigurationService>(),
289+
provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
290+
_factory.CreateLogger<AnalysisService>());
291+
}
292+
);
239293

240294
_languageServer = new OmnisharpLanguageServerBuilder(_serviceCollection)
241295
{
@@ -248,10 +302,11 @@ public void StartLanguageService(
248302

249303
_logger.LogInformation("Starting language server");
250304

251-
Task.Factory.StartNew(() => _languageServer.StartAsync(),
252-
CancellationToken.None,
253-
TaskCreationOptions.LongRunning,
254-
TaskScheduler.Default);
305+
Task.Run(_languageServer.StartAsync);
306+
//Task.Factory.StartNew(() => _languageServer.StartAsync(),
307+
// CancellationToken.None,
308+
// TaskCreationOptions.LongRunning,
309+
// TaskScheduler.Default);
255310

256311
_logger.LogInformation(
257312
string.Format(

src/PowerShellEditorServices.Engine/PowerShellEditorServices.Engine.csproj

+18-1
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,32 @@
1010
<LangVersion>Latest</LangVersion>
1111
</PropertyGroup>
1212

13+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14+
<LangVersion>latest</LangVersion>
15+
<CheckForOverflowUnderflow></CheckForOverflowUnderflow>
16+
<DocumentationFile></DocumentationFile>
17+
<DocumentationFile></DocumentationFile>
18+
</PropertyGroup>
19+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
20+
<LangVersion>latest</LangVersion>
21+
</PropertyGroup>
1322
<ItemGroup>
1423
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="2.2.0" />
1524
<PackageReference Include="OmniSharp.Extensions.LanguageServer" Version="0.13.2-*" />
1625
<PackageReference Include="PowerShellStandard.Library" Version="5.1.1" />
1726
<PackageReference Include="Serilog.Extensions.Logging" Version="2.0.4" />
18-
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
27+
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
1928
<PackageReference Include="System.IO.Pipes.AccessControl" Version="4.5.1" />
2029
<PackageReference Include="System.Security.Principal" Version="4.3.0" />
2130
<PackageReference Include="System.Security.Principal.Windows" Version="4.5.1" />
31+
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" />
32+
<PackageReference Include="UnixConsoleEcho" Version="0.1.0" />
2233
</ItemGroup>
2334

35+
<ItemGroup>
36+
<Folder Include="Services\PowerShellContext\Session\" />
37+
<Folder Include="Services\PowerShellContext\Console\" />
38+
<Folder Include="Services\PowerShellContext\Extensions\" />
39+
<Folder Include="Services\PowerShellContext\Components\" />
40+
</ItemGroup>
2441
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
using System;
7+
using System.Collections.Generic;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
11+
namespace Microsoft.PowerShell.EditorServices.Components
12+
{
13+
/// <summary>
14+
/// Provides a default implementation for the IComponentRegistry
15+
/// interface.
16+
/// </summary>
17+
public class ComponentRegistry : IComponentRegistry
18+
{
19+
private Dictionary<Type, object> componentRegistry =
20+
new Dictionary<Type, object>();
21+
22+
/// <summary>
23+
/// Registers an instance of the specified component type
24+
/// or throws an ArgumentException if an instance has
25+
/// already been registered.
26+
/// </summary>
27+
/// <param name="componentType">
28+
/// The component type that the instance represents.
29+
/// </param>
30+
/// <param name="componentInstance">
31+
/// The instance of the component to be registered.
32+
/// </param>
33+
/// <returns>
34+
/// The provided component instance for convenience in assignment
35+
/// statements.
36+
/// </returns>
37+
public object Register(Type componentType, object componentInstance)
38+
{
39+
this.componentRegistry.Add(componentType, componentInstance);
40+
return componentInstance;
41+
}
42+
43+
44+
/// <summary>
45+
/// Gets the registered instance of the specified
46+
/// component type or throws a KeyNotFoundException if
47+
/// no instance has been registered.
48+
/// </summary>
49+
/// <param name="componentType">
50+
/// The component type for which an instance will be retrieved.
51+
/// </param>
52+
/// <returns>The implementation of the specified type.</returns>
53+
public object Get(Type componentType)
54+
{
55+
return this.componentRegistry[componentType];
56+
}
57+
58+
/// <summary>
59+
/// Attempts to retrieve the instance of the specified
60+
/// component type and, if found, stores it in the
61+
/// componentInstance parameter.
62+
/// </summary>
63+
/// <param name="componentInstance">
64+
/// The out parameter in which the found instance will be stored.
65+
/// </param>
66+
/// <param name="componentType">
67+
/// The component type for which an instance will be retrieved.
68+
/// </param>
69+
/// <returns>
70+
/// True if a registered instance was found, false otherwise.
71+
/// </returns>
72+
public bool TryGet(Type componentType, out object componentInstance)
73+
{
74+
componentInstance = null;
75+
76+
if (this.componentRegistry.TryGetValue(componentType, out componentInstance))
77+
{
78+
return componentInstance != null;
79+
}
80+
81+
return false;
82+
}
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
using System;
7+
8+
namespace Microsoft.PowerShell.EditorServices.Components
9+
{
10+
/// <summary>
11+
/// Specifies the contract for a registry of component interfaces.
12+
/// </summary>
13+
public interface IComponentRegistry
14+
{
15+
/// <summary>
16+
/// Registers an instance of the specified component type
17+
/// or throws an ArgumentException if an instance has
18+
/// already been registered.
19+
/// </summary>
20+
/// <param name="componentType">
21+
/// The component type that the instance represents.
22+
/// </param>
23+
/// <param name="componentInstance">
24+
/// The instance of the component to be registered.
25+
/// </param>
26+
/// <returns>
27+
/// The provided component instance for convenience in assignment
28+
/// statements.
29+
/// </returns>
30+
object Register(
31+
Type componentType,
32+
object componentInstance);
33+
34+
/// <summary>
35+
/// Gets the registered instance of the specified
36+
/// component type or throws a KeyNotFoundException if
37+
/// no instance has been registered.
38+
/// </summary>
39+
/// <param name="componentType">
40+
/// The component type for which an instance will be retrieved.
41+
/// </param>
42+
/// <returns>The implementation of the specified type.</returns>
43+
object Get(Type componentType);
44+
45+
/// <summary>
46+
/// Attempts to retrieve the instance of the specified
47+
/// component type and, if found, stores it in the
48+
/// componentInstance parameter.
49+
/// </summary>
50+
/// <param name="componentType">
51+
/// The component type for which an instance will be retrieved.
52+
/// </param>
53+
/// <param name="componentInstance">
54+
/// The out parameter in which the found instance will be stored.
55+
/// </param>
56+
/// <returns>
57+
/// True if a registered instance was found, false otherwise.
58+
/// </returns>
59+
bool TryGet(Type componentType, out object componentInstance);
60+
}
61+
}

0 commit comments

Comments
 (0)