private static InvocationExpressionSyntax GetNewInvocation(InvocationExpressionSyntax invocation)
        {
            ArgumentListSyntax argumentList = invocation.ArgumentList;
            SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;

            if (arguments.Count == 1)
            {
                ArgumentSyntax argument = arguments[0];
                arguments = arguments.ReplaceAt(0, argument.WithExpression(CSharpFactory.StringLiteralExpression("").WithTriviaFrom(argument.Expression)));
            }
            else
            {
                arguments = arguments.RemoveAt(0);
            }

            return(RefactoringUtility.ChangeInvokedMethodName(invocation, "Fail")
                   .WithArgumentList(argumentList.WithArguments(arguments)));
        }
Exemplo n.º 2
0
        private static Task <Document> SimplifyNullChckWithFirstOrDefault(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            NullCheckExpressionInfo nullCheck = NullCheckExpressionInfo(node, NullCheckStyles.ComparisonToNull | NullCheckStyles.IsNull);

            var invocation = (InvocationExpressionSyntax)nullCheck.Expression;

            ExpressionSyntax newNode = RefactoringUtility.ChangeInvokedMethodName(invocation, "Any");

            if (node.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.IsPatternExpression))
            {
                newNode = LogicalNotExpression(newNode.TrimTrivia().Parenthesize());
            }

            newNode = newNode.WithTriviaFrom(node);

            return(document.ReplaceNodeAsync(node, newNode, cancellationToken));
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            ConditionalExpressionInfo conditionalExpressionInfo,
            ExpressionSyntax whenNull,
            ExpressionSyntax whenNotNull,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(whenNotNull, cancellationToken);

            if (typeSymbol?.IsErrorType() == false &&
                (typeSymbol.IsReferenceType || typeSymbol.IsValueType) &&
                semanticModel.IsDefaultValue(typeSymbol, whenNull, cancellationToken) &&
                !RefactoringUtility.ContainsOutArgumentWithLocal(whenNotNull, semanticModel, cancellationToken) &&
                !conditionalExpressionInfo.ConditionalExpression.IsInExpressionTree(semanticModel, cancellationToken))
            {
                context.ReportDiagnostic(
                    DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression,
                    conditionalExpressionInfo.ConditionalExpression);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out InvocationExpressionSyntax invocation))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.CombineEnumerableWhereMethodChain:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Combine 'Where' method chain",
                        cancellationToken => CombineEnumerableWhereMethodChainRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfAnyMethod:
                {
                    string propertyName = diagnostic.Properties["PropertyName"];

                    CodeAction codeAction = CodeAction.Create(
                        $"Use '{propertyName}' property instead of calling 'Any'",
                        cancellationToken => UseCountOrLengthPropertyInsteadOfAnyMethodRefactoring.RefactorAsync(context.Document, invocation, propertyName, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfCountMethod:
                {
                    string propertyName = diagnostic.Properties["PropertyName"];

                    CodeAction codeAction = CodeAction.Create(
                        $"Use '{propertyName}' property instead of calling 'Count'",
                        cancellationToken => UseCountOrLengthPropertyInsteadOfCountMethodRefactoring.RefactorAsync(context.Document, invocation, diagnostic.Properties["PropertyName"], cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseBitwiseOperationInsteadOfCallingHasFlag:
                {
                    CodeAction codeAction = CodeAction.Create(
                        UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.Title,
                        cancellationToken => UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.RemoveRedundantToStringCall:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Remove redundant 'ToString' call",
                        cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallCastInsteadOfSelect:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Cast' instead of 'Select'",
                        cancellationToken => CallCastInsteadOfSelectRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.RemoveRedundantStringToCharArrayCall:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Remove redundant 'ToCharArray' call",
                        cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallFindInsteadOfFirstOrDefault:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Find' instead of 'FirstOrDefault'",
                        cancellationToken => CallFindInsteadOfFirstOrDefaultRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseElementAccessInsteadOfElementAt:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use [] instead of calling 'ElementAt'",
                        cancellationToken => UseElementAccessInsteadOfElementAtRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseElementAccessInsteadOfFirst:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use [] instead of calling 'First'",
                        cancellationToken => UseElementAccessInsteadOfFirstRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallStringConcatInsteadOfStringJoin:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Concat' instead of 'Join'",
                        cancellationToken => CallStringConcatInsteadOfStringJoinRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallDebugFailInsteadOfDebugAssert:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Fail' instead of 'Assert'",
                        cancellationToken => CallDebugFailInsteadOfDebugAssertRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallExtensionMethodAsInstanceMethod:
                {
                    CodeAction codeAction = CodeAction.Create(
                        CallExtensionMethodAsInstanceMethodRefactoring.Title,
                        cancellationToken => CallExtensionMethodAsInstanceMethodRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallThenByInsteadOfOrderBy:
                {
                    SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

                    string oldName = invocationInfo.NameText;

                    string newName = (string.Equals(oldName, "OrderBy", StringComparison.Ordinal))
                                ? "ThenBy"
                                : "ThenByDescending";

                    CodeAction codeAction = CodeAction.Create(
                        $"Call '{newName}' instead of '{oldName}'",
                        cancellationToken => CallThenByInsteadOfOrderByRefactoring.RefactorAsync(context.Document, invocation, newName, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
Exemplo n.º 5
0
        private static async Task <Document> RefactorAsync(
            Document document,
            StringConcatenationExpressionInfo concatenationInfo,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

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

            IdentifierNameSyntax stringBuilderName = IdentifierName(name);

            TypeSyntax type = semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_StringBuilder).ToMinimalTypeSyntax(semanticModel, statement.SpanStart);

            var statements = new List <StatementSyntax>()
            {
                LocalDeclarationStatement(VarType(), Identifier(name).WithRenameAnnotation(), ObjectCreationExpression(type, ArgumentList())).WithLeadingTrivia(statement.GetLeadingTrivia())
            };

            ExpressionSyntax newInvocation = null;

            foreach (ExpressionSyntax expression in concatenationInfo.Expressions(leftToRight: true))
            {
                if (expression.IsKind(SyntaxKind.InterpolatedStringExpression))
                {
                    var interpolatedString = (InterpolatedStringExpressionSyntax)expression;

                    bool isVerbatim = interpolatedString.IsVerbatim();

                    SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

                    for (int j = 0; j < contents.Count; j++)
                    {
                        (SyntaxKind contentKind, string methodName, ImmutableArray <ArgumentSyntax> arguments) = RefactoringUtility.ConvertInterpolatedStringToStringBuilderMethod(contents[j], isVerbatim);

                        newInvocation = SimpleMemberInvocationExpression(
                            newInvocation ?? stringBuilderName,
                            IdentifierName(methodName),
                            ArgumentList(arguments.ToSeparatedSyntaxList()));
                    }
                }
                else
                {
                    newInvocation = SimpleMemberInvocationExpression(
                        newInvocation ?? stringBuilderName,
                        IdentifierName("Append"),
                        Argument(expression.WithoutTrivia()));
                }
            }

            statements.Add(ExpressionStatement(newInvocation));

            statements.Add(statement
                           .ReplaceNode(concatenationInfo.BinaryExpression, SimpleMemberInvocationExpression(stringBuilderName, IdentifierName("ToString")))
                           .WithTrailingTrivia(statement.GetTrailingTrivia())
                           .WithoutLeadingTrivia());

            if (statement.IsEmbedded())
            {
                BlockSyntax block = Block(statements).WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(statement, block, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                for (int i = 0; i < statements.Count; i++)
                {
                    statements[i] = statements[i].WithFormatterAnnotation();
                }

                return(await document.ReplaceNodeAsync(statement, statements, cancellationToken).ConfigureAwait(false));
            }
        }
        private static InvocationExpressionSyntax ConvertInterpolatedStringExpressionToInvocationExpression(
            InterpolatedStringExpressionSyntax interpolatedString,
            SimpleMemberInvocationExpressionInfo 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++)
            {
                (SyntaxKind contentKind, string methodName, ImmutableArray <ArgumentSyntax> arguments) = RefactoringUtility.ConvertInterpolatedStringToStringBuilderMethod(contents[i], isVerbatim);

                if (i == contents.Count - 1 &&
                    isAppendLine &&
                    string.Equals(methodName, "Append", StringComparison.Ordinal) &&
                    (contentKind == 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.ToSeparatedSyntaxList()).WithoutTrailingTrivia());
                }
                else
                {
                    newExpression = SimpleMemberInvocationExpression(
                        newExpression,
                        IdentifierName(methodName),
                        ArgumentList(arguments.ToSeparatedSyntaxList()));
                }

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

            return(newExpression);
        }