Пример #1
0
        public static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo)
        {
            ExpressionSyntax expression = invocationInfo.InvocationExpression.WalkUpParentheses();

            SyntaxNode parent = expression.Parent;

            SyntaxKind kind = parent.Kind();

            if (kind == SyntaxKind.SimpleMemberAccessExpression)
            {
                SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo(parent.Parent);

                if (!invocationInfo2.Success)
                {
                    return;
                }

                Analyze(context, invocationInfo, invocationInfo2);
            }
            else if (kind == SyntaxKind.Argument)
            {
                Analyze(context, invocationInfo, (ArgumentSyntax)parent);
            }
            else if (kind == SyntaxKind.EqualsExpression ||
                     kind == SyntaxKind.NotEqualsExpression)
            {
                Analyze(context, invocationInfo, expression, (BinaryExpressionSyntax)parent);
            }
        }
Пример #2
0
        public static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo)
        {
            ExpressionSyntax expression = invocationInfo.Expression;

            if (expression.Kind() != SyntaxKind.InvocationExpression)
            {
                return;
            }

            SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo((InvocationExpressionSyntax)expression);

            if (!invocationInfo2.Success)
            {
                return;
            }

            if (!StringUtility.Equals(invocationInfo2.NameText, "OrderBy", "OrderByDescending"))
            {
                return;
            }

            if (IsOrderByOrOrderByDescending(invocationInfo.InvocationExpression, context.SemanticModel, context.CancellationToken) &&
                IsOrderByOrOrderByDescending(invocationInfo2.InvocationExpression, context.SemanticModel, context.CancellationToken))
            {
                context.ReportDiagnostic(
                    DiagnosticDescriptors.CallThenByInsteadOfOrderBy,
                    invocationInfo.Name,
                    (invocationInfo.NameText == "OrderByDescending") ? "Descending" : null);
            }
        }
Пример #3
0
        public override bool IsFixableStatement(
            StatementSyntax statement,
            string name,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (statement.SpanOrLeadingTriviaContainsDirectives())
                return false;

            if (!(statement is ExpressionStatementSyntax expressionStatement))
                return false;

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expressionStatement.Expression);

            if (!invocationInfo.Success)
                return false;

            if (!(WalkDownMethodChain(invocationInfo).Expression is IdentifierNameSyntax identifierName))
                return false;

            if (name != identifierName.Identifier.ValueText)
                return false;

            IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocationInfo.InvocationExpression, cancellationToken);

            return methodSymbol?.IsStatic == false
                && SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingType, typeSymbol)
                && SymbolEqualityComparer.Default.Equals(methodSymbol.ReturnType, typeSymbol);
        }
Пример #4
0
        public static bool IsFixable(
            InvocationExpressionSyntax invocation,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (!invocationInfo.Success)
            {
                return(false);
            }

            if (invocationInfo.Arguments.Count != 1)
            {
                return(false);
            }

            MemberAccessExpressionSyntax memberAccess = GetTopmostMemberAccessExpression(invocationInfo.MemberAccessExpression);

            if (invocationInfo.NameText != "HasFlag")
            {
                return(false);
            }

            IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(memberAccess, cancellationToken);

            return(methodSymbol?.Name == "HasFlag" &&
                   !methodSymbol.IsStatic &&
                   methodSymbol.IsReturnType(SpecialType.System_Boolean) &&
                   methodSymbol.HasSingleParameter(SpecialType.System_Enum) &&
                   methodSymbol.IsContainingType(SpecialType.System_Enum));
        }
            static string GetName2(InvocationExpressionSyntax invocationExpression)
            {
                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

                if (!invocationInfo.Success)
                {
                    return(null);
                }

                if (invocationInfo.Arguments.Any())
                {
                    return(null);
                }

                if (invocationInfo.NameText != "Kind")
                {
                    return(null);
                }

                if (invocationInfo.Expression is not IdentifierNameSyntax identifierName)
                {
                    return(null);
                }

                return(identifierName.Identifier.ValueText);
            }
        private static bool VerifyAwaitType(AwaitExpressionSyntax awaitExpression, ITypeSymbol typeArgument, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (!typeArgument.Equals(semanticModel.GetTypeSymbol(awaitExpression, cancellationToken)))
            {
                return(false);
            }

            ExpressionSyntax expression = awaitExpression.Expression;

            ITypeSymbol expressionTypeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

            if (expressionTypeSymbol == null)
            {
                return(false);
            }

            if (expressionTypeSymbol.OriginalDefinition.EqualsOrInheritsFrom(MetadataNames.System_Threading_Tasks_Task_T))
            {
                return(true);
            }

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            return(invocationInfo.Success &&
                   invocationInfo.Arguments.Count == 1 &&
                   invocationInfo.NameText == "ConfigureAwait" &&
                   expressionTypeSymbol.OriginalDefinition.HasMetadataName(MetadataNames.System_Runtime_CompilerServices_ConfiguredTaskAwaitable_T));
        }
        public static void AnalyzeWhere(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationInfo.Expression);

            if (!invocationInfo2.Success)
            {
                return;
            }

            if (invocationInfo2.Arguments.Count != 1)
            {
                return;
            }

            if (invocationInfo2.NameText != "Where")
            {
                return;
            }

            InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression;

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IMethodSymbol methodSymbol = semanticModel.GetExtensionMethodInfo(invocation, cancellationToken).Symbol;

            if (methodSymbol == null)
            {
                return;
            }

            if (!SymbolUtility.IsLinqExtensionOfIEnumerableOfTWithoutParameters(methodSymbol, invocationInfo.NameText, semanticModel))
            {
                return;
            }

            IMethodSymbol methodSymbol2 = semanticModel.GetExtensionMethodInfo(invocationInfo2.InvocationExpression, cancellationToken).Symbol;

            if (methodSymbol2 == null)
            {
                return;
            }

            if (!SymbolUtility.IsLinqWhere(methodSymbol2, semanticModel, allowImmutableArrayExtension: true))
            {
                return;
            }

            TextSpan span = TextSpan.FromBounds(invocationInfo2.Name.SpanStart, invocation.Span.End);

            if (invocation.ContainsDirectives(span))
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.SimplifyLinqMethodChain,
                Location.Create(invocation.SyntaxTree, span));
        }
