[英]Changing syntax token with Roslyn
I am trying to rewrite code with Roslyn. 我正在尝试用Roslyn重写代码。 I want to change GreaterThanToken to EqualsEqualsToken.
我想将GreaterThanToken更改为EqualsEqualsToken。 Here is my code so far:
到目前为止,这是我的代码:
ToParse.cs: ToParse.cs:
public class ToParse
{
public bool MethodToConvert(int param)
{
return (1 > param);
}
}
Program.cs: Program.cs中:
class Rewriter : SyntaxRewriter
{
private readonly SyntaxKind _replace;
private readonly SyntaxKind _replacewith;
public Rewriter(SyntaxKind replace, SyntaxKind replacewith)
{
_replace = replace;
_replacewith = replacewith;
}
public override SyntaxToken VisitToken(SyntaxToken token)
{
if (token.Kind != _replace)
return token;
return Syntax.Token(_replacewith);
}
}
Usage: 用法:
var code = new StreamReader("ToParse.cs").ReadToEnd();
var tree = SyntaxTree.ParseText(code);
var root = tree.GetRoot();
var rewriter = new Rewriter(SyntaxKind.GreaterThanToken, SyntaxKind.EqualsEqualsToken);
var newRoot = rewriter.Visit(root);
var newTree = SyntaxTree.Create((CompilationUnitSyntax)newRoot);
var compilation = Compilation.Create("TestAssembly.dll",
new CompilationOptions(OutputKind.DynamicallyLinkedLibrary),
references: new[]{ new MetadataFileReference(typeof(object).Assembly.Location)},
syntaxTrees: new[] { newTree });
Console.WriteLine(newTree);
EmitResult res;
using (var file = new FileStream("e:\\TestAssembly.dll", FileMode.Create))
res = compilation.Emit(file);
After execution, Console.WriteLine prints changed tokens return (1 == param);
执行后,Console.WriteLine打印更改的令牌
return (1 == param);
But when I open testassembly.dll with ilspy I still see return 1 > param;
但是当我用ilspy打开testassembly.dll时,我仍然看到
return 1 > param;
Any suggestions? 有什么建议?
[Note: You're using a slightly older version of Roslyn. [注意:你使用的是较旧版本的Roslyn。 This answer should work for that version too, but I may reference classes and members by more recent names so that they match the source available on CodePlex .]
这个答案也适用于该版本,但我可以通过更新的名称引用类和成员,以便它们与CodePlex上可用的源匹配。
The original tree that you've parsed contains a BinaryExpressionSyntax
node with a SyntaxKind
of GreaterThanExpression
. 您已解析的原始树包含
BinaryExpressionSyntax
节点,其SyntaxKind
为GreaterThanExpression
。 When you swap out the GreaterThanToken
with an EqualsEqualsToken
inside this BinaryExpressionSyntax
, it does not automatically adjust the containing SyntaxNode
's kind to EqualsExpression
. 当你换出
GreaterThanToken
与EqualsEqualsToken
这里面BinaryExpressionSyntax
,它不会自动调整包含SyntaxNode
的实物 EqualsExpression
。
As a result, you end up with a GreaterThanExpression
with an EqualsEqualsToken
. 因此,您最终会得到一个带有
EqualsEqualsToken
的GreaterThanExpression
。 Since this is not a syntax tree that could have been legally generated by the compiler itself, you may see unexpected behavior like this. 由于这不是编译器本身可以合法生成的语法树,因此您可能会看到类似的意外行为。
To generate a correct tree in this case, I'd recommend rewriting the node itself instead of the token by overriding CSharpSyntaxRewriter.VisitBinaryExpression
and doing something like this: 要在这种情况下生成正确的树,我建议通过重写
CSharpSyntaxRewriter.VisitBinaryExpression
并执行以下操作来重写节点本身而不是令牌:
public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
{
if (node.CSharpKind() == SyntaxKind.GreaterThanExpression)
{
return SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, node.Left, node.Right);
}
return node;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.