private static async Task <Document> RefactorAsync(
            Document document,
            AttributeSyntax attribute,
            CancellationToken cancellationToken)
        {
            TypeDeclarationSyntax typeDeclaration = attribute.FirstAncestor <TypeDeclarationSyntax>();

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

            string propertyName = NameGenerator.Default.EnsureUniqueName(DefaultNames.DebuggerDisplayPropertyName, semanticModel, typeDeclaration.OpenBraceToken.Span.End);

            AttributeArgumentSyntax argument = attribute.ArgumentList.Arguments.First();

            TypeDeclarationSyntax newTypeDeclaration = typeDeclaration.ReplaceNode(
                argument,
                argument.WithExpression(
                    StringLiteralExpression($"{{{propertyName},nq}}")).WithTriviaFrom(argument.Expression));

            string value = semanticModel
                           .GetDeclaredSymbol(typeDeclaration, cancellationToken)
                           .GetAttribute(MetadataNames.System_Diagnostics_DebuggerDisplayAttribute)
                           .ConstructorArguments[0]
                           .Value
                           .ToString();

            bool isVerbatim = SyntaxInfo.StringLiteralExpressionInfo(argument.Expression).IsVerbatim;

            ExpressionSyntax returnExpression = GetReturnExpression(value, isVerbatim);

            PropertyDeclarationSyntax propertyDeclaration = MarkTypeWithDebuggerDisplayAttributeRefactoring.DebuggerDisplayPropertyDeclaration(propertyName, returnExpression);

            newTypeDeclaration = MemberDeclarationInserter.Default.Insert(newTypeDeclaration, propertyDeclaration);

            return(await document.ReplaceNodeAsync(typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false));
        }
        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);
        }
Beispiel #4
0
        public static Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            TextSpan span,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            ExpressionSyntax[] expressions = binaryExpression.AsChain(span).ToArray();

            ExpressionSyntax firstExpression = expressions[0];

            bool isVerbatim;
            var  isInterpolated = false;

            if (firstExpression is InterpolatedStringExpressionSyntax interpolatedString)
            {
                isVerbatim     = interpolatedString.IsVerbatim();
                isInterpolated = true;
            }
            else
            {
                isVerbatim = SyntaxInfo.StringLiteralExpressionInfo(firstExpression).IsVerbatim;
            }

            StringBuilder sb = StringBuilderCache.GetInstance();

            var builder = new StringLiteralTextBuilder(sb, isVerbatim: isVerbatim, isInterpolated: isInterpolated);

            builder.AppendStart();

            foreach (ExpressionSyntax expression in expressions)
            {
                switch (expression.Kind())
                {
                case SyntaxKind.StringLiteralExpression:
                {
                    builder.Append((LiteralExpressionSyntax)expression);
                    break;
                }

                case SyntaxKind.InterpolatedStringExpression:
                {
                    builder.Append((InterpolatedStringExpressionSyntax)expression);
                    break;
                }
                }
            }

            builder.AppendEnd();

            string newText = builder.ToString();

            StringBuilderCache.Free(sb);

            TextSpan changedSpan = TextSpan.FromBounds(firstExpression.SpanStart, expressions.Last().Span.End);

            return(document.WithTextChangeAsync(changedSpan, newText, cancellationToken));
        }
        private static async Task <Document> RefactorAsync(
            Document document,
            AttributeSyntax attribute,
            CancellationToken cancellationToken)
        {
            TypeDeclarationSyntax typeDeclaration = attribute.FirstAncestor <TypeDeclarationSyntax>();

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

            string propertyName = NameGenerator.Default.EnsureUniqueMemberName(PropertyName, semanticModel, typeDeclaration.OpenBraceToken.Span.End, cancellationToken: cancellationToken);

            AttributeArgumentSyntax argument = attribute.ArgumentList.Arguments.First();

            TypeDeclarationSyntax newTypeDeclaration = typeDeclaration.ReplaceNode(
                argument,
                argument.WithExpression(
                    StringLiteralExpression($"{{{propertyName},nq}}")).WithTriviaFrom(argument.Expression));

            string value = semanticModel
                           .GetDeclaredSymbol(typeDeclaration, cancellationToken)
                           .GetAttribute(semanticModel.GetTypeByMetadataName(MetadataNames.System_Diagnostics_DebuggerDisplayAttribute))
                           .ConstructorArguments[0]
                           .Value
                           .ToString();

            ExpressionSyntax returnExpression = GetReturnExpression(value, SyntaxInfo.StringLiteralExpressionInfo(argument.Expression).IsVerbatim);

            PropertyDeclarationSyntax propertyDeclaration = PropertyDeclaration(
                SingletonList(
                    AttributeList(
                        Attribute(
                            ParseName("System.Diagnostics.DebuggerBrowsableAttribute"),
                            AttributeArgument(
                                SimpleMemberAccessExpression(
                                    ParseName("System.Diagnostics.DebuggerBrowsableState").WithSimplifierAnnotation(),
                                    IdentifierName("Never"))
                                )
                            ).WithSimplifierAnnotation()
                        )
                    ),
                Modifiers.Private(),
                CSharpTypeFactory.StringType(),
                default(ExplicitInterfaceSpecifierSyntax),
                Identifier(propertyName).WithRenameAnnotation(),
                AccessorList(
                    GetAccessorDeclaration(
                        Block(
                            ReturnStatement(returnExpression)))));

            propertyDeclaration = propertyDeclaration.WithFormatterAnnotation();

            newTypeDeclaration = MemberDeclarationInserter.Default.Insert(newTypeDeclaration, propertyDeclaration);

            return(await document.ReplaceNodeAsync(typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false));
        }
