public async Task <ImmutableArray <ProjectAnalysisResult> > AnalyzeSolutionAsync( Solution solution, Func <Project, bool> predicate, CancellationToken cancellationToken = default) { foreach (string id in Options.IgnoredDiagnosticIds.OrderBy(f => f)) { WriteLine($"Ignore diagnostic '{id}'", Verbosity.Diagnostic); } ImmutableArray <ProjectId> projectIds = solution .GetProjectDependencyGraph() .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); WriteLine($"Analyze solution '{solution.FilePath}'", ConsoleColor.Cyan, Verbosity.Minimal); var results = new List <ProjectAnalysisResult>(); Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; for (int i = 0; i < projectIds.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); Project project = solution.GetProject(projectIds[i]); if (predicate == null || predicate(project)) { WriteLine($"Analyze '{project.Name}' {$"{i + 1}/{projectIds.Length}"}", Verbosity.Minimal); ProjectAnalysisResult result = await AnalyzeProjectCoreAsync(project, cancellationToken).ConfigureAwait(false); if (result != null) { results.Add(result); } } else { WriteLine($"Skip '{project.Name}' {$"{i + 1}/{projectIds.Length}"}", ConsoleColor.DarkGray, Verbosity.Minimal); } lastElapsed = stopwatch.Elapsed; } stopwatch.Stop(); WriteLine($"Done analyzing solution '{solution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); if (results.Count > 0) { WriteProjectAnalysisResults(results, cancellationToken); } return(results.ToImmutableArray()); }
public async Task <ProjectAnalysisResult> AnalyzeProjectAsync(Project project, CancellationToken cancellationToken = default) { ProjectAnalysisResult result = await AnalyzeProjectCoreAsync(project, cancellationToken).ConfigureAwait(false); WriteProjectAnalysisResults(new ProjectAnalysisResult[] { result }, cancellationToken); return(result); }
public async Task <ProjectAnalysisResult> AnalyzeProjectAsync(Project project, CancellationToken cancellationToken = default) { WriteLine($"Analyze '{project.Name}'", ConsoleColor.Cyan, Verbosity.Minimal); Stopwatch stopwatch = Stopwatch.StartNew(); ProjectAnalysisResult result = await AnalyzeProjectCoreAsync(project, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); WriteLine($"Done analyzing project '{project.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); WriteProjectAnalysisResults(new ProjectAnalysisResult[] { result }, cancellationToken); return(result); }
private async Task <ProjectAnalysisResult> AnalyzeProjectCoreAsync(Project project, CancellationToken cancellationToken = default) { ImmutableArray <DiagnosticAnalyzer> analyzers = _analyzerLoader.GetAnalyzers(project: project); if (!analyzers.Any()) { WriteLine($" No analyzers found to analyze '{project.Name}'", ConsoleColors.DarkGray, Verbosity.Normal); } if (analyzers.Any() || !Options.IgnoreCompilerDiagnostics) { return(await AnalyzeProjectCoreAsync(project, analyzers, cancellationToken).ConfigureAwait(false)); } return(ProjectAnalysisResult.Create(project)); }
private async Task <ProjectAnalysisResult> AnalyzeProjectCoreAsync(Project project, ImmutableArray <DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken = default) { LogHelpers.WriteUsedAnalyzers(analyzers, null, Options, ConsoleColors.DarkGray, Verbosity.Diagnostic); cancellationToken.ThrowIfCancellationRequested(); Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); ImmutableArray <Diagnostic> compilerDiagnostics = (Options.IgnoreCompilerDiagnostics) ? ImmutableArray <Diagnostic> .Empty : compilation.GetDiagnostics(cancellationToken); compilerDiagnostics = FilterDiagnostics(compilerDiagnostics, project, cancellationToken).ToImmutableArray(); ImmutableArray <Diagnostic> diagnostics = ImmutableArray <Diagnostic> .Empty; ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> telemetry = ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty; if (analyzers.Any()) { var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions( options: project.AnalyzerOptions, onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>), concurrentAnalysis: Options.ConcurrentAnalysis, logAnalyzerExecutionTime: Options.LogAnalyzerExecutionTime, reportSuppressedDiagnostics: Options.ReportSuppressedDiagnostics); var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, compilationWithAnalyzersOptions); if (Options.LogAnalyzerExecutionTime) { AnalysisResult analysisResult = await compilationWithAnalyzers.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false); diagnostics = analysisResult.GetAllDiagnostics(); telemetry = analysisResult.AnalyzerTelemetryInfo; } else { diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false); } } string projectDirectoryPath = Path.GetDirectoryName(project.FilePath); LogHelpers.WriteDiagnostics(FilterDiagnostics(diagnostics.Where(f => f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray(), baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: " ", verbosity: Verbosity.Detailed); #if DEBUG if (ConsoleOut.Verbosity >= Verbosity.Detailed && diagnostics.Any(f => f.IsAnalyzerExceptionDiagnostic())) { Console.Write("Stop (Y/N)? "); if (char.ToUpperInvariant((char)Console.Read()) == 'Y') { throw new OperationCanceledException(); } } #endif diagnostics = FilterDiagnostics(diagnostics.Where(f => !f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray(); LogHelpers.WriteDiagnostics(compilerDiagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: " ", verbosity: Verbosity.Normal); LogHelpers.WriteDiagnostics(diagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: " ", verbosity: Verbosity.Normal); return(ProjectAnalysisResult.Create(project, compilerDiagnostics, diagnostics, telemetry)); }
public async Task <ImmutableArray <ProjectAnalysisResult> > AnalyzeSolutionAsync(Solution solution, CancellationToken cancellationToken = default) { foreach (string id in Options.IgnoredDiagnosticIds.OrderBy(f => f)) { WriteLine($"Ignore diagnostic '{id}'", Verbosity.Diagnostic); } ImmutableArray <ProjectId> projectIds = solution .GetProjectDependencyGraph() .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); WriteLine($"Analyze solution '{solution.FilePath}'", ConsoleColor.Cyan, Verbosity.Minimal); var results = new List <ProjectAnalysisResult>(); Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; for (int i = 0; i < projectIds.Length; i++) { cancellationToken.ThrowIfCancellationRequested(); Project project = solution.GetProject(projectIds[i]); if (Options.IsSupportedProject(project)) { WriteLine($"Analyze '{project.Name}' {$"{i + 1}/{projectIds.Length}"}", Verbosity.Minimal); ProjectAnalysisResult result = await AnalyzeProjectAsync(project, cancellationToken).ConfigureAwait(false); if (result != null) { results.Add(result); } } else { WriteLine($"Skip '{project.Name}' {$"{i + 1}/{projectIds.Length}"}", ConsoleColor.DarkGray, Verbosity.Minimal); } lastElapsed = stopwatch.Elapsed; } stopwatch.Stop(); if (results.Count > 0) { if (Options.ExecutionTime) { WriteExecutionTime(results); } int totalCount = 0; foreach (ProjectAnalysisResult result in results) { IEnumerable <Diagnostic> diagnostics = result.Diagnostics .Where(f => !f.IsAnalyzerExceptionDiagnostic()) .Concat(result.CompilerDiagnostics); totalCount += FilterDiagnostics(diagnostics, cancellationToken).Count(); } if (totalCount > 0) { WriteLine(Verbosity.Minimal); Dictionary <DiagnosticDescriptor, int> diagnosticsByDescriptor = results .SelectMany(f => FilterDiagnostics(f.Diagnostics.Concat(f.CompilerDiagnostics), cancellationToken)) .GroupBy(f => f.Descriptor, DiagnosticDescriptorComparer.Id) .ToDictionary(f => f.Key, f => f.Count()); int maxCountLength = Math.Max(totalCount.ToString().Length, diagnosticsByDescriptor.Max(f => f.Value.ToString().Length)); int maxIdLength = diagnosticsByDescriptor.Max(f => f.Key.Id.Length); foreach (KeyValuePair <DiagnosticDescriptor, int> kvp in diagnosticsByDescriptor.OrderBy(f => f.Key.Id)) { WriteLine($"{kvp.Value.ToString().PadLeft(maxCountLength)} {kvp.Key.Id.PadRight(maxIdLength)} {kvp.Key.Title}", Verbosity.Normal); } WriteLine($"{totalCount} {((totalCount == 1) ? "diagnostic" : "diagnostics")} found", ConsoleColor.Green, Verbosity.Minimal); WriteLine(Verbosity.Minimal); } } WriteLine($"Done analyzing solution '{solution.FilePath}' in {stopwatch.Elapsed:mm\\:ss\\.ff}", Verbosity.Minimal); return(results.ToImmutableArray()); }