Skip to content

Commit

Permalink
Remove IProjectSnapshotManagerAccessor and IProjectSnapshotChangeTrig…
Browse files Browse the repository at this point in the history
…ger completely

Fixes dotnet#9950

This is a pretty significant change that requires refactoring of how the project snapshot manager is exported within Visual Studio. The IProjectSnapshotManagerAccessor implementations and usages have been completely removed, and IProjectSnapshotChangeTrigger has also been deleted. Now, if a service wants to subscribe to project change events, they can import an IProjectSnapshotManager. And, if that service wants to be loaded when the Razor tooling is boot-strapped, they can export themselves as an IRazorStartupService.
  • Loading branch information
DustinCampbell committed Mar 12, 2024
1 parent 81a31ef commit 8729930
Show file tree
Hide file tree
Showing 60 changed files with 619 additions and 828 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void Cleanup()

private List<Task> Tasks { get; } = new List<Task>();

private DefaultProjectSnapshotManager ProjectManager { get; set; }
private ProjectSnapshotManager ProjectManager { get; set; }

[Benchmark(Description = "Generates the code for 100 files", OperationsPerInvoke = 100)]
public async Task BackgroundCodeGeneration_Generate100FilesAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void Setup()
ProjectManager = CreateProjectSnapshotManager();
}

private DefaultProjectSnapshotManager ProjectManager { get; set; }
private ProjectSnapshotManager ProjectManager { get; set; }

[Benchmark(Description = "Initializes a project and 100 files", OperationsPerInvoke = 100)]
public async Task ProjectLoad_AddProjectAnd100Files()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void Setup()
ProjectManager = CreateProjectSnapshotManager();
}

private DefaultProjectSnapshotManager ProjectManager { get; set; }
private ProjectSnapshotManager ProjectManager { get; set; }

[Benchmark(Description = "Does thread contention add/remove of documents", OperationsPerInvoke = 100)]
public async Task ProjectMutation_Mutates100kFilesAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ protected ProjectSnapshotManagerBenchmarkBase(int documentCount = 100)
Dispatcher = new LSPProjectSnapshotManagerDispatcher(ErrorReporter);
}

