Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public void StartDebugService(
Task.WhenAll(tasks)
.ContinueWith(async task => {
_logger.LogInformation("Starting debug server");
await _debugServer.StartAsync();
await _debugServer.StartAsync(_languageServer.LanguageServer.Services);
_logger.LogInformation(
$"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}");
});
Expand All @@ -327,6 +327,12 @@ public void StartDebugService(
default:
throw new NotSupportedException("not supported");
}

_debugServer.SessionEnded += (sender, eventArgs) =>
{
_debugServer.Dispose();
StartDebugService(config, profilePaths, useExistingSession);
};
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@
<PackageReference Include="OmniSharp.Extensions.DebugAdapter.Server" Version="1.0.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\DebugAdapter\Handlers\" />
<Folder Include="Services\DebugAdapter\Debugging\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected override (Stream input, Stream output) GetInputOutputStreams()
_outNamedPipeName,
out NamedPipeServerStream outNamedPipe);

var logger = _loggerFactory.CreateLogger("NamedPipeConnection");
var logger = LoggerFactory.CreateLogger("NamedPipeConnection");

logger.LogInformation("Waiting for connection");
namedPipe.WaitForConnection();
Expand Down
76 changes: 27 additions & 49 deletions src/PowerShellEditorServices.Engine/Server/PsesDebugServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,24 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System.Collections.Generic;
using System;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell.EditorServices.Engine.Handlers;
using Microsoft.PowerShell.EditorServices.Engine.Hosting;
using Microsoft.PowerShell.EditorServices.Engine.Services;
using Microsoft.PowerShell.EditorServices.Engine.Services.PowerShellContext;
using OmniSharp.Extensions.DebugAdapter.Protocol.Serialization;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Server;

