private static async Task <Document> RefactorAsync(
            Document document,
            InterpolatedStringExpressionSyntax interpolatedString,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            int position = interpolatedString.SpanStart;

            bool isVerbatim = interpolatedString.IsVerbatim();

            ExpressionSyntax newNode = null;

            SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

            InterpolatedStringContentSyntax content1 = contents[0];
            InterpolatedStringContentSyntax content2 = contents[1];

            if (content1.Kind() == SyntaxKind.InterpolatedStringText)
            {
                ExpressionSyntax expression1 = GetExpression((InterpolatedStringTextSyntax)content1, isVerbatim);
                ExpressionSyntax expression2 = ((InterpolationSyntax)content2).Expression;

                newNode = CreateAddExpression(expression1, expression2, position, semanticModel, cancellationToken, isLeft: false);
            }
            else if (content2.Kind() == SyntaxKind.InterpolatedStringText)
            {
                ExpressionSyntax expression1 = ((InterpolationSyntax)content1).Expression;
                ExpressionSyntax expression2 = GetExpression((InterpolatedStringTextSyntax)content2, isVerbatim);

                newNode = CreateAddExpression(expression1, expression2, position, semanticModel, cancellationToken, isLeft: true);
            }
            else
            {
                ExpressionSyntax expression1 = ((InterpolationSyntax)content1).Expression;
                ExpressionSyntax expression2 = ((InterpolationSyntax)content2).Expression;

                bool isLiteral = expression1 is LiteralExpressionSyntax;

                BinaryExpressionSyntax addExpression = CreateAddExpression(expression1, expression2, position, semanticModel, cancellationToken, isLeft: !isLiteral);

                newNode = CreateAddExpression(addExpression.Left, addExpression.Right, position, semanticModel, cancellationToken, isLeft: isLiteral);
            }

            for (int i = 2; i < contents.Count; i++)
            {
                InterpolatedStringContentSyntax content = contents[i];

                ExpressionSyntax expression = (content.Kind() == SyntaxKind.InterpolatedStringText)
                    ? GetExpression((InterpolatedStringTextSyntax)content, isVerbatim)
                    : ((InterpolationSyntax)content).Expression;

                newNode = CreateAddExpression(newNode, expression, position, semanticModel, cancellationToken, isLeft: false);
            }

            newNode = newNode.Parenthesize().WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(interpolatedString, newNode, cancellationToken).ConfigureAwait(false));
        }
    private static bool TryEvaluateInterpolatedString(InterpolatedStringExpressionSyntax interpolation, out string result)
    {
        SyntaxList <InterpolatedStringContentSyntax> contents = interpolation.Contents;

        var builder = new StringBuilder();

        for (int i = 0; i < contents.Count; i++)
        {
            InterpolatedStringContentSyntax content = contents[i];
            if (content is InterpolationSyntax interpolationSyntax && TryEvaluateString(interpolationSyntax.Expression, out string text))
            {
                builder.Append(text);
            }
Example #3
0
        private Statement GetStatement(InterpolatedStringContentSyntax interpolatedStringContentSyntax)
        {
            if (interpolatedStringContentSyntax is InterpolationSyntax interpolationSyntax)
            {
                return(statementInterpreterHandler.GetStatement(interpolationSyntax.Expression));
            }
            else
            {
                var stringTextSyntax = (InterpolatedStringTextSyntax)interpolatedStringContentSyntax;

                return(new ConstantStatement(stringTextSyntax.TextToken.Text));
            }
        }
Example #4
0
        static string GetInterpolatedText(InterpolatedStringContentSyntax contentSyntax, SemanticModel model)
        {
            if (contentSyntax is InterpolatedStringTextSyntax interpolatedStringTextSyntax)
            {
                return(interpolatedStringTextSyntax.TextToken.Text);
            }

            if (contentSyntax is InterpolationSyntax interpolationSyntax)
            {
                return(GetStringValue(interpolationSyntax.Expression, model));
            }

            return(contentSyntax.GetType().Name);
        }
Example #5
0
        public static InterpolatedStringContentConversion Create(InterpolatedStringContentSyntax content, bool isVerbatim)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            InterpolatedStringContentConversion conversion;

            if (!TryCreate(content, isVerbatim, out conversion))
            {
                throw new ArgumentException("", nameof(content));
            }

            return(conversion);
        }
        public CSharpSyntaxNode Convert(TemplateExpression node)
        {
            SyntaxList <InterpolatedStringContentSyntax> contents = new SyntaxList <InterpolatedStringContentSyntax>();
            InterpolatedStringContentSyntax head = node.Head.ToCsNode <InterpolatedStringContentSyntax>();

            if (head != null)
            {
                contents = contents.Add(head);
            }

            foreach (Node templateSpan in node.TemplateSpans)
            {
                var content = templateSpan.ToCsNode <SyntaxList <InterpolatedStringContentSyntax> >();
                contents = contents.AddRange(content);
            }

            return(SyntaxFactory.InterpolatedStringExpression(SyntaxFactory.Token(SyntaxKind.InterpolatedStringStartToken), contents));
        }
Example #7
0
        public static bool CanRefactor(InterpolatedStringExpressionSyntax interpolatedString)
        {
            SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

            if (contents.Count == 1)
            {
                InterpolatedStringContentSyntax content = contents[0];

                if (content.IsKind(SyntaxKind.Interpolation))
                {
                    var interpolation = (InterpolationSyntax)content;

                    if (interpolation?.IsMissing == false)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #8
0
 public TameInterpolatedStringContentSyntax(InterpolatedStringContentSyntax node)
 {
     Node = node;
     AddChildren();
 }
Example #9
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var cancellationToken = context.CancellationToken;
            var semanticModel     = await context.Document.GetSemanticModelAsync(cancellationToken);

            if (semanticModel == null)
            {
                return;
            }

            var tree = await context.Document.GetSyntaxRootAsync(cancellationToken);

            if (tree == null)
            {
                return;
            }

            var node = tree.FindNode(context.Span);

            if (!(node is MethodDeclarationSyntax methodDeclarationSyntax))
            {
                return;
            }

            var method = ModelExtensions.GetDeclaredSymbol(semanticModel, methodDeclarationSyntax) as IMethodSymbol;

            if (method == null ||
                method.IsStatic ||
                method.IsAbstract ||
                method.ContainingType.TypeKind != TypeKind.Class)
            {
                return;
            }

            var diagnosticScopeType   = semanticModel.Compilation.GetTypeByMetadataName(AzureCorePipelineDiagnosticScopeTypeName);
            var clientDiagnosticsType = semanticModel.Compilation.GetTypeByMetadataName(AzureCorePipelineClientDiagnosticsTypeName);
            var exceptionType         = semanticModel.Compilation.GetTypeByMetadataName(SystemExceptionTypeName);

            if (diagnosticScopeType == null ||
                clientDiagnosticsType == null ||
                exceptionType == null)
            {
                return;
            }

            string clientDiagnosticsMember = null;

            foreach (var member in method.ContainingType.GetMembers())
            {
                if ((member is IFieldSymbol fieldSymbol && SymbolEqualityComparer.Default.Equals(clientDiagnosticsType, fieldSymbol.Type)) ||
                    (member is IPropertySymbol propertySymbol && SymbolEqualityComparer.Default.Equals(clientDiagnosticsType, propertySymbol.Type))
                    )
                {
                    clientDiagnosticsMember = member.Name;
                }
            }

            if (clientDiagnosticsMember == null)
            {
                return;
            }

            Task <Document> AddDiagnosticScope()
            {
                var generator = SyntaxGenerator.GetGenerator(context.Document);

                var preconditions = new List <StatementSyntax>();
                var mainLogic     = new List <SyntaxNode>();

                IEnumerable <StatementSyntax> statements;

                if (methodDeclarationSyntax.Body != null)
                {
                    statements = methodDeclarationSyntax.Body.Statements;
                }
                else if (methodDeclarationSyntax.ExpressionBody != null)
                {
                    statements = new [] { (StatementSyntax)generator.ReturnStatement(methodDeclarationSyntax.ExpressionBody.Expression) };
                }
                else
                {
                    return(Task.FromResult(context.Document));
                }

                foreach (var statement in statements)
                {
                    if (mainLogic.Count > 0 ||
                        IncludeInScopeBody(statement))
                    {
                        mainLogic.Add(statement);
                    }
                    else
                    {
                        preconditions.Add(statement);
                    }
                }

                // Trim Async off the scope name
                var scopeName = method.Name;

                if (scopeName.EndsWith(AsyncSuffix))
                {
                    scopeName = scopeName.Substring(0, scopeName.Length - AsyncSuffix.Length);
                }

                // $"{nameof(Type}}.{nameof(Method)}"
                var interpolatedStringParts = new InterpolatedStringContentSyntax[]
                {
                    Interpolation((ExpressionSyntax)generator.NameOfExpression(generator.IdentifierName(method.ContainingType.Name))),
                    InterpolatedStringText(Token(SyntaxTriviaList.Empty, SyntaxKind.InterpolatedStringTextToken, ".", ".", SyntaxTriviaList.Empty)),
                    Interpolation((ExpressionSyntax)generator.NameOfExpression(generator.IdentifierName(scopeName)))
                };

                var initializer = generator.InvocationExpression(
                    generator.MemberAccessExpression(generator.IdentifierName(clientDiagnosticsMember), "CreateScope"),
                    InterpolatedStringExpression(
                        Token(SyntaxKind.InterpolatedStringStartToken),
                        List(interpolatedStringParts),
                        Token(SyntaxKind.InterpolatedStringEndToken)
                        )
                    );

                var declaration = (LocalDeclarationStatementSyntax)generator.LocalDeclarationStatement(diagnosticScopeType, ScopeVariableName, initializer);

                declaration = declaration.WithUsingKeyword(Token(SyntaxKind.UsingKeyword));

                preconditions.Add(declaration);
                preconditions.Add(
                    (StatementSyntax)generator.ExpressionStatement(
                        generator.InvocationExpression(
                            generator.MemberAccessExpression(generator.IdentifierName(ScopeVariableName), "Start"))));

                preconditions.Add(
                    (StatementSyntax)generator.TryCatchStatement(
                        mainLogic,
                        generator.CatchClause(exceptionType, "ex", new[]
                {
                    generator.ExpressionStatement(
                        generator.InvocationExpression(
                            generator.MemberAccessExpression(generator.IdentifierName(ScopeVariableName), "Failed"),
                            generator.Argument(generator.IdentifierName("ex")))),
                    generator.ThrowStatement()
                })
                        ));

                var newMethodDeclaration = methodDeclarationSyntax.WithExpressionBody(null)
                                           .WithBody(Block(preconditions))
                                           .WithSemicolonToken(default);
        public static InterpolatedStringContentConversion Create(InterpolatedStringContentSyntax content, bool isVerbatim)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            SyntaxKind kind = content.Kind();

            switch (kind)
            {
            case SyntaxKind.Interpolation:
            {
                var interpolation = (InterpolationSyntax)content;

                InterpolationAlignmentClauseSyntax alignmentClause = interpolation.AlignmentClause;
                InterpolationFormatClauseSyntax    formatClause    = interpolation.FormatClause;

                if (alignmentClause != null ||
                    formatClause != null)
                {
                    var sb = new StringBuilder();
                    sb.Append("\"{0");

                    if (alignmentClause != null)
                    {
                        sb.Append(',');
                        sb.Append(alignmentClause.Value.ToString());
                    }

                    if (formatClause != null)
                    {
                        sb.Append(':');
                        sb.Append(formatClause.FormatStringToken.Text);
                    }

                    sb.Append("}\"");

                    return(new InterpolatedStringContentConversion(kind, "AppendFormat", SeparatedList(new ArgumentSyntax[] { Argument(ParseExpression(sb.ToString())), Argument(interpolation.Expression) })));
                }
                else
                {
                    return(new InterpolatedStringContentConversion(kind, "Append", SingletonSeparatedList(Argument(interpolation.Expression))));
                }
            }

            case SyntaxKind.InterpolatedStringText:
            {
                var interpolatedStringText = (InterpolatedStringTextSyntax)content;

                string text = interpolatedStringText.TextToken.Text;

                text = (isVerbatim)
                            ? "@\"" + text + "\""
                            : "\"" + text + "\"";

                ExpressionSyntax stringLiteral = ParseExpression(text);

                return(new InterpolatedStringContentConversion(kind, "Append", SingletonSeparatedList(Argument(stringLiteral))));
            }

            default:
            {
                throw new ArgumentException("", nameof(content));
            }
            }
        }
        Refactor(InterpolatedStringContentSyntax content, bool isVerbatim)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            SyntaxKind kind = content.Kind();

            switch (kind)
            {
            case SyntaxKind.Interpolation:
            {
                var interpolation = (InterpolationSyntax)content;

                InterpolationAlignmentClauseSyntax alignmentClause = interpolation.AlignmentClause;
                InterpolationFormatClauseSyntax    formatClause    = interpolation.FormatClause;

                if (alignmentClause != null ||
                    formatClause != null)
                {
                    StringBuilder sb = StringBuilderCache.GetInstance();

                    sb.Append("\"{0");

                    if (alignmentClause != null)
                    {
                        sb.Append(',');
                        sb.Append(alignmentClause.Value.ToString());
                    }

                    if (formatClause != null)
                    {
                        sb.Append(':');
                        sb.Append(formatClause.FormatStringToken.Text);
                    }

                    sb.Append("}\"");

                    ExpressionSyntax expression = ParseExpression(StringBuilderCache.GetStringAndFree(sb));

                    return(kind, "AppendFormat", ImmutableArray.Create(Argument(expression), Argument(interpolation.Expression)));
                }
                else
                {
                    return(kind, "Append", ImmutableArray.Create(Argument(interpolation.Expression)));
                }
            }

            case SyntaxKind.InterpolatedStringText:
            {
                var interpolatedStringText = (InterpolatedStringTextSyntax)content;

                string text = interpolatedStringText.TextToken.Text;

                text = StringUtility.ReplaceDoubleBracesWithSingleBrace(text);

                text = (isVerbatim)
                            ? "@\"" + text + "\""
                            : "\"" + text + "\"";

                ExpressionSyntax stringLiteral = ParseExpression(text);

                return(kind, "Append", ImmutableArray.Create(Argument(stringLiteral)));
            }

            default:
            {
                throw new ArgumentException("", nameof(content));
            }
            }
        }
Example #12
0
        public static bool TryCreate(InterpolatedStringContentSyntax content, bool isVerbatim, out InterpolatedStringContentConversion conversion)
        {
            switch (content?.Kind())
            {
            case SyntaxKind.Interpolation:
            {
                var interpolation = (InterpolationSyntax)content;

                InterpolationAlignmentClauseSyntax alignmentClause = interpolation.AlignmentClause;
                InterpolationFormatClauseSyntax    formatClause    = interpolation.FormatClause;

                if (alignmentClause != null ||
                    formatClause != null)
                {
                    var sb = new StringBuilder();
                    sb.Append("\"{0");

                    if (alignmentClause != null)
                    {
                        sb.Append(',');
                        sb.Append(alignmentClause.Value.ToString());
                    }

                    if (formatClause != null)
                    {
                        sb.Append(':');
                        sb.Append(formatClause.FormatStringToken.Text);
                    }

                    sb.Append("}\"");

                    conversion = new InterpolatedStringContentConversion("AppendFormat", SeparatedList(new ArgumentSyntax[] { Argument(ParseExpression(sb.ToString())), Argument(interpolation.Expression) }));
                    return(true);
                }
                else
                {
                    conversion = new InterpolatedStringContentConversion("Append", SingletonSeparatedList(Argument(interpolation.Expression)));
                    return(true);
                }
            }

            case SyntaxKind.InterpolatedStringText:
            {
                var interpolatedStringText = (InterpolatedStringTextSyntax)content;

                string text = interpolatedStringText.TextToken.Text;

                text = (isVerbatim)
                            ? "@\"" + text + "\""
                            : "\"" + text + "\"";

                ExpressionSyntax stringLiteral = ParseExpression(text);

                conversion = new InterpolatedStringContentConversion("Append", SingletonSeparatedList(Argument(stringLiteral)));
                return(true);
            }
            }

            conversion = default(InterpolatedStringContentConversion);
            return(false);
        }