0

当我尝试注释类、属性和方法,然后尝试检索带注释的节点时,只返回类一。为什么?

这是注释的代码

SyntaxAnnotation propertyAnnotation = null;
SyntaxAnnotation classAnnotation = null;
SyntaxAnnotation setMethodAnnotation = null;

document = document
    .AnnotateClass(classDeclaration, out classAnnotation)
    .AnnotateProperty(propertyDeclaration, out propertyAnnotation)
    .AnnotateSetMethod(setMethodDeclaration, out setMethodAnnotation);

我在 IDocument 上定义了这些扩展方法

    internal static IDocument AnnotateSetMethod(this IDocument document, MethodDeclarationSyntax method,
                                                                        out SyntaxAnnotation annotation)
    {
        annotation = new SyntaxAnnotation();

        var newRoot = document.GetSyntaxRoot()
                                .ReplaceNode(method, method.WithAdditionalAnnotations(annotation));

        return document.UpdateSyntaxRoot(newRoot);

    }

    internal static IDocument AnnotateProperty(this IDocument document, PropertyDeclarationSyntax property,
                                               out SyntaxAnnotation annotation)
    {
        annotation = new SyntaxAnnotation();

        var newRoot = document.GetSyntaxRoot()
                                .ReplaceNode(property, property.WithAdditionalAnnotations(annotation));

        return document.UpdateSyntaxRoot(newRoot);
    }

    internal static IDocument AnnotateClass(this IDocument document, ClassDeclarationSyntax classDeclaration,
                                              out 

        SyntaxAnnotation annotation)
        {
            annotation = new SyntaxAnnotation();

            var newRoot = document.GetSyntaxRoot()
                                    .ReplaceNode(classDeclaration, classDeclaration.WithAdditionalAnnotations(annotation));

            return document.UpdateSyntaxRoot(newRoot);
        }

public static TSyntaxNode GetAnnotatedNode<TSyntaxNode>(this IDocument document, SyntaxAnnotation annotation)
                where TSyntaxNode : CommonSyntaxNode
            {
                return document.GetSyntaxRoot().GetAnnotatedNode<TSyntaxNode>(annotation);
            }

如果我这样做

var propertyDeclaration = document.GetAnnotatedNode<PropertyDeclarationSyntax>(propertyAnnotation);

我收到一个错误,但如果我尝试使用 ClassDeclarationSyntax 它工作正常。

4

1 回答 1

1

我的水晶球告诉我,除了 AnnotateClass 之外的所有 .Replace 节点调用都失败了。看看你得到的新根是否与旧根完全相同。

这是因为一旦你给类添加了注解,你现在就有了一棵新树,所以你拥有的属性语法不再“在”那棵树中——它是一个新节点。这是不变性的方式——一旦在某处创建了新节点,树中的所有节点实际上都是新的,因为您可以从任何其他节点到达任何节点。(正是因为这个问题,我们一开始就添加了语法注释......否则你会创建几个节点并且无法返回它们。)

你有几种方法可以解决这个问题:

  1. 使用 SyntaxRewriter 在一个阶段完成全部重写。您覆盖 VisitClass、VisitProperty 等,并一次生成带有注释的新节点。
  2. 与其调用 ReplaceNode,不如调用 ReplaceNodes,在其中一次替换所有三个节点。

在任何一种情况下,出于性能原因,进行一次重写总是比一堆重写更可取。就像我说的,一旦你替换了树中的一个节点并取回了一个新的根,你所有的实例都已经改变了,可能需要重新创建。这很昂贵并且会产生内存压力。

[从技术上讲,这种说法是谎言:我们确实懒惰地构建东西并重复使用很多东西。但重写越少越好。]

于 2013-11-01T21:57:26.223 回答