语法重写

本文关键字:重写 语法 | 更新日期: 2023-09-27 18:05:39

我需要使用Roslyn转换某个类的所有属性。

在不使对语法树的引用无效的情况下,对语法树应用多个转换的推荐方法是什么


以下是我尝试过的以及我遇到的问题:

  • 在第一个过程中,CSharpSyntaxWalker的后代访问所有PropertyDeclarationSyntax节点,并将它们存储在列表中。

  • 在第二次传递中,CSharpSyntaxRewriter正在转换节点,同时在转换之前检查每个访问节点是否等于列表中的一个

我尝试的问题是:当我转换属性时,我会向类添加新字段,这会导致类发生变化。列表中对其他属性的所有引用在该类的新树中都将无效。

重新访问整个类似乎效率很低,而且无论哪种方式,由于引用差异,我都无法检测到已经处理的属性节点。

语法重写

我不建议引用要修改的SyntaxTree中的节点。在您的情况下,只在单个过程中使用CSharpSyntaxRewriter(而不保留预处理过程中的引用(就足够了,因为它的VisitPropertyDeclaration方法每个属性只调用一次,所以不需要跟踪您已经修改的节点。

CSharpSyntaxRewriter还自下而上访问节点,因此重写应该始终使用原始树中的节点进行调用。很可能您已经通过对base.VisitPropertyDeclaration()的调用修改了node,然后才将其引用与存储的引用进行比较。因此,如果你真的想的话,你仍然可以保留和比较参考文献。

public class PropertyRewriter : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        // 'node' should be still from the original syntax tree here
        node = (PropertyDeclarationSyntax)base.VisitPropertyDeclaration(node);
        // 'node' might be replaced here
        return node;
    }
}

您可以对它们进行注释,而不是保留对要修改的节点的引用。只要节点本身不被替换,节点的注释将在包含SyntraxTree的修改后仍然有效。你可以这样添加它们:

node = node.WithAdditionalAnnotations(
        new SyntaxAnnotation("propertyToChange", "todo"));

要再次检索注释,请使用node.GetAnnotations("propertyToChange")GetAnnotatedNodesOrTokens("propertyToChange")检索具有给定类型注释("propertyToChange"(的所有节点或令牌。