private async Task <Project> FixAllAnalyerDiagnosticsInScopeAsync(FixAllScope scope, ImmutableArray <DiagnosticAnalyzer> analyzers, ImmutableArray <CodeFixProvider> codeFixProviders, int?codeFixIndex, string codeFixEquivalenceKey, Project project, int numberOfIterations, IVerifier verifier, CancellationToken cancellationToken) { var expectedNumberOfIterations = numberOfIterations; if (numberOfIterations < 0) { numberOfIterations = -numberOfIterations; } var previousDiagnostics = ImmutableArray.Create <Diagnostic>(); bool done; do { var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, CompilerDiagnostics, cancellationToken).ConfigureAwait(false); if (analyzerDiagnostics.Length == 0) { break; } if (!AreDiagnosticsDifferent(analyzerDiagnostics, previousDiagnostics)) { break; } verifier.False(--numberOfIterations < -1, "The upper limit for the number of fix all iterations was exceeded"); Diagnostic firstDiagnostic = null; CodeFixProvider effectiveCodeFixProvider = null; string equivalenceKey = null; foreach (var diagnostic in analyzerDiagnostics) { var actions = new List <(CodeAction, CodeFixProvider)>(); foreach (var codeFixProvider in codeFixProviders) { if (!codeFixProvider.FixableDiagnosticIds.Contains(diagnostic.Id)) { // do not pass unsupported diagnostics to a code fix provider continue; } var context = new CodeFixContext(project.GetDocument(diagnostic.Location.SourceTree), diagnostic, (a, d) => actions.Add((a, codeFixProvider)), cancellationToken); await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false); } var actionToApply = TryGetCodeActionToApply(actions.Select(a => a.Item1).ToList(), codeFixIndex, codeFixEquivalenceKey, verifier); if (actionToApply != null) { firstDiagnostic = diagnostic; effectiveCodeFixProvider = actions.SingleOrDefault(a => a.Item1 == actionToApply).Item2; equivalenceKey = actionToApply.EquivalenceKey; break; } } var fixAllProvider = effectiveCodeFixProvider?.GetFixAllProvider(); if (firstDiagnostic == null || fixAllProvider == null) { numberOfIterations++; break; } previousDiagnostics = analyzerDiagnostics; done = true; FixAllContext.DiagnosticProvider fixAllDiagnosticProvider = TestDiagnosticProvider.Create(analyzerDiagnostics); var analyzerDiagnosticIds = analyzers.SelectMany(x => x.SupportedDiagnostics).Select(x => x.Id); var compilerDiagnosticIds = codeFixProviders.SelectMany(codeFixProvider => codeFixProvider.FixableDiagnosticIds).Where(x => x.StartsWith("CS", StringComparison.Ordinal) || x.StartsWith("BC", StringComparison.Ordinal)); var disabledDiagnosticIds = project.CompilationOptions.SpecificDiagnosticOptions.Where(x => x.Value == ReportDiagnostic.Suppress).Select(x => x.Key); var relevantIds = analyzerDiagnosticIds.Concat(compilerDiagnosticIds).Except(disabledDiagnosticIds).Distinct(); var fixAllContext = new FixAllContext(project.GetDocument(firstDiagnostic.Location.SourceTree), effectiveCodeFixProvider, scope, equivalenceKey, relevantIds, fixAllDiagnosticProvider, cancellationToken); var action = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false); if (action == null) { return(project); } var fixedProject = await ApplyFixAsync(project, action, cancellationToken).ConfigureAwait(false); if (fixedProject != project) { done = false; project = await RecreateProjectDocumentsAsync(fixedProject, verifier, cancellationToken).ConfigureAwait(false); } }while (!done); if (expectedNumberOfIterations >= 0) { verifier.Equal(expectedNumberOfIterations, expectedNumberOfIterations - numberOfIterations, $"Expected '{expectedNumberOfIterations}' iterations but found '{expectedNumberOfIterations - numberOfIterations}' iterations."); } else { verifier.True(numberOfIterations >= 0, "The upper limit for the number of code fix iterations was exceeded"); } return(project); }