private static bool CanReplaceInterpolationWithStringLiteralInnerText(SeparatedSyntaxList <ArgumentSyntax> arguments, bool isVerbatim)
        {
            bool result = false;

            for (int i = 1; i < arguments.Count; i++)
            {
                ExpressionSyntax expression = arguments[i].Expression;

                StringLiteralExpressionInfo info = SyntaxInfo.StringLiteralExpressionInfo(expression);

                if (info.Success)
                {
                    if (isVerbatim == info.IsVerbatim &&
                        info.Expression.GetLeadingTrivia().IsEmptyOrWhitespace() &&
                        info.Expression.GetTrailingTrivia().IsEmptyOrWhitespace())
                    {
                        result = true;
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            return(result);
        }
        public static void AnalyzeInterpolation(SyntaxNodeAnalysisContext context)
        {
            var interpolation = (InterpolationSyntax)context.Node;

            if (interpolation.AlignmentClause != null)
            {
                return;
            }

            if (interpolation.FormatClause != null)
            {
                return;
            }

            StringLiteralExpressionInfo stringLiteralInfo = SyntaxInfo.StringLiteralExpressionInfo(interpolation.Expression);

            if (!stringLiteralInfo.Success)
            {
                return;
            }

            if (!(interpolation.Parent is InterpolatedStringExpressionSyntax interpolatedString))
            {
                return;
            }

            if (interpolatedString.StringStartToken.ValueText.Contains("@") != stringLiteralInfo.IsVerbatim)
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UnnecessaryInterpolation, interpolation);
        }
Example #3
0
        public void Append(LiteralExpressionSyntax stringLiteral)
        {
            if (stringLiteral == null)
            {
                return;
            }

            if (!stringLiteral.IsKind(SyntaxKind.StringLiteralExpression))
            {
                throw new ArgumentException("", nameof(stringLiteral));
            }

            StringLiteralExpressionInfo literalInfo = SyntaxInfo.StringLiteralExpressionInfo(stringLiteral);
            bool isVerbatim = literalInfo.IsVerbatim;

            if (IsVerbatim == isVerbatim)
            {
                string text = literalInfo.Text;

                int length = text.Length;

                if (length == 0)
                {
                    return;
                }

                int startIndex = StringBuilder.Length;

                if (isVerbatim)
                {
                    StringBuilder.Append(text, 2, length - 3);
                }
                else
                {
                    StringBuilder.Append(text, 1, length - 2);
                }

                if (IsInterpolated)
                {
                    StringBuilder.Replace("{", "{{", startIndex);
                    StringBuilder.Replace("}", "}}", startIndex);
                }
            }
            else
            {
                Append(literalInfo.ValueText);
            }
        }
Example #4
0
        private static int GetStartIndex(StringLiteralExpressionInfo info, TextSpan span)
        {
            int spanStart = info.Expression.SpanStart;

            int index = span.Start - spanStart;

            string text = info.Text;

            if (info.IsVerbatim)
            {
                if (index > 1 &&
                    StringLiteralParser.CanExtractSpan(text, 2, text.Length - 3, span.Offset(-spanStart), isVerbatim: true, isInterpolatedText: false))
                {
                    return(index);
                }
            }
            else if (index > 0 &&
                     StringLiteralParser.CanExtractSpan(text, 1, text.Length - 2, span.Offset(-spanStart), isVerbatim: false, isInterpolatedText: false))
            {
                return(index);
            }

            return(-1);
        }
Example #5
0
        private static void AnalyzeAddExpression(SyntaxNodeAnalysisContext context)
        {
            SyntaxNode node = context.Node;

            if (node.ContainsDiagnostics)
            {
                return;
            }

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

            if (node.IsParentKind(SyntaxKind.AddExpression))
            {
                return;
            }

            var addExpression = (BinaryExpressionSyntax)node;

            ExpressionSyntax firstExpression = null;
            ExpressionSyntax lastExpression  = null;
            bool             isLiteral       = false;
            bool             isVerbatim      = false;

            foreach (ExpressionSyntax expression in addExpression.AsChain().Reverse())
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                switch (expression.Kind())
                {
                case SyntaxKind.StringLiteralExpression:
                {
                    StringLiteralExpressionInfo stringLiteral = SyntaxInfo.StringLiteralExpressionInfo(expression);

                    bool isVerbatim2 = stringLiteral.IsVerbatim;

                    if (firstExpression == null)
                    {
                        firstExpression = expression;
                        isLiteral       = true;
                        isVerbatim      = isVerbatim2;
                    }
                    else if (!isLiteral ||
                             isVerbatim != isVerbatim2 ||
                             (!isVerbatim && !CheckHexadecimalEscapeSequence(stringLiteral)))
                    {
                        if (lastExpression != null)
                        {
                            Analyze(context, firstExpression, lastExpression, isVerbatim);
                        }

                        firstExpression = null;
                        lastExpression  = null;
                    }
                    else
                    {
                        lastExpression = expression;
                    }

                    break;
                }

                case SyntaxKind.InterpolatedStringExpression:
                {
                    var interpolatedString = ((InterpolatedStringExpressionSyntax)expression);

                    bool isVerbatim2 = interpolatedString.IsVerbatim();

                    if (firstExpression == null)
                    {
                        firstExpression = expression;
                        isLiteral       = false;
                        isVerbatim      = isVerbatim2;
                    }
                    else if (isLiteral ||
                             isVerbatim != isVerbatim2 ||
                             (!isVerbatim && !CheckHexadecimalEscapeSequence(interpolatedString)))
                    {
                        if (lastExpression != null)
                        {
                            Analyze(context, firstExpression, lastExpression, isVerbatim);
                        }

                        firstExpression = null;
                        lastExpression  = null;
                    }
                    else
                    {
                        lastExpression = expression;
                    }

                    break;
                }

                default:
                {
                    if (lastExpression != null)
                    {
                        Analyze(context, firstExpression, lastExpression, isVerbatim);
                    }

                    firstExpression = null;
                    lastExpression  = null;
                    break;
                }
                }
            }

            if (lastExpression != null)
            {
                Analyze(context, firstExpression, lastExpression, isVerbatim);
            }
        }
        private static InterpolatedStringExpressionSyntax ReplaceInterpolationWithStringLiteralInnerText(
            SeparatedSyntaxList <ArgumentSyntax> arguments,
            InterpolatedStringExpressionSyntax interpolatedString,
            string text)
        {
            StringBuilder sb = StringBuilderCache.GetInstance();

            int pos = 0;

            SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

            for (int i = 0; i < contents.Count; i++)
            {
                if (contents[i].Kind() != SyntaxKind.Interpolation)
                {
                    continue;
                }

                var interpolation = (InterpolationSyntax)contents[i];

                ExpressionSyntax expression = interpolation.Expression;

                if (expression?.Kind() != SyntaxKind.NumericLiteralExpression)
                {
                    continue;
                }

                var index = (int)((LiteralExpressionSyntax)expression).Token.Value;

                if (index < 0)
                {
                    continue;
                }

                if (index >= arguments.Count)
                {
                    continue;
                }

                ExpressionSyntax argumentExpression = arguments[index + 1].Expression;

                StringLiteralExpressionInfo stringLiteral = SyntaxInfo.StringLiteralExpressionInfo(argumentExpression);

                if (!stringLiteral.Success)
                {
                    continue;
                }

                sb.Append(text, pos, interpolation.SpanStart - pos);

                int startIndex = sb.Length;
                sb.Append(stringLiteral.InnerText);
                sb.Replace("{", "{{", startIndex);
                sb.Replace("}", "}}", startIndex);

                pos = interpolation.Span.End;
            }

            sb.Append(text, pos, text.Length - pos);

            return((InterpolatedStringExpressionSyntax)ParseExpression(StringBuilderCache.GetStringAndFree(sb)));
        }
Example #7
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, LiteralExpressionSyntax literalExpression)
        {
            StringLiteralExpressionInfo info = SyntaxInfo.StringLiteralExpressionInfo(literalExpression);

            Debug.Assert(info.Success);

            if (!info.Success)
            {
                return;
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.InsertStringInterpolation) &&
                context.SupportsCSharp6 &&
                context.Span.End < literalExpression.Span.End)
            {
                int startIndex = GetStartIndex(info, context.Span);

                if (startIndex != -1)
                {
                    context.RegisterRefactoring(
                        "Insert interpolation",
                        cancellationToken =>
                    {
                        return(ReplaceWithInterpolatedStringAsync(
                                   context.Document,
                                   literalExpression,
                                   startIndex,
                                   context.Span.Length,
                                   addNameOf: false,
                                   cancellationToken: cancellationToken));
                    });

                    if (!context.Span.IsEmpty)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        string name = StringLiteralParser.Parse(literalExpression.Token.Text, startIndex, context.Span.Length, info.IsVerbatim, isInterpolatedText: false);

                        foreach (ISymbol symbol in semanticModel.LookupSymbols(literalExpression.SpanStart))
                        {
                            if (string.Equals(name, symbol.MetadataName, StringComparison.Ordinal))
                            {
                                context.RegisterRefactoring(
                                    "Insert interpolation with nameof",
                                    cancellationToken =>
                                {
                                    return(ReplaceWithInterpolatedStringAsync(
                                               context.Document,
                                               literalExpression,
                                               startIndex,
                                               context.Span.Length,
                                               addNameOf: true,
                                               cancellationToken: cancellationToken));
                                });

                                break;
                            }
                        }
                    }
                }
            }

            if (context.Span.IsBetweenSpans(literalExpression))
            {
                if (info.IsVerbatim)
                {
                    if (info.ContainsEscapeSequence)
                    {
                        if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiteral))
                        {
                            context.RegisterRefactoring(
                                "Replace verbatim string literal with regular string literal",
                                ct => ReplaceWithRegularStringLiteralAsync(context.Document, literalExpression, ct));
                        }

                        if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiterals) &&
                            info.ContainsLinefeed)
                        {
                            context.RegisterRefactoring(
                                "Replace verbatim string literal with regular string literals",
                                ct => ReplaceWithRegularStringLiteralsAsync(context.Document, literalExpression, ct));
                        }
                    }
                }
                else if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceRegularStringLiteralWithVerbatimStringLiteral) &&
                         info.ContainsEscapeSequence)
                {
                    context.RegisterRefactoring(
                        "Replace regular string literal with verbatim string literal",
                        ct => ReplaceWithVerbatimStringLiteralAsync(context.Document, literalExpression, ct));
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringEmptyInsteadOfEmptyStringLiteral) &&
                CanReplaceWithStringEmpty(literalExpression))
            {
                context.RegisterRefactoring(
                    "Replace \"\" with 'string.Empty'",
                    ct => ReplaceWithStringEmptyAsync(context.Document, literalExpression, ct));
            }
        }