/// <summary> /// Given a set of compiler or <see cref="DiagnosticAnalyzer"/> generated <paramref name="diagnostics"/>, returns the effective diagnostics after applying the below filters: /// 1) <see cref="CompilationOptions.SpecificDiagnosticOptions"/> specified for the given <paramref name="compilation"/>. /// 2) <see cref="CompilationOptions.GeneralDiagnosticOption"/> specified for the given <paramref name="compilation"/>. /// 3) Diagnostic suppression through applied <see cref="System.Diagnostics.CodeAnalysis.SuppressMessageAttribute"/>. /// 4) Pragma directives for the given <paramref name="compilation"/>. /// </summary> public static IEnumerable<Diagnostic> GetEffectiveDiagnostics(IEnumerable<Diagnostic> diagnostics, Compilation compilation) { if (diagnostics == null) { throw new ArgumentNullException(nameof(diagnostics)); } if (compilation == null) { throw new ArgumentNullException(nameof(compilation)); } var suppressMessageState = new SuppressMessageAttributeState(compilation); foreach (var diagnostic in diagnostics.ToImmutableArray()) { if (diagnostic != null) { var effectiveDiagnostic = compilation.Options.FilterDiagnostic(diagnostic); if (effectiveDiagnostic != null) { effectiveDiagnostic = suppressMessageState.ApplySourceSuppressions(effectiveDiagnostic); yield return effectiveDiagnostic; } } } }
private static IEnumerable<Diagnostic> GetEffectiveDiagnosticsImpl(ImmutableArray<Diagnostic> diagnostics, Compilation compilation) { var suppressMessageState = new SuppressMessageAttributeState(compilation); foreach (var diagnostic in diagnostics) { if (diagnostic != null) { var effectiveDiagnostic = compilation.Options.FilterDiagnostic(diagnostic); if (effectiveDiagnostic != null) { yield return suppressMessageState.ApplySourceSuppressions(effectiveDiagnostic); } } } }
private static void VerifyNoResolution(string source, string[] fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope scope, string language, string rootNamespace) { var compilation = CreateCompilation(source, language, rootNamespace); foreach (var fxCopName in fxCopFullyQualifiedNames) { var symbols = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, fxCopName, scope); Assert.True(symbols.FirstOrDefault() == null, string.Format("Did not expect FxCop fully-qualified name '{0}' to resolve to any symbol: resolved to:\r\n{1}", fxCopName, string.Join("\r\n", symbols))); } }
private ImmutableArray<Diagnostic> FilterDiagnosticsSuppressedInSource(ImmutableArray<Diagnostic> diagnostics, Compilation compilation, SuppressMessageAttributeState suppressMessageState) { if (diagnostics.IsEmpty) { return diagnostics; } var reportSuppressedDiagnostics = compilation.Options.ReportSuppressedDiagnostics; var builder = ImmutableArray.CreateBuilder<Diagnostic>(); for (var i = 0; i < diagnostics.Length; i++) { #if DEBUG // We should have ignored diagnostics with invalid locations and reported analyzer exception diagnostic for the same. DiagnosticAnalysisContextHelpers.VerifyDiagnosticLocationsInCompilation(diagnostics[i], compilation); #endif var diagnostic = suppressMessageState.ApplySourceSuppressions(diagnostics[i]); if (!reportSuppressedDiagnostics && diagnostic.IsSuppressed) { // Diagnostic suppressed in source. continue; } builder.Add(diagnostic); } return builder.ToImmutable(); }
private static void VerifyResolution(string markup, string[] fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope scope, string language, string rootNamespace) { // Parse out the span containing the declaration of the expected symbol string source; int? pos; IDictionary<string, IList<TextSpan>> spans; MarkupTestFile.GetPositionAndSpans(markup, out source, out pos, out spans); Assert.True(pos != null || spans.Count > 0, "Must specify a position or spans marking expected symbols for resolution"); // Get the expected symbol from the given position var syntaxTree = CreateSyntaxTree(source, language); var compilation = CreateCompilation(syntaxTree, language, rootNamespace); var model = compilation.GetSemanticModel(syntaxTree); var expectedSymbols = new List<ISymbol>(); bool shouldResolveSingleSymbol = pos != null; if (shouldResolveSingleSymbol) { expectedSymbols.Add(GetSymbolAtPosition(model, pos.Value)); } else { foreach (var span in spans.Values.First()) { expectedSymbols.Add(GetSymbolAtPosition(model, span.Start)); } } // Resolve the symbol based on each given FxCop fully-qualified name foreach (var fxCopName in fxCopFullyQualifiedNames) { var symbols = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, fxCopName, scope); if (shouldResolveSingleSymbol) { var expectedSymbol = expectedSymbols.Single(); if (symbols.Count() > 1) { Assert.True(false, string.Format("Expected to resolve FxCop fully-qualified name '{0}' to '{1}': got multiple symbols:\r\n{2}", fxCopName, expectedSymbol, string.Join("\r\n", symbols))); } var symbol = symbols.SingleOrDefault(); Assert.True(expectedSymbol == symbol, string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbol '{1}': got '{2}'", fxCopName, expectedSymbol, symbol)); } else { foreach (var symbol in symbols) { Assert.True(expectedSymbols.Contains(symbol), string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbols:\r\n{1}\r\nResolved to unexpected symbol '{2}'", fxCopName, string.Join("\r\n", expectedSymbols), symbol)); } } } }