public void Contains_WithAttributes_AllAttributesSpecified_Found() { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B"))); var exemptions = new ExemptionCollection(exemption); Assert.True(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B")))); Assert.True(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Parameter", "B"), Tuple.Create("Assembly", "A")))); // order doesn't matter }
public void Contains_WithAttributes_MoreAttributesSpecified_Found() { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B"))); var exemptions = new ExemptionCollection(exemption); Assert.True(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B"), Tuple.Create("Namespace", "C")))); }
public void Contains_WithAttributes_LessAttributesSpecified_NotFound() { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B"))); var exemptions = new ExemptionCollection(exemption); Assert.False(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "A")))); }
public void Contains_WithAttributes_WrongAttributesSpecified_NotFound(string name1, string value1, string name2, string value2) { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"), Tuple.Create("Parameter", "B"))); var exemptions = new ExemptionCollection(exemption); Assert.False(exemptions.Contains("foo", new AttributeCollection(Tuple.Create(name1, value1), Tuple.Create(name2, value2)))); }
public void Contains_WithAttribute_WrongAttributeSpecified_NotFound(string name, string value) { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"))); var exemptions = new ExemptionCollection(exemption); Assert.False(exemptions.Contains("foo", new AttributeCollection(Tuple.Create(name, value)))); }
public void Contains_WithAttribute_AttributeSpecified_Found() { var exemption = Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A"))); var exemptions = new ExemptionCollection(exemption); Assert.True(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "A")))); }
private bool IsLiteralValueExempt(string literal) { if (literal.Length == 1) { return(true); } if (_exemptStrings.Contains(literal, DefaultAttributes)) { return(true); } var braceStack = new Stack <char>(); var isOnlyCharactersWeDontCareAbout = true; for (var i = 0; isOnlyCharactersWeDontCareAbout && (i < literal.Length); ++i) { var isOpenBrace = literal[i] == '{'; var isCloseBrace = literal[i] == '}'; if (isOpenBrace) { braceStack.Push(literal[i]); } if (isCloseBrace && braceStack.Any()) { braceStack.Pop(); } isOnlyCharactersWeDontCareAbout = char.IsDigit(literal, i) || char.IsWhiteSpace(literal, i) || char.IsPunctuation(literal, i) || char.IsSeparator(literal, i) || char.IsControl(literal, i) || char.IsSymbol(literal, i) || literal[i] == '\\' || isOpenBrace || isCloseBrace || (braceStack.Count % 2 != 0 && char.IsLetter(literal, i)); // it's a string formatting character } if (isOnlyCharactersWeDontCareAbout) { return(true); } if (Guid.TryParse(literal, out var guid)) { return(true); } if (Regex.IsMatch(literal, @"^\s*#[\da-fA-F]{2,8}\s*$")) { // It's a color hex code e.g. #FF or #AA0033FF return(true); } return(_exemptStrings.Matches(literal, DefaultAttributes)); }
private bool IsSymbolExempt(ISymbol symbol, ExemptionCollection exemptions, params Tuple <string, string>[] additionalAttributes) { if (symbol == null) { return(false); } var attributes = DefaultAttributes; foreach (var additionalAttribute in additionalAttributes) { attributes.Add(additionalAttribute.Item1, additionalAttribute.Item2); } var symbolName = symbol.GetFullName(); if (exemptions.Contains(symbolName, attributes) || exemptions.Matches(symbolName, attributes)) { return(true); } return(false); }
public void Contains_WithMultiValuedAttribute_WrongValueSpecified_NotFound() { var exemptions = new ExemptionCollection(Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A|B")))); Assert.False(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "D")))); }
public void Contains_WithMultiValuedAttribute_ValueNotSpecified_Found() { var exemptions = new ExemptionCollection(Tuple.Create("foo", new AttributeCollection(Tuple.Create("Assembly", "A|B")))); Assert.True(exemptions.Contains("foo", new AttributeCollection(Tuple.Create("Assembly", "A")))); }
public void Contains_NoAttribute_MixedCase_Found() { var exemptions = new ExemptionCollection("foo"); Assert.True(exemptions.Contains("FOO")); }
/// <summary> /// Determines if a particular file should be analyzed for string literals and, if it should, /// reports each string literal that is not exempt. /// </summary> /// <remarks> /// String literals can be exempt in many ways: /// - The assembly is exempt /// - The file is exempt /// - The scope containing the literal is exempt /// - The invocation using the literal is exempt /// - The literal's value is exempt /// </remarks> /// <param name="context"> /// An object containing the syntax tree and any options for this compilation. /// </param> public void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { SyntaxNode root = context.Tree.GetRoot(context.CancellationToken); SemanticModel semanticModel = _compilation.GetSemanticModel(context.Tree); // Bail out if this file is exempt var currentFilePath = context.Tree.FilePath; if (IsFileExempt(currentFilePath)) { return; } try { // Populate exemptions from attributes on the assembly AddExemptionsFromAttributes(_compilation.Assembly.GetAttributes(), null, semanticModel); // Bail out if the entire assembly is exempt e.g. [assembly: <ExemptAttribute>] if (_exemptAssemblies.Contains(_compilation.AssemblyName) || _exemptAssemblies.Matches(_compilation.AssemblyName)) { return; } // Populate exemptions from attributes decorating syntax AddExemptionsFromAttributes(root.DescendantNodes().OfType <AttributeSyntax>(), semanticModel); // Bail out if there was an attribute indicating that this file is exempt if (IsFileExempt(currentFilePath)) { return; } // Find every string literal and see if it should be reported foreach (StringLiteral literal in StringLiteral.GetStringLiterals(root.DescendantNodes())) { if (IsLiteralValueExempt(literal.Value)) { continue; } if (IsLiteralExemptFromAncestor(literal.Syntax, semanticModel)) { continue; } var diagnostic = Diagnostic.Create(StringsShouldBeInResourcesAnalyzer.Rule, literal.Syntax?.GetLocation(), literal.Value); context.ReportDiagnostic(diagnostic); } } catch (AttributeMissingTargetException ex) { var diagnostic = Diagnostic.Create( StringsShouldBeInResourcesAnalyzer.AttributeMissingTargetRule, Location.None, ex.AttributeName, ex.ScopeName, context.Tree.FilePath); context.ReportDiagnostic(diagnostic); } }
private bool IsFileExempt(string filePath) { return(_exemptFilenames.Contains(filePath) || _exemptFilenames.Matches(filePath)); }