0

I obtained a IMethodSymbol object from the given SemanticModel, but then realized the symbol lacks the reference to its declaration syntax.

Let us assume I can easily create the respect SyntaxTree object for any symbol.

How can I "refresh" the IMethodSymbol object?

Here is what I have so far:

IMethodSymbol methodSymbol = ...;
if (methodSymbol.DeclaringSyntaxReferences.Length == 0)
{
    var syntaxTree = ...;
    var compilation = semanticModel.Compilation.AddSyntaxTrees(syntaxTree);
    semanticModel = compilation.GetSemanticModel(semanticModel.SyntaxTree);
    methodSymbol = ???;
}

The new semanticModel object is linked to the new compilation object which extends the old one with the relevant syntax tree. I do not want to repeat the whole process I used to get the methodSymbol object in the first place.

Surely I should be able to leverage the fact that I already have it from the other instance of the semantic model. But how?

mark
  • 59,016
  • 79
  • 296
  • 580

1 Answers1

1

This appears to be a hack, but we could add a kind of reference by annotating a SynatxNode:

MethodDeclarationSyntax method = ...
// create annotation
var methodAnnotation = new SyntaxAnnotation("MethodWithoutReferences");
         
// nodes are immutable, i.e., we have to create a copy containing our annotated method
var newMethod = method.WithAdditionalAnnotations(methodAnnotation);
var newRoot = root.ReplaceNode(method, newMethod);
    
// retrieve the annotated node   
var annotatedMethod = newRoot.GetAnnotatedNodes(methodSymbolAnnotation).Single();
var methodSymbol = semanticModel.GetDeclaredSymbol(annotatedMethod);
momo
  • 3,313
  • 2
  • 19
  • 37
  • Very interesting approach. But it does not exactly answer the question. You are not leveraging the existence of `methodSymbol` linked to the previous instance of the semantic model. Instead you are saying something like this "Use whatever algorithm you have to find the declaration, annotate it and then find it the second time using the annotation". I understand the rationale - to find the annotated node may be simpler than the original process. But you imply here that it is not possible to "reuse" the previously found symbol. – mark Nov 08 '21 at 17:53
  • @mark To the best of my knowledge, we can't find a previous existing reference in a new semantic model. A concept such as a globally unique identifier is missing. This is why I proposed the "annotation way" – momo Nov 09 '21 at 09:28
  • The problem is annotation creates a whole new `SyntaxTree` instance. And it can be problematic. Because my guess the new tree is not equivalent to the old one? – mark Nov 11 '21 at 02:59
  • It doesn't create a new instance of `SyntaxTree`. We only *replace* a single node (and perhaps its children) within the *same* syntax tree. In addition, the `IsEquivalentTo(...)` method will return true since annotations are ignored. – momo Nov 11 '21 at 18:48
  • Oh, that is much better. I will have to find time to explore it. – mark Nov 11 '21 at 20:48
  • Sorry, I must correct myself: it generates a new `SyntaxTree` because SyntaxTrees are per se immutable. The `IsEquivalentTo(...)` function, however, will ignore the annotation and treat the syntax trees as equal. – momo Nov 11 '21 at 20:59