private async Task <DiagnosticFixResult> FixDiagnosticsAsync( DiagnosticDescriptor descriptor, ImmutableArray <DiagnosticAnalyzer> analyzers, ImmutableArray <CodeFixProvider> fixers, Project project, CancellationToken cancellationToken) { ImmutableArray <Diagnostic> .Builder fixedDiagnostics = ImmutableArray.CreateBuilder <Diagnostic>(); ImmutableArray <Diagnostic> diagnostics = ImmutableArray <Diagnostic> .Empty; ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty; ImmutableArray <Diagnostic> previousDiagnosticsToFix = ImmutableArray <Diagnostic> .Empty; int length = 0; var fixKind = DiagnosticFixKind.NotFixed; while (true) { Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); ImmutableArray <Diagnostic> compilerDiagnostics = compilation.GetDiagnostics(cancellationToken); if (!VerifyCompilerDiagnostics(compilerDiagnostics, project)) { fixKind = DiagnosticFixKind.CompilerError; if (!previousDiagnostics.Any()) { break; } } if (analyzers.IsDefault) { diagnostics = compilerDiagnostics; } else { diagnostics = await compilation.GetAnalyzerDiagnosticsAsync(analyzers, Options.CompilationWithAnalyzersOptions, cancellationToken).ConfigureAwait(false); } diagnostics = diagnostics .Where(f => f.Id == descriptor.Id && f.Severity >= Options.SeverityLevel) .ToImmutableArray(); if (fixKind == DiagnosticFixKind.CompilerError) { break; } else if (fixKind == DiagnosticFixKind.Success) { if (Options.BatchSize <= 0 || length <= Options.BatchSize) { break; } } else if (previousDiagnostics.Any() && fixKind != DiagnosticFixKind.PartiallyFixed) { break; } length = diagnostics.Length; if (length == 0) { break; } if (length == previousDiagnostics.Length && !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any()) { break; } fixedDiagnostics.AddRange(previousDiagnosticsToFix.Except(diagnostics, DiagnosticDeepEqualityComparer.Instance)); previousDiagnostics = diagnostics; if (Options.FixAllScope == FixAllScope.Document) { foreach (IGrouping <SyntaxTree, Diagnostic> grouping in diagnostics .GroupBy(f => f.Location.SourceTree) .OrderByDescending(f => f.Count())) { IEnumerable <Diagnostic> syntaxTreeDiagnostics = grouping.AsEnumerable(); if (Options.BatchSize > 0) { syntaxTreeDiagnostics = syntaxTreeDiagnostics.Take(Options.BatchSize); } ImmutableArray <Diagnostic> diagnosticsCandidate = syntaxTreeDiagnostics.ToImmutableArray(); DiagnosticFixKind fixKindCandidate = await FixDiagnosticsAsync(diagnosticsCandidate, descriptor, fixers, project, cancellationToken).ConfigureAwait(false); if (fixKindCandidate == DiagnosticFixKind.Success || fixKindCandidate == DiagnosticFixKind.PartiallyFixed) { diagnostics = diagnosticsCandidate; fixKind = fixKindCandidate; break; } } } else { if (Options.BatchSize > 0 && length > Options.BatchSize) { diagnostics = ImmutableArray.CreateRange(diagnostics, 0, Options.BatchSize, f => f); } fixKind = await FixDiagnosticsAsync(diagnostics, descriptor, fixers, project, cancellationToken).ConfigureAwait(false); } previousDiagnosticsToFix = diagnostics; project = CurrentSolution.GetProject(project.Id); } fixedDiagnostics.AddRange(previousDiagnosticsToFix.Except(diagnostics, DiagnosticDeepEqualityComparer.Instance)); return(new DiagnosticFixResult(fixKind, fixedDiagnostics.ToImmutableArray())); }
public DiagnosticFixResult(DiagnosticFixKind kind, ImmutableArray <Diagnostic> fixedDiagnostics) { Kind = kind; FixedDiagnostics = fixedDiagnostics; }