public async Task <ProjectFixResult> FixProjectAsync(Project project, CancellationToken cancellationToken = default) { (ImmutableArray <DiagnosticAnalyzer> analyzers, ImmutableArray <CodeFixProvider> fixers) = CodeAnalysisHelpers.GetAnalyzersAndFixers( project: project, analyzerAssemblies: _analyzerAssemblies, analyzerReferences: _analyzerReferences, options: Options); ProjectFixResult fixResult = await FixProjectAsync(project, analyzers, fixers, cancellationToken).ConfigureAwait(false); Compilation compilation = await CurrentSolution.GetProject(project.Id).GetCompilationAsync(cancellationToken).ConfigureAwait(false); Dictionary <string, ImmutableArray <CodeFixProvider> > fixersById = fixers .SelectMany(f => f.FixableDiagnosticIds.Select(id => (id, fixer: f))) .GroupBy(f => f.id) .ToDictionary(f => f.Key, g => g.Select(f => f.fixer).Distinct().ToImmutableArray()); ImmutableArray <Diagnostic> unfixableDiagnostics = await GetDiagnosticsAsync( analyzers, fixResult.FixedDiagnostics, compilation, f => !fixersById.TryGetValue(f.id, out ImmutableArray <CodeFixProvider> fixers2), cancellationToken) .ConfigureAwait(false); ImmutableArray <Diagnostic> unfixedDiagnostics = await GetDiagnosticsAsync( analyzers, fixResult.FixedDiagnostics.Concat(unfixableDiagnostics), compilation, f => fixersById.TryGetValue(f.id, out ImmutableArray <CodeFixProvider> fixers2), cancellationToken) .ConfigureAwait(false); int numberOfAddedFileBanners = 0; if (Options.FileBannerLines.Any()) { numberOfAddedFileBanners = await AddFileBannerAsync(CurrentSolution.GetProject(project.Id), Options.FileBannerLines, cancellationToken).ConfigureAwait(false); } ImmutableArray <DocumentId> formattedDocuments = ImmutableArray <DocumentId> .Empty; if (Options.Format) { formattedDocuments = await FormatProjectAsync(CurrentSolution.GetProject(project.Id), cancellationToken).ConfigureAwait(false); } return(new ProjectFixResult( kind: fixResult.Kind, fixedDiagnostics: fixResult.FixedDiagnostics, unfixedDiagnostics: unfixedDiagnostics, unfixableDiagnostics: unfixableDiagnostics, analyzers: fixResult.Analyzers, fixers: fixResult.Fixers, numberOfFormattedDocuments: formattedDocuments.Length, numberOfAddedFileBanners: numberOfAddedFileBanners)); }
public async Task <ImmutableArray <ProjectFixResult> > FixSolutionAsync(Func <Project, bool> predicate, CancellationToken cancellationToken = default) { ImmutableArray <ProjectId> projects = CurrentSolution .GetProjectDependencyGraph() .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); var results = new List <ProjectFixResult>(); Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; for (int i = 0; i < projects.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); Project project = CurrentSolution.GetProject(projects[i]); if (predicate == null || predicate(project)) { WriteLine($"Fix '{project.Name}' {$"{i + 1}/{projects.Length}"}", ConsoleColor.Cyan, Verbosity.Minimal); ProjectFixResult result = await FixProjectAsync(project, cancellationToken).ConfigureAwait(false); results.Add(result); if (result.Kind == ProjectFixKind.CompilerError) { break; } } else { WriteLine($"Skip '{project.Name}' {$"{i + 1}/{projects.Length}"}", ConsoleColor.DarkGray, Verbosity.Minimal); results.Add(ProjectFixResult.Skipped); } TimeSpan elapsed = stopwatch.Elapsed; WriteLine($"Done fixing '{project.Name}' in {elapsed - lastElapsed:mm\\:ss\\.ff}", Verbosity.Normal); lastElapsed = elapsed; } stopwatch.Stop(); WriteLine($"Done fixing solution '{CurrentSolution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); LogHelpers.WriteProjectFixResults(results, Options, FormatProvider); return(results.ToImmutableArray()); }
public async Task FixSolutionAsync(CancellationToken cancellationToken = default) { foreach (string id in Options.IgnoredCompilerDiagnosticIds.OrderBy(f => f)) { WriteLine($"Ignore compiler diagnostic '{id}'", Verbosity.Diagnostic); } foreach (string id in Options.IgnoredDiagnosticIds.OrderBy(f => f)) { WriteLine($"Ignore diagnostic '{id}'", Verbosity.Diagnostic); } ImmutableArray <ProjectId> projects = CurrentSolution .GetProjectDependencyGraph() .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); var results = new List <ProjectFixResult>(); Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; for (int i = 0; i < projects.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); Project project = CurrentSolution.GetProject(projects[i]); if (Options.IsSupportedProject(project)) { WriteLine($"Fix '{project.Name}' {$"{i + 1}/{projects.Length}"}", ConsoleColor.Cyan, Verbosity.Minimal); ProjectFixResult result = await FixProjectAsync(project, cancellationToken).ConfigureAwait(false); results.Add(result); WriteFixSummary( result.FixedDiagnostics, result.UnfixedDiagnostics, result.UnfixableDiagnostics, indent: " ", formatProvider: FormatProvider, verbosity: Verbosity.Detailed); if (result.Kind == ProjectFixKind.CompilerError) { break; } } else { WriteLine($"Skip '{project.Name}' {$"{i + 1}/{projects.Length}"}", ConsoleColor.DarkGray, Verbosity.Minimal); results.Add(ProjectFixResult.Skipped); } TimeSpan elapsed = stopwatch.Elapsed; WriteLine($"Done fixing '{project.Name}' in {elapsed - lastElapsed:mm\\:ss\\.ff}", Verbosity.Normal); lastElapsed = elapsed; } stopwatch.Stop(); WriteProjectFixResults(results, Options, FormatProvider); WriteLine($"Done fixing solution '{CurrentSolution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); }
public async Task <ProjectFixResult> FixProjectAsync(Project project, CancellationToken cancellationToken = default) { (ImmutableArray <DiagnosticAnalyzer> analyzers, ImmutableArray <CodeFixProvider> fixers) = _analyzerLoader.GetAnalyzersAndFixers(project: project); FixResult fixResult = await FixProjectAsync(project, analyzers, fixers, cancellationToken).ConfigureAwait(false); project = CurrentSolution.GetProject(project.Id); Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); Dictionary <string, ImmutableArray <CodeFixProvider> > fixersById = fixers .SelectMany(f => f.FixableDiagnosticIds.Select(id => (id, fixer: f))) .GroupBy(f => f.id) .ToDictionary(f => f.Key, g => g.Select(f => f.fixer).Distinct().ToImmutableArray()); ImmutableArray <Diagnostic> unfixableDiagnostics = await GetDiagnosticsAsync( analyzers, fixResult.FixedDiagnostics, compilation, project.AnalyzerOptions, f => !fixersById.ContainsKey(f.id), cancellationToken) .ConfigureAwait(false); ImmutableArray <Diagnostic> unfixedDiagnostics = await GetDiagnosticsAsync( analyzers, fixResult.FixedDiagnostics.Concat(unfixableDiagnostics), compilation, project.AnalyzerOptions, f => fixersById.ContainsKey(f.id), cancellationToken) .ConfigureAwait(false); int numberOfAddedFileBanners = 0; if (Options.FileBannerLines.Any()) { numberOfAddedFileBanners = await AddFileBannerAsync(CurrentSolution.GetProject(project.Id), Options.FileBannerLines, cancellationToken).ConfigureAwait(false); } ImmutableArray <DocumentId> formattedDocuments = ImmutableArray <DocumentId> .Empty; if (Options.Format) { formattedDocuments = await FormatProjectAsync(CurrentSolution.GetProject(project.Id), cancellationToken).ConfigureAwait(false); } var result = new ProjectFixResult( kind: fixResult.Kind, fixedDiagnostics: fixResult.FixedDiagnostics.Select(f => DiagnosticInfo.Create(f)), unfixedDiagnostics: unfixedDiagnostics.Select(f => DiagnosticInfo.Create(f)), unfixableDiagnostics: unfixableDiagnostics.Select(f => DiagnosticInfo.Create(f)), numberOfFormattedDocuments: (Options.FileBannerLines.Any()) ? formattedDocuments.Length : -1, numberOfAddedFileBanners: (Options.Format) ? numberOfAddedFileBanners : -1); LogHelpers.WriteFixSummary( fixResult.FixedDiagnostics, unfixedDiagnostics, unfixableDiagnostics, baseDirectoryPath: Path.GetDirectoryName(project.FilePath), indentation: " ", formatProvider: FormatProvider, verbosity: Verbosity.Detailed); return(result); }