예제 #1
0
        private void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            ExpressionSyntax expression = invocation.Expression;

            if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                ArgumentListSyntax argumentList = invocation.ArgumentList;

                if (argumentList?.IsMissing == false)
                {
                    int argumentCount = argumentList.Arguments.Count;

                    string methodName = memberAccess.Name?.Identifier.ValueText;

                    if (argumentCount == 0)
                    {
                        switch (methodName)
                        {
                        case "Any":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            UseCountOrLengthPropertyInsteadOfAnyMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Cast":
                        {
                            CallOfTypeInsteadOfWhereAndCastRefactoring.Analyze(context, invocation);
                            break;
                        }

                        case "Count":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            UseInsteadOfCountMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "First":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            UseElementAccessInsteadOfFirstRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "FirstOrDefault":
                        case "Last":
                        case "LastOrDefault":
                        case "LongCount":
                        case "Single":
                        case "SingleOrDefault":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            break;
                        }
                        }
                    }
                    else if (argumentCount == 1)
                    {
                        switch (methodName)
                        {
                        case "ElementAt":
                        {
                            UseElementAccessInsteadOfElementAtRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "FirstOrDefault":
                        {
                            CallFindMethodInsteadOfFirstOrDefaultMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Select":
                        {
                            UseCastMethodInsteadOfSelectMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Where":
                        {
                            CombineEnumerableWhereMethodChainRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }
                        }
                    }
                }
            }

            if (UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.CanRefactor(invocation, context.SemanticModel, context.CancellationToken))
            {
                context.ReportDiagnostic(DiagnosticDescriptors.UseBitwiseOperationInsteadOfCallingHasFlag, invocation);
            }

            RemoveRedundantToStringCallRefactoring.Analyze(context, invocation);

            RemoveRedundantStringToCharArrayCallRefactoring.Analyze(context, invocation);
        }
        private void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            ExpressionSyntax expression = invocation.Expression;

            if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                ArgumentListSyntax argumentList = invocation.ArgumentList;

                if (argumentList?.IsMissing == false)
                {
                    int argumentCount = argumentList.Arguments.Count;

                    string methodName = memberAccess.Name?.Identifier.ValueText;

                    if (argumentCount == 0)
                    {
                        switch (methodName)
                        {
                        case "Any":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            UseCountOrLengthPropertyInsteadOfAnyMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Cast":
                        {
                            CallOfTypeInsteadOfWhereAndCastRefactoring.Analyze(context, invocation);
                            break;
                        }

                        case "Count":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            UseInsteadOfCountMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "First":
                        case "FirstOrDefault":
                        case "Last":
                        case "LastOrDefault":
                        case "LongCount":
                        case "Single":
                        case "SingleOrDefault":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            break;
                        }
                        }
                    }
                    else if (argumentCount == 1)
                    {
                        switch (methodName)
                        {
                        case "FirstOrDefault":
                        {
                            CallFindInsteadOfFirstOrDefaultRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Where":
                        {
                            CombineEnumerableWhereMethodChainRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }
                        }
                    }
                }
            }

            if (UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.CanRefactor(invocation, context.SemanticModel, context.CancellationToken) &&
                !invocation.SpanContainsDirectives())
            {
                context.ReportDiagnostic(DiagnosticDescriptors.UseBitwiseOperationInsteadOfCallingHasFlag, invocation);
            }

            RemoveRedundantStringToCharArrayCallRefactoring.Analyze(context, invocation);

            CombineEnumerableWhereAndAnyRefactoring.AnalyzeInvocationExpression(context);

            if (!invocation.ContainsDiagnostics)
            {
                if (!invocation.SpanContainsDirectives())
                {
                    CallExtensionMethodAsInstanceMethodRefactoring.AnalysisResult result =
                        CallExtensionMethodAsInstanceMethodRefactoring.Analyze(invocation, context.SemanticModel, context.CancellationToken);

                    if (result.Success &&
                        context.SemanticModel
                        .GetEnclosingNamedType(result.InvocationExpression.SpanStart, context.CancellationToken)?
                        .Equals(result.MethodSymbol.ContainingType) == false)
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.CallExtensionMethodAsInstanceMethod, invocation);
                    }
                }

                MemberInvocationExpression memberInvocation;
                if (MemberInvocationExpression.TryCreate(invocation, out memberInvocation))
                {
                    if (!invocation.SpanContainsDirectives())
                    {
                        UseRegexInstanceInsteadOfStaticMethodRefactoring.Analyze(context, memberInvocation);
                    }

                    string methodName = memberInvocation.NameText;

                    AvoidNullReferenceExceptionRefactoring.Analyze(context, memberInvocation);

                    int argumentCount = memberInvocation.ArgumentList.Arguments.Count;

                    switch (argumentCount)
                    {
                    case 0:
                        {
                            switch (methodName)
                            {
                            case "First":
                            {
                                if (!memberInvocation.Expression.IsKind(SyntaxKind.InvocationExpression) &&
                                    UseElementAccessInsteadOfFirstRefactoring.CanRefactor(memberInvocation, context.SemanticModel, context.CancellationToken))
                                {
                                    context.ReportDiagnostic(DiagnosticDescriptors.UseElementAccessInsteadOfFirst, memberInvocation.Name);
                                }

                                break;
                            }

                            case "ToString":
                            {
                                RemoveRedundantToStringCallRefactoring.Analyze(context, memberInvocation);
                                break;
                            }
                            }

                            break;
                        }

                    case 1:
                    {
                        switch (methodName)
                        {
                        case "ElementAt":
                        {
                            if (!memberInvocation.Expression.IsKind(SyntaxKind.InvocationExpression) &&
                                UseElementAccessInsteadOfElementAtRefactoring.CanRefactor(memberInvocation, context.SemanticModel, context.CancellationToken))
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.UseElementAccessInsteadOfElementAt, memberInvocation.Name);
                            }

                            break;
                        }
                        }

                        break;
                    }
                    }

                    switch (methodName)
                    {
                    case "Append":
                    case "AppendLine":
                    case "AppendFormat":
                    case "Insert":
                    {
                        OptimizeStringBuilderAppendCallRefactoring.Analyze(context, memberInvocation);
                        break;
                    }

                    case "Select":
                    {
                        if (argumentCount == 1 ||
                            argumentCount == 2)
                        {
                            CallCastInsteadOfSelectRefactoring.Analyze(context, memberInvocation);
                        }

                        break;
                    }

                    case "OrderBy":
                    case "OrderByDescending":
                    {
                        if (argumentCount == 1 ||
                            argumentCount == 2 ||
                            argumentCount == 3)
                        {
                            CallThenByInsteadOfOrderByRefactoring.Analyze(context, memberInvocation);
                        }

                        break;
                    }
                    }

                    if (UseMethodChainingRefactoring.IsFixable(memberInvocation, context.SemanticModel, context.CancellationToken))
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.UseMethodChaining, memberInvocation.InvocationExpression);
                    }
                }
            }
        }
