我在重建语句时遇到问题。我想重建片段代码:
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, >, -);
-> for(var j = k; j > 15; j--){}
.此外,我不知道如何分隔列表中的元素 <ArgumentListSyntax>
至 IdentifierNameSyntax
或 LiteralExpressionSyntax
,当会有两个IdentifierNameSyntax
或 LiteralExpressionSyntax
在名单上。所以我不知道我的尝试解决是否正确。
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);
}
最佳答案
您不需要在 ArgumentListSyntax
中分隔元素到文字或标识符,因为你实际上有一个支持调用的正式结构:FOR(j, variable|integer, variable|integer, >|<|<=|>=, -|+);
所以你假设第二个和第三个参数可能是文字或标识符,第四个是比较元素等等。因此,您需要检查输入参数是否满足这些条件,如果满足则做一些有用的事情:
...
// 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, >, >, >, -, "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
...
}
关于c# - Roslyn C# 为 for 语句重建不正确的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53380917/