コード例 #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":
                        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);
                    }
                }
            }
        }
コード例 #2
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out StatementSyntax statement))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.AddEmptyLineAfterLastStatementInDoStatement:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Add empty line",
                        cancellationToken =>
                        {
                            return(AddEmptyLineAfterLastStatementInDoStatementRefactoring.RefactorAsync(
                                       context.Document,
                                       statement,
                                       cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.InlineLazyInitialization:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Inline lazy initialization",
                        cancellationToken =>
                        {
                            return(InlineLazyInitializationRefactoring.RefactorAsync(
                                       context.Document,
                                       (IfStatementSyntax)statement,
                                       cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.RemoveRedundantDisposeOrCloseCall:
                {
                    var expressionStatement = (ExpressionStatementSyntax)statement;
                    var invocation          = (InvocationExpressionSyntax)expressionStatement.Expression;
                    var memberAccess        = (MemberAccessExpressionSyntax)invocation.Expression;

                    CodeAction codeAction = CodeAction.Create(
                        $"Remove redundant '{memberAccess.Name?.Identifier.ValueText}' call",
                        cancellationToken => RemoveRedundantDisposeOrCloseCallRefactoring.RefactorAsync(context.Document, expressionStatement, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.RemoveRedundantStatement:
                {
                    CodeAction codeAction = CodeAction.Create(
                        $"Remove redundant {CSharpFacts.GetTitle(statement)}",
                        cancellationToken => RemoveRedundantStatementRefactoring.RefactorAsync(context.Document, statement, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UseMethodChaining:
                {
                    var expressionStatement = (ExpressionStatementSyntax)statement;

                    UseMethodChainingAnalysis analysis;
                    if (expressionStatement.Expression.Kind() == SyntaxKind.InvocationExpression)
                    {
                        analysis = UseMethodChainingAnalysis.WithoutAssignmentAnalysis;
                    }
                    else
                    {
                        analysis = UseMethodChainingAnalysis.WithAssignmentAnalysis;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Use method chaining",
                        cancellationToken => UseMethodChainingRefactoring.RefactorAsync(context.Document, analysis, expressionStatement, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }