Пример #1
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxToken token)
        {
            if (context.IsAnyRefactoringEnabled(
                    RefactoringDescriptors.JoinStringExpressions,
                    RefactoringDescriptors.UseStringBuilderInsteadOfConcatenation) &&
                context.Span.IsEmptyAndContainedInSpan(token) &&
                token.IsParentKind(SyntaxKind.AddExpression))
            {
                var addExpression = (BinaryExpressionSyntax)token.Parent;

                while (addExpression.IsParentKind(SyntaxKind.AddExpression))
                {
                    addExpression = (BinaryExpressionSyntax)addExpression.Parent;
                }

                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(addExpression, semanticModel, context.CancellationToken);

                if (concatenationInfo.Success)
                {
                    if (context.IsRefactoringEnabled(RefactoringDescriptors.JoinStringExpressions))
                    {
                        JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo);
                    }

                    if (context.IsRefactoringEnabled(RefactoringDescriptors.UseStringBuilderInsteadOfConcatenation))
                    {
                        UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo);
                    }
                }
            }
        }
        public static void ComputeRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo)
        {
            if (concatenationInfo.ContainsNonLiteralExpression)
            {
                if (concatenationInfo.ContainsLiteralExpression || concatenationInfo.ContainsInterpolatedStringExpression)
                {
                    context.RegisterRefactoring(
                        "Join string expressions",
                        cancellationToken => ToInterpolatedStringAsync(context.Document, concatenationInfo, cancellationToken));
                }
            }
            else if (concatenationInfo.ContainsLiteralExpression)
            {
                context.RegisterRefactoring(
                    "Join string literals",
                    cancellationToken => ToStringLiteralAsync(context.Document, concatenationInfo, multiline: false, cancellationToken: cancellationToken));

                if (concatenationInfo.OriginalExpression
                    .DescendantTrivia(concatenationInfo.Span ?? concatenationInfo.OriginalExpression.Span)
                    .Any(f => f.IsEndOfLineTrivia()))
                {
                    context.RegisterRefactoring(
                        "Join string literals into multiline string literal",
                        cancellationToken => ToStringLiteralAsync(context.Document, concatenationInfo, multiline: true, cancellationToken: cancellationToken));
                }
            }
        }
        public static void ComputeRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo)
        {
            StringConcatenationAnalysis analysis = concatenationInfo.Analyze();

            if (analysis.ContainsNonStringLiteral)
            {
                if (analysis.ContainsStringLiteral || analysis.ContainsInterpolatedString)
                {
                    context.RegisterRefactoring(
                        "Join string expressions",
                        cancellationToken => ToInterpolatedStringAsync(context.Document, concatenationInfo, cancellationToken),
                        RefactoringIdentifiers.JoinStringExpressions);
                }
            }
            else if (analysis.ContainsStringLiteral)
            {
                context.RegisterRefactoring(
                    "Join string literals",
                    cancellationToken => ToStringLiteralAsync(context.Document, concatenationInfo, multiline: false, cancellationToken: cancellationToken),
                    RefactoringIdentifiers.JoinStringExpressions);

                if (concatenationInfo.BinaryExpression
                    .DescendantTrivia(concatenationInfo.Span ?? concatenationInfo.BinaryExpression.Span)
                    .Any(f => f.IsEndOfLineTrivia()))
                {
                    context.RegisterRefactoring(
                        "Join string literals into multiline string literal",
                        cancellationToken => ToStringLiteralAsync(context.Document, concatenationInfo, multiline: true, cancellationToken: cancellationToken),
                        EquivalenceKey.Join(RefactoringIdentifiers.JoinStringExpressions, "Multiline"));
                }
            }
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, cancellationToken);

            StringConcatenationAnalysis analysis = concatenationInfo.Analyze();

            ExpressionSyntax newNode;

            if (analysis.ContainsStringLiteral)
            {
                if (analysis.ContainsVerbatimExpression &&
                    concatenationInfo.ContainsMultiLineExpression())
                {
                    newNode = concatenationInfo.ToMultiLineStringLiteralExpression();
                }
                else
                {
                    newNode = concatenationInfo.ToStringLiteralExpression();
                }
            }
            else
            {
                newNode = concatenationInfo.ToInterpolatedStringExpression();
            }

            newNode = newNode.WithTriviaFrom(binaryExpression);

            return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false));
        }
        public static void AnalyzeAddExpression(SyntaxNodeAnalysisContext context)
        {
            SyntaxNode node = context.Node;

            if (node.ContainsDiagnostics)
            {
                return;
            }

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

            var addExpression = (BinaryExpressionSyntax)node;

            StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(addExpression, context.SemanticModel, context.CancellationToken);

            if (concatenationInfo.Success &&
                !concatenationInfo.ContainsNonSpecificExpression &&
                (concatenationInfo.ContainsLiteralExpression ^ concatenationInfo.ContainsInterpolatedStringExpression) &&
                (concatenationInfo.ContainsRegular ^ concatenationInfo.ContainsVerbatim) &&
                (concatenationInfo.ContainsVerbatim || addExpression.IsSingleLine(includeExteriorTrivia: false, cancellationToken: context.CancellationToken)))
            {
                context.ReportDiagnostic(DiagnosticDescriptors.JoinStringExpressions, addExpression);
            }
        }
