Skip to content

Commit

Permalink
feat: lsp-progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Anakael committed Jan 20, 2025
1 parent 8b293ef commit 56dadd8
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 13 deletions.
11 changes: 9 additions & 2 deletions src/OmniSharp.Abstractions/Eventing/IEventEmitterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public static void UnresolvedDepdendencies(this IEventEmitter emitter, string pr
});
}

public static void ProjectLoadingStarted(this IEventEmitter emitter, string projectPath) =>
emitter.Emit(
EventTypes.ProjectLoadingStarted,
projectPath);

public static void ProjectInformation(this IEventEmitter emitter,
HashedString projectId,
HashedString sessionId,
Expand All @@ -55,7 +60,8 @@ public static void ProjectInformation(this IEventEmitter emitter,
IEnumerable<HashedString> references,
IEnumerable<HashedString> fileExtensions,
IEnumerable<int> fileCounts,
bool sdkStyleProject)
bool sdkStyleProject,
string projectFilePath)
{
var projectConfiguration = new ProjectConfigurationMessage()
{
Expand All @@ -68,7 +74,8 @@ public static void ProjectInformation(this IEventEmitter emitter,
References = references.Select(hashed => hashed.Value),
FileExtensions = fileExtensions.Select(hashed => hashed.Value),
FileCounts = fileCounts,
SdkStyleProject = sdkStyleProject
SdkStyleProject = sdkStyleProject,
ProjectFilePath = projectFilePath
};

emitter.Emit(
Expand Down
1 change: 1 addition & 0 deletions src/OmniSharp.Abstractions/Models/Events/EventTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace OmniSharp.Models.Events
{
public static class EventTypes
{
public const string ProjectLoadingStarted = nameof(ProjectLoadingStarted);
public const string ProjectAdded = nameof(ProjectAdded);
public const string ProjectChanged = nameof(ProjectChanged);
public const string ProjectRemoved = nameof(ProjectRemoved);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ public class ProjectConfigurationMessage
public IEnumerable<string> FileExtensions { get; set; }
public IEnumerable<int> FileCounts { get; set; }
public bool SdkStyleProject { get; set; }
public string ProjectFilePath { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
Expand All @@ -6,6 +7,7 @@
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone;
using OmniSharp.LanguageServerProtocol.Handlers;
using OmniSharp.Models.Diagnostics;
using OmniSharp.Models.Events;
Expand All @@ -16,6 +18,8 @@ public class LanguageServerEventEmitter : IEventEmitter
{
private readonly ILanguageServer _server;
private readonly DocumentVersions _documentVersions;
private readonly ConcurrentDictionary<string, IWorkDoneObserver> _projectObservers = new();
private IWorkDoneObserver _restoreObserver;

public LanguageServerEventEmitter(ILanguageServer server)
{
Expand Down Expand Up @@ -46,6 +50,14 @@ public void Emit(string kind, object args)
}
}
break;
case EventTypes.ProjectLoadingStarted:
string projectPath = (string)args;
IWorkDoneObserver projectObserver = _server.WorkDoneManager
.Create(new WorkDoneProgressBegin { Title = $"Loading {projectPath}" })
.GetAwaiter()
.GetResult();
_projectObservers.TryAdd(projectPath, projectObserver);
break;
case EventTypes.ProjectAdded:
case EventTypes.ProjectChanged:
case EventTypes.ProjectRemoved:
Expand All @@ -54,13 +66,31 @@ public void Emit(string kind, object args)

// work done??
case EventTypes.PackageRestoreStarted:
_server.SendNotification($"o#/{kind}".ToLowerInvariant(), JToken.FromObject(args));
_restoreObserver = _server.WorkDoneManager
.Create(new WorkDoneProgressBegin { Title = "Restoring" })
.GetAwaiter()
.GetResult();
break;
case EventTypes.PackageRestoreFinished:
_server.SendNotification($"o#/{kind}".ToLowerInvariant(), JToken.FromObject(args));
_restoreObserver.OnNext(new WorkDoneProgressReport { Message = "Restored" });
_restoreObserver.OnCompleted();
break;
case EventTypes.UnresolvedDependencies:
_server.SendNotification($"o#/{kind}".ToLowerInvariant(), JToken.FromObject(args));
break;

case EventTypes.Error:
case EventTypes.ProjectConfiguration:
_server.SendNotification($"o#/{kind}".ToLowerInvariant(), JToken.FromObject(args));
ProjectConfigurationMessage projectMessage = (ProjectConfigurationMessage)args;
if (_projectObservers.TryGetValue(projectMessage.ProjectFilePath, out IWorkDoneObserver obs))
{
obs.OnNext(new WorkDoneProgressReport { Message = $"Loaded {projectMessage.ProjectFilePath}" });
obs.OnCompleted();
}
break;
case EventTypes.ProjectDiagnosticStatus:
_server.SendNotification($"o#/{kind}".ToLowerInvariant(), JToken.FromObject(args));
break;
Expand Down
35 changes: 29 additions & 6 deletions src/OmniSharp.LanguageServerProtocol/LanguageServerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class LanguageServerHost : IDisposable
private CompositionHost _compositionHost;
private IServiceProvider _serviceProvider;
private readonly Action<ILoggingBuilder> _configureLogging;
private IObserver<WorkDoneProgressReport> _workDoneObserver = null!;

public LanguageServerHost(
Stream input,
Expand All @@ -65,6 +66,7 @@ public LanguageServerHost(
.ConfigureLogging(AddLanguageProtocolLogging(application.LogLevel))
.OnInitialize(Initialize)
.OnInitialized(Initialized)
.OnStarted(Started)
.WithServices(ConfigureServices);

_application = application;
Expand Down Expand Up @@ -137,6 +139,19 @@ public async Task Start()

logger.LogInformation($"Omnisharp server running using Lsp at location '{environment.TargetDirectory}' on host {environment.HostProcessId}.");

await Task.WhenAll(
_compositionHost
.GetExports<IProjectSystem>()
.Select(ps => ps.WaitForIdleAsync())
.ToArray());

_workDoneObserver.OnNext(new WorkDoneProgressReport
{
Message = "Language Server ready",
Percentage = 100,
});
_workDoneObserver.OnCompleted();

Console.CancelKeyPress += (sender, e) =>
{
Cancel();
Expand Down Expand Up @@ -330,6 +345,7 @@ static Func<JToken, CancellationToken, Task<JToken>> CreateInteropHandler(
private Task Initialize(ILanguageServer server, InitializeParams initializeParams,
CancellationToken cancellationToken)
{
_workDoneObserver = server.WorkDoneManager.For(initializeParams, new WorkDoneProgressBegin { Message = "Initialize Language Server" });
(_serviceProvider, _compositionHost) =
CreateCompositionHost(server, initializeParams, _application, _services, _configureLogging);
var handlers = ConfigureCompositionHost(server, _compositionHost);
Expand All @@ -342,18 +358,25 @@ private Task Initialize(ILanguageServer server, InitializeParams initializeParam
_serviceProvider.GetRequiredService<IFileSystemNotifier>()));
});

_workDoneObserver.OnNext(new WorkDoneProgressReport { Message = "Initialized handlers", Percentage = 10 });
return Task.CompletedTask;
}

public async Task Initialized(ILanguageServer server, InitializeParams request, InitializeResult response, CancellationToken cancellationToken)
public Task Initialized(ILanguageServer server, InitializeParams request, InitializeResult response, CancellationToken cancellationToken)
{
_workDoneObserver.OnNext(new WorkDoneProgressReport { Message = "Initialize workspace", Percentage = 20 });
WorkspaceInitializer.Initialize(_serviceProvider, _compositionHost);
return Task.CompletedTask;
}

await Task.WhenAll(
_compositionHost
.GetExports<IProjectSystem>()
.Select(ps => ps.WaitForIdleAsync())
.ToArray());
public Task Started(ILanguageServer server, CancellationToken cancellationToken)
{
_workDoneObserver.OnNext(new WorkDoneProgressReport
{
Message = "Language Server started",
Percentage = 30,
});
return Task.CompletedTask;
}

internal void UnderTest(IServiceProvider serviceProvider, CompositionHost compositionHost)
Expand Down
1 change: 1 addition & 0 deletions src/OmniSharp.MSBuild/Notification/IMSBuildEventSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
public interface IMSBuildEventSink
{
void ProjectLoadingStarted(string projectPath);
void ProjectLoaded(ProjectLoadedEventArgs e);
}
}
16 changes: 15 additions & 1 deletion src/OmniSharp.MSBuild/ProjectLoadListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public ProjectLoadListener(ILoggerFactory loggerFactory, IEventEmitter eventEmit
_eventEmitter = eventEmitter;
}

public void ProjectLoadingStarted(string projectPath) =>
_eventEmitter.ProjectLoadingStarted(projectPath);

public void ProjectLoaded(ProjectLoadedEventArgs args)
{
try
Expand All @@ -53,7 +56,18 @@ public void ProjectLoaded(ProjectLoadedEventArgs args)
var (hashedFileExtensions, fileCounts) = GetUniqueHashedFileExtensionsAndCounts(args);

var sdkStyleProject = IsSdkStyleProject(args);
_eventEmitter.ProjectInformation(projectId, sessionId, (int)outputKind, projectCapabilities, targetFrameworks, sdkVersion, hashedReferences, hashedFileExtensions, fileCounts, sdkStyleProject);
_eventEmitter.ProjectInformation(
projectId,
sessionId,
(int)outputKind,
projectCapabilities,
targetFrameworks,
sdkVersion,
hashedReferences,
hashedFileExtensions,
fileCounts,
sdkStyleProject,
args.Project.ProjectFileLocation.File);
}
catch (Exception ex)
{
Expand Down
19 changes: 15 additions & 4 deletions src/OmniSharp.MSBuild/ProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using OmniSharp.Eventing;
Expand All @@ -18,15 +20,13 @@
using OmniSharp.MSBuild.Models.Events;
using OmniSharp.MSBuild.Notification;
using OmniSharp.MSBuild.ProjectFile;
using OmniSharp.Options;
using OmniSharp.Roslyn.CSharp.Services.Diagnostics;
using OmniSharp.Roslyn.CSharp.Services.Refactoring.V2;
using OmniSharp.Options;
using OmniSharp.Roslyn.EditorConfig;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Services;
using OmniSharp.Utilities;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;
using OmniSharp.Roslyn.EditorConfig;

namespace OmniSharp.MSBuild
{
Expand Down Expand Up @@ -310,6 +310,17 @@ private void ProcessQueue(CancellationToken cancellationToken)
private (ProjectFileInfo, ProjectLoadedEventArgs) LoadOrReloadProject(string projectFilePath, Func<(ProjectFileInfo, ImmutableArray<MSBuildDiagnostic>, ProjectLoadedEventArgs)> loader)
{
_logger.LogInformation($"Loading project: {projectFilePath}");
foreach (IMSBuildEventSink eventSink in _eventSinks)
{
try
{
eventSink.ProjectLoadingStarted(projectFilePath);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception thrown while calling event sinks");
}
}

try
{
Expand Down
4 changes: 4 additions & 0 deletions tests/OmniSharp.MSBuild.Tests/NotificationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public void ProjectLoaded(ProjectLoadedEventArgs e)
{
_onLoaded(e);
}

public void ProjectLoadingStarted(string projectPath)
{
}
}

[Fact]
Expand Down

0 comments on commit 56dadd8

Please sign in to comment.