【问题标题】:Roslyn C# rebuild incorrect expression for to for statementRoslyn C# 为 to for 语句重建不正确的表达式
【发布时间】:2018-11-19 18:49:44
【问题描述】:

rebuild for 语句有问题。我想重建片段代码:

FOR(j, variable or integer, integer, > or < or <= or >=, - or +);

for(var j = variable or integer; j > or < or >= or <= 15; j-- or j++){}

例如FOR(j, k, &gt;, -); -> for(var j = k; j &gt; 15; j--){}。此外,我不知道如何将列表&lt;ArgumentListSyntax&gt; 上的元素分隔为IdentifierNameSyntaxLiteralExpressionSyntax,当列表上会有两个IdentifierNameSyntaxLiteralExpressionSyntax 时。所以不知道我的尝试是否正确。

public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
{
    // FOR(j, k, 10, >, -);

    if (node.Kind() == SyntaxKind.InvocationExpression)
    {
        InvocationExpressionSyntax invocationExpression = node;

        if (invocationExpression.GetFirstToken().ToString() == "FOR")
        {
            //List<ArgumentSyntax> argumentList = new List<ArgumentSyntax>();
            //List<IdentifierNameSyntax> test = new List<IdentifierNameSyntax>();
            var tmp = node.ChildNodes().OfType<ArgumentListSyntax>().FirstOrDefault();
            var tmp1 = tmp.ChildNodes().OfType<ArgumentSyntax>().FirstOrDefault();
            var tmp2 = tmp1.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault();
            var tmp3 = tmp.Arguments.ElementAt(1);
            var tmp4 = tmp3.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault();

            Console.WriteLine(tmp.Arguments.ElementAt(0));
            Console.WriteLine(tmp.Arguments);
            Console.WriteLine(tmp2.GetFirstToken());
            Console.WriteLine(tmp4);


            node = node.ReplaceNode(node, SyntaxFactory.ForStatement(SyntaxKind.ForKeyword, SyntaxKind.OpenParenToken,
                                    SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var"), )));
        }

    }
    return base.VisitInvocationExpression(node);
}

【问题讨论】:

    标签: c# for-loop roslyn


    【解决方案1】:

    您不需要将ArgumentListSyntax 中的元素与文字或标识符分开,因为您实际上具有支持调用的正式结构:FOR(j, variable|integer, variable|integer, &gt;|&lt;|&lt;=|&gt;=, -|+); 因此您假设第二个和第三个参数可能是文字或标识符,第四是比较元素等等。因此,您需要检查输入参数是否满足这些条件,如果可以满足,请做一些有用的事情:

    ...
    // FOR(j, variable | integer, variable | integer, > | < | <= | >=, - | +);
    if (node.Expression is IdentifierNameSyntax identifier && identifier.Identifier.ValueText.Equals("FOR"))
    {
        var arguments = node.ArgumentList.Arguments;
        if (arguments.Count != 5) return node;
        var second = arguments[1].Expression;
        switch (second)
        {
            case IdentifierNameSyntax variable:
                // and some sepcific logic for identifier
                break;
    
            case LiteralExpressionSyntax literal when literal.Kind() == SyntaxKind.NumericLiteralExpression:
                // and some sepcific logic for literals and check, 
                // that the input literal is integer and is not rational value
                break;
    
            default:
                // current argument isn't literal or identifier you can not do anything
                return node;
        }
    
        // do the similar check for the other arguments
        // and replace node as you wish
        ...
    }
    

    如果您仍然假设您的调用可以包含几个其他节点作为参数,例如for(j, "foo", "foo", method(), initValue, method(), 15, &gt;, &gt;, &gt;, -, "foo"),您将需要通过不同的逻辑获取参数,例如获取第一个文字或标识符或其他内容:

    ...
        // the same code from the example above
    
        // here you can use an another logic to retrieve expression that you want
        var second = arguments.First(x => x.IsKind(SyntaxKind.NumericLiteralExpression) || x.IsKind(SyntaxKind.IdentifierName)).Expression; 
        switch (second)
        {
            // the same code from the example above
        }
        // the same code from the example above
    
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多