Пример #6
0
        private static Task <Document> RefactorAsync(
            Document document,
            StringConcatenationExpressionInfo concatenationInfo,
            ExpressionSyntax expression,
            CancellationToken cancellationToken)
        {
            if (concatenationInfo.Span.HasValue)
            {
                TextSpan span = concatenationInfo.Span.Value;

                int start = concatenationInfo.BinaryExpression.SpanStart;

                string s = concatenationInfo.BinaryExpression.ToString();

                s = s.Remove(span.Start - start)
                    + expression
                    + s.Substring(span.End - start);

                expression = SyntaxFactory.ParseExpression(s);
            }

            expression = expression
                         .WithTriviaFrom(concatenationInfo.BinaryExpression)
                         .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(concatenationInfo.BinaryExpression, expression, cancellationToken));
        }
 private static void RegisterRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo, StatementSyntax statement)
 {
     context.RegisterRefactoring(
         "Use StringBuilder instead of concatenation",
         cancellationToken => RefactorAsync(context.Document, concatenationInfo, statement, cancellationToken),
         RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation);
 }
Пример #8
0
        private static Task <Document> ToInterpolatedStringAsync(
            Document document,
            StringConcatenationExpressionInfo concatenationInfo,
            CancellationToken cancellationToken)
        {
            InterpolatedStringExpressionSyntax newExpression = concatenationInfo.ToInterpolatedStringExpression();

            return(RefactorAsync(document, concatenationInfo, newExpression, cancellationToken));
        }
        private static bool ContainsMultiLine(StringConcatenationExpressionInfo concatenationInfo, CancellationToken cancellationToken)
        {
            foreach (ExpressionSyntax expression in concatenationInfo.Expressions)
            {
                if (expression.IsMultiLine(includeExteriorTrivia: false, cancellationToken: cancellationToken))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #10
0
        public static Task <Document> ToStringLiteralAsync(
            Document document,
            StringConcatenationExpressionInfo concatenationInfo,
            bool multiline,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            ExpressionSyntax newExpression = (multiline)
                ? concatenationInfo.ToMultiLineStringLiteralExpression()
                : concatenationInfo.ToStringLiteralExpression();

            return(RefactorAsync(document, concatenationInfo, newExpression, cancellationToken));
        }
        public static void ComputeRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo)
        {
            BinaryExpressionSyntax expression = concatenationInfo.OriginalExpression;

            switch (expression.Parent.Kind())
            {
            case SyntaxKind.SimpleAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            {
                var assignment = (AssignmentExpressionSyntax)expression.Parent;

                if (assignment.IsParentKind(SyntaxKind.ExpressionStatement) &&
                    assignment.Right == expression)
                {
                    RegisterRefactoring(context, concatenationInfo, (StatementSyntax)assignment.Parent);
                }

                break;
            }

            case SyntaxKind.EqualsValueClause:
            {
                var equalsValue = (EqualsValueClauseSyntax)expression.Parent;

                if (equalsValue.IsParentKind(SyntaxKind.VariableDeclarator))
                {
                    var variableDeclarator = (VariableDeclaratorSyntax)equalsValue.Parent;

                    if (variableDeclarator.IsParentKind(SyntaxKind.VariableDeclaration))
                    {
                        var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;

                        if (variableDeclaration.IsParentKind(SyntaxKind.LocalDeclarationStatement) &&
                            variableDeclaration.Variables.Count == 1)
                        {
                            RegisterRefactoring(context, concatenationInfo, (StatementSyntax)variableDeclaration.Parent);
                        }
                    }
                }

                break;
            }
            }
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, cancellationToken);

            if (concatenationInfo.Success)
            {
                ExpressionSyntax newNode = null;

                if (concatenationInfo.ContainsLiteralExpression)
                {
                    if (concatenationInfo.ContainsVerbatim &&
                        ContainsMultiLine(concatenationInfo, cancellationToken))
                    {
                        newNode = concatenationInfo.ToMultilineStringLiteral();
                    }
                    else
                    {
                        newNode = concatenationInfo.ToStringLiteral();
                    }
                }
                else
                {
                    newNode = concatenationInfo.ToInterpolatedString();
                }

                newNode = newNode.WithTriviaFrom(binaryExpression);

                return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false));
            }

            Debug.Fail(binaryExpression.ToString());

            return(document);
        }