예제 #3
0
        private void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            if (GeneratedCodeAnalyzer?.IsGeneratedCode(context) == true)
            {
                return;
            }

            var invocation = (InvocationExpressionSyntax)context.Node;

            ExpressionSyntax expression = invocation.Expression;

            if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                ArgumentListSyntax argumentList = invocation.ArgumentList;

                if (argumentList?.IsMissing == false)
                {
                    int argumentCount = argumentList.Arguments.Count;

                    string methodName = memberAccess.Name?.Identifier.ValueText;

                    if (argumentCount == 0)
                    {
                        switch (methodName)
                        {
                        case "Any":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            ReplaceAnyMethodWithCountOrLengthPropertyRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Cast":
                        {
                            ReplaceWhereAndCastWithOfTypeRefactoring.Analyze(context, invocation);
                            break;
                        }

                        case "Count":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            ReplaceCountMethodRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "First":
                        case "FirstOrDefault":
                        case "Last":
                        case "LastOrDefault":
                        case "LongCount":
                        case "Single":
                        case "SingleOrDefault":
                        {
                            SimplifyLinqMethodChainRefactoring.Analyze(context, invocation, memberAccess, methodName);
                            break;
                        }
                        }
                    }
                    else if (argumentCount == 1)
                    {
                        switch (methodName)
                        {
                        case "Select":
                        {
                            ReplaceSelectWithCastRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }

                        case "Where":
                        {
                            CombineEnumerableWhereMethodChainRefactoring.Analyze(context, invocation, memberAccess);
                            break;
                        }
                        }
                    }
                }
            }

            if (ReplaceHasFlagWithBitwiseOperationRefactoring.CanRefactor(invocation, context.SemanticModel, context.CancellationToken))
            {
                context.ReportDiagnostic(
                    DiagnosticDescriptors.UseBitwiseOperationInsteadOfHasFlagMethod,
                    invocation.GetLocation());
            }

            if (RemoveRedundantToStringCallRefactoring.CanRefactor(invocation, context.SemanticModel, context.CancellationToken))
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                TextSpan span = TextSpan.FromBounds(memberAccess.OperatorToken.Span.Start, invocation.Span.End);

                if (!invocation.ContainsDirectives(span))
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.RemoveRedundantToStringCall,
                        Location.Create(invocation.SyntaxTree, span));
                }
            }

            if (RemoveRedundantStringToCharArrayCallRefactoring.CanRefactor(invocation, context.SemanticModel, context.CancellationToken))
            {
                var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression;

                TextSpan span = TextSpan.FromBounds(memberAccess.OperatorToken.Span.Start, invocation.Span.End);

                if (!invocation.ContainsDirectives(span))
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.RemoveRedundantStringToCharArrayCall,
                        Location.Create(invocation.SyntaxTree, span));
                }
            }
        }