Пример #8
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);
        }
        private static bool IsFixable(InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

            if (!invocationInfo.Success)
            {
                return(false);
            }

            IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocationInfo.InvocationExpression, cancellationToken);

            if (methodSymbol == null)
            {
                return(false);
            }

            if (!methodSymbol.IsContainingType(SpecialType.System_String))
            {
                return(false);
            }

            if (!methodSymbol.IsReturnType(SpecialType.System_String))
            {
                return(false);
            }

            switch (methodSymbol.Name)
            {
            case "Substring":
            {
                if (methodSymbol.HasTwoParameters(SpecialType.System_Int32, SpecialType.System_Int32))
                {
                    return(true);
                }

                break;
            }

            case "Remove":
            {
                if (methodSymbol.HasSingleParameter(SpecialType.System_Int32))
                {
                    return(true);
                }

                break;
            }

            case "Format":
            {
                return(true);
            }
            }

            return(false);
        }
        private static string GetTextToAppend(ExpressionStatementSyntax expressionStatement)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(GetInvocationExpression(expressionStatement));

            SimpleMemberInvocationExpressionInfo firstMemberInvocation = UseMethodChainingAnalysis.WalkDownMethodChain(invocationInfo);

            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

            return(invocationExpression
                   .ToString()
                   .Substring(firstMemberInvocation.OperatorToken.SpanStart - invocationExpression.SpanStart));
        }
Пример #11
0
        public static async Task <Document> RefactorAsync(
            Document document,
            InvocationExpressionSyntax invocationExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            MemberDeclarationSyntax memberDeclaration = invocationExpression.FirstAncestor <MemberDeclarationSyntax>();

            Debug.Assert(memberDeclaration != null, "");

            if (memberDeclaration != null)
            {
                TypeDeclarationSyntax typeDeclaration = memberDeclaration.FirstAncestor <TypeDeclarationSyntax>();

                Debug.Assert(typeDeclaration != null, "");

                if (typeDeclaration != null)
                {
                    SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

                    string fieldName = NameGenerator.Default.EnsureUniqueLocalName("_regex", semanticModel, invocationExpression.SpanStart, cancellationToken: cancellationToken);

                    MemberAccessExpressionSyntax newMemberAccess = invocationInfo.MemberAccessExpression.WithExpression(IdentifierName(Identifier(fieldName).WithRenameAnnotation()));

                    ArgumentListPair pair = RewriteArgumentLists(invocationInfo.ArgumentList, semanticModel, cancellationToken);

                    InvocationExpressionSyntax newInvocationExpression = invocationExpression
                                                                         .WithExpression(newMemberAccess)
                                                                         .WithArgumentList(pair.ArgumentList1);

                    TypeDeclarationSyntax newTypeDeclaration = typeDeclaration.ReplaceNode(invocationExpression, newInvocationExpression);

                    TypeSyntax regexType = ParseTypeName("System.Text.RegularExpressions.Regex").WithSimplifierAnnotation();

                    FieldDeclarationSyntax fieldDeclaration = FieldDeclaration(
                        Modifiers.Private_Static_ReadOnly(),
                        regexType,
                        Identifier(fieldName),
                        EqualsValueClause(
                            ObjectCreationExpression(regexType, pair.ArgumentList2)));

                    SyntaxList <MemberDeclarationSyntax> newMembers = MemberDeclarationInserter.Default.Insert(newTypeDeclaration.Members, fieldDeclaration);

                    newTypeDeclaration = newTypeDeclaration.WithMembers(newMembers);

                    return(await document.ReplaceNodeAsync(typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false));
                }
            }

            return(document);
        }
        public static bool IsFixable(
            InvocationExpressionSyntax invocation,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (!ParentIsElementAccessOrForEachExpression(invocation.WalkUpParentheses()))
            {
                return(false);
            }

            SimpleMemberInvocationExpressionInfo info = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (!info.Success)
            {
                return(false);
            }

            if (info.Arguments.Any())
            {
                return(false);
            }

            if (!string.Equals(info.NameText, "ToCharArray"))
            {
                return(false);
            }

            IMethodSymbol methodSymbol = semanticModel.GetMethodSymbol(invocation, cancellationToken);

            if (!SymbolUtility.IsPublicInstanceNonGeneric(methodSymbol, "ToCharArray"))
            {
                return(false);
            }

            if (methodSymbol.ContainingType?.SpecialType != SpecialType.System_String)
            {
                return(false);
            }

            if (methodSymbol.Parameters.Any())
            {
                return(false);
            }

            if (!(methodSymbol.ReturnType is IArrayTypeSymbol arrayType))
            {
                return(false);
            }

            return(arrayType.ElementType.SpecialType == SpecialType.System_Char);
        }
