Skip to content

Add powershellcontext #1005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PowerShellEditorServices.build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ $script:RequiredBuildAssets = @{
'publish/OmniSharp.Extensions.LanguageServer.dll',
'publish/Serilog.dll',
'publish/Serilog.Extensions.Logging.dll',
'publish/Serilog.Sinks.Console.dll',
'publish/Serilog.Sinks.File.dll',
'publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll',
'publish/Microsoft.Extensions.DependencyInjection.dll',
'publish/Microsoft.Extensions.Logging.Abstractions.dll',
Expand Down
125 changes: 90 additions & 35 deletions src/PowerShellEditorServices.Engine/Hosting/EditorServicesHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
//

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
Expand Down Expand Up @@ -60,11 +63,19 @@ public class EditorServicesHost

private readonly HostDetails _hostDetails;

private readonly PSHost _internalHost;

private readonly bool _enableConsoleRepl;

private readonly HashSet<string> _featureFlags;

private readonly string[] _additionalModules;

private ILanguageServer _languageServer;

private readonly Extensions.Logging.ILogger _logger;
private Microsoft.Extensions.Logging.ILogger _logger;

private readonly ILoggerFactory _factory;
private ILoggerFactory _factory;

#endregion

Expand Down Expand Up @@ -126,24 +137,15 @@ public EditorServicesHost(
Validate.IsNotNull(nameof(internalHost), internalHost);

_serviceCollection = new ServiceCollection();

Log.Logger = new LoggerConfiguration().Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
_factory = new LoggerFactory().AddSerilog(Log.Logger);
_logger = _factory.CreateLogger<EditorServicesHost>();

_hostDetails = hostDetails;

/*
this.hostDetails = hostDetails;
this.enableConsoleRepl = enableConsoleRepl;
this.bundledModulesPath = bundledModulesPath;
this.additionalModules = additionalModules ?? Array.Empty<string>();
this.featureFlags = new HashSet<string>(featureFlags ?? Array.Empty<string>();
this.serverCompletedTask = new TaskCompletionSource<bool>();
this.internalHost = internalHost;
*/
//this._hostDetails = hostDetails;
this._enableConsoleRepl = enableConsoleRepl;
//this.bundledModulesPath = bundledModulesPath;
this._additionalModules = additionalModules ?? Array.Empty<string>();
this._featureFlags = new HashSet<string>(featureFlags ?? Array.Empty<string>());
//this.serverCompletedTask = new TaskCompletionSource<bool>();
this._internalHost = internalHost;

#if DEBUG
if (waitForDebugger)
Expand Down Expand Up @@ -174,6 +176,12 @@ public EditorServicesHost(
/// <param name="logLevel">The minimum level of log messages to be written.</param>
public void StartLogging(string logFilePath, PsesLogLevel logLevel)
{
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext()
.WriteTo.File(logFilePath)
.CreateLogger();
_factory = new LoggerFactory().AddSerilog(Log.Logger);
_logger = _factory.CreateLogger<EditorServicesHost>();

FileVersionInfo fileVersionInfo =
FileVersionInfo.GetVersionInfo(this.GetType().GetTypeInfo().Assembly.Location);

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

string logHeader = $@"
PowerShell Editor Services Host v{fileVersionInfo.FileVersion} starting (PID {Process.GetCurrentProcess().Id}
PowerShell Editor Services Host v{fileVersionInfo.FileVersion} starting (PID {Process.GetCurrentProcess().Id})

Host application details:

Expand Down Expand Up @@ -219,23 +227,69 @@ public void StartLanguageService(
{
while (System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine($"{Process.GetCurrentProcess().Id}");
System.Console.WriteLine($"{Process.GetCurrentProcess().Id}");
Thread.Sleep(2000);
}

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

_serviceCollection.AddSingleton<WorkspaceService>();
_serviceCollection.AddSingleton<SymbolsService>();
_serviceCollection.AddSingleton<ConfigurationService>();
_serviceCollection.AddSingleton<AnalysisService>(
(provider) => {
return AnalysisService.Create(
provider.GetService<ConfigurationService>(),
provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
_factory.CreateLogger<AnalysisService>());
}
);
var logger = _factory.CreateLogger<PowerShellContextService>();
var powerShellContext = new PowerShellContextService(
logger,
_featureFlags.Contains("PSReadLine"));

// TODO: Bring this back
//EditorServicesPSHostUserInterface hostUserInterface =
// _enableConsoleRepl
// ? (EditorServicesPSHostUserInterface)new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost)
// : new ProtocolPSHostUserInterface(powerShellContext, messageSender, logger);
EditorServicesPSHostUserInterface hostUserInterface =
(EditorServicesPSHostUserInterface)new TerminalPSHostUserInterface(powerShellContext, logger, _internalHost);


EditorServicesPSHost psHost =
new EditorServicesPSHost(
powerShellContext,
_hostDetails,
hostUserInterface,
logger);

Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost);
powerShellContext.Initialize(profilePaths, initialRunspace, true, hostUserInterface);

powerShellContext.ImportCommandsModuleAsync(
Path.Combine(
Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location),
@"..\Commands"));

// TODO: This can be moved to the point after the $psEditor object
// gets initialized when that is done earlier than LanguageServer.Initialize
foreach (string module in this._additionalModules)
{
var command =
new System.Management.Automation.PSCommand()
.AddCommand("Microsoft.PowerShell.Core\\Import-Module")
.AddParameter("Name", module);

powerShellContext.ExecuteCommandAsync<System.Management.Automation.PSObject>(
command,
sendOutputToHost: false,
sendErrorToHost: true);
}

_serviceCollection
.AddSingleton<WorkspaceService>()
.AddSingleton<SymbolsService>()
.AddSingleton<ConfigurationService>()
.AddSingleton<PowerShellContextService>(powerShellContext)
.AddSingleton<AnalysisService>(
(provider) => {
return AnalysisService.Create(
provider.GetService<ConfigurationService>(),
provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
_factory.CreateLogger<AnalysisService>());
}
);

_languageServer = new OmnisharpLanguageServerBuilder(_serviceCollection)
{
Expand All @@ -248,10 +302,11 @@ public void StartLanguageService(

_logger.LogInformation("Starting language server");

Task.Factory.StartNew(() => _languageServer.StartAsync(),
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
Task.Run(_languageServer.StartAsync);
//Task.Factory.StartNew(() => _languageServer.StartAsync(),
// CancellationToken.None,
// TaskCreationOptions.LongRunning,
// TaskScheduler.Default);

_logger.LogInformation(
string.Format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,32 @@
<LangVersion>Latest</LangVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<LangVersion>latest</LangVersion>
<CheckForOverflowUnderflow></CheckForOverflowUnderflow>
<DocumentationFile></DocumentationFile>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="2.2.0" />
<PackageReference Include="OmniSharp.Extensions.LanguageServer" Version="0.13.0-*" />
<PackageReference Include="PowerShellStandard.Library" Version="5.1.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="2.0.4" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
<PackageReference Include="System.IO.Pipes.AccessControl" Version="4.5.1" />
<PackageReference Include="System.Security.Principal" Version="4.3.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="4.5.1" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.9.0" />
<PackageReference Include="UnixConsoleEcho" Version="0.1.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\PowerShellContext\Session\" />
<Folder Include="Services\PowerShellContext\Console\" />
<Folder Include="Services\PowerShellContext\Extensions\" />
<Folder Include="Services\PowerShellContext\Components\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.PowerShell.EditorServices.Components
{
/// <summary>
/// Provides a default implementation for the IComponentRegistry
/// interface.
/// </summary>
public class ComponentRegistry : IComponentRegistry
{
private Dictionary<Type, object> componentRegistry =
new Dictionary<Type, object>();

/// <summary>
/// Registers an instance of the specified component type
/// or throws an ArgumentException if an instance has
/// already been registered.
/// </summary>
/// <param name="componentType">
/// The component type that the instance represents.
/// </param>
/// <param name="componentInstance">
/// The instance of the component to be registered.
/// </param>
/// <returns>
/// The provided component instance for convenience in assignment
/// statements.
/// </returns>
public object Register(Type componentType, object componentInstance)
{
this.componentRegistry.Add(componentType, componentInstance);
return componentInstance;
}


/// <summary>
/// Gets the registered instance of the specified
/// component type or throws a KeyNotFoundException if
/// no instance has been registered.
/// </summary>
/// <param name="componentType">
/// The component type for which an instance will be retrieved.
/// </param>
/// <returns>The implementation of the specified type.</returns>
public object Get(Type componentType)
{
return this.componentRegistry[componentType];
}

/// <summary>
/// Attempts to retrieve the instance of the specified
/// component type and, if found, stores it in the
/// componentInstance parameter.
/// </summary>
/// <param name="componentInstance">
/// The out parameter in which the found instance will be stored.
/// </param>
/// <param name="componentType">
/// The component type for which an instance will be retrieved.
/// </param>
/// <returns>
/// True if a registered instance was found, false otherwise.
/// </returns>
public bool TryGet(Type componentType, out object componentInstance)
{
componentInstance = null;

if (this.componentRegistry.TryGetValue(componentType, out componentInstance))
{
return componentInstance != null;
}

return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;

namespace Microsoft.PowerShell.EditorServices.Components
{
/// <summary>
/// Specifies the contract for a registry of component interfaces.
/// </summary>
public interface IComponentRegistry
{
/// <summary>
/// Registers an instance of the specified component type
/// or throws an ArgumentException if an instance has
/// already been registered.
/// </summary>
/// <param name="componentType">
/// The component type that the instance represents.
/// </param>
/// <param name="componentInstance">
/// The instance of the component to be registered.
/// </param>
/// <returns>
/// The provided component instance for convenience in assignment
/// statements.
/// </returns>
object Register(
Type componentType,
object componentInstance);

/// <summary>
/// Gets the registered instance of the specified
/// component type or throws a KeyNotFoundException if
/// no instance has been registered.
/// </summary>
/// <param name="componentType">
/// The component type for which an instance will be retrieved.
/// </param>
/// <returns>The implementation of the specified type.</returns>
object Get(Type componentType);

/// <summary>
/// Attempts to retrieve the instance of the specified
/// component type and, if found, stores it in the
/// componentInstance parameter.
/// </summary>
/// <param name="componentType">
/// The component type for which an instance will be retrieved.
/// </param>
/// <param name="componentInstance">
/// The out parameter in which the found instance will be stored.
/// </param>
/// <returns>
/// True if a registered instance was found, false otherwise.
/// </returns>
bool TryGet(Type componentType, out object componentInstance);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline

Loading