Exemple #1
0
        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());
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        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));
        }
Exemple #6
0
        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());
        }