Batch solution diagnostics updates

This commit is contained in:
Matt Parker
2025-11-23 12:21:24 +10:00
parent fa1a6413ee
commit d06312d58f

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis.Threading; using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Threading;
using Microsoft.VisualStudio.SolutionPersistence.Model; using Microsoft.VisualStudio.SolutionPersistence.Model;
using SharpIDE.Application.Features.Analysis; using SharpIDE.Application.Features.Analysis;
using SharpIDE.Application.Features.Evaluation; using SharpIDE.Application.Features.Evaluation;
@@ -18,10 +19,19 @@ public enum FileChangeType
CompletionChange // Apply only in memory, as well as notify tabs of new content CompletionChange // Apply only in memory, as well as notify tabs of new content
} }
public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileManager openTabsFileManager) public class FileChangedService
{ {
private readonly RoslynAnalysis _roslynAnalysis = roslynAnalysis; private readonly RoslynAnalysis _roslynAnalysis;
private readonly IdeOpenTabsFileManager _openTabsFileManager = openTabsFileManager; private readonly IdeOpenTabsFileManager _openTabsFileManager;
private readonly AsyncBatchingWorkQueue _updateSolutionDiagnosticsQueue;
public static readonly IAsynchronousOperationListener NullListener = new AsynchronousOperationListenerProvider.NullOperationListener();
public FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileManager openTabsFileManager)
{
_roslynAnalysis = roslynAnalysis;
_openTabsFileManager = openTabsFileManager;
_updateSolutionDiagnosticsQueue = new AsyncBatchingWorkQueue(TimeSpan.FromMilliseconds(200), ProcessBatchAsync, NullListener, CancellationToken.None);
}
public SharpIdeSolutionModel SolutionModel { get; set; } = null!; public SharpIdeSolutionModel SolutionModel { get; set; } = null!;
@@ -105,6 +115,11 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
await afterSaveTask; await afterSaveTask;
} }
private async ValueTask ProcessBatchAsync(CancellationToken cancellationToken)
{
await _roslynAnalysis.UpdateSolutionDiagnostics(cancellationToken);
}
private CancellationSeries _updateSolutionDiagnosticsCtSeries = new(); private CancellationSeries _updateSolutionDiagnosticsCtSeries = new();
private async Task HandleCsprojChanged(SharpIdeFile file) private async Task HandleCsprojChanged(SharpIdeFile file)
{ {
@@ -114,7 +129,7 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
await ProjectEvaluation.ReloadProject(file.Path); await ProjectEvaluation.ReloadProject(file.Path);
await _roslynAnalysis.ReloadProject(project, CancellationToken.None); await _roslynAnalysis.ReloadProject(project, CancellationToken.None);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
private async Task HandleWorkspaceFileChanged(SharpIdeFile file, string newContents) private async Task HandleWorkspaceFileChanged(SharpIdeFile file, string newContents)
@@ -122,7 +137,7 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
await _roslynAnalysis.UpdateDocument(file, newContents); await _roslynAnalysis.UpdateDocument(file, newContents);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
private async Task HandleWorkspaceFileAdded(SharpIdeFile file, string contents) private async Task HandleWorkspaceFileAdded(SharpIdeFile file, string contents)
@@ -130,7 +145,7 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
await _roslynAnalysis.AddDocument(file, contents); await _roslynAnalysis.AddDocument(file, contents);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
private async Task HandleWorkspaceFileRemoved(SharpIdeFile file) private async Task HandleWorkspaceFileRemoved(SharpIdeFile file)
@@ -138,7 +153,7 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
await _roslynAnalysis.RemoveDocument(file); await _roslynAnalysis.RemoveDocument(file);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
private async Task HandleWorkspaceFileMoved(SharpIdeFile file, string oldFilePath) private async Task HandleWorkspaceFileMoved(SharpIdeFile file, string oldFilePath)
@@ -146,7 +161,7 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
await _roslynAnalysis.MoveDocument(file, oldFilePath); await _roslynAnalysis.MoveDocument(file, oldFilePath);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
private async Task HandleWorkspaceFileRenamed(SharpIdeFile file, string oldFilePath) private async Task HandleWorkspaceFileRenamed(SharpIdeFile file, string oldFilePath)
@@ -154,6 +169,6 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
await _roslynAnalysis.RenameDocument(file, oldFilePath); await _roslynAnalysis.RenameDocument(file, oldFilePath);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts); _updateSolutionDiagnosticsQueue.AddWork();
} }
} }