예제 #1
0
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            SyntaxNode parent = invocationInfo.InvocationExpression.WalkUpParentheses().Parent;

            if (parent.Kind() != SyntaxKind.LogicalNotExpression)
            {
                return;
            }

            SingleParameterLambdaExpressionInfo lambdaInfo = SyntaxInfo.SingleParameterLambdaExpressionInfo(invocationInfo.Arguments.First().Expression.WalkDownParentheses());

            if (!lambdaInfo.Success)
            {
                return;
            }

            ExpressionSyntax expression = GetReturnExpression(lambdaInfo.Body)?.WalkDownParentheses();

            if (expression?.IsKind(SyntaxKind.LogicalNotExpression) != true)
            {
                return;
            }

            if (!context.SemanticModel.TryGetExtensionMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, ExtensionMethodKind.Reduced, context.CancellationToken))
            {
                return;
            }

            if (!methodInfo.IsLinqExtensionOfIEnumerableOfTWithPredicate())
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.SimplifyLogicalNegation, parent);
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

            if (invocationExpression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                return;
            }

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

            if (!semanticModel.TryGetExtensionMethodInfo(invocationExpression, out MethodInfo methodInfo, ExtensionMethodKind.Reduced, cancellationToken))
            {
                return;
            }

            if (!methodInfo.IsLinqExtensionOfIEnumerableOfTWithoutParameters("Any"))
            {
                return;
            }

            string propertyName = CSharpUtility.GetCountOrLengthPropertyName(invocationInfo.Expression, semanticModel, cancellationToken);

            if (propertyName == null)
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.UseCountOrLengthPropertyInsteadOfAnyMethod,
                Location.Create(context.Node.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.Span.Start, invocationExpression.Span.End)),
                ImmutableDictionary.CreateRange(new KeyValuePair <string, string>[] { new KeyValuePair <string, string>("PropertyName", propertyName) }),
                propertyName);
        }
        private static bool IsFixable(
            SyntaxNodeAnalysisContext context,
            MemberInvocationExpressionInfo invocationInfo,
            ArgumentSyntax argument,
            SeparatedSyntaxList <ArgumentSyntax> arguments)
        {
            if (object.ReferenceEquals(argument, arguments[0]))
            {
                ExpressionSyntax expression = arguments[1].Expression?.WalkDownParentheses();

                if (expression != null)
                {
                    SyntaxKind kind = expression.Kind();

                    if (kind == SyntaxKind.InvocationExpression)
                    {
                        return(TryCreateCaseChangingInvocation(expression, out MemberInvocationExpressionInfo invocationInfo2) &&
                               invocationInfo.NameText == invocationInfo2.NameText &&
                               CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken) &&
                               CheckSymbol(invocationInfo2, context.SemanticModel, context.CancellationToken));
                    }
                    else if (kind == SyntaxKind.StringLiteralExpression)
                    {
                        return(CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken));
                    }
                }
            }
            else
            {
                return(arguments[0].Expression?.WalkDownParentheses().Kind() == SyntaxKind.StringLiteralExpression &&
                       CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken));
            }

            return(false);
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            ExpressionSyntax expression = invocationInfo.InvocationExpression.WalkUpParentheses();

            SyntaxNode parent = expression.Parent;

            SyntaxKind kind = parent.Kind();

            if (kind == SyntaxKind.SimpleMemberAccessExpression)
            {
                MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo(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);
            }
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            ExpressionSyntax expression = invocationInfo.Expression;

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

            var memberAccessExpression = (MemberAccessExpressionSyntax)expression;

            var fieldSymbol = context.SemanticModel.GetSymbol(memberAccessExpression, context.CancellationToken) as IFieldSymbol;

            if (fieldSymbol == null)
            {
                return;
            }

            INamedTypeSymbol containingType = fieldSymbol.ContainingType;

            if (containingType?.TypeKind != TypeKind.Enum)
            {
                return;
            }

            if (containingType.HasAttribute(context.GetTypeByMetadataName(MetadataNames.System_FlagsAttribute)))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseNameOfOperator, invocationInfo.InvocationExpression);
        }