namespace Microsoft.PowerShell.EditorServices.Engine.Server
{
internal class PsesDebugServer
internal class PsesDebugServer : IDisposable
{
protected readonly ILoggerFactory _loggerFactory;
private readonly Stream _inputStream;
private readonly Stream _outputStream;
private readonly TaskCompletionSource<bool> _serverStart;


private IJsonRpcServer _jsonRpcServer;

Expand All @@ -40,65 +32,51 @@ internal PsesDebugServer(
_loggerFactory = factory;
_inputStream = inputStream;
_outputStream = outputStream;
_serverStart = new TaskCompletionSource<bool>();

}

public async Task StartAsync()
public async Task StartAsync(IServiceProvider languageServerServiceProvider)
{
_jsonRpcServer = await JsonRpcServer.From(options =>
{
options.Serializer = new DapProtocolSerializer();
options.Reciever = new DapReciever();
options.LoggerFactory = _loggerFactory;
ILogger logger = options.LoggerFactory.CreateLogger("DebugOptionsStartup");
options.AddHandler<PowershellInitializeHandler>();
// options.Services = new ServiceCollection()
// .AddSingleton<WorkspaceService>()
// .AddSingleton<SymbolsService>()
// .AddSingleton<ConfigurationService>()
// .AddSingleton<PowerShellContextService>(
// (provider) =>
// GetFullyInitializedPowerShellContext(
// provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
// _profilePaths))
// .AddSingleton<TemplateService>()
// .AddSingleton<EditorOperationsService>()
// .AddSingleton<ExtensionService>(
// (provider) =>
// {
// var extensionService = new ExtensionService(
// provider.GetService<PowerShellContextService>(),
// provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>());
// extensionService.InitializeAsync(
// serviceProvider: provider,
// editorOperations: provider.GetService<EditorOperationsService>())
// .Wait();
// return extensionService;
// })
// .AddSingleton<AnalysisService>(
// (provider) =>
// {
// return AnalysisService.Create(
// provider.GetService<ConfigurationService>(),
// provider.GetService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(),
// options.LoggerFactory.CreateLogger<AnalysisService>());
// });

options.Services = new ServiceCollection()
.AddSingleton(languageServerServiceProvider.GetService<PowerShellContextService>())
.AddSingleton<DebugService>()
.AddSingleton<DebugStateService>()
.AddSingleton<DebugEventHandlerService>();

options
.WithInput(_inputStream)
.WithOutput(_outputStream);

logger.LogInformation("Adding handlers");

options
.WithHandler<InitializeHandler>()
.WithHandler<LaunchHandler>()
.WithHandler<AttachHandler>();

logger.LogInformation("Handlers added");
});
}

public async Task WaitForShutdown()
public void Dispose()
{
_jsonRpcServer.Dispose();
}

#region Events

public event EventHandler SessionEnded;

internal void OnSessionEnded()
{
await _serverStart.Task;
//await _languageServer.;
SessionEnded?.Invoke(this, null);
}

#endregion
}
}
16 changes: 8 additions & 8 deletions src/PowerShellEditorServices.Engine/Server/PsesLanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ namespace Microsoft.PowerShell.EditorServices.Engine.Server
{
internal abstract class PsesLanguageServer
{
protected readonly ILoggerFactory _loggerFactory;
internal ILoggerFactory LoggerFactory { get; private set; }
internal ILanguageServer LanguageServer { get; private set; }

private readonly LogLevel _minimumLogLevel;
private readonly bool _enableConsoleRepl;
private readonly HashSet<string> _featureFlags;
Expand All @@ -32,8 +34,6 @@ internal abstract class PsesLanguageServer
private readonly ProfilePaths _profilePaths;
private readonly TaskCompletionSource<bool> _serverStart;

private ILanguageServer _languageServer;

internal PsesLanguageServer(
ILoggerFactory factory,
LogLevel minimumLogLevel,
Expand All @@ -44,7 +44,7 @@ internal PsesLanguageServer(
PSHost internalHost,
ProfilePaths profilePaths)
{
_loggerFactory = factory;
LoggerFactory = factory;
_minimumLogLevel = minimumLogLevel;
_enableConsoleRepl = enableConsoleRepl;
_featureFlags = featureFlags;
Expand All @@ -57,10 +57,10 @@ internal PsesLanguageServer(

public async Task StartAsync()
{
_languageServer = await LanguageServer.From(options =>
LanguageServer = await OmniSharp.Extensions.LanguageServer.Server.LanguageServer.From(options =>
{
options.AddDefaultLoggingProvider();
options.LoggerFactory = _loggerFactory;
options.LoggerFactory = LoggerFactory;
ILogger logger = options.LoggerFactory.CreateLogger("OptionsStartup");
options.Services = new ServiceCollection()
.AddSingleton<WorkspaceService>()
Expand Down Expand Up @@ -155,14 +155,14 @@ await serviceProvider.GetService<PowerShellContextService>().SetWorkingDirectory
public async Task WaitForShutdown()
{
await _serverStart.Task;
await _languageServer.WaitForExit;
await LanguageServer.WaitForExit;
}

private PowerShellContextService GetFullyInitializedPowerShellContext(
OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer languageServer,
ProfilePaths profilePaths)
{
var logger = _loggerFactory.CreateLogger<PowerShellContextService>();
var logger = LoggerFactory.CreateLogger<PowerShellContextService>();

// PSReadLine can only be used when -EnableConsoleRepl is specified otherwise
// issues arise when redirecting stdio.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System.Management.Automation;
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell.EditorServices.Engine.Services.DebugAdapter;
using Microsoft.PowerShell.EditorServices.Engine.Services.PowerShellContext;
using Microsoft.PowerShell.EditorServices.Utility;
using OmniSharp.Extensions.DebugAdapter.Protocol.Events;
using OmniSharp.Extensions.JsonRpc;

namespace Microsoft.PowerShell.EditorServices.Engine.Services
{
public class DebugEventHandlerService
{
private readonly ILogger<DebugEventHandlerService> _logger;
private readonly PowerShellContextService _powerShellContextService;
private readonly DebugService _debugService;
private readonly DebugStateService _debugStateService;
private readonly IJsonRpcServer _jsonRpcServer;

public DebugEventHandlerService(
ILoggerFactory factory,
PowerShellContextService powerShellContextService,
DebugService debugService,
DebugStateService debugStateService,
IJsonRpcServer jsonRpcServer)
{
_logger = factory.CreateLogger<DebugEventHandlerService>();
_powerShellContextService = powerShellContextService;
_debugService = debugService;
_debugStateService = debugStateService;
_jsonRpcServer = jsonRpcServer;
}

internal void RegisterEventHandlers()
{
_powerShellContextService.RunspaceChanged += PowerShellContext_RunspaceChangedAsync;
_debugService.BreakpointUpdated += DebugService_BreakpointUpdatedAsync;
_debugService.DebuggerStopped += DebugService_DebuggerStoppedAsync;
_powerShellContextService.DebuggerResumed += PowerShellContext_DebuggerResumedAsync;
}

internal void UnregisterEventHandlers()
{
_powerShellContextService.RunspaceChanged -= PowerShellContext_RunspaceChangedAsync;
_debugService.BreakpointUpdated -= DebugService_BreakpointUpdatedAsync;
_debugService.DebuggerStopped -= DebugService_DebuggerStoppedAsync;
_powerShellContextService.DebuggerResumed -= PowerShellContext_DebuggerResumedAsync;
}

#region Event Handlers

private void DebugService_DebuggerStoppedAsync(object sender, DebuggerStoppedEventArgs e)
{
// Provide the reason for why the debugger has stopped script execution.
// See https://github.com/Microsoft/vscode/issues/3648
// The reason is displayed in the breakpoints viewlet. Some recommended reasons are:
// "step", "breakpoint", "function breakpoint", "exception" and "pause".
// We don't support exception breakpoints and for "pause", we can't distinguish
// between stepping and the user pressing the pause/break button in the debug toolbar.
string debuggerStoppedReason = "step";
if (e.OriginalEvent.Breakpoints.Count > 0)
{
debuggerStoppedReason =
e.OriginalEvent.Breakpoints[0] is CommandBreakpoint
? "function breakpoint"
: "breakpoint";
}

_jsonRpcServer.SendNotification(EventNames.Stopped,
new StoppedEvent
{
ThreadId = 1,
Reason = debuggerStoppedReason
});
}

private void PowerShellContext_RunspaceChangedAsync(object sender, RunspaceChangedEventArgs e)
{
if (_debugStateService.WaitingForAttach &&
e.ChangeAction == RunspaceChangeAction.Enter &&
e.NewRunspace.Context == RunspaceContext.DebuggedRunspace)
{
// Send the InitializedEvent so that the debugger will continue
// sending configuration requests
_debugStateService.WaitingForAttach = false;
_jsonRpcServer.SendNotification(EventNames.Initialized);
}
else if (
e.ChangeAction == RunspaceChangeAction.Exit &&
(_powerShellContextService.IsDebuggerStopped))
{
// Exited the session while the debugger is stopped,
// send a ContinuedEvent so that the client changes the
// UI to appear to be running again
_jsonRpcServer.SendNotification(EventNames.Continued,
new ContinuedEvent
{
ThreadId = 1,
AllThreadsContinued = true
});
}
}

private void PowerShellContext_DebuggerResumedAsync(object sender, DebuggerResumeAction e)
{
_jsonRpcServer.SendNotification(EventNames.Continued,
new ContinuedEvent
{
AllThreadsContinued = true,
ThreadId = 1
});
}

private void DebugService_BreakpointUpdatedAsync(object sender, BreakpointUpdatedEventArgs e)
{
string reason = "changed";

if (_debugStateService.SetBreakpointInProgress)
{
// Don't send breakpoint update notifications when setting
// breakpoints on behalf of the client.
return;
}

switch (e.UpdateType)
{
case BreakpointUpdateType.Set:
reason = "new";
break;

case BreakpointUpdateType.Removed:
reason = "removed";
break;
}

OmniSharp.Extensions.DebugAdapter.Protocol.Models.Breakpoint breakpoint;
if (e.Breakpoint is LineBreakpoint)
{
breakpoint = LspBreakpointUtils.CreateBreakpoint(BreakpointDetails.Create(e.Breakpoint));
}
else if (e.Breakpoint is CommandBreakpoint)
{
_logger.LogTrace("Function breakpoint updated event is not supported yet");
return;
}
else
{
_logger.LogError($"Unrecognized breakpoint type {e.Breakpoint.GetType().FullName}");
return;
}

breakpoint.Verified = e.UpdateType != BreakpointUpdateType.Disabled;

_jsonRpcServer.SendNotification(EventNames.Breakpoint,
new BreakpointEvent
{
Reason = reason,
Breakpoint = breakpoint
});
}

#endregion
}
}
Loading