Use CancellationSeries for Solution Diagnostics

This commit is contained in:
Matt Parker
2025-11-21 21:42:55 +10:00
parent f7c2f7fdfc
commit 05744ed96d

View File

@@ -1,4 +1,5 @@
using Microsoft.VisualStudio.SolutionPersistence.Model; using Microsoft.CodeAnalysis.Threading;
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;
using SharpIDE.Application.Features.Events; using SharpIDE.Application.Features.Events;
@@ -104,73 +105,55 @@ public class FileChangedService(RoslynAnalysis roslynAnalysis, IdeOpenTabsFileMa
await afterSaveTask; await afterSaveTask;
} }
private CancellationTokenSource _updateSolutionDiagnosticsCts = new(); private CancellationSeries _updateSolutionDiagnosticsCtSeries = new();
private async Task HandleCsprojChanged(SharpIdeFile file) private async Task HandleCsprojChanged(SharpIdeFile file)
{ {
var project = SolutionModel.AllProjects.SingleOrDefault(p => p.FilePath == file.Path); var project = SolutionModel.AllProjects.SingleOrDefault(p => p.FilePath == file.Path);
if (project is null) return; if (project is null) return;
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
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.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
private async Task HandleWorkspaceFileChanged(SharpIdeFile file, string newContents) private async Task HandleWorkspaceFileChanged(SharpIdeFile file, string newContents)
{ {
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.UpdateDocument(file, newContents); await _roslynAnalysis.UpdateDocument(file, newContents);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
private async Task HandleWorkspaceFileAdded(SharpIdeFile file, string contents) private async Task HandleWorkspaceFileAdded(SharpIdeFile file, string contents)
{ {
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.AddDocument(file, contents); await _roslynAnalysis.AddDocument(file, contents);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
private async Task HandleWorkspaceFileRemoved(SharpIdeFile file) private async Task HandleWorkspaceFileRemoved(SharpIdeFile file)
{ {
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.RemoveDocument(file); await _roslynAnalysis.RemoveDocument(file);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
private async Task HandleWorkspaceFileMoved(SharpIdeFile file, string oldFilePath) private async Task HandleWorkspaceFileMoved(SharpIdeFile file, string oldFilePath)
{ {
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.MoveDocument(file, oldFilePath); await _roslynAnalysis.MoveDocument(file, oldFilePath);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
private async Task HandleWorkspaceFileRenamed(SharpIdeFile file, string oldFilePath) private async Task HandleWorkspaceFileRenamed(SharpIdeFile file, string oldFilePath)
{ {
var newCts = new CancellationTokenSource(); var newCts = _updateSolutionDiagnosticsCtSeries.CreateNext();
var oldCts = Interlocked.Exchange(ref _updateSolutionDiagnosticsCts, newCts);
await oldCts.CancelAsync();
oldCts.Dispose();
await _roslynAnalysis.RenameDocument(file, oldFilePath); await _roslynAnalysis.RenameDocument(file, oldFilePath);
GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget();
await _roslynAnalysis.UpdateSolutionDiagnostics(newCts.Token); await _roslynAnalysis.UpdateSolutionDiagnostics(newCts);
} }
} }