private static bool ParentDeclarationIsNotConstant(LiteralExpressionSyntax syntax) { LocalDeclarationStatementSyntax localDeclaration = null; var fieldDeclaration = syntax.Ancestors() .OfType <FieldDeclarationSyntax>() .FirstOrDefault(x => x.Modifiers.Any(SyntaxKind.ConstKeyword)); if (fieldDeclaration == null) { localDeclaration = syntax.Ancestors() .OfType <LocalDeclarationStatementSyntax>() .FirstOrDefault(x => x.Modifiers.Any(SyntaxKind.ConstKeyword)); } return(fieldDeclaration == null && localDeclaration == null); }
private static SyntaxNode GetEnclosingMember(LiteralExpressionSyntax literal) { foreach (var ancestor in literal.Ancestors()) { switch (ancestor.Kind()) { case SyntaxKind.ParenthesizedLambdaExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.VariableDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.LocalFunctionStatement: return(ancestor); } } return(null); }
public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction( c => { LiteralExpressionSyntax literalNode = (LiteralExpressionSyntax)c.Node; if (!literalNode.IsPartOfStructuredTrivia() && !literalNode.Ancestors().Any(e => e.IsKind(SyntaxKind.VariableDeclarator) || e.IsKind(SyntaxKind.EnumDeclaration) || e.IsKind(SyntaxKind.Attribute)) && !Exceptions.Contains(literalNode.Token.Text)) { c.ReportDiagnostic(Diagnostic.Create(Rule, literalNode.GetLocation())); } }, SyntaxKind.NumericLiteralExpression); }
private static SyntaxNode GetEnclosingMember(LiteralExpressionSyntax literal) { foreach (var ancestor in literal.Ancestors()) { if (ancestor.IsKind(SyntaxKind.ParenthesizedLambdaExpression)) { return(null); } else if (ancestor.IsAnyKind(PossibleEnclosingSyntax)) { return(ancestor); } else { // do nothing } } return(null); }
private static SyntaxNode GetEnclosingMember(LiteralExpressionSyntax literal) { foreach (var ancestor in literal.Ancestors()) { switch (ancestor.Kind()) { case SyntaxKind.MultiLineFunctionLambdaExpression: case SyntaxKind.SingleLineFunctionLambdaExpression: return(null); case SyntaxKind.VariableDeclarator: case SyntaxKind.PropertyBlock: case SyntaxKind.FunctionBlock: return(ancestor); default: // do nothing break; } } return(null); }
private static bool IsNoCandidateDiagnostic(LiteralExpressionSyntax literal) { return(literal.ToString() != "\"\"" || literal.Ancestors().OfType <AttributeArgumentSyntax>().Any() || literal.Ancestors().OfType <ParameterListSyntax>().Any()); }
private static bool IsNoCandidateDiagnostic(LiteralExpressionSyntax literal) { return literal.ToString() != "\"\"" || literal.Ancestors().OfType<AttributeArgumentSyntax>().Any() || literal.Ancestors().OfType<ParameterListSyntax>().Any(); }
private static bool InAllowedDeclarationContext(LiteralExpressionSyntax literalExpression, Settings settings) { bool result = literalExpression.Ancestors() .Any(ancestor => { bool allowed = false; switch (ancestor.Kind()) { case SyntaxKind.LocalDeclarationStatement: allowed = ((LocalDeclarationStatementSyntax)ancestor).Modifiers.Any(SyntaxKind.ConstKeyword); break; case SyntaxKind.FieldDeclaration: // Allow any static readonly field to use unnamed numeric literals in expressions because sometimes // arrays of numeric literals are needed (e.g., Crc32Code) or special instances are created (e.g., // Color.FromArgb(225, 255, 255), new DateTime(1970, 1, 1)). Also, allow fields that are set to // single, non-calculated constants. In these cases the field name is good enough documentation. FieldDeclarationSyntax fieldDeclaration = (FieldDeclarationSyntax)ancestor; SyntaxTokenList fieldModifiers = fieldDeclaration.Modifiers; allowed = fieldModifiers.Any(SyntaxKind.ConstKeyword) || (fieldModifiers.Any(SyntaxKind.StaticKeyword) && fieldModifiers.Any(SyntaxKind.ReadOnlyKeyword)) || HasParentChain( literalExpression, SyntaxKind.EqualsValueClause, SyntaxKind.VariableDeclarator, SyntaxKind.VariableDeclaration, SyntaxKind.FieldDeclaration); break; case SyntaxKind.PropertyDeclaration: // Allow property initializers that are set to single, non-calculated constants. The property name is good enough. allowed = HasParentChain(literalExpression, SyntaxKind.EqualsValueClause, SyntaxKind.PropertyDeclaration); break; case SyntaxKind.BracketedArgumentList: // Allow small numeric literals as indexer arguments (e.g., for sequential item access). Since 0, 1, // and 2 are allowed by default, it's common to see other small sequential indexes used too. // Note: ArrayRankSpecifier (e.g., in new string[7]) is a different syntax kind, so this won't allow // magic numbers for array ranks (just indexes). byte indexValue; allowed = HasParentChain(literalExpression, SyntaxKind.Argument, SyntaxKind.BracketedArgumentList) && byte.TryParse(literalExpression.Token.Text, out indexValue); break; case SyntaxKind.EnumMemberDeclaration: case SyntaxKind.AttributeArgument: allowed = true; break; case SyntaxKind.MethodDeclaration: // Unit test methods typically use lots of numeric literals for test cases, and they don't need to be named constants. allowed = IsUnitTestMethod((BaseMethodDeclarationSyntax)ancestor, settings); break; case SyntaxKind.ClassDeclaration: // Unit test classes typically use lots of numeric literals for test cases, and they don't need to be named constants. allowed = IsUnitTestClass((ClassDeclarationSyntax)ancestor, settings); break; case SyntaxKind.InvocationExpression: // Allow cases like item.GetXxx(n) for n in [0,255] to handle cases like IDataRecord.Get and Array.Get accessors. allowed = IsGetIndexInvocation(literalExpression); break; } return(allowed); }); return(result); }
private static bool HasAttributes(LiteralExpressionSyntax literalExpression) => literalExpression.Ancestors().Any(expr => expr.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.Attribute));