예제 #6
0
        public static bool CanRefactor(
            MemberInvocationExpressionInfo invocationInfo,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax argumentExpression = invocationInfo.Arguments[0].Expression;

            if (argumentExpression?.IsMissing != false)
            {
                return(false);
            }

            if (invocationInfo.Expression?.IsMissing != false)
            {
                return(false);
            }

            if (!semanticModel.TryGetExtensionMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, ExtensionMethodKind.Reduced, cancellationToken))
            {
                return(false);
            }

            if (!methodInfo.IsLinqElementAt(allowImmutableArrayExtension: true))
            {
                return(false);
            }

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

            return(SymbolUtility.HasAccessibleIndexer(typeSymbol, semanticModel, invocationInfo.InvocationExpression.SpanStart));
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            ExpressionSyntax expression = invocationInfo.Expression;

            if (expression.IsKind(SyntaxKind.InvocationExpression))
            {
                MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo((InvocationExpressionSyntax)expression);

                if (invocationInfo2.Success)
                {
                    switch (invocationInfo2.NameText)
                    {
                    case "OrderBy":
                    case "OrderByDescending":
                    {
                        if (IsLinqExtensionOfIEnumerableOfT(context, invocationInfo.InvocationExpression) &&
                            IsLinqExtensionOfIEnumerableOfT(context, invocationInfo2.InvocationExpression))
                        {
                            context.ReportDiagnostic(
                                DiagnosticDescriptors.CallThenByInsteadOfOrderBy,
                                invocationInfo.Name,
                                (invocationInfo.NameText == "OrderByDescending") ? "Descending" : null);
                        }

                        break;
                    }
                    }
                }
            }
        }