Пример #13
0
        private static Task <Document> AddCallToConfigureAwaitRefactorAsync(
            Document document,
            AwaitExpressionSyntax awaitExpression,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax expression = awaitExpression.Expression;

            SyntaxTriviaList leading = default;

            switch (expression.Kind())
            {
            case SyntaxKind.SimpleMemberAccessExpression:
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                leading = memberAccess.OperatorToken.LeadingTrivia;
                break;
            }

            case SyntaxKind.InvocationExpression:
            {
                var invocation = (InvocationExpressionSyntax)expression;

                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

                leading = invocationInfo.OperatorToken.LeadingTrivia;
                break;
            }
            }

            SyntaxTrivia last = leading.LastOrDefault();

            last = (last.IsWhitespaceTrivia()) ? last : default;

            ParenthesizedExpressionSyntax expression2 = expression.WithoutTrailingTrivia().Parenthesize();

            if (last.IsWhitespaceTrivia())
            {
                expression2 = expression2.WithTrailingTrivia(SyntaxTriviaAnalysis.DetermineEndOfLine(awaitExpression));
            }

            InvocationExpressionSyntax newInvocationExpression = InvocationExpression(
                SimpleMemberAccessExpression(
                    expression2,
                    Token(SyntaxKind.DotToken).WithLeadingTrivia(last),
                    IdentifierName("ConfigureAwait")),
                ArgumentList(
                    Token(SyntaxKind.OpenParenToken),
                    SingletonSeparatedList(Argument(FalseLiteralExpression())),
                    Token(default, SyntaxKind.CloseParenToken, expression.GetTrailingTrivia())));
Пример #14
0
        public static SimpleMemberInvocationExpressionInfo WalkDownMethodChain(SimpleMemberInvocationExpressionInfo invocationInfo)
        {
            while (true)
            {
                SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationInfo.Expression);

                if (invocationInfo2.Success)
                {
                    invocationInfo = invocationInfo2;
                }
                else
                {
                    break;
                }
            }

            return(invocationInfo);
        }
Пример #15
0
        private static bool TryCreateCaseChangingInvocation(ExpressionSyntax expression, out SimpleMemberInvocationExpressionInfo invocationInfo)
        {
            invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            if (invocationInfo.Success &&
                !invocationInfo.Arguments.Any())
            {
                string name = invocationInfo.NameText;

                return(name == "ToLower" ||
                       name == "ToLowerInvariant" ||
                       name == "ToUpper" ||
                       name == "ToUpperInvariant");
            }

            invocationInfo = default(SimpleMemberInvocationExpressionInfo);
            return(false);
        }
        public static Task <Document> RefactorAsync(
            Document document,
            SimpleMemberInvocationExpressionInfo invocationInfo,
            CancellationToken cancellationToken)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationInfo.Expression);

            SyntaxTriviaList trivia = invocationInfo2.InvocationExpression
                                      .GetTrailingTrivia()
                                      .EmptyIfWhitespace()
                                      .AddRange(invocationInfo.InvocationExpression.GetTrailingTrivia());

            InvocationExpressionSyntax newNode = invocationInfo2
                                                 .WithName("AppendLine")
                                                 .InvocationExpression
                                                 .WithTrailingTrivia(trivia);

            return(document.ReplaceNodeAsync(invocationInfo.InvocationExpression, newNode, cancellationToken));
        }
        private static InvocationExpressionSyntax CreateInvocationExpression(
            InvocationExpressionSyntax innerInvocationExpression,
            InvocationExpressionSyntax outerInvocationExpression)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(innerInvocationExpression);

            switch (invocationInfo.NameText)
            {
            case "Substring":
            {
                SeparatedSyntaxList <ArgumentSyntax> arguments = invocationInfo.Arguments;

                ArgumentListSyntax argumentList = ArgumentList(
                    Argument(invocationInfo.Expression),
                    arguments[0],
                    arguments[1]
                    );

                return(CreateNewInvocationExpression(outerInvocationExpression, "Append", argumentList));
            }

            case "Remove":
            {
                SeparatedSyntaxList <ArgumentSyntax> arguments = invocationInfo.Arguments;

                ArgumentListSyntax argumentList = ArgumentList(
                    Argument(invocationInfo.Expression),
                    Argument(NumericLiteralExpression(0)),
                    arguments[0]
                    );

                return(CreateNewInvocationExpression(outerInvocationExpression, "Append", argumentList));
            }

            case "Format":
            {
                return(CreateNewInvocationExpression(outerInvocationExpression, "AppendFormat", invocationInfo.ArgumentList));
            }
            }

            Debug.Fail(innerInvocationExpression.ToString());
            return(outerInvocationExpression);
        }
        private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            if (invocation.ContainsDiagnostics)
            {
                return;
            }

            if (invocation.SpanContainsDirectives())
            {
                return;
            }

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (invocationInfo.Arguments.Count != 1)
            {
                return;
            }

            if (!invocationInfo.Name.IsKind(SyntaxKind.IdentifierName))
            {
                return;
            }

            if (invocationInfo.NameText != "HasFlag")
            {
                return;
            }

            if (!IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(
                context,
                DiagnosticRules.UseHasFlagMethodOrBitwiseOperator,
                invocation,
                "bitwise operator");
        }
