/// <summary> /// Check the solution for compiler errors and warnings, uses: /// </summary> public static async Task NoCompilerErrorsAsync(Solution solution, IReadOnlyList <string> allowedIds, AllowedDiagnostics allowedDiagnostics) { var diagnostics = await Analyze.GetDiagnosticsAsync(solution).ConfigureAwait(false); var introducedDiagnostics = diagnostics .SelectMany(x => x) .Where(x => IsIncluded(x, allowedDiagnostics)) .ToArray(); if (introducedDiagnostics.Select(x => x.Id) .Except(allowedIds ?? Enumerable.Empty <string>()) .Any()) { var error = StringBuilderPool.Borrow(); error.AppendLine($"Found error{(introducedDiagnostics.Length > 1 ? "s" : string.Empty)}."); foreach (var introducedDiagnostic in introducedDiagnostics) { var errorInfo = await introducedDiagnostic.ToStringAsync(solution).ConfigureAwait(false); error.AppendLine($"{errorInfo}"); } throw AssertException.Create(StringBuilderPool.Return(error)); } }
private static async Task AssertNoCompilerErrorsAsync(CodeFixProvider codeFix, Solution fixedSolution) { var diagnostics = await Analyze.GetDiagnosticsAsync(fixedSolution).ConfigureAwait(false); var introducedDiagnostics = diagnostics .SelectMany(x => x) .Where(IsIncluded) .ToArray(); if (introducedDiagnostics.Select(x => x.Id) .Except(DiagnosticSettings.AllowedErrorIds()) .Any()) { var errorBuilder = StringBuilderPool.Borrow(); errorBuilder.AppendLine($"{codeFix} introduced syntax error{(introducedDiagnostics.Length > 1 ? "s" : string.Empty)}."); foreach (var introducedDiagnostic in introducedDiagnostics) { var errorInfo = await introducedDiagnostic.ToStringAsync(fixedSolution).ConfigureAwait(false); errorBuilder.AppendLine($"{errorInfo}"); } errorBuilder.AppendLine("First source file with error is:"); var sources = await Task.WhenAll(fixedSolution.Projects.SelectMany(p => p.Documents).Select(d => CodeReader.GetStringFromDocumentAsync(d, Formatter.Annotation, CancellationToken.None))); var lineSpan = introducedDiagnostics.First().Location.GetMappedLineSpan(); var match = sources.SingleOrDefault(x => CodeReader.FileName(x) == lineSpan.Path); errorBuilder.Append(match); errorBuilder.AppendLine(); throw AssertException.Create(errorBuilder.Return()); } }
/// <summary> /// Verifies that <paramref name="code"/> produces no diagnostics when analyzed with <paramref name="analyzer"/>. /// </summary> /// <param name="analyzer">The analyzer.</param> /// <param name="code"> /// The code to create the solution from. /// Can be a .cs, .csproj or .sln file /// </param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/> to use.</param> /// <param name="metadataReferences">The metadata references to use when compiling.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task ValidAsync(DiagnosticAnalyzer analyzer, FileInfo code, CSharpCompilationOptions compilationOptions, IReadOnlyList <MetadataReference> metadataReferences) { var diagnostics = await Analyze.GetDiagnosticsAsync(analyzer, code, compilationOptions, metadataReferences) .ConfigureAwait(false); if (diagnostics.SelectMany(x => x).Any()) { throw AssertException.Create(string.Join(Environment.NewLine, diagnostics.SelectMany(x => x))); } }
/// <summary> /// Verifies that <paramref name="solution"/> produces no diagnostics when analyzed with <paramref name="analyzer"/>. /// </summary> /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/>.</param> /// <param name="solution">The <see cref="Solution"/> for which no errors or warnings are expected.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task ValidAsync(DiagnosticAnalyzer analyzer, Solution solution) { var diagnostics = await Analyze.GetDiagnosticsAsync(solution, analyzer) .ConfigureAwait(false); if (diagnostics.SelectMany(x => x).Any()) { throw AssertException.Create(string.Join(Environment.NewLine, diagnostics.SelectMany(x => x))); } }
private static async Task VerifyNoCompilerErrorsAsync(CodeFixProvider fix, Solution fixedSolution) { var diagnostics = await Analyze.GetDiagnosticsAsync(fixedSolution).ConfigureAwait(false); var introducedDiagnostics = diagnostics .SelectMany(x => x) .Where(IsIncluded) .ToArray(); if (introducedDiagnostics.Select(x => x.Id) #pragma warning disable CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() .Except(SuppressedDiagnostics) #pragma warning restore CS0618 // Suppress until removed. Will be replaced with Metadatareferences.FromAttributes() .Any()) { var errorBuilder = StringBuilderPool.Borrow(); errorBuilder.AppendLine($"{fix.GetType().Name} introduced syntax error{(introducedDiagnostics.Length > 1 ? "s" : string.Empty)}."); foreach (var introducedDiagnostic in introducedDiagnostics) { errorBuilder.AppendLine($"{introducedDiagnostic.ToErrorString()}"); } var sources = await Task.WhenAll(fixedSolution.Projects.SelectMany(p => p.Documents).Select(d => CodeReader.GetStringFromDocumentAsync(d, CancellationToken.None))); errorBuilder.AppendLine("First source file with error is:"); var lineSpan = introducedDiagnostics.First().Location.GetMappedLineSpan(); if (sources.TrySingle(x => CodeReader.FileName(x) == lineSpan.Path, out var match)) { errorBuilder.AppendLine(match); } else if (sources.TryFirst(x => CodeReader.FileName(x) == lineSpan.Path, out _)) { errorBuilder.AppendLine($"Found more than one document for {lineSpan.Path}."); foreach (string source in sources.Where(x => CodeReader.FileName(x) == lineSpan.Path)) { errorBuilder.AppendLine(source); } } else { errorBuilder.AppendLine($"Did not find a single document for {lineSpan.Path}."); } throw new AssertException(errorBuilder.Return()); } }
/// <summary> /// Creates a new instance of the <see cref="Benchmark"/> class. /// </summary> public static async Task <Benchmark> CreateAsync(Project project, DiagnosticAnalyzer analyzer) { var benchmarkAnalyzer = new BenchmarkAnalyzer(analyzer); await Analyze.GetDiagnosticsAsync(project, benchmarkAnalyzer).ConfigureAwait(false); return(new Benchmark( analyzer, benchmarkAnalyzer.SyntaxNodeActions, benchmarkAnalyzer.CompilationStartActions, benchmarkAnalyzer.CompilationActions, benchmarkAnalyzer.SemanticModelActions, benchmarkAnalyzer.SymbolActions, benchmarkAnalyzer.CodeBlockStartActions, benchmarkAnalyzer.CodeBlockActions, benchmarkAnalyzer.SyntaxTreeActions, benchmarkAnalyzer.OperationActions, benchmarkAnalyzer.OperationBlockActions, benchmarkAnalyzer.OperationBlockStartActions)); }
/// <summary> /// Verifies that <paramref name="code"/> produces no diagnostics when analyzed with <paramref name="analyzer"/>. /// </summary> /// <param name="analyzer">The analyzer.</param> /// <param name="code">The code to analyze.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/> to use.</param> /// <param name="metadataReferences">The metadata references to use when compiling.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task ValidAsync(DiagnosticAnalyzer analyzer, IReadOnlyList <string> code, CSharpCompilationOptions compilationOptions, IReadOnlyList <MetadataReference> metadataReferences) { var diagnostics = await Analyze.GetDiagnosticsAsync( analyzer, code, compilationOptions, metadataReferences) .ConfigureAwait(false); if (diagnostics.SelectMany(x => x).Any()) { var builder = StringBuilderPool.Borrow().AppendLine("Expected no diagnostics, found:"); foreach (var diagnostic in diagnostics.SelectMany(x => x)) { builder.AppendLine(diagnostic.ToString(code)); } throw AssertException.Create(builder.Return()); } }