Пример #13
0
        public static void ComputeRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo)
        {
            BinaryExpressionSyntax binaryExpression = concatenationInfo.BinaryExpression;

            if (binaryExpression.IsParentKind(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression))
            {
                var assignment = (AssignmentExpressionSyntax)binaryExpression.Parent;

                if (assignment.IsParentKind(SyntaxKind.ExpressionStatement) &&
                    assignment.Right == binaryExpression)
                {
                    RegisterRefactoring(context, concatenationInfo, (StatementSyntax)assignment.Parent);
                }
            }
            else
            {
                SingleLocalDeclarationStatementInfo info = SyntaxInfo.SingleLocalDeclarationStatementInfo(binaryExpression);

                if (info.Success)
                {
                    RegisterRefactoring(context, concatenationInfo, info.Statement);
                }
            }
        }
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression)
        {
            if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateOperator))
            {
                SyntaxToken operatorToken = binaryExpression.OperatorToken;

                if (operatorToken.Span.Contains(context.Span) &&
                    NegateOperatorRefactoring.CanBeNegated(operatorToken))
                {
                    context.RegisterRefactoring(
                        "Negate operator",
                        cancellationToken => NegateOperatorRefactoring.RefactorAsync(context.Document, operatorToken, cancellationToken));
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.FormatBinaryExpression))
            {
                FormatBinaryExpressionRefactoring.ComputeRefactorings(context, binaryExpression);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateBinaryExpression))
            {
                NegateBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandCoalesceExpression) &&
                binaryExpression.OperatorToken.Span.Contains(context.Span))
            {
                ExpandCoalesceExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.JoinStringExpressions,
                    RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation) &&
                context.Span.IsBetweenSpans(binaryExpression) &&
                binaryExpression.IsKind(SyntaxKind.AddExpression))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, context.CancellationToken);
                if (concatenationInfo.Success)
                {
                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions))
                    {
                        JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo);
                    }

                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation))
                    {
                        UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo);
                    }
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapExpressionsInBinaryExpression) &&
                context.Span.IsBetweenSpans(binaryExpression))
            {
                SwapExpressionsInBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceAsWithCast) &&
                context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(binaryExpression))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                if (ReplaceAsWithCastRefactoring.CanRefactor(binaryExpression, semanticModel, context.CancellationToken))
                {
                    context.RegisterRefactoring(
                        "Replace as with cast",
                        cancellationToken => ReplaceAsWithCastRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken));
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateIsExpression))
            {
                NegateIsExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.Span.IsContainedInSpanOrBetweenSpans(binaryExpression.OperatorToken))
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringEquals))
                {
                    await ReplaceEqualsExpressionWithStringEqualsRefactoring.ComputeRefactoringAsync(context, binaryExpression).ConfigureAwait(false);
                }

                if (context.IsAnyRefactoringEnabled(
                        RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrEmpty,
                        RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrWhiteSpace))
                {
                    await ReplaceEqualsExpressionRefactoring.ComputeRefactoringsAsync(context, binaryExpression).ConfigureAwait(false);
                }
            }

            if (!context.Span.IsBetweenSpans(binaryExpression) &&
                context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.ExtractExpressionFromCondition,
                    RefactoringIdentifiers.JoinStringExpressions))
            {
                BinaryExpressionSelection binaryExpressionSelection = BinaryExpressionSelection.Create(binaryExpression, context.Span);

                if (binaryExpressionSelection.Expressions.Length > 1)
                {
                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExtractExpressionFromCondition))
                    {
                        ExtractConditionRefactoring.ComputeRefactoring(context, binaryExpressionSelection);
                    }

                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions) &&
                        binaryExpression.IsKind(SyntaxKind.AddExpression))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        StringConcatenationExpressionInfo concatenation = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpressionSelection, semanticModel, context.CancellationToken);
                        if (concatenation.Success)
                        {
                            JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenation);
                        }
                    }
                }
            }
        }
