我在使用Roslyn向SyntaxTree添加表达式时遇到了一些问题。我需要实现的目标如下: 每当我找到一个特殊的陈述时,我想在这个陈述之后插入一个或多个表达式。
让我们说我要插入声明" myVar = myVar + 1"在每个写入变量" testVar"。
的语句之后以下代码段:
a = 10;
testVar = 50;
a = testVar / a;
testVar = a;
应该变成这段代码:
a = 10;
testVar = 50;
myVar = myVar + 1;
a = testVar / a;
testVar = a;
myVar = myVar + 1;
我当前的方法使用SyntaxVisitor和方法' SyntaxNode VisitExpressionStatement(ExpressionStatement node)'。 此方法访问SyntaxTree中的所有表达式,并允许使用它返回的SyntaxNode替换访问过的表达式。 但是,我不想替换语句,而是在它们之后添加新表达式,这基本上需要返回两个表达式。 我发现的唯一解决方案是使用" BlockSyntax"它充当两个表达式的容器(参见代码片段[0])。不幸的是," BlockSyntax"在自身周围引入花括号,这导致以下结果:
a = 10;
{
testVar = 50;
myVar = myVar + 1;
}
a = testVar / a;
{
testVar = a;
myVar = myVar + 1;
}
这种方法对我来说是不可接受的,因为我不想操纵范围。 有没有办法在我选择的位置使用Roslyn插入任意表达式?
[0]
public SyntaxNode VisitExpressionStatement(ExpressionStatement node){
if(node has special characteristics){
var newExpression = ...
var newStatmentList = new Roslyn.Compilers.CSharp.SyntaxList<StatementSyntax>();
newStatmentList = newStatmentList.Insert(newStatmentList.Count, node);
newStatmentList = newStatmentList.Insert(newStatmentList.Count, newExpression);
BlockSyntax newBlock = Syntax.Block(newStatmentList);
return newBlock;
}
else {
return node;
}
}
答案 0 :(得分:1)
我的策略是欺骗BlockSyntax
。查看我的similar question。
所以我添加了BlockSyntax
,但我通过将{
和}
令牌标记为缺失来“删除”它们。我还没有遇到过这种方法的任何问题,但它似乎更像是一种解决方法而非解决方案。
var statements = new SyntaxList<StatementSyntax>();
//Tried bundling newNode and invocation together
statements.Add(SyntaxFactory.ExpressionStatement(newNode));
statements.Add(SyntaxFactory.ExpressionStatement(invocation));
var wrapper = SyntaxFactory.Block(statements);
//Now we can remove the { and } braces
wrapper = wrapper.WithOpenBraceToken(SyntaxFactory.MissingToken(SyntaxKind.OpenBraceToken))
.WithCloseBraceToken(SyntaxFactory.MissingToken(SyntaxKind.CloseBraceToken));
请注意,我说我正在“删除”它们。这里的问题是你生成的SyntaxTree
仍然会出现在C#编译器中,就好像它放置了BlockSyntax
一样。这可能也可能不重要。
例如:
如果您将此树作为字符串输出到文件,您会没事的。
如果您正在编译此树,我相信编译器会将BlockSyntax
解释为您重写它的现有位置,并且所有作用域语义仍将被强制执行,就好像它在那里一样。 / p>
有关生成“奇怪”树木的更多信息,请查看我的博文:Don't Trust SyntaxNode.ToFullString()