Пример #19
0
        private static void RemoveCallToConfigureAwait(SyntaxNodeAnalysisContext context)
        {
            var awaitExpression = (AwaitExpressionSyntax)context.Node;

            ExpressionSyntax expression = awaitExpression.Expression;

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            if (!IsConfigureAwait(expression))
            {
                return;
            }

            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(expression, context.CancellationToken);

            if (typeSymbol == null)
            {
                return;
            }

            switch (typeSymbol.MetadataName)
            {
            case "ConfiguredTaskAwaitable":
            case "ConfiguredTaskAwaitable`1":
            case "ConfiguredValueTaskAwaitable":
            case "ConfiguredValueTaskAwaitable`1":
            {
                if (typeSymbol.ContainingNamespace.HasMetadataName(MetadataNames.System_Runtime_CompilerServices))
                {
                    DiagnosticHelpers.ReportDiagnostic(
                        context,
                        DiagnosticRules.ReportOnly.RemoveCallToConfigureAwait,
                        Location.Create(
                            awaitExpression.SyntaxTree,
                            TextSpan.FromBounds(invocationInfo.OperatorToken.SpanStart, expression.Span.End)),
                        AnalyzerOptions.RemoveCallToConfigureAwait);
                }

                break;
            }
            }
        }
Пример #20
0
        private static Task <Document> UseElementAccessInsteadOfCallingFirstAsync(
            Document document,
            InvocationExpressionSyntax invocationExpression,
            CancellationToken cancellationToken)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

            ArgumentListSyntax argumentList = invocationInfo.ArgumentList;

            SyntaxToken openParenToken  = argumentList.OpenParenToken;
            SyntaxToken closeParenToken = argumentList.CloseParenToken;

            ElementAccessExpressionSyntax elementAccessExpression = ElementAccessExpression(
                invocationInfo.Expression.WithoutTrailingTrivia(),
                BracketedArgumentList(
                    Token(SyntaxTriviaList.Empty, SyntaxKind.OpenBracketToken, openParenToken.TrailingTrivia),
                    SingletonSeparatedList(argumentList.Arguments.FirstOrDefault() ?? Argument(NumericLiteralExpression(0))),
                    Token(closeParenToken.LeadingTrivia, SyntaxKind.CloseBracketToken, closeParenToken.TrailingTrivia)));

            return(document.ReplaceNodeAsync(invocationExpression, elementAccessExpression, cancellationToken));
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(
                    root,
                    context.Span,
                    out SyntaxNode node,
                    getInnermostNodeForTie: false,
                    predicate: f => f.IsKind(SyntaxKind.Argument, SyntaxKind.InvocationExpression)))
            {
                return;
            }

            Diagnostic diagnostic = context.Diagnostics[0];
            Document   document   = context.Document;

            if (node is ArgumentSyntax argument)
            {
                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo((InvocationExpressionSyntax)argument.Parent.Parent);

                CodeAction codeAction = CodeAction.Create(
                    $"Optimize '{invocationInfo.NameText}' call",
                    ct => RefactorAsync(document, argument, invocationInfo, ct),
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
            else if (node is InvocationExpressionSyntax invocationExpression)
            {
                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

                CodeAction codeAction = CodeAction.Create(
                    $"Optimize '{invocationInfo.NameText}' call",
                    ct => RefactorAsync(document, invocationInfo, ct),
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
        }
        internal static async Task <Document> RefactorAsync(
            Document document,
            InvocationExpressionSyntax invocation,
            CancellationToken cancellationToken)
        {
            SimpleMemberInvocationExpressionInfo info = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(info.Expression, cancellationToken);

            if ((typeSymbol as IArrayTypeSymbol)?.Rank == 1)
            {
                NameSyntax arrayName = ParseName("System.Array")
                                       .WithLeadingTrivia(invocation.GetLeadingTrivia())
                                       .WithSimplifierAnnotation();

                MemberAccessExpressionSyntax newMemberAccess = SimpleMemberAccessExpression(
                    arrayName,
                    info.OperatorToken,
                    IdentifierName("Find").WithTriviaFrom(info.Name));

                ArgumentListSyntax argumentList = invocation.ArgumentList;

                InvocationExpressionSyntax newInvocation = InvocationExpression(
                    newMemberAccess,
                    ArgumentList(
                        Argument(info.Expression.WithoutTrivia()),
                        argumentList.Arguments.First()
                        ).WithTriviaFrom(argumentList));

                return(await document.ReplaceNodeAsync(invocation, newInvocation, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                IdentifierNameSyntax newName = IdentifierName("Find").WithTriviaFrom(info.Name);

                return(await document.ReplaceNodeAsync(info.Name, newName, cancellationToken).ConfigureAwait(false));
            }
        }
Пример #23
0
            private bool IsCompletedTask(ExpressionSyntax expression)
            {
                if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var simpleMemberAccess = (MemberAccessExpressionSyntax)expression;

                    return(string.Equals(simpleMemberAccess.Name.Identifier.ValueText, "CompletedTask", StringComparison.Ordinal) &&
                           SemanticModel.GetSymbol(expression, CancellationToken) is IPropertySymbol propertySymbol &&
                           IsTaskOrTaskOrT(propertySymbol.ContainingType));
                }
                else
                {
                    SimpleMemberInvocationExpressionInfo memberInvocation = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

                    if (memberInvocation.Success)
                    {
                        switch (memberInvocation.NameText)
                        {
                        case "FromCanceled":
                        case "FromException":
                        case "FromResult":
                        {
                            if (SemanticModel.GetSymbol(expression, CancellationToken) is IMethodSymbol methodSymbol &&
                                (methodSymbol.Arity == 0 || methodSymbol.Arity == 1) &&
                                methodSymbol.Parameters.Length == 1 &&
                                IsTaskOrTaskOrT(methodSymbol.ContainingType))
                            {
                                return(true);
                            }

                            break;
                        }
                        }
                    }
                }

                return(false);
            }
Пример #24
0
        private static async Task <Document> RefactorAsync(
            Document document,
            UsingStatementSyntax usingStatement,
            CancellationToken cancellationToken)
        {
            VariableDeclaratorSyntax declarator = usingStatement.Declaration.Variables.Single();

            var whileStatement = (WhileStatementSyntax)usingStatement.Statement.SingleNonBlockStatementOrDefault();

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(declarator.Initializer.Value);

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            string name = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.ForEachVariable, semanticModel, usingStatement.SpanStart, cancellationToken: cancellationToken);

            StatementSyntax statement = whileStatement.Statement;

            var rewriter = new Rewriter(
                semanticModel.GetDeclaredSymbol(declarator, cancellationToken),
                declarator.Identifier.ValueText,
                name,
                semanticModel,
                cancellationToken);

            var newStatement = (StatementSyntax)rewriter.Visit(statement);

            ForEachStatementSyntax forEachStatement = ForEachStatement(
                VarType(),
                Identifier(name).WithRenameAnnotation(),
                invocationInfo.Expression,
                newStatement);

            forEachStatement = forEachStatement
                               .WithTriviaFrom(usingStatement)
                               .WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(usingStatement, forEachStatement, cancellationToken).ConfigureAwait(false));
        }
        private static bool IsConfiguredTaskAwaitableOfT(
            ExpressionSyntax expression,
            INamedTypeSymbol expressionTypeSymbol,
            SemanticModel semanticModel)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            if (!invocationInfo.Success)
            {
                return(false);
            }

            if (invocationInfo.Arguments.Count != 1)
            {
                return(false);
            }

            if (invocationInfo.NameText != "ConfigureAwait")
            {
                return(false);
            }

            return(expressionTypeSymbol.ConstructedFrom.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Runtime_CompilerServices_ConfiguredTaskAwaitable_T)));
        }
        public static bool IsFixable(
            InvocationExpressionSyntax invocation,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (!invocationInfo.Success)
            {
                return(false);
            }

            if (invocationInfo.Arguments.Count != 1)
            {
                return(false);
            }

            if (invocationInfo.NameText != "HasFlag")
            {
                return(false);
            }

            return(IsFixable(invocationInfo, semanticModel, cancellationToken));
        }
        private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            if (invocation.ContainsDiagnostics)
            {
                return;
            }

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (!invocationInfo.Success)
            {
                return;
            }

            string methodName = invocationInfo.NameText;

            int argumentCount = invocationInfo.Arguments.Count;

            switch (argumentCount)
            {
            case 0:
            {
                switch (methodName)
                {
                case "Any":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCountOrLengthPropertyInsteadOfAnyMethod))
                    {
                        UseCountOrLengthPropertyInsteadOfAnyMethodAnalysis.Analyze(context, invocationInfo);
                    }

                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhere(context, invocationInfo);
                        OptimizeLinqMethodCallAnalysis.AnalyzeAny(context, invocationInfo);
                    }

                    break;
                }

                case "Cast":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhereAndCast(context, invocationInfo);
                    }

                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.RemoveRedundantCast))
                    {
                        RemoveRedundantCastAnalyzer.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "Count":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall) &&
                        !OptimizeLinqMethodCallAnalysis.AnalyzeSelectManyAndCount(context, invocationInfo))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeCount(context, invocationInfo);
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhere(context, invocationInfo);
                    }

                    break;
                }

                case "First":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        if (CanUseElementAccess(context, invocationInfo) &&
                            UseElementAccessAnalysis.IsFixableFirst(invocationInfo, context.SemanticModel, context.CancellationToken))
                        {
                            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseElementAccess, Location.Create(invocation.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationInfo.ArgumentList.Span.End)));
                        }

                        OptimizeLinqMethodCallAnalysis.AnalyzeWhere(context, invocationInfo);
                        OptimizeLinqMethodCallAnalysis.AnalyzeFirst(context, invocationInfo);
                    }

                    break;
                }

                case "Max":
                case "Min":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeSelectAndMinOrMax(context, invocationInfo);
                    }

                    break;
                }

                case "Reverse":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeOrderByAndReverse(context, invocationInfo);
                    }

                    break;
                }

                case "ToString":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.RemoveRedundantToStringCall))
                    {
                        RemoveRedundantToStringCallAnalysis.Analyze(context, invocationInfo);
                    }

                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseNameOfOperator) &&
                        ((CSharpCompilation)context.Compilation).LanguageVersion >= LanguageVersion.CSharp6)
                    {
                        UseNameOfOperatorAnalyzer.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "ToLower":
                case "ToLowerInvariant":
                case "ToUpper":
                case "ToUpperInvariant":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseStringComparison))
                    {
                        UseStringComparisonAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "FirstOrDefault":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhere(context, invocationInfo);
                        OptimizeLinqMethodCallAnalysis.AnalyzeFirstOrDefault(context, invocationInfo);
                    }

                    break;
                }

                case "Last":
                case "LastOrDefault":
                case "LongCount":
                case "Single":
                case "SingleOrDefault":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhere(context, invocationInfo);
                    }

                    break;
                }

                case "OfType":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall) &&
                        !invocation.SpanContainsDirectives())
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeOfType(context, invocationInfo);
                    }

                    break;
                }

                case "ToCharArray":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.RemoveRedundantStringToCharArrayCall))
                    {
                        RemoveRedundantStringToCharArrayCallAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }
                }

                break;
            }

            case 1:
            {
                switch (methodName)
                {
                case "All":
                case "Any":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.SimplifyLogicalNegation))
                    {
                        SimplifyLogicalNegationAnalyzer.Analyze(context, invocationInfo);
                    }

                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall) &&
                        !invocation.SpanContainsDirectives())
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeWhereAndAny(context, invocationInfo);
                    }

                    break;
                }

                case "ContainsKey":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeMethodCall))
                    {
                        OptimizeMethodCallAnalysis.OptimizeDictionaryContainsKey(context, invocationInfo);
                    }

                    break;
                }

                case "ElementAt":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall) &&
                        CanUseElementAccess(context, invocationInfo) &&
                        UseElementAccessAnalysis.IsFixableElementAt(invocationInfo, context.SemanticModel, context.CancellationToken))
                    {
                        DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseElementAccess, Location.Create(invocation.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationInfo.ArgumentList.Span.End)));
                    }

                    break;
                }

                case "FirstOrDefault":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        OptimizeLinqMethodCallAnalysis.AnalyzeFirstOrDefault(context, invocationInfo);
                    }

                    break;
                }

                case "GetValueOrDefault":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpression) &&
                        invocationInfo.Name.IsKind(SyntaxKind.IdentifierName) &&
                        !invocation.IsParentKind(SyntaxKind.InvocationExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression) &&
                        context.SemanticModel
                        .GetMethodSymbol(invocationInfo.InvocationExpression, context.CancellationToken)?
                        .ContainingType
                        .OriginalDefinition
                        .SpecialType == SpecialType.System_Nullable_T)
                    {
                        DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCoalesceExpression, invocationInfo.Name);
                    }

                    break;
                }

                case "Where":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.CombineEnumerableWhereMethodChain))
                    {
                        CombineEnumerableWhereMethodChainAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "HasFlag":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.ConvertHasFlagCallToBitwiseOperationOrViceVersa) &&
                        context.IsAnalyzerSuppressed(AnalyzerOptions.ConvertBitwiseOperationToHasFlagCall) &&
                        !invocation.SpanContainsDirectives() &&
                        ConvertHasFlagCallToBitwiseOperationAnalysis.IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
                    {
                        DiagnosticHelpers.ReportDiagnostic(
                            context,
                            DiagnosticDescriptors.ConvertHasFlagCallToBitwiseOperationOrViceVersa,
                            invocation);
                    }

                    break;
                }

                case "Select":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        CallCastInsteadOfSelectAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "OrderBy":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.CallThenByInsteadOfOrderBy))
                    {
                        CallThenByInsteadOfOrderByAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }
                }

                break;
            }

            case 2:
            {
                switch (invocationInfo.NameText)
                {
                case "IsMatch":
                case "Match":
                case "Matches":
                case "Split":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseRegexInstanceInsteadOfStaticMethod) &&
                        !invocation.SpanContainsDirectives())
                    {
                        UseRegexInstanceInsteadOfStaticMethodAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "Select":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeLinqMethodCall))
                    {
                        CallCastInsteadOfSelectAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "OrderBy":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.CallThenByInsteadOfOrderBy))
                    {
                        CallThenByInsteadOfOrderByAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }
                }

                break;
            }

            case 3:
            {
                switch (invocationInfo.NameText)
                {
                case "IsMatch":
                case "Match":
                case "Matches":
                case "Split":
                case "Replace":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseRegexInstanceInsteadOfStaticMethod) &&
                        !invocation.SpanContainsDirectives())
                    {
                        UseRegexInstanceInsteadOfStaticMethodAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "OrderBy":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.CallThenByInsteadOfOrderBy))
                    {
                        CallThenByInsteadOfOrderByAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }

                case "Compare":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeMethodCall))
                    {
                        OptimizeMethodCallAnalysis.OptimizeStringCompare(context, invocationInfo);
                    }

                    break;
                }
                }

                break;
            }

            case 4:
            {
                switch (invocationInfo.NameText)
                {
                case "Replace":
                {
                    if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseRegexInstanceInsteadOfStaticMethod) &&
                        !invocation.SpanContainsDirectives())
                    {
                        UseRegexInstanceInsteadOfStaticMethodAnalysis.Analyze(context, invocationInfo);
                    }

                    break;
                }
                }

                break;
            }
            }

            switch (methodName)
            {
            case "ElementAtOrDefault":
            case "FirstOrDefault":
            case "LastOrDefault":
            case "SingleOrDefault":
            {
                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.AvoidNullReferenceException))
                {
                    if (argumentCount == 0 ||
                        argumentCount == 1 ||
                        argumentCount == 2)
                    {
                        AvoidNullReferenceExceptionAnalyzer.Analyze(context, invocationInfo);
                    }
                }

                break;
            }

            case "Append":
            case "AppendLine":
            case "AppendFormat":
            case "Insert":
            {
                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeStringBuilderAppendCall))
                {
                    OptimizeStringBuilderAppendCallAnalysis.Analyze(context, invocationInfo);
                }

                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.AvoidBoxingOfValueType))
                {
                    AvoidBoxingOfValueTypeAnalysis.Analyze(context, invocationInfo);
                }

                break;
            }

            case "Assert":
            {
                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeMethodCall) &&
                    (argumentCount >= 1 && argumentCount <= 3))
                {
                    OptimizeMethodCallAnalysis.OptimizeDebugAssert(context, invocationInfo);
                }

                break;
            }

            case "Join":
            {
                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.OptimizeMethodCall) &&
                    argumentCount >= 2)
                {
                    OptimizeMethodCallAnalysis.OptimizeStringJoin(context, invocationInfo);
                }

                break;
            }
            }

            if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseMethodChaining) &&
                UseMethodChainingAnalysis.IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
            {
                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseMethodChaining, invocationInfo.InvocationExpression);
            }
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            UseMethodChainingAnalysis analysis,
            ExpressionStatementSyntax expressionStatement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            InvocationExpressionSyntax invocationExpression = GetInvocationExpression(expressionStatement);

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocationExpression);

            ITypeSymbol returnType = semanticModel.GetMethodSymbol(invocationExpression, cancellationToken).ReturnType;

            string name = ((IdentifierNameSyntax)UseMethodChainingAnalysis.WalkDownMethodChain(invocationInfo).Expression).Identifier.ValueText;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(expressionStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(expressionStatement);

            string indentation = SyntaxTriviaAnalysis.GetIncreasedIndentation(expressionStatement, cancellationToken);

            var sb = new StringBuilder(invocationExpression.ToString());

            int j = index;

            while (j < statements.Count - 1)
            {
                StatementSyntax statement = statements[j + 1];

                if (!analysis.IsFixableStatement(statement, name, returnType, semanticModel, cancellationToken))
                {
                    break;
                }

                sb.AppendLine();
                sb.Append(indentation);
                sb.Append(GetTextToAppend((ExpressionStatementSyntax)statement));

                j++;
            }

            StatementSyntax lastStatement = statements[j];

            SyntaxList <StatementSyntax> newStatements = statements;

            while (j > index)
            {
                newStatements = newStatements.RemoveAt(j);
                j--;
            }

            ExpressionSyntax newInvocationExpression = SyntaxFactory.ParseExpression(sb.ToString());

            SyntaxTriviaList trailingTrivia = statementsInfo
                                              .Parent
                                              .DescendantTrivia(TextSpan.FromBounds(invocationExpression.Span.End, lastStatement.Span.End))
                                              .ToSyntaxTriviaList()
                                              .EmptyIfWhitespace()
                                              .AddRange(lastStatement.GetTrailingTrivia());

            ExpressionStatementSyntax newExpressionStatement = expressionStatement
                                                               .ReplaceNode(invocationExpression, newInvocationExpression)
                                                               .WithLeadingTrivia(expressionStatement.GetLeadingTrivia())
                                                               .WithTrailingTrivia(trailingTrivia)
                                                               .WithFormatterAndSimplifierAnnotation();

            newStatements = newStatements.ReplaceAt(index, newExpressionStatement);

            return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));
        }
        private static Task <Document> UsePatternMatchingAsync(
            Document document,
            SwitchStatementSyntax switchStatement,
            CancellationToken cancellationToken)
        {
            SyntaxList <SwitchSectionSyntax> newSections = switchStatement.Sections.Select(section =>
            {
                if (!(section.Labels.Single() is CaseSwitchLabelSyntax label))
                {
                    return(section);
                }

                SyntaxList <StatementSyntax> statements = section.Statements;

                StatementSyntax statement = statements[0];

                if (statement is BlockSyntax block)
                {
                    statement = block.Statements.FirstOrDefault();
                }

                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                var castExpression = (CastExpressionSyntax)localInfo.Value;

                CasePatternSwitchLabelSyntax newLabel = CasePatternSwitchLabel(
                    DeclarationPattern(
                        castExpression.Type,
                        SingleVariableDesignation(localInfo.Identifier)),
                    label.ColonToken);

                SwitchSectionSyntax newSection = section.RemoveStatement(localInfo.Statement);

                newSection = newSection.WithLabels(newSection.Labels.ReplaceAt(0, newLabel));

                return(newSection.WithFormatterAnnotation());
            })
                                                           .ToSyntaxList();

            ExpressionSyntax expression = switchStatement.Expression;

            ExpressionSyntax newExpression = expression;

            LocalDeclarationStatementSyntax localDeclaration = null;

            if (expression.IsKind(SyntaxKind.InvocationExpression))
            {
                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

                newExpression = invocationInfo.Expression;
            }
            else
            {
                localDeclaration = (LocalDeclarationStatementSyntax)switchStatement.PreviousStatement();

                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(localInfo.Value);

                newExpression = invocationInfo.Expression;
            }

            SwitchStatementSyntax newSwitchStatement = switchStatement
                                                       .WithExpression(newExpression.WithTriviaFrom(expression))
                                                       .WithSections(newSections);

            if (localDeclaration != null)
            {
                StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(switchStatement);

                newSwitchStatement = newSwitchStatement.WithLeadingTrivia(localDeclaration.GetLeadingTrivia());

                SyntaxList <StatementSyntax> newStatements = statementsInfo.Statements
                                                             .Replace(switchStatement, newSwitchStatement)
                                                             .RemoveAt(statementsInfo.IndexOf(localDeclaration));

                return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
            }
            else
            {
                return(document.ReplaceNodeAsync(switchStatement, newSwitchStatement, cancellationToken));
            }
        }
        private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

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

            RemoveRedundantStringToCharArrayCallAnalysis.Analyze(context, invocation);

            SimplifyLinqMethodChainAnalysis.AnalyzeWhereAndAny(context);

            if (!invocation.ContainsDiagnostics)
            {
                if (!invocation.SpanContainsDirectives())
                {
                    CallExtensionMethodAsInstanceMethodAnalysisResult analysis = CallExtensionMethodAsInstanceMethodAnalysis.Analyze(invocation, context.SemanticModel, allowAnyExpression: false, cancellationToken: context.CancellationToken);

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

                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

                if (invocationInfo.Success)
                {
                    if (!invocation.SpanContainsDirectives())
                    {
                        UseRegexInstanceInsteadOfStaticMethodAnalysis.Analyze(context, invocationInfo);
                    }

                    string methodName = invocationInfo.NameText;

                    AvoidNullReferenceExceptionAnalyzer.Analyze(context, invocationInfo);

                    CallStringConcatInsteadOfStringJoinAnalysis.Analyze(context, invocationInfo);

                    int argumentCount = invocationInfo.Arguments.Count;

                    switch (argumentCount)
                    {
                    case 0:
                        {
                            switch (methodName)
                            {
                            case "Any":
                            {
                                UseCountOrLengthPropertyInsteadOfAnyMethodAnalysis.Analyze(context, invocationInfo);

                                SimplifyLinqMethodChainAnalysis.AnalyzeWhere(context, invocationInfo);
                                break;
                            }

                            case "Cast":
                            {
                                SimplifyLinqMethodChainAnalysis.AnalyzeWhereAndCast(context, invocationInfo);
                                RemoveRedundantCastAnalyzer.Analyze(context, invocationInfo);
                                break;
                            }

                            case "Count":
                            {
                                UseInsteadOfCountMethodAnalysis.Analyze(context, invocationInfo);
                                SimplifyLinqMethodChainAnalysis.AnalyzeWhere(context, invocationInfo);
                                break;
                            }

                            case "First":
                            {
                                if (!invocationInfo.Expression.IsKind(SyntaxKind.InvocationExpression) &&
                                    UseElementAccessInsteadOfFirstAnalysis.IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
                                {
                                    context.ReportDiagnostic(DiagnosticDescriptors.UseElementAccessInsteadOfFirst, invocationInfo.Name);
                                }

                                SimplifyLinqMethodChainAnalysis.AnalyzeWhere(context, invocationInfo);
                                break;
                            }

                            case "ToString":
                            {
                                RemoveRedundantToStringCallAnalysis.Analyze(context, invocationInfo);
                                UseNameOfOperatorAnalyzer.Analyze(context, invocationInfo);
                                break;
                            }

                            case "ToLower":
                            case "ToLowerInvariant":
                            case "ToUpper":
                            case "ToUpperInvariant":
                            {
                                UseStringComparisonAnalysis.Analyze(context, invocationInfo);
                                break;
                            }

                            case "FirstOrDefault":
                            case "Last":
                            case "LastOrDefault":
                            case "LongCount":
                            case "Single":
                            case "SingleOrDefault":
                            {
                                SimplifyLinqMethodChainAnalysis.AnalyzeWhere(context, invocationInfo);
                                break;
                            }
                            }

                            break;
                        }

                    case 1:
                    {
                        switch (methodName)
                        {
                        case "All":
                        case "Any":
                        {
                            SimplifyLogicalNegationAnalyzer.Analyze(context, invocationInfo);
                            break;
                        }

                        case "ElementAt":
                        {
                            if (!invocationInfo.Expression.IsKind(SyntaxKind.InvocationExpression) &&
                                UseElementAccessInsteadOfElementAtAnalysis.IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.UseElementAccessInsteadOfElementAt, invocationInfo.Name);
                            }

                            break;
                        }

                        case "FirstOrDefault":
                        {
                            SimplifyLinqMethodChainAnalysis.AnalyzeFirstOrDefault(context, invocationInfo);
                            CallFindInsteadOfFirstOrDefaultAnalysis.Analyze(context, invocationInfo);
                            break;
                        }

                        case "Where":
                        {
                            CombineEnumerableWhereMethodChainAnalysis.Analyze(context, invocationInfo);
                            break;
                        }
                        }

                        break;
                    }
                    }

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

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

                        break;
                    }

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

                        break;
                    }
                    }

                    if (UseMethodChainingAnalysis.IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.UseMethodChaining, invocationInfo.InvocationExpression);
                    }
                }
            }
        }