Пример #15
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression)
        {
            SyntaxToken operatorToken = binaryExpression.OperatorToken;

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertOperator) &&
                context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(operatorToken) &&
                InvertOperatorRefactoring.CanBeInverted(operatorToken))
            {
                context.RegisterRefactoring(
                    "Invert operator",
                    cancellationToken => InvertOperatorRefactoring.RefactorAsync(context.Document, operatorToken, cancellationToken),
                    RefactoringIdentifiers.InvertOperator);
            }

            if (context.Span.IsEmptyAndContainedInSpan(operatorToken))
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertBinaryExpression))
                {
                    InvertBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
                }

                if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapBinaryOperands))
                {
                    SwapBinaryOperandsRefactoring.ComputeRefactoring(context, binaryExpression);
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.FormatBinaryExpression))
            {
                FormatBinaryExpressionRefactoring.ComputeRefactorings(context, binaryExpression);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandCoalesceExpression) &&
                operatorToken.Span.Contains(context.Span))
            {
                ExpandCoalesceExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.ExtractExpressionFromCondition,
                    RefactoringIdentifiers.JoinStringExpressions,
                    RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation) &&
                !context.Span.IsEmpty &&
                binaryExpression.IsKind(SyntaxKind.AddExpression, SyntaxKind.LogicalAndExpression, SyntaxKind.LogicalOrExpression))
            {
                ExpressionChain chain = binaryExpression.AsChain(context.Span);

                ExpressionChain.Enumerator en = chain.GetEnumerator();

                if (en.MoveNext() &&
                    en.MoveNext())
                {
                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExtractExpressionFromCondition))
                    {
                        ExtractConditionRefactoring.ComputeRefactoring(context, chain);
                    }

                    if (binaryExpression.IsKind(SyntaxKind.AddExpression))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(chain, semanticModel, context.CancellationToken);
                        if (concatenationInfo.Success)
                        {
                            if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions))
                            {
                                JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo);
                            }

                            if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation))
                            {
                                UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo);
                            }
                        }
                    }
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceAsWithCast) &&
                context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(binaryExpression))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                if (ReplaceAsWithCastAnalysis.IsFixable(binaryExpression, semanticModel, context.CancellationToken))
                {
                    context.RegisterRefactoring(
                        ReplaceAsWithCastRefactoring.Title,
                        cancellationToken => ReplaceAsWithCastRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        RefactoringIdentifiers.ReplaceAsWithCast);
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertIsExpression))
            {
                InvertIsExpressionRefactoring.ComputeRefactoring(context, binaryExpression);
            }

            if (context.Span.IsContainedInSpanOrBetweenSpans(operatorToken))
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringEquals))
                {
                    await ReplaceEqualsExpressionWithStringEqualsRefactoring.ComputeRefactoringAsync(context, binaryExpression).ConfigureAwait(false);
                }

                if (context.IsAnyRefactoringEnabled(
                        RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrEmpty,
                        RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrWhiteSpace))
                {
                    await ReplaceEqualsExpressionRefactoring.ComputeRefactoringsAsync(context, binaryExpression).ConfigureAwait(false);
                }
            }
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            INamedTypeSymbol stringBuilderSymbol = context.GetTypeByMetadataName(MetadataNames.System_Text_StringBuilder);

            if (stringBuilderSymbol != null)
            {
                InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

                if (context.SemanticModel.TryGetMethodInfo(invocationExpression, out MethodInfo methodInfo, context.CancellationToken) &&
                    !methodInfo.IsExtensionMethod &&
                    methodInfo.ContainingType?.Equals(stringBuilderSymbol) == true)
                {
                    ImmutableArray <IParameterSymbol>    parameters = methodInfo.Parameters;
                    SeparatedSyntaxList <ArgumentSyntax> arguments  = invocationInfo.Arguments;

                    if (parameters.Length == 1 &&
                        arguments.Count == 1 &&
                        methodInfo.IsName("Append", "AppendLine"))
                    {
                        ArgumentSyntax argument = arguments.First();

                        ExpressionSyntax expression = argument.Expression;

                        SyntaxKind expressionKind = expression.Kind();

                        switch (expressionKind)
                        {
                        case SyntaxKind.InterpolatedStringExpression:
                        {
                            context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                            return;
                        }

                        case SyntaxKind.AddExpression:
                        {
                            StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo((BinaryExpressionSyntax)expression, context.SemanticModel, context.CancellationToken);
                            if (concatenationInfo.Success)
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                                return;
                            }

                            break;
                        }

                        default:
                        {
                            if (expressionKind == SyntaxKind.InvocationExpression &&
                                IsFixable((InvocationExpressionSyntax)expression, context.SemanticModel, context.CancellationToken))
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                                return;
                            }

                            if (methodInfo.IsName("Append") &&
                                parameters.Length == 1 &&
                                parameters[0].Type.IsObject() &&
                                context.SemanticModel.GetTypeSymbol(argument.Expression, context.CancellationToken).IsValueType)
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, argument);
                                return;
                            }

                            break;
                        }
                        }
                    }
                    else if (parameters.Length > 1 &&
                             methodInfo.IsName("Insert") &&
                             methodInfo.HasParameters(SpecialType.System_Int32, SpecialType.System_Object) &&
                             context.SemanticModel
                             .GetTypeSymbol(arguments[1].Expression, context.CancellationToken)
                             .IsValueType)
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, arguments[1]);
                    }
                }
            }
        }
        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())
            };

            ImmutableArray <ExpressionSyntax> expressions = concatenationInfo.Expressions;

            ExpressionSyntax newInvocation = null;

            for (int i = 0; i < expressions.Length; i++)
            {
                if (expressions[i].IsKind(SyntaxKind.InterpolatedStringExpression))
                {
                    var interpolatedString = (InterpolatedStringExpressionSyntax)expressions[i];

                    bool isVerbatim = interpolatedString.IsVerbatim();

                    SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

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

                        newInvocation = SimpleMemberInvocationExpression(
                            newInvocation ?? stringBuilderName,
                            IdentifierName(conversion.MethodName),
                            ArgumentList(conversion.Arguments));
                    }
                }
                else
                {
                    newInvocation = SimpleMemberInvocationExpression(
                        newInvocation ?? stringBuilderName,
                        IdentifierName("Append"),
                        Argument(expressions[i].WithoutTrivia()));
                }
            }

            statements.Add(ExpressionStatement(newInvocation));

            statements.Add(statement
                           .ReplaceNode(concatenationInfo.OriginalExpression, 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));
            }
        }