예제 #8
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ArgumentSyntax argument))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.OptimizeStringBuilderAppendCall:
                {
                    MemberInvocationExpressionInfo invocationInfo = SyntaxInfo.MemberInvocationExpressionInfo((InvocationExpressionSyntax)argument.Parent.Parent);

                    CodeAction codeAction = CodeAction.Create(
                        $"Optimize '{invocationInfo.NameText}' call",
                        cancellationToken => OptimizeStringBuilderAppendCallRefactoring.RefactorAsync(context.Document, argument, invocationInfo, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        public static bool IsFixable(
            MemberInvocationExpressionInfo invocationInfo,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

            if (!invocationInfo.Expression.IsKind(SyntaxKind.BaseExpression) &&
                semanticModel.TryGetMethodInfo(invocationExpression, out MethodInfo info, cancellationToken) &&
                info.IsName("ToString") &&
                info.IsPublic &&
                !info.IsStatic &&
                info.IsReturnType(SpecialType.System_String) &&
                !info.IsGenericMethod &&
                !info.IsExtensionMethod &&
                !info.Parameters.Any())
            {
                INamedTypeSymbol containingType = info.ContainingType;

                if (containingType?.IsReferenceType == true &&
                    containingType.SpecialType != SpecialType.System_Enum)
                {
                    if (containingType.IsString())
                    {
                        return(true);
                    }

                    if (invocationExpression.IsParentKind(SyntaxKind.Interpolation))
                    {
                        return(IsNotHidden(info.Symbol, containingType));
                    }

                    ExpressionSyntax expression = invocationExpression.WalkUpParentheses();

                    SyntaxNode parent = expression.Parent;

                    if (parent?.IsKind(SyntaxKind.AddExpression) == true &&
                        !parent.ContainsDiagnostics &&
                        IsNotHidden(info.Symbol, containingType))
                    {
                        var addExpression = (BinaryExpressionSyntax)expression.Parent;

                        ExpressionSyntax left  = addExpression.Left;
                        ExpressionSyntax right = addExpression.Right;

                        if (left == expression)
                        {
                            return(IsFixable(invocationInfo, addExpression, right, left, semanticModel, cancellationToken));
                        }
                        else
                        {
                            return(IsFixable(invocationInfo, addExpression, left, right, semanticModel, cancellationToken));
                        }
                    }
                }
            }

            return(false);
        }
        private static InvocationExpressionSyntax ConvertInterpolatedStringExpressionToInvocationExpression(
            InterpolatedStringExpressionSyntax interpolatedString,
            MemberInvocationExpressionInfo invocationInfo,
            SemanticModel semanticModel)
        {
            bool isVerbatim = interpolatedString.IsVerbatim();

            bool isAppendLine = string.Equals(invocationInfo.NameText, "AppendLine", StringComparison.Ordinal);

            InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression;

            InvocationExpressionSyntax newExpression = null;

            SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

            for (int i = 0; i < contents.Count; i++)
            {
                InterpolatedStringContentConversion conversion = InterpolatedStringContentConversion.Create(contents[i], isVerbatim);

                string methodName = conversion.MethodName;
                SeparatedSyntaxList <ArgumentSyntax> arguments = conversion.Arguments;

                if (i == contents.Count - 1 &&
                    isAppendLine &&
                    string.Equals(methodName, "Append", StringComparison.Ordinal) &&
                    (conversion.Kind == SyntaxKind.InterpolatedStringText ||
                     semanticModel.IsImplicitConversion(((InterpolationSyntax)contents[i]).Expression, semanticModel.Compilation.GetSpecialType(SpecialType.System_String))))
                {
                    methodName = "AppendLine";
                }

                if (newExpression == null)
                {
                    newExpression = invocation
                                    .ReplaceNode(invocationInfo.Name, IdentifierName(methodName).WithTriviaFrom(invocationInfo.Name))
                                    .WithArgumentList(invocation.ArgumentList.WithArguments(arguments).WithoutTrailingTrivia());
                }
                else
                {
                    newExpression = SimpleMemberInvocationExpression(
                        newExpression,
                        IdentifierName(methodName),
                        ArgumentList(arguments));
                }

                if (i == contents.Count - 1 &&
                    isAppendLine &&
                    !string.Equals(methodName, "AppendLine", StringComparison.Ordinal))
                {
                    newExpression = SimpleMemberInvocationExpression(
                        newExpression,
                        IdentifierName("AppendLine"),
                        ArgumentList());
                }
            }

            return(newExpression);
        }
        public static bool IsFixable(
            MemberInvocationExpressionInfo invocationInfo,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

            SyntaxNode parent = invocationExpression.Parent;

            switch (parent?.Kind())
            {
            case SyntaxKind.ExpressionStatement:
            {
                var expressionStatement = (ExpressionStatementSyntax)parent;

                if (!(WalkDownMethodChain(invocationInfo).Expression is IdentifierNameSyntax identifierName))
                {
                    break;
                }

                string name = identifierName.Identifier.ValueText;

                return(WithoutAssignment.Analyze(invocationInfo, expressionStatement, name, semanticModel, cancellationToken));
            }

            case SyntaxKind.SimpleAssignmentExpression:
            {
                var assinmentExpression = (AssignmentExpressionSyntax)parent;

                if (!(assinmentExpression.Left is IdentifierNameSyntax identifierName))
                {
                    break;
                }

                if (assinmentExpression.Right != invocationExpression)
                {
                    break;
                }

                if (!(assinmentExpression.Parent is ExpressionStatementSyntax expressionStatement))
                {
                    break;
                }

                string name = identifierName.Identifier.ValueText;

                if (name != (WalkDownMethodChain(invocationInfo).Expression as IdentifierNameSyntax)?.Identifier.ValueText)
                {
                    break;
                }

                return(WithAssignment.Analyze(invocationInfo, expressionStatement, name, semanticModel, cancellationToken));
            }
            }

            return(false);
        }
        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)
            {
                BaseTypeDeclarationSyntax typeDeclaration = memberDeclaration.FirstAncestor <BaseTypeDeclarationSyntax>();

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

                if (typeDeclaration != null)
                {
                    MemberInvocationExpressionInfo invocationInfo = SyntaxInfo.MemberInvocationExpressionInfo(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);

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

                    TypeSyntax regexType = semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_RegularExpressions_Regex).ToMinimalTypeSyntax(semanticModel, typeDeclaration.SpanStart);

                    FieldDeclarationSyntax fieldDeclaration = FieldDeclaration(
                        (ShouldBeStatic(memberDeclaration, semanticModel, cancellationToken))
                            ? Modifiers.PrivateStaticReadOnly()
                            : Modifiers.PrivateReadOnly(),
                        regexType,
                        Identifier(fieldName),
                        EqualsValueClause(
                            ObjectCreationExpression(regexType, pair.ArgumentList2)));

                    SyntaxList <MemberDeclarationSyntax> newMembers = newTypeDeclaration
                                                                      .GetMembers()
                                                                      .InsertMember(fieldDeclaration, MemberDeclarationComparer.ByKind);

                    newTypeDeclaration = newTypeDeclaration.WithMembers(newMembers);

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

            return(document);
        }
 private static bool CheckSymbol(
     MemberInvocationExpressionInfo invocationInfo,
     SemanticModel semanticModel,
     CancellationToken cancellationToken)
 {
     return(semanticModel.TryGetMethodInfo(invocationInfo.InvocationExpression, out MethodInfo info, cancellationToken) &&
            info.IsPublicInstanceStringMethod() &&
            info.ReturnsString &&
            !info.Parameters.Any());
 }
        public bool Analyze(
            MemberInvocationExpressionInfo invocationInfo,
            StatementSyntax statement,
            string name,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (statement.SpanOrTrailingTriviaContainsDirectives())
            {
                return(false);
            }

            StatementsInfo statementsInfo = SyntaxInfo.StatementsInfo(statement);

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

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            if (statements.Count == 1)
            {
                return(false);
            }

            if (!semanticModel.TryGetMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, cancellationToken))
            {
                return(false);
            }

            ITypeSymbol typeSymbol = methodInfo.ReturnType;

            int i = statements.IndexOf(statement);

            if (i != 0 &&
                IsFixableStatement(statements[i - 1], name, typeSymbol, semanticModel, cancellationToken))
            {
                return(false);
            }

            int j = i;

            while (j < statements.Count - 1)
            {
                if (!IsFixableStatement(statements[j + 1], name, typeSymbol, semanticModel, cancellationToken))
                {
                    break;
                }

                j++;
            }

            return(j > i);
        }
예제 #15
0
        private static bool IsFixable(InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            MemberInvocationExpressionInfo invocationInfo = SyntaxInfo.MemberInvocationExpressionInfo(invocationExpression);

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

            if (!semanticModel.TryGetMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, cancellationToken))
            {
                return(false);
            }

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

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

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

                break;
            }

            case "Remove":
            {
                if (methodInfo.HasParameter(SpecialType.System_Int32))
                {
                    return(true);
                }

                break;
            }

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

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

            MemberInvocationExpressionInfo firstMemberInvocation = WalkDownMethodChain(invocationInfo);

            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

            return(invocationExpression
                   .ToString()
                   .Substring(firstMemberInvocation.OperatorToken.SpanStart - invocationExpression.SpanStart));
        }
