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 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 MarkupTestFile.GetPositionAndSpans(markup, out var source, out var pos, out IDictionary <string, ImmutableArray <TextSpan> > 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)); } } } }
public CompilationAnalyzer( Compilation compilation, INamedTypeSymbol suppressMessageAttributeType ) { _state = new SuppressMessageAttributeState( compilation, suppressMessageAttributeType ); }
public void TestResolveEnumFieldWithoutName() { var source = @" enum E { $$, } "; var syntaxTree = CreateSyntaxTree(source, LanguageNames.CSharp); var compilation = CreateCompilation(syntaxTree, LanguageNames.CSharp, ""); _ = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, "E.", SuppressMessageAttributeState.TargetScope.Member); }
/// <summary> /// Gets the <see cref="SuppressionInfo"/> for suppressed diagnostics, i.e. <see cref="IsSuppressed"/> = true. /// Otherwise, returns null. /// </summary> public SuppressionInfo GetSuppressionInfo(Compilation compilation) { if (!IsSuppressed) { return(null); } SuppressMessageAttributeState suppressMessageState = new SuppressMessageAttributeState(compilation); if (!suppressMessageState.IsDiagnosticSuppressed(this, out AttributeData attribute)) { attribute = null; } return(new SuppressionInfo(this.Id, attribute)); }
public void AnalyzeAssemblyOrModuleAttribute(SyntaxNode attributeSyntax, SemanticModel model, Action <Diagnostic> reportDiagnostic, CancellationToken cancellationToken) { if (!_state.IsSuppressMessageAttributeWithNamedArguments(attributeSyntax, model, cancellationToken, out var namedAttributeArguments)) { return; } if (!SuppressMessageAttributeState.HasValidScope(namedAttributeArguments, out var targetScope)) { reportDiagnostic(Diagnostic.Create(s_invalidScopeDescriptor, attributeSyntax.GetLocation())); return; } if (!_state.HasValidTarget(namedAttributeArguments, targetScope, out var targetHasDocCommentIdFormat, out var targetSymbolString, out var targetValueOperation, out var resolvedSymbols)) { reportDiagnostic(Diagnostic.Create(s_invalidOrMissingTargetDescriptor, attributeSyntax.GetLocation())); return; } // We want to flag valid target which uses legacy format to update to Roslyn based DocCommentId format. if (resolvedSymbols.Length > 0 && !targetHasDocCommentIdFormat) { RoslynDebug.Assert(!string.IsNullOrEmpty(targetSymbolString)); RoslynDebug.Assert(targetValueOperation != null); var properties = ImmutableDictionary <string, string?> .Empty; if (resolvedSymbols.Length == 1) { // We provide a code fix for the case where the target resolved to a single symbol. var docCommentId = DocumentationCommentId.CreateDeclarationId(resolvedSymbols[0]); if (!string.IsNullOrEmpty(docCommentId)) { // Suppression target has an optional "~" prefix to distinguish it from legacy FxCop suppressions. // IDE suppression code fixes emit this prefix, so we we also add this prefix to new suppression target string. properties = properties.Add(DocCommentIdKey, "~" + docCommentId); } } reportDiagnostic(Diagnostic.Create(LegacyFormatTargetDescriptor, targetValueOperation.Syntax.GetLocation(), properties !, targetSymbolString)); return; } }
public SuppressionInfo?GetSuppressionInfo(Compilation compilation) { if (!IsSuppressed) { return(null); } AttributeData?attribute; var suppressMessageState = new SuppressMessageAttributeState(compilation); if (!suppressMessageState.IsDiagnosticSuppressed( this, getSemanticModel: (compilation, tree) => compilation.GetSemanticModel(tree), out attribute)) { attribute = null; } return(new SuppressionInfo(this.Id, attribute)); }
public void AnalyzeAssemblyOrModuleAttribute(SyntaxNode attributeSyntax, SemanticModel model, Action <Diagnostic> reportDiagnostic, CancellationToken cancellationToken) { if (!_state.IsSuppressMessageAttributeWithNamedArguments(attributeSyntax, model, cancellationToken, out var namedAttributeArguments)) { return; } DiagnosticDescriptor rule; if (SuppressMessageAttributeState.HasInvalidScope(namedAttributeArguments, out var targetScope)) { rule = s_invalidScopeDescriptor; } else if (_state.HasInvalidOrMissingTarget(namedAttributeArguments, targetScope)) { rule = s_invalidOrMissingTargetDescriptor; } else { return; } reportDiagnostic(Diagnostic.Create(rule, attributeSyntax.GetLocation())); }