Beispiel #6
0
        public static Task <Document> RefactorAsync(
            Document document,
            InterpolationSyntax interpolation,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var interpolatedString = (InterpolatedStringExpressionSyntax)interpolation.Parent;

            string s = interpolatedString.ToString();

            s = s.Substring(0, interpolation.SpanStart - interpolatedString.SpanStart)
                + StringUtility.DoubleBraces(SyntaxInfo.StringLiteralExpressionInfo(interpolation.Expression).InnerText)
                + s.Substring(interpolation.Span.End - interpolatedString.SpanStart);

            var newInterpolatedString = (InterpolatedStringExpressionSyntax)SyntaxFactory.ParseExpression(s)
                                        .WithTriviaFrom(interpolatedString);

            return(document.ReplaceNodeAsync(interpolatedString, newInterpolatedString, cancellationToken));
        }
Beispiel #7
0
        public 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.ThrowIfCancellationRequested();

                switch (expression.Kind())
                {
                case SyntaxKind.StringLiteralExpression:
                {
                    bool isVerbatim2 = SyntaxInfo.StringLiteralExpressionInfo(expression).IsVerbatim;

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

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

                    break;
                }

                case SyntaxKind.InterpolatedStringExpression:
                {
                    bool isVerbatim2 = ((InterpolatedStringExpressionSyntax)expression).IsVerbatim();

                    if (firstExpression == null)
                    {
                        firstExpression = expression;
                        isLiteral       = false;
                        isVerbatim      = isVerbatim2;
                    }
                    else if (isLiteral ||
                             isVerbatim != isVerbatim2)
                    {
                        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)));
        }
Beispiel #9
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;
            var isLiteral  = false;
            var isVerbatim = false;
            int startLine  = -1;

            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;

                        if (isVerbatim)
                        {
                            startLine = expression.SyntaxTree.GetLineSpan(expression.GetSpan()).StartLine();
                        }
                    }
                    else if (!isLiteral ||
                             isVerbatim != isVerbatim2 ||
                             (!isVerbatim && !CheckHexadecimalEscapeSequence(stringLiteral)))
                    {
                        if (lastExpression != null)
                        {
                            Analyze(context, firstExpression, lastExpression, isVerbatim);
                        }

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

                        if (isVerbatim)
                        {
                            FileLinePositionSpan lineSpan = expression.SyntaxTree.GetLineSpan(expression.GetSpan());

                            if (startLine != lineSpan.EndLine())
                            {
                                firstExpression = null;
                                lastExpression  = null;
                            }
                            else
                            {
                                startLine = lineSpan.StartLine();
                            }
                        }
                    }

                    break;
                }

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

                    bool isVerbatim2 = interpolatedString.IsVerbatim();

                    if (firstExpression == null)
                    {
                        firstExpression = expression;
                        isLiteral       = false;
                        isVerbatim      = isVerbatim2;

                        if (isVerbatim)
                        {
                            startLine = expression.SyntaxTree.GetLineSpan(expression.GetSpan()).StartLine();
                        }
                    }
                    else if (isLiteral ||
                             isVerbatim != isVerbatim2 ||
                             (!isVerbatim && !CheckHexadecimalEscapeSequence(interpolatedString)))
                    {
                        if (lastExpression != null)
                        {
                            Analyze(context, firstExpression, lastExpression, isVerbatim);
                        }

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

                        if (isVerbatim)
                        {
                            FileLinePositionSpan lineSpan = expression.SyntaxTree.GetLineSpan(expression.GetSpan());

                            if (startLine != lineSpan.EndLine())
                            {
                                firstExpression = null;
                                lastExpression  = null;
                            }
                            else
                            {
                                startLine = lineSpan.StartLine();
                            }
                        }
                    }

                    break;
                }

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

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

            if (lastExpression != null)
            {
                Analyze(context, firstExpression, lastExpression, isVerbatim);
            }
        }
Beispiel #10
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));
            }
        }