Splitting expressions with Roslyn

I am using Roslyn and I want to split the statement like below,

string stringVariable = "string";
int intVariable = 10;
Console.Write(stringVariable + string.Concat("string1","string2") + intVariable.ToString()) 

      

  • Console.Write()

  • stringVariable

  • string.Concat("string1","string2")

  • intVariable.ToString()

I asked a question and got an answer to Split Expressions Split Expressions with Roslyn , but this sentence splits string.Concat("string1", "string2")

as below,

  • string.Concat()

  • string1

  • string2

But I don't want to break up the inner expressions, I need to keep the inner expressions as they are. How can I do this with Roslin?

0


source to share


1 answer


The expression Console.Write(stringVariable + string.Concat("string1","string2") + intVariable.ToString())

is equal InvocationExpressionSyntax

. InvocationExpressionSyntax can be divided into expression and arguments .

Here, part of the expression will have Console.Write

and part of the argument will have a value stringVariable + string.Concat("string1","string2") + intVariable.ToString()

.

Now the argument will be BinaryExpressionSyntax

.

We can share BinaryExpressionSyntax by visiting SyntaxNodes

. Therefore, when you visit, we can just avoid passing "internal expression" by defining the syntax (eg InvocationExpressionSyntax

, MemberAccessExpressionSyntax

etc.).

The code to visit the binary expression as above would be.



public class BinaryExpressionVisitor : CSharpSyntaxRewriter
{
    List<string> restrictedTokens = new List<string>();
    internal List<object> binaryExpressionNodes = new List<object>();

    public BinaryExpressionVisitor()
    {
        restrictedTokens.Add("IdentifierToken");
        restrictedTokens.Add("NumericLiteralToken");
        restrictedTokens.Add("StringLiteralToken");
    }

    public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
    {
        return base.VisitBinaryExpression(node);
    }

    public override SyntaxNode Visit(SyntaxNode node)
    {
        if (node.GetType().Name != "BinaryExpressionSyntax" && node.GetType().Name != "ParenthesizedExpressionSyntax")
            binaryExpressionNodes.Add(node);
        return base.Visit(node);
    }

    public override SyntaxToken VisitToken(SyntaxToken token)
    {
        if (!restrictedTokens.Contains(token.CSharpKind().ToString().Trim()))
            binaryExpressionNodes.Add(token);
        SyntaxToken baseToken = base.VisitToken(token);
        return baseToken;
    }

    public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
    {
        return node;//Bypassing the expression instead of base.Visit(node)
    }

    public override SyntaxToken VisitListSeparator(SyntaxToken separator)
    {
        SyntaxToken baseToken = base.VisitListSeparator(separator);
        return baseToken;
    }
}

      

The class can be called,

BinaryExpressionVisitor expressionVisitor = new BinaryExpressionVisitor();
expressionVisitor.VisitBinaryExpression(binaryExpressions);
List<object> nodeList = expressionVisitor.binaryExpressionNodes;

      

nodeList will have the following result.

  • [0] = "IdentifierNameSyntax IdentifierName stringVariable"
  • [1] = "SyntaxToken PlusToken +"
  • [2] = "InvocationExpressionSyntax InvocationExpression string.Concat (\" string1 \ ", \" string2 \ ")"
  • [3] = "SyntaxToken PlusToken +"
  • [4] = "InvocationExpressionSyntax InvocationExpression intVariable.ToString ()"
0


source







All Articles