예제 #1
0
        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);
            }
        }
예제 #3
0
        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);
                }
                }
            }
        }
예제 #4
0
        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);
        }