public static async Task ExecuteAsync(CompilationWithAnalyzers compilation) { await compilation.GetAllDiagnosticsAsync(); using (MemoryStream assemblyStream = new MemoryStream()) using (MemoryStream pdbStream = new MemoryStream()) { var result = compilation.Compilation.Emit(assemblyStream, pdbStream); if (!IsWrittenToDisk || !ShouldBreakAtEnd) { return; } Diagnostic[] diagnostics = result.Diagnostics.OrderByDescending(x => x.Severity).ToArray(); if (result.Success) { Success(diagnostics); return; } string[] errors = diagnostics.TakeWhile(x => x.Severity == DiagnosticSeverity.Error).Select(x => x.ToString()).ToArray(); try { File.WriteAllLines(ErrorFile, errors); } finally { Failure(diagnostics, errors); } } }
private static async Task <ImmutableArray <Diagnostic> > GetProjectAnalyzerDiagnosticsAsync(ImmutableArray <DiagnosticAnalyzer> analyzers, Project project, CancellationToken cancellationToken) { var supportedDiagnosticsSpecificOptions = new Dictionary <string, ReportDiagnostic>(); foreach (var analyzer in analyzers) { foreach (var diagnostic in analyzer.SupportedDiagnostics) { // make sure the analyzers we are testing are enabled supportedDiagnosticsSpecificOptions[diagnostic.Id] = ReportDiagnostic.Default; } } // Report exceptions during the analysis process as errors supportedDiagnosticsSpecificOptions.Add("AD0001", ReportDiagnostic.Error); // update the project compilation options var modifiedSpecificDiagnosticOptions = supportedDiagnosticsSpecificOptions.ToImmutableDictionary().SetItems(project.CompilationOptions.SpecificDiagnosticOptions); var modifiedCompilationOptions = project.CompilationOptions.WithSpecificDiagnosticOptions(modifiedSpecificDiagnosticOptions); var processedProject = project.WithCompilationOptions(modifiedCompilationOptions); Compilation compilation = await processedProject.GetCompilationAsync(cancellationToken).ConfigureAwait(false); CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, cancellationToken: cancellationToken); //var diagnostics = await FixAllContextHelper.GetAllDiagnosticsAsync(compilation, compilationWithAnalyzers, analyzers, project.Documents, true, cancellationToken).ConfigureAwait(false); var diagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync(); return(diagnostics); }
/// <summary> /// Returns a list of all analyzer diagnostics inside the specific project. This is an asynchronous operation. /// </summary> /// <param name="analyzers">The list of analyzers that should be used</param> /// <param name="project">The project that should be analyzed</param> /// <param name="cancellationToken">The cancellation token that the task will observe.</param> /// <returns>A list of diagnostics inside the project</returns> private static async Task <ImmutableArray <Diagnostic> > GetProjectAnalyzerDiagnosticsAsync(ImmutableArray <DiagnosticAnalyzer> analyzers, Project project, CancellationToken cancellationToken) { Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, cancellationToken: cancellationToken); var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); // We want analyzer diagnostics and analyzer exceptions return(allDiagnostics.RemoveRange(compilation.GetDiagnostics())); }
public static async Task <ImmutableArray <Diagnostic> > GetAllDiagnosticsAsync(Compilation compilation, CompilationWithAnalyzers compilationWithAnalyzers, ImmutableArray <DiagnosticAnalyzer> analyzers, IEnumerable <Document> documents, bool includeCompilerDiagnostics, CancellationToken cancellationToken) { if (GetAnalyzerSyntaxDiagnosticsAsync == null || GetAnalyzerSemanticDiagnosticsAsync == null) { // In everything except Roslyn 1.1, we use GetAllDiagnosticsAsync and return the result. var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); return(allDiagnostics); } compilationWithAnalyzers.Compilation.GetDeclarationDiagnostics(cancellationToken); // Note that the following loop to obtain syntax and semantic diagnostics for each document cannot operate // on parallel due to our use of a single CompilationWithAnalyzers instance. var diagnostics = ImmutableArray.CreateBuilder <Diagnostic>(); foreach (var document in documents) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var syntaxDiagnostics = await GetAnalyzerSyntaxDiagnosticsAsync(compilationWithAnalyzers, syntaxTree, cancellationToken).ConfigureAwait(false); diagnostics.AddRange(syntaxDiagnostics); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticDiagnostics = await GetAnalyzerSemanticDiagnosticsAsync(compilationWithAnalyzers, semanticModel, default(TextSpan?), cancellationToken).ConfigureAwait(false); diagnostics.AddRange(semanticDiagnostics); } foreach (var analyzer in analyzers) { diagnostics.AddRange(await GetAnalyzerCompilationDiagnosticsAsync(compilationWithAnalyzers, ImmutableArray.Create(analyzer), cancellationToken).ConfigureAwait(false)); } if (includeCompilerDiagnostics) { // This is the special handling for cases where code fixes operate on warnings produced by the C# // compiler, as opposed to being created by specific analyzers. var compilerDiagnostics = compilation.GetDiagnostics(cancellationToken); diagnostics.AddRange(compilerDiagnostics); } return(diagnostics.ToImmutable()); }
public Task <ImmutableArray <Diagnostic> > GetDiagnosticsWithAnalyzers() => _compWithAnalyzers.GetAllDiagnosticsAsync();
public static async Task <ImmutableArray <Diagnostic> > GetAllDiagnosticsAsync(Compilation compilation, CompilationWithAnalyzers compilationWithAnalyzers, ImmutableArray <DiagnosticAnalyzer> analyzers, IEnumerable <Document> documents, bool includeCompilerDiagnostics, CancellationToken cancellationToken) { return(await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false)); }
//--------------------------------------------------------------------- protected async Task <Diagnostic[]> GetDiagnosticsAsync( Document[] documents, DiagnosticAnalyzer analyzer, string[] additionalEnabledDiagnostics = null) { var projects = new HashSet <Project>(); foreach (Document document in documents) { projects.Add(document.Project); } var diagnostics = new List <Diagnostic>(); foreach (Project project in projects) { Compilation compilation = await project.GetCompilationAsync(); // Enable any additional diagnostics CompilationOptions options = compilation.Options; if (additionalEnabledDiagnostics?.Length > 0) { options = compilation.Options .WithSpecificDiagnosticOptions(additionalEnabledDiagnostics.ToDictionary(s => s, _ => ReportDiagnostic.Info)); } CompilationWithAnalyzers compilationWithAnalyzers = compilation .WithOptions(options) .WithAnalyzers(ImmutableArray.Create(analyzer)); ImmutableArray <Diagnostic> diags = await compilationWithAnalyzers.GetAllDiagnosticsAsync(); foreach (Diagnostic diag in diags) { TestContext.WriteLine("Diagnostics: " + diag); } Assume.That(diags.Any(d => d.Id == "AD0001"), Is.False, "diagnostics with AD0001 present"); // Filter out non-error diagnostics not produced by our analyzer // We want to KEEP errors because we might have written bad code. But sometimes we leave warnings in to make the // test code more convenient diags = diags.Where(d => d.Severity == DiagnosticSeverity.Error || analyzer.SupportedDiagnostics.Any(s => s.Id.Equals(d.Id))) .ToImmutableArray(); foreach (Diagnostic diag in diags) { if (diag.Location == Location.None || diag.Location.IsInMetadata) { diagnostics.Add(diag); } else { foreach (Document document in documents) { SyntaxTree tree = await document.GetSyntaxTreeAsync(); if (tree == diag.Location.SourceTree) { diagnostics.Add(diag); } } } } } return(diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray()); }