Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
482 views
in Technique[技术] by (71.8m points)

c# - Where is my annotation?

When I try to annotate class, property and method, and then try to retrieve annotated node, only the class one is returned. Why?

Here is the code that annotates

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

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

I have these extension methods on IDocument defined

    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);
            }

And if I do

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

I get an error, but if I try with ClassDeclarationSyntax it works fine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My crystal ball is telling me that the .Replace node calls in all but your AnnotateClass are failing. See if the new roots you get back are the exact same object as the old roots.

This is because once you've added an annotation to the class, you now have a new tree, and so the property syntax you have is no longer "in" that tree -- it's a new node. This is the way of immutability -- once a new node is created somewhere, all the nodes in the tree are effectively new since you can get to any node from any other node. (It's because of this problem that we added syntax annotations in the first place....otherwise you'd make a few nodes and have no way to get back to them.)

You have a few ways to approach this:

  1. Use a SyntaxRewriter where you do the rewrite all in one stage. You override VisitClass, VisitProperty, etc and produce new nodes with annotations all at once.
  2. Rather than calling ReplaceNode, call ReplaceNodes, where you replace all three nodes at once.

In either case, doing a single rewrite is always preferable to a bunch of rewrites for performance reasons. Like I said, once you replace a node in a tree and get back a new root, all your instances have changed and may have to be re-created. This is expensive and produces memory pressure.

[Technically, that statement is a lie: we do build stuff lazily and reuse lots stuff. But the less rewrites the better.]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...