Splitting expressions with Roslyn

I am working on developing an application that rephrases code CSharp

. I do this with Roslyn

. I ran into a problem with splitting expressions

.

Example class

class Program
{
    static void Main(string[] args)
    {
        float floatVariable = 20;
        Int16 intVariable = 10;
        string str = "School";
        Console.Write(str + floatVariable.ToString() + intVariable.ToString()); // Facing problem with this statement
    }
}

      

Sample code I am using

string code = new StreamReader(classPath).ReadToEnd();
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var syntaxRoot = syntaxTree.GetRoot();

//This will get the method and local variables declared inside the method
var MyMethods = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (MethodDeclarationSyntax mds in MyMethods)
{
    syntaxTree = CSharpSyntaxTree.ParseText(mds.ToFullString());
    IEnumerable<SyntaxNode> nodes = syntaxTree.GetRoot().DescendantNodes();
    IEnumerable<VariableDeclarationSyntax> variableDeclarations =       nodes.OfType<VariableDeclarationSyntax>();
    foreach (VariableDeclarationSyntax variable in variableDeclarations)
    {
    // I will collect the variable details like Datatype, variable names and initialized values  here
    }


    foreach (StatementSyntax statement in mds.Body.Statements)
    {
        if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
        {
            //I want to split the expressions "Console.Write(str + floatVariable.ToString() + intVariable.ToString());" as below

            //1. intVariable.ToString()
            //2. floatVariable.ToString()
            //3. str

            //Then I have to find the whole data type from the resolved result of above 3 => string here            
        }
    }
}

      

Any help would be appreciated.

Edit: I'm having problems splitting parameterized expression statements. I'm trying to do this,

if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
{
    ExpressionStatementSyntax expression = statement as ExpressionStatementSyntax;
    var expressions = expression.Expression.DescendantNodes();
}

      

But this breaks each token as a separate item. I just want to split into Console.Write(str + floatVariable.ToString() + intVariable.ToString())

  • Console.Write ()
  • st
  • intVariable.ToString ()
  • floatVariable.ToString ()
+3


source to share


1 answer


It's hard to say what exactly you want to do, because you indicated that the code should only do one specific case, not in general.

The way I interpret it:

  • For a call expression, return the expression that is being called, and also exit into its arguments, if any.
  • For binary operators, omit in both children.
  • For all other expressions, return the expression directly.


With this specification and usage, the CSharpSyntaxVisitor

code could look like this:

public static IEnumerable<ExpressionSyntax> Split(ExpressionSyntax expression)
{
    return new SplitVisitor().Visit(expression);
}

class SplitVisitor : CSharpSyntaxVisitor<IEnumerable<ExpressionSyntax>>
{
    public override IEnumerable<ExpressionSyntax> VisitInvocationExpression(
        InvocationExpressionSyntax node)
    {
        yield return node.Expression;

        var argumentExpressions = node.ArgumentList.Arguments
            .SelectMany(a => Visit(a.Expression));
        foreach (var expression in argumentExpressions)
            yield return expression;
    }

    public override IEnumerable<ExpressionSyntax> VisitBinaryExpression(
        BinaryExpressionSyntax node)
    {
        foreach (var expression in Visit(node.Left))
            yield return expression;
        foreach (var expression in Visit(node.Right))
            yield return expression;
    }

    public override IEnumerable<ExpressionSyntax> DefaultVisit(SyntaxNode node)
    {
        var expression = node as ExpressionSyntax;
        if (expression != null)
            yield return expression;
    }
}

      

+1


source







All Articles