internal DefaultProjectSnapshotManager CreateProjectSnapshotManager()
internal ProjectSnapshotManager CreateProjectSnapshotManager()
{
return new DefaultProjectSnapshotManager(
return new ProjectSnapshotManager(
projectEngineFactoryProvider: StaticProjectEngineFactoryProvider.Instance,
dispatcher: Dispatcher,
errorReporter: ErrorReporter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public static void AddDocumentManagementServices(this IServiceCollection service
services.AddSingleton(sp => new Lazy<IDocumentContextFactory>(sp.GetRequiredService<IDocumentContextFactory>));

services.AddSingleton<IDocumentVersionCache, DocumentVersionCache>();
services.AddSingleton((services) => (IProjectSnapshotChangeTrigger)services.GetRequiredService<IDocumentVersionCache>());
services.AddSingleton((services) => (IRazorStartupService)services.GetRequiredService<IDocumentVersionCache>());

services.AddSingleton<RemoteTextLoaderFactory, DefaultRemoteTextLoaderFactory>();
services.AddSingleton<ISnapshotResolver, SnapshotResolver>();
Expand Down Expand Up @@ -247,7 +247,7 @@ public static void AddDocumentManagementServices(this IServiceCollection service
var errorReporter = services.GetRequiredService<IErrorReporter>();
var projectEngineFactoryProvider = new LspProjectEngineFactoryProvider(optionsManager);

return new DefaultProjectSnapshotManager(
return new ProjectSnapshotManager(
projectEngineFactoryProvider,
dispatcher,
errorReporter);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
internal sealed class FallbackProjectManager(
ProjectConfigurationFilePathStore projectConfigurationFilePathStore,
LanguageServerFeatureOptions languageServerFeatureOptions,
IProjectSnapshotManagerAccessor projectManagerAccessor,
ProjectSnapshotManagerBase projectManager,
ProjectSnapshotManagerDispatcher dispatcher,
IWorkspaceProvider workspaceProvider,
ITelemetryReporter telemetryReporter)
{
private readonly ProjectConfigurationFilePathStore _projectConfigurationFilePathStore = projectConfigurationFilePathStore;
private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions;
private readonly IProjectSnapshotManagerAccessor _projectManagerAccessor = projectManagerAccessor;
private readonly ProjectSnapshotManagerBase _projectManager = projectManager;
private readonly ProjectSnapshotManagerDispatcher _dispatcher = dispatcher;
private readonly IWorkspaceProvider _workspaceProvider = workspaceProvider;
private readonly ITelemetryReporter _telemetryReporter = telemetryReporter;
Expand All @@ -44,8 +44,7 @@ internal async Task DynamicFileAddedAsync(
{
try
{
if (_projectManagerAccessor.TryGetInstance(out var projectSnapshotManager) &&
projectSnapshotManager.TryGetLoadedProject(razorProjectKey, out var project))
if (_projectManager.TryGetLoadedProject(razorProjectKey, out var project))
{
if (project is ProjectSnapshot { HostProject: FallbackHostProject })
{
Expand Down Expand Up @@ -77,8 +76,7 @@ internal async Task DynamicFileRemovedAsync(
{
try
{
if (_projectManagerAccessor.TryGetInstance(out var projectSnapshotManager) &&
projectSnapshotManager.TryGetLoadedProject(razorProjectKey, out var project) &&
if (_projectManager.TryGetLoadedProject(razorProjectKey, out var project) &&
project is ProjectSnapshot { HostProject: FallbackHostProject })
{
// If this is a fallback project, then Roslyn may not track documents in the project, so these dynamic file notifications
Expand Down Expand Up @@ -116,7 +114,7 @@ private async Task AddFallbackProjectAsync(ProjectId projectId, string filePath,

await _dispatcher
.RunAsync(
() => _projectManagerAccessor.Instance.ProjectAdded(hostProject),
() => _projectManager.ProjectAdded(hostProject),
cancellationToken)
.ConfigureAwait(false);

Expand All @@ -139,7 +137,7 @@ private async Task AddFallbackDocumentAsync(ProjectKey projectKey, string filePa

await _dispatcher
.RunAsync(
() => _projectManagerAccessor.Instance.DocumentAdded(projectKey, hostDocument, textLoader),
() => _projectManager.DocumentAdded(projectKey, hostDocument, textLoader),
cancellationToken)
.ConfigureAwait(false);
}
Expand Down Expand Up @@ -182,7 +180,7 @@ private async Task RemoveFallbackDocumentAsync(ProjectId projectId, string fileP

await _dispatcher
.RunAsync(
() => _projectManagerAccessor.Instance.DocumentRemoved(razorProjectKey, hostDocument),
() => _projectManager.DocumentRemoved(razorProjectKey, hostDocument),
cancellationToken)
.ConfigureAwait(false);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;

internal interface IProjectSnapshotManager
{
event EventHandler<ProjectChangeEventArgs> PriorityChanged;
event EventHandler<ProjectChangeEventArgs> Changed;

ImmutableArray<IProjectSnapshot> GetProjects();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
// (language version, extensions, named configuration).
//
// The implementation will create a ProjectSnapshot for each HostProject.
internal class DefaultProjectSnapshotManager : ProjectSnapshotManagerBase
internal class ProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher,
IErrorReporter errorReporter) : ProjectSnapshotManagerBase
{
public override event EventHandler<ProjectChangeEventArgs>? PriorityChanged;
public override event EventHandler<ProjectChangeEventArgs>? Changed;

// Each entry holds a ProjectState and an optional ProjectSnapshot. ProjectSnapshots are
Expand All @@ -36,45 +40,13 @@ internal class DefaultProjectSnapshotManager : ProjectSnapshotManagerBase

// We have a queue for changes because if one change results in another change aka, add -> open we want to make sure the "add" finishes running first before "open" is notified.
private readonly Queue<ProjectChangeEventArgs> _notificationWork = new();
private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider;
private readonly IErrorReporter _errorReporter;
private readonly ProjectSnapshotManagerDispatcher _dispatcher;

public DefaultProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher,
IErrorReporter errorReporter)
{
_projectEngineFactoryProvider = projectEngineFactoryProvider;
_dispatcher = dispatcher;
_errorReporter = errorReporter;
}
private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider = projectEngineFactoryProvider;
private readonly IErrorReporter _errorReporter = errorReporter;
private readonly ProjectSnapshotManagerDispatcher _dispatcher = dispatcher;

// internal for testing
internal bool IsSolutionClosing { get; private set; }

internal void InitializeChangeTriggers(IEnumerable<IProjectSnapshotChangeTrigger> triggers)
{
using (_rwLocker.EnterReadLock())
{
foreach (var trigger in triggers)
{
if (trigger is IPriorityProjectSnapshotChangeTrigger)
{
trigger.Initialize(this);
}
}

foreach (var trigger in triggers)
{
if (trigger is not IPriorityProjectSnapshotChangeTrigger)
{
trigger.Initialize(this);
}
}
}
}

public override ImmutableArray<IProjectSnapshot> GetProjects()
{
using var _ = _rwLocker.EnterReadLock();
Expand Down Expand Up @@ -405,6 +377,7 @@ private void NotifyListenersCore(ProjectChangeEventArgs e)
{
// Don't dequeue yet, we want the notification to sit in the queue until we've finished notifying to ensure other calls to NotifyListeners know there's a currently running event loop.
var args = _notificationWork.Peek();
PriorityChanged?.Invoke(this, args);
Changed?.Invoke(this, args);

_notificationWork.Dequeue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;

internal abstract class ProjectSnapshotManagerBase : IProjectSnapshotManager
{
public abstract event EventHandler<ProjectChangeEventArgs> PriorityChanged;
public abstract event EventHandler<ProjectChangeEventArgs> Changed;

public abstract ImmutableArray<IProjectSnapshot> GetProjects();
Expand Down
Loading

0 comments on commit 8729930

Please sign in to comment.