Skip to content

Commit

Permalink
Rationalize how ProjectSnapshotManager is updated (#10101)
Browse files Browse the repository at this point in the history
This change adds `Update(...)` and `UpdateAsync(...)` to
`IProjectSnapshotManager` in order to streamline code that updates it.
This means that it is no longer necessary to carry around a
`ProjectSnapshotManagerDispatcher` in order to update
`IProjectSnapshotManager`. There is further work needed to do away with
`ProjectSnaapshotManagerDispatcher` completely, but this is a big step
in the right direction.

I took care to make the commit history meaningful, so it should be
manageable for reviewers.
  • Loading branch information
DustinCampbell authored Mar 18, 2024
2 parents 004be9d + fb8eb56 commit 486a51e
Show file tree
Hide file tree
Showing 61 changed files with 1,467 additions and 1,136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ internal async Task<IDocumentSnapshot> GetDocumentSnapshotAsync(string projectFi

var projectManager = CreateProjectSnapshotManager();

await Dispatcher.RunAsync(
() =>
await projectManager.UpdateAsync(
updater =>
{
projectManager.ProjectAdded(hostProject);
updater.ProjectAdded(hostProject);
var tagHelpers = CommonResources.LegacyTagHelpers;
var projectWorkspaceState = ProjectWorkspaceState.Create(tagHelpers, CodeAnalysis.CSharp.LanguageVersion.CSharp11);
projectManager.ProjectWorkspaceStateChanged(hostProject.Key, projectWorkspaceState);
projectManager.DocumentAdded(hostProject.Key, hostDocument, textLoader);
updater.ProjectWorkspaceStateChanged(hostProject.Key, projectWorkspaceState);
updater.DocumentAdded(hostProject.Key, hostDocument, textLoader);
},
CancellationToken.None);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public async Task SetupAsync()
{
ProjectManager = CreateProjectSnapshotManager();

await Dispatcher.RunAsync(
() => ProjectManager.ProjectAdded(HostProject),
await ProjectManager.UpdateAsync(
updater => updater.ProjectAdded(HostProject),
CancellationToken.None);

ProjectManager.Changed += SnapshotManager_Changed;
Expand All @@ -40,12 +40,12 @@ public void Cleanup()
[Benchmark(Description = "Generates the code for 100 files", OperationsPerInvoke = 100)]
public async Task BackgroundCodeGeneration_Generate100FilesAsync()
{
await Dispatcher.RunAsync(
() =>
await ProjectManager.UpdateAsync(
updater =>
{
for (var i = 0; i < Documents.Length; i++)
{
ProjectManager.DocumentAdded(HostProject.Key, Documents[i], TextLoaders[i % 4]);
updater.DocumentAdded(HostProject.Key, Documents[i], TextLoaders[i % 4]);
}
},
CancellationToken.None);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ public void Setup()
[Benchmark(Description = "Initializes a project and 100 files", OperationsPerInvoke = 100)]
public async Task ProjectLoad_AddProjectAnd100Files()
{
await Dispatcher.RunAsync(
() =>
await ProjectManager.UpdateAsync(
updater =>
{
ProjectManager.ProjectAdded(HostProject);
updater.ProjectAdded(HostProject);

for (var i = 0; i < Documents.Length; i++)
{
ProjectManager.DocumentAdded(HostProject.Key, Documents[i], TextLoaders[i % 4]);
updater.DocumentAdded(HostProject.Key, Documents[i], TextLoaders[i % 4]);
}
},
CancellationToken.None);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ public void Setup()
[Benchmark(Description = "Does thread contention add/remove of documents", OperationsPerInvoke = 100)]
public async Task ProjectMutation_Mutates100kFilesAsync()
{
await Dispatcher.RunAsync(() =>
{
ProjectManager.ProjectAdded(HostProject);
}, CancellationToken.None);
await ProjectManager.UpdateAsync(
updater => updater.ProjectAdded(HostProject),
CancellationToken.None);

var cancellationSource = new CancellationTokenSource();
var done = false;
Expand All @@ -45,9 +44,9 @@ await Dispatcher.RunAsync(() =>
for (var i = 0; i < Documents.Length; i++)
{
var document = Documents[i];
await Dispatcher.RunAsync(() => ProjectManager.DocumentAdded(HostProject.Key, document, TextLoaders[i % 4]), CancellationToken.None).ConfigureAwait(false);
await ProjectManager.UpdateAsync(updater => updater.DocumentAdded(HostProject.Key, document, TextLoaders[i % 4]), CancellationToken.None).ConfigureAwait(false);
Thread.Sleep(0);
await Dispatcher.RunAsync(() => ProjectManager.DocumentRemoved(HostProject.Key, document), CancellationToken.None).ConfigureAwait(false);
await ProjectManager.UpdateAsync(updater => updater.DocumentRemoved(HostProject.Key, document), CancellationToken.None).ConfigureAwait(false);
Thread.Sleep(0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ public static void AddDocumentManagementServices(this IServiceCollection service

// Add project snapshot manager
services.AddSingleton<IProjectEngineFactoryProvider, LspProjectEngineFactoryProvider>();
services.AddSingleton<ProjectSnapshotManagerBase, ProjectSnapshotManager>();
services.AddSingleton<IProjectSnapshotManager>(services => services.GetRequiredService<ProjectSnapshotManagerBase>());
services.AddSingleton<IProjectSnapshotManager, ProjectSnapshotManager>();
}

public static void AddHandlerWithCapabilities<T>(this IServiceCollection services)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,19 @@ internal sealed class GeneratedDocumentPublisher : IGeneratedDocumentPublisher,
{
private readonly Dictionary<DocumentKey, PublishData> _publishedCSharpData;
private readonly Dictionary<string, PublishData> _publishedHtmlData;
private readonly ProjectSnapshotManagerBase _projectManager;
private readonly IProjectSnapshotManager _projectManager;
private readonly ProjectSnapshotManagerDispatcher _dispatcher;
private readonly IClientConnection _clientConnection;
private readonly LanguageServerFeatureOptions _options;
private readonly ILogger _logger;

public GeneratedDocumentPublisher(
ProjectSnapshotManagerBase projectManager,
IProjectSnapshotManager projectManager,
ProjectSnapshotManagerDispatcher dispatcher,
IClientConnection clientConnection,
LanguageServerFeatureOptions options,
IRazorLoggerFactory loggerFactory)
{

_projectManager = projectManager;
_dispatcher = dispatcher;
_clientConnection = clientConnection;
Expand Down Expand Up @@ -183,8 +182,6 @@ private void ProjectManager_Changed(object? sender, ProjectChangeEventArgs args)

_dispatcher.AssertRunningOnDispatcher();

Assumes.NotNull(_projectManager);

switch (args.Kind)
{
case ProjectChangeKind.DocumentChanged:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ internal class OpenDocumentGenerator : IRazorStartupService, IDisposable
// a document for each keystroke.
private static readonly TimeSpan s_batchingTimeSpan = TimeSpan.FromMilliseconds(10);

private readonly ProjectSnapshotManagerBase _projectManager;
private readonly IProjectSnapshotManager _projectManager;
private readonly ProjectSnapshotManagerDispatcher _dispatcher;
private readonly LanguageServerFeatureOptions _options;
private readonly IReadOnlyList<DocumentProcessedListener> _listeners;
private readonly BatchingWorkQueue _workQueue;

public OpenDocumentGenerator(
IEnumerable<DocumentProcessedListener> listeners,
ProjectSnapshotManagerBase projectManager,
IProjectSnapshotManager projectManager,
ProjectSnapshotManagerDispatcher dispatcher,
LanguageServerFeatureOptions options,
IErrorReporter errorReporter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
[RazorLanguageServerEndpoint(LanguageServerConstants.RazorMonitorProjectConfigurationFilePathEndpoint)]
internal class MonitorProjectConfigurationFilePathEndpoint : IRazorNotificationHandler<MonitorProjectConfigurationFilePathParams>, IDisposable
{
private readonly ProjectSnapshotManagerBase _projectManager;
private readonly IProjectSnapshotManager _projectManager;
private readonly ProjectSnapshotManagerDispatcher _dispatcher;
private readonly WorkspaceDirectoryPathResolver _workspaceDirectoryPathResolver;
private readonly IEnumerable<IProjectConfigurationFileChangeListener> _listeners;
Expand All @@ -34,7 +34,7 @@ internal class MonitorProjectConfigurationFilePathEndpoint : IRazorNotificationH
public bool MutatesSolutionState => false;

public MonitorProjectConfigurationFilePathEndpoint(
ProjectSnapshotManagerBase projectManager,
IProjectSnapshotManager projectManager,
ProjectSnapshotManagerDispatcher dispatcher,
WorkspaceDirectoryPathResolver workspaceDirectoryPathResolver,
IEnumerable<IProjectConfigurationFileChangeListener> listeners,
Expand Down Expand Up @@ -163,7 +163,7 @@ public async Task HandleNotificationAsync(MonitorProjectConfigurationFilePathPar
}
}

private async Task RemoveMonitorAsync(string projectKeyId, bool removeProject, CancellationToken cancellationToken)
private Task RemoveMonitorAsync(string projectKeyId, bool removeProject, CancellationToken cancellationToken)
{
// Should no longer monitor configuration output paths for the project
if (_outputPathMonitors.TryRemove(projectKeyId, out var removedEntry))
Expand All @@ -178,11 +178,16 @@ private async Task RemoveMonitorAsync(string projectKeyId, bool removeProject, C

if (removeProject)
{
await _dispatcher.RunAsync(() =>
{
_projectManager.ProjectRemoved(ProjectKey.FromString(projectKeyId));
}, cancellationToken).ConfigureAwait(false);
return _projectManager.UpdateAsync(
(updater, projectKey) =>
{
updater.ProjectRemoved(projectKey);
},
state: ProjectKey.FromString(projectKeyId),
cancellationToken);
}

return Task.CompletedTask;
}

public void Dispose()
Expand Down
Loading

0 comments on commit 486a51e

Please sign in to comment.