private async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(IEnumerable <DiagnosticData> diagnosticsToFix, Func <Project, bool> shouldFixInProject, bool filterStaleDiagnostics, CancellationToken cancellationToken) { var builder = ImmutableDictionary.CreateBuilder <DocumentId, List <DiagnosticData> >(); foreach (var diagnosticData in diagnosticsToFix.Where(IsDocumentDiagnostic)) { RoslynDebug.AssertNotNull(diagnosticData.DocumentId); if (!builder.TryGetValue(diagnosticData.DocumentId, out var diagnosticsPerDocument)) { diagnosticsPerDocument = new List <DiagnosticData>(); builder[diagnosticData.DocumentId] = diagnosticsPerDocument; } diagnosticsPerDocument.Add(diagnosticData); } if (builder.Count == 0) { return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty); } var finalBuilder = ImmutableDictionary.CreateBuilder <Document, ImmutableArray <Diagnostic> >(); var latestDocumentDiagnosticsMap = filterStaleDiagnostics ? new Dictionary <DocumentId, ImmutableHashSet <DiagnosticData> >() : null; foreach (var group in builder.GroupBy(kvp => kvp.Key.ProjectId)) { var projectId = group.Key; var project = _workspace.CurrentSolution.GetProject(projectId); if (project == null || !shouldFixInProject(project)) { continue; } if (filterStaleDiagnostics) { RoslynDebug.AssertNotNull(latestDocumentDiagnosticsMap); var uniqueDiagnosticIds = group.SelectMany(kvp => kvp.Value.Select(d => d.Id)).ToImmutableHashSet(); var latestProjectDiagnostics = (await _diagnosticService.GetDiagnosticsForIdsAsync(project.Solution, project.Id, diagnosticIds: uniqueDiagnosticIds, includeSuppressedDiagnostics: true, cancellationToken: cancellationToken) .ConfigureAwait(false)).Where(IsDocumentDiagnostic); latestDocumentDiagnosticsMap.Clear(); foreach (var kvp in latestProjectDiagnostics.Where(d => d.DocumentId != null).GroupBy(d => d.DocumentId !)) { latestDocumentDiagnosticsMap.Add(kvp.Key, kvp.ToImmutableHashSet()); } } foreach (var documentDiagnostics in group) { var document = project.GetDocument(documentDiagnostics.Key); if (document == null) { continue; } IEnumerable <DiagnosticData> documentDiagnosticsToFix; if (filterStaleDiagnostics) { RoslynDebug.AssertNotNull(latestDocumentDiagnosticsMap); if (!latestDocumentDiagnosticsMap.TryGetValue(document.Id, out var latestDocumentDiagnostics)) { // Ignore stale diagnostics in error list. latestDocumentDiagnostics = ImmutableHashSet <DiagnosticData> .Empty; } // Filter out stale diagnostics in error list. documentDiagnosticsToFix = documentDiagnostics.Value.Where(d => latestDocumentDiagnostics.Contains(d) || SuppressionHelpers.IsSynthesizedExternalSourceDiagnostic(d)); } else { documentDiagnosticsToFix = documentDiagnostics.Value; } if (documentDiagnosticsToFix.Any()) { var diagnostics = await documentDiagnosticsToFix.ToDiagnosticsAsync(project, cancellationToken).ConfigureAwait(false); finalBuilder.Add(document, diagnostics); } } } return(finalBuilder.ToImmutableDictionary());
private async Task <ImmutableDictionary <Project, ImmutableArray <Diagnostic> > > GetProjectDiagnosticsToFixAsync(IEnumerable <DiagnosticData> diagnosticsToFix, Func <Project, bool> shouldFixInProject, bool filterStaleDiagnostics, CancellationToken cancellationToken) { bool isProjectDiagnostic(DiagnosticData d) => d.DataLocation == null && d.ProjectId != null; var builder = ImmutableDictionary.CreateBuilder <ProjectId, List <DiagnosticData> >(); foreach (var diagnosticData in diagnosticsToFix.Where(isProjectDiagnostic)) { if (!builder.TryGetValue(diagnosticData.ProjectId, out var diagnosticsPerProject)) { diagnosticsPerProject = new List <DiagnosticData>(); builder[diagnosticData.ProjectId] = diagnosticsPerProject; } diagnosticsPerProject.Add(diagnosticData); } if (builder.Count == 0) { return(ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty); } var finalBuilder = ImmutableDictionary.CreateBuilder <Project, ImmutableArray <Diagnostic> >(); var latestDiagnosticsToFixOpt = filterStaleDiagnostics ? new HashSet <DiagnosticData>() : null; foreach (var kvp in builder) { var projectId = kvp.Key; var project = _workspace.CurrentSolution.GetProject(projectId); if (project == null || !shouldFixInProject(project)) { continue; } var diagnostics = kvp.Value; IEnumerable <DiagnosticData> projectDiagnosticsToFix; if (filterStaleDiagnostics) { var uniqueDiagnosticIds = diagnostics.Select(d => d.Id).ToImmutableHashSet(); var latestDiagnosticsFromDiagnosticService = (await _diagnosticService.GetDiagnosticsForIdsAsync(project.Solution, project.Id, diagnosticIds: uniqueDiagnosticIds, includeSuppressedDiagnostics: true, cancellationToken: cancellationToken) .ConfigureAwait(false)); latestDiagnosticsToFixOpt.Clear(); latestDiagnosticsToFixOpt.AddRange(latestDiagnosticsFromDiagnosticService.Where(isProjectDiagnostic)); // Filter out stale diagnostics in error list. projectDiagnosticsToFix = diagnostics.Where(d => latestDiagnosticsFromDiagnosticService.Contains(d) || SuppressionHelpers.IsSynthesizedExternalSourceDiagnostic(d)); } else { projectDiagnosticsToFix = diagnostics; } if (projectDiagnosticsToFix.Any()) { var projectDiagnostics = await projectDiagnosticsToFix.ToDiagnosticsAsync(project, cancellationToken).ConfigureAwait(false); finalBuilder.Add(project, projectDiagnostics); } } return(finalBuilder.ToImmutableDictionary()); }