private static void Analyze( SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo, ArgumentSyntax argument) { if (!(argument.Parent is ArgumentListSyntax argumentList)) { return; } SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments; if (arguments.Count != 2) { return; } SimpleMemberInvocationExpressionInfo equalsInvocation = SyntaxInfo.SimpleMemberInvocationExpressionInfo(argumentList.Parent); if (!equalsInvocation.Success) { return; } if (equalsInvocation.NameText != "Equals") { return; } if (!IsFixable(context, invocationInfo, argument, arguments)) { return; } IMethodSymbol methodSymbol = context.SemanticModel.GetMethodSymbol(equalsInvocation.InvocationExpression, context.CancellationToken); if (!SymbolUtility.IsPublicStaticNonGeneric(methodSymbol, "Equals")) { return; } if (!methodSymbol.IsContainingType(SpecialType.System_String)) { return; } if (!methodSymbol.IsReturnType(SpecialType.System_Boolean)) { return; } if (!methodSymbol.HasTwoParameters(SpecialType.System_String, SpecialType.System_String)) { return; } ReportDiagnostic(context, equalsInvocation); }
public static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context) { var invocation = (InvocationExpressionSyntax)context.Node; ExpressionSyntax expression = invocation.Expression; if (expression == null) { return; } if (invocation.SpanContainsDirectives()) { return; } ArgumentListSyntax argumentList = invocation.ArgumentList; if (argumentList == null) { return; } SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments; if (arguments.Count < 1 || arguments.Count > 3) { return; } if (arguments[0].Expression?.Kind() != SyntaxKind.FalseLiteralExpression) { return; } IMethodSymbol methodSymbol = context.SemanticModel.GetMethodSymbol(invocation, context.CancellationToken); if (!SymbolUtility.IsPublicStaticNonGeneric(methodSymbol, "Assert")) { return; } if (methodSymbol.ContainingType?.HasMetadataName(MetadataNames.System_Diagnostics_Debug) != true) { return; } if (!methodSymbol.ReturnsVoid) { return; } ImmutableArray <IParameterSymbol> assertParameters = methodSymbol.Parameters; int length = assertParameters.Length; if (assertParameters[0].Type.SpecialType != SpecialType.System_Boolean) { return; } for (int i = 1; i < length; i++) { if (assertParameters[i].Type.SpecialType != SpecialType.System_String) { return; } } if (!ContainsFailMethod()) { return; } if (expression.Kind() != SyntaxKind.SimpleMemberAccessExpression && context.SemanticModel.GetSpeculativeMethodSymbol(invocation.SpanStart, GetNewInvocation(invocation))? .ContainingType? .HasMetadataName(MetadataNames.System_Diagnostics_Debug) != true) { return; } if (expression.Kind() == SyntaxKind.SimpleMemberAccessExpression) { expression = ((MemberAccessExpressionSyntax)expression).Name; } Debug.Assert(expression.Kind() == SyntaxKind.IdentifierName, expression.Kind().ToString()); DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.CallDebugFailInsteadOfDebugAssert, expression); bool ContainsFailMethod() { foreach (ISymbol symbol in methodSymbol.ContainingType.GetMembers("Fail")) { if (symbol is IMethodSymbol failMethodSymbol && SymbolUtility.IsPublicStaticNonGeneric(failMethodSymbol) && failMethodSymbol.ReturnsVoid) { ImmutableArray <IParameterSymbol> failParameters = failMethodSymbol.Parameters; if (failParameters.Length == ((length == 1) ? 1 : length - 1) && failParameters.All(f => f.Type.SpecialType == SpecialType.System_String)) { return(true); } } } return(false); } }
internal static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo) { if (!ValidateMethodNameAndArgumentCount()) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocationInfo.InvocationExpression, cancellationToken); if (!SymbolUtility.IsPublicStaticNonGeneric(methodSymbol)) { return; } if (methodSymbol.ContainingType?.Equals(context.GetTypeByMetadataName(MetadataNames.System_Text_RegularExpressions_Regex)) != true) { return; } SeparatedSyntaxList <ArgumentSyntax> arguments = invocationInfo.Arguments; if (!ValidateArgument(arguments[1])) { return; } if (methodSymbol.Name == "Replace") { if (arguments.Count == 4 && !ValidateArgument(arguments[3])) { return; } } else if (arguments.Count == 3 && !ValidateArgument(arguments[2])) { return; } context.ReportDiagnostic(DiagnosticDescriptors.UseRegexInstanceInsteadOfStaticMethod, invocationInfo.Name); bool ValidateMethodNameAndArgumentCount() { switch (invocationInfo.NameText) { case "IsMatch": case "Match": case "Matches": case "Split": { int count = invocationInfo.Arguments.Count; return(count >= 2 && count <= 3); } case "Replace": { int count = invocationInfo.Arguments.Count; return(count >= 3 && count <= 4); } } return(false); } bool ValidateArgument(ArgumentSyntax argument) { ExpressionSyntax expression = argument.Expression; if (expression == null) { return(false); } if (expression.WalkDownParentheses() is LiteralExpressionSyntax) { return(true); } if (!semanticModel.HasConstantValue(expression, cancellationToken)) { return(false); } ISymbol symbol = semanticModel.GetSymbol(expression, cancellationToken); Debug.Assert(symbol != null); if (symbol == null) { return(true); } switch (symbol.Kind) { case SymbolKind.Field: { return(((IFieldSymbol)symbol).HasConstantValue); } case SymbolKind.Method: { if (((IMethodSymbol)symbol).MethodKind != MethodKind.BuiltinOperator) { return(false); } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken); if (typeSymbol == null) { return(false); } return(typeSymbol.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_RegularExpressions_RegexOptions))); } default: { return(false); } } } }
public static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo) { InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression; ArgumentSyntax firstArgument = invocationInfo.Arguments.FirstOrDefault(); if (firstArgument == null) { return; } if (invocationInfo.NameText != "Join") { return; } if (invocationInfo.MemberAccessExpression.SpanOrTrailingTriviaContainsDirectives() || invocationInfo.ArgumentList.OpenParenToken.ContainsDirectives || firstArgument.ContainsDirectives) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocation, cancellationToken); if (!SymbolUtility.IsPublicStaticNonGeneric(methodSymbol, "Join")) { return; } if (methodSymbol.ContainingType?.SpecialType != SpecialType.System_String) { return; } if (!methodSymbol.IsReturnType(SpecialType.System_String)) { return; } ImmutableArray <IParameterSymbol> parameters = methodSymbol.Parameters; if (parameters.Length != 2) { return; } if (parameters[0].Type.SpecialType != SpecialType.System_String) { return; } if (!parameters[1].IsParameterArrayOf(SpecialType.System_String, SpecialType.System_Object) && !parameters[1].Type.OriginalDefinition.IsIEnumerableOfT()) { return; } if (firstArgument.Expression == null) { return; } if (!CSharpUtility.IsEmptyStringExpression(firstArgument.Expression, semanticModel, cancellationToken)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.CallStringConcatInsteadOfStringJoin, invocationInfo.Name); }