public static async Task <ImmutableDictionary <DiagnosticAnalyzer, AnalysisResult> > AnalyzeAsync(this CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken) { var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false); // Run all analyzers at once. // REVIEW: why there are 2 different cancellation token? one that I can give to constructor and one I can give in to each method? // REVIEW: we drop all those allocations for the diagnostics returned. can we avoid this? await analyzerDriver.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false); // this is wierd, but now we iterate through each analyzer for each tree to get cached result. // REVIEW: no better way to do this? var noSpanFilter = default(TextSpan?); var analyzers = analyzerDriver.Analyzers; var compilation = analyzerDriver.Compilation; var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalysisResult>(); foreach (var analyzer in analyzers) { var result = new Builder(project, version); // REVIEW: more unnecessary allocations just to get diagnostics per analyzer var oneAnalyzers = ImmutableArray.Create(analyzer); foreach (var tree in compilation.SyntaxTrees) { var model = compilation.GetSemanticModel(tree); var syntax = await analyzerDriver.GetAnalyzerSyntaxDiagnosticsAsync(tree, oneAnalyzers, cancellationToken).ConfigureAwait(false); Contract.Requires(syntax.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(syntax, analyzerDriver.Compilation).Count()); result.AddSyntaxDiagnostics(tree, syntax); var semantic = await analyzerDriver.GetAnalyzerSemanticDiagnosticsAsync(model, noSpanFilter, oneAnalyzers, cancellationToken).ConfigureAwait(false); Contract.Requires(semantic.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(semantic, analyzerDriver.Compilation).Count()); result.AddSemanticDiagnostics(tree, semantic); } var rest = await analyzerDriver.GetAnalyzerCompilationDiagnosticsAsync(oneAnalyzers, cancellationToken).ConfigureAwait(false); Contract.Requires(rest.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(rest, analyzerDriver.Compilation).Count()); result.AddCompilationDiagnostics(rest); builder.Add(analyzer, result.ToResult()); } return(builder.ToImmutable()); }