예제 #17
0
        internal static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocationExpression = (InvocationExpressionSyntax)context.Node;

            if (!invocationExpression.ContainsDiagnostics &&
                !invocationExpression.SpanContainsDirectives())
            {
                MemberInvocationExpressionInfo invocationInfo = SyntaxInfo.MemberInvocationExpressionInfo(invocationExpression);
                if (invocationInfo.Success &&
                    invocationInfo.NameText == "Any")
                {
                    ArgumentSyntax argument1 = invocationInfo.Arguments.SingleOrDefault(shouldthrow: false);

                    if (argument1 != null)
                    {
                        MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo(invocationInfo.Expression);
                        if (invocationInfo2.Success &&
                            invocationInfo2.NameText == "Where")
                        {
                            ArgumentSyntax argument2 = invocationInfo2.Arguments.SingleOrDefault(shouldthrow: false);

                            if (argument2 != null)
                            {
                                SemanticModel     semanticModel     = context.SemanticModel;
                                CancellationToken cancellationToken = context.CancellationToken;

                                if (semanticModel.TryGetExtensionMethodInfo(invocationExpression, out MethodInfo methodInfo, ExtensionMethodKind.None, cancellationToken) &&
                                    methodInfo.IsLinqExtensionOfIEnumerableOfTWithPredicate("Any") &&
                                    semanticModel.TryGetExtensionMethodInfo(invocationInfo2.InvocationExpression, out MethodInfo methodInfo2, ExtensionMethodKind.None, cancellationToken) &&
                                    methodInfo2.IsLinqWhere(allowImmutableArrayExtension: true))
                                {
                                    SingleParameterLambdaExpressionInfo lambda = SyntaxInfo.SingleParameterLambdaExpressionInfo(argument1.Expression);
                                    if (lambda.Success &&
                                        lambda.Body is ExpressionSyntax)
                                    {
                                        SingleParameterLambdaExpressionInfo lambda2 = SyntaxInfo.SingleParameterLambdaExpressionInfo(argument2.Expression);
                                        if (lambda2.Success &&
                                            lambda2.Body is ExpressionSyntax &&
                                            lambda.ParameterName.Equals(lambda2.ParameterName, StringComparison.Ordinal))
                                        {
                                            context.ReportDiagnostic(
                                                DiagnosticDescriptors.SimplifyLinqMethodChain,
                                                Location.Create(context.SyntaxTree(), TextSpan.FromBounds(invocationInfo2.Name.SpanStart, invocationExpression.Span.End)));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #18
0
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

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

            var methodSymbol = semanticModel.GetSymbol(invocationExpression, cancellationToken) as IMethodSymbol;

            if (methodSymbol == null)
            {
                return;
            }

            if (!ExtensionMethodInfo.TryCreate(methodSymbol, semanticModel, out ExtensionMethodInfo extensionMethodInfo, ExtensionMethodKind.Reduced))
            {
                return;
            }

            if (!extensionMethodInfo.MethodInfo.IsLinqCast())
            {
                return;
            }

            ITypeSymbol typeArgument = extensionMethodInfo.ReducedSymbol.TypeArguments.SingleOrDefault(shouldThrow: false);

            if (typeArgument == null)
            {
                return;
            }

            var memberAccessExpressionType = semanticModel.GetTypeSymbol(invocationInfo.Expression, cancellationToken) as INamedTypeSymbol;

            if (memberAccessExpressionType?.IsConstructedFromIEnumerableOfT() != true)
            {
                return;
            }

            if (!typeArgument.Equals(memberAccessExpressionType.TypeArguments[0]))
            {
                return;
            }

            if (invocationExpression.ContainsDirectives(TextSpan.FromBounds(invocationInfo.Expression.Span.End, invocationExpression.Span.End)))
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.RemoveRedundantCast,
                Location.Create(invocationExpression.SyntaxTree, TextSpan.FromBounds(invocationInfo.Name.SpanStart, invocationInfo.ArgumentList.Span.End)));
        }
        internal static Task <Document> RefactorAsync(
            Document document,
            MemberInvocationExpressionInfo invocationInfo,
            string comparisonName,
            CancellationToken cancellationToken)
        {
            SeparatedSyntaxList <ArgumentSyntax> arguments = invocationInfo.Arguments;

            InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression;

            if (arguments.Count == 2)
            {
                ArgumentListSyntax newArgumentList = ArgumentList(
                    CreateArgument(arguments[0]),
                    CreateArgument(arguments[1]),
                    Argument(CreateStringComparison(comparisonName)));

                InvocationExpressionSyntax newNode = invocation.WithArgumentList(newArgumentList);

                return(document.ReplaceNodeAsync(invocation, newNode, cancellationToken));
            }
            else
            {
                var memberAccess  = (MemberAccessExpressionSyntax)invocation.Expression;
                var invocation2   = (InvocationExpressionSyntax)memberAccess.Expression;
                var memberAccess2 = (MemberAccessExpressionSyntax)invocation2.Expression;

                MemberAccessExpressionSyntax newMemberAccess = memberAccess.WithExpression(memberAccess2.Expression);

                bool isContains = memberAccess.Name.Identifier.ValueText == "Contains";

                if (isContains)
                {
                    newMemberAccess = newMemberAccess.WithName(newMemberAccess.Name.WithIdentifier(Identifier("IndexOf").WithTriviaFrom(newMemberAccess.Name.Identifier)));
                }

                ArgumentListSyntax newArgumentList = ArgumentList(
                    CreateArgument(arguments[0]),
                    Argument(CreateStringComparison(comparisonName)));

                ExpressionSyntax newNode = invocation
                                           .WithExpression(newMemberAccess)
                                           .WithArgumentList(newArgumentList);

                if (isContains)
                {
                    newNode = GreaterThanOrEqualExpression(newNode.Parenthesize(), NumericLiteralExpression(0)).Parenthesize();
                }

                return(document.ReplaceNodeAsync(invocation, newNode, cancellationToken));
            }
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            if (IsFixable(invocationInfo, context.SemanticModel, context.CancellationToken))
            {
                InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

                TextSpan span = TextSpan.FromBounds(invocationInfo.OperatorToken.Span.Start, invocationExpression.Span.End);

                if (!invocationExpression.ContainsDirectives(span))
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.RemoveRedundantToStringCall,
                        Location.Create(invocationExpression.SyntaxTree, span));
                }
            }
        }
        protected static MemberInvocationExpressionInfo WalkDownMethodChain(MemberInvocationExpressionInfo invocationInfo)
        {
            while (true)
            {
                MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo(invocationInfo.Expression);

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

            return(invocationInfo);
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            MemberInvocationExpressionInfo invocationInfo,
            ArgumentSyntax argument)
        {
            if (!(argument.Parent is ArgumentListSyntax argumentList))
            {
                return;
            }

            SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;

            if (arguments.Count != 2)
            {
                return;
            }

            MemberInvocationExpressionInfo equalsInvocation = SyntaxInfo.MemberInvocationExpressionInfo(argumentList.Parent);

            if (!equalsInvocation.Success)
            {
                return;
            }

            if (equalsInvocation.NameText != "Equals")
            {
                return;
            }

            if (!IsFixable(context, invocationInfo, argument, arguments))
            {
                return;
            }

            if (!context.SemanticModel.TryGetMethodInfo(equalsInvocation.InvocationExpression, out MethodInfo info, context.CancellationToken) ||
                !info.IsPublicStaticStringMethod("Equals") ||
                !info.ReturnsBoolean ||
                !info.HasParameters(SpecialType.System_String, SpecialType.System_String))
            {
                return;
            }

            ReportDiagnostic(context, equalsInvocation);
        }
예제 #23
0
        public static Task <Document> RefactorAsync(
            Document document,
            MemberInvocationExpressionInfo invocationInfo,
            CancellationToken cancellationToken)
        {
            MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo(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)
        {
            MemberInvocationExpressionInfo invocationInfo = SyntaxInfo.MemberInvocationExpressionInfo(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);
        }
        protected 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);
            }

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

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

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

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

            if (!semanticModel.TryGetMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, cancellationToken))
            {
                return(false);
            }

            return(!methodInfo.IsStatic &&
                   methodInfo.ContainingType?.Equals(typeSymbol) == true &&
                   methodInfo.ReturnType.Equals(typeSymbol));
        }
        private static bool RegisterCodeFix(
            CodeFixContext context,
            Diagnostic diagnostic,
            MemberInvocationExpressionInfo invocationInfo,
            INamedTypeSymbol comparisonSymbol,
            string comparisonName)
        {
            if (!comparisonSymbol.ExistsField(comparisonName))
            {
                return(false);
            }

            CodeAction codeAction = CodeAction.Create(
                GetTitle(comparisonName),
                cancellationToken => UseStringComparisonRefactoring.RefactorAsync(context.Document, invocationInfo, comparisonName, cancellationToken),
                GetEquivalenceKey(DiagnosticIdentifiers.UseStringComparison, comparisonName));

            context.RegisterCodeFix(codeAction, diagnostic);
            return(true);
        }
        private static bool IsFixable(
            MemberInvocationExpressionInfo invocationInfo,
            BinaryExpressionSyntax addExpression,
            ExpressionSyntax left,
            ExpressionSyntax right,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (semanticModel.GetTypeSymbol(left, cancellationToken)?.SpecialType == SpecialType.System_String)
            {
                BinaryExpressionSyntax newAddExpression = addExpression.ReplaceNode(right, invocationInfo.Expression);

                return(semanticModel
                       .GetSpeculativeMethodSymbol(addExpression.SpanStart, newAddExpression)?
                       .ContainingType?
                       .SpecialType == SpecialType.System_String);
            }

            return(false);
        }
예제 #28
0
        public static Task <Document> RefactorAsync(
            Document document,
            InvocationExpressionSyntax invocationExpression,
            CancellationToken cancellationToken)
        {
            MemberInvocationExpressionInfo invocationInfo  = SyntaxInfo.MemberInvocationExpressionInfo(invocationExpression);
            MemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.MemberInvocationExpressionInfo(invocationInfo.Expression);

            SingleParameterLambdaExpressionInfo lambda  = SyntaxInfo.SingleParameterLambdaExpressionInfo((LambdaExpressionSyntax)invocationInfo.Arguments.First().Expression);
            SingleParameterLambdaExpressionInfo lambda2 = SyntaxInfo.SingleParameterLambdaExpressionInfo((LambdaExpressionSyntax)invocationInfo2.Arguments.First().Expression);

            BinaryExpressionSyntax logicalAnd = CSharpFactory.LogicalAndExpression(
                ((ExpressionSyntax)lambda2.Body).Parenthesize(),
                ((ExpressionSyntax)lambda.Body).Parenthesize());

            InvocationExpressionSyntax newNode = invocationInfo2.InvocationExpression
                                                 .ReplaceNode(invocationInfo2.Name, invocationInfo.Name.WithTriviaFrom(invocationInfo2.Name))
                                                 .WithArgumentList(invocationInfo2.ArgumentList.ReplaceNode((ExpressionSyntax)lambda2.Body, logicalAnd));

            return(document.ReplaceNodeAsync(invocationExpression, newNode, cancellationToken));
        }
예제 #29
0
        public static bool CanRefactor(MemberInvocationExpressionInfo invocationInfo, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (invocationInfo.Expression?.IsMissing != false)
            {
                return(false);
            }

            if (!semanticModel.TryGetExtensionMethodInfo(invocationInfo.InvocationExpression, out MethodInfo methodInfo, ExtensionMethodKind.Reduced, cancellationToken))
            {
                return(false);
            }

            if (!methodInfo.IsLinqExtensionOfIEnumerableOfTWithoutParameters("First", allowImmutableArrayExtension: true))
            {
                return(false);
            }

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

            return(SymbolUtility.HasAccessibleIndexer(typeSymbol, semanticModel, invocationInfo.InvocationExpression.SpanStart));
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            MemberInvocationExpressionInfo invocationInfo,
            ExpressionSyntax leftOrRight,
            BinaryExpressionSyntax binaryExpression)
        {
            if (object.ReferenceEquals(leftOrRight, binaryExpression.Left))
            {
                ExpressionSyntax right = binaryExpression.Right?.WalkDownParentheses();

                if (right != null)
                {
                    SyntaxKind kind = right.Kind();

                    if (kind == SyntaxKind.InvocationExpression)
                    {
                        if (TryCreateCaseChangingInvocation(right, out MemberInvocationExpressionInfo invocationInfo2) &&
                            invocationInfo.NameText == invocationInfo2.NameText &&
                            CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken) &&
                            CheckSymbol(invocationInfo2, context.SemanticModel, context.CancellationToken))
                        {
                            ReportDiagnostic(context, binaryExpression);
                        }
                    }
                    else if (kind == SyntaxKind.StringLiteralExpression)
                    {
                        if (CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken))
                        {
                            ReportDiagnostic(context, binaryExpression);
                        }
                    }
                }
            }
            else if (binaryExpression.Left?.WalkDownParentheses().Kind() == SyntaxKind.StringLiteralExpression &&
                     CheckSymbol(invocationInfo, context.SemanticModel, context.CancellationToken))
            {
                ReportDiagnostic(context, binaryExpression);
            }
        }