给定通过不同的 `SemanticModel` 实例获得的匹配 IMethodSymbol 对象,如何获取 IMethodSymbol 对象?

Posted

技术标签:

【中文标题】给定通过不同的 `SemanticModel` 实例获得的匹配 IMethodSymbol 对象,如何获取 IMethodSymbol 对象?【英文标题】:How to get the IMethodSymbol object given the matching IMethodSymbol object obtained through a different `SemanticModel` instance? 【发布时间】:2021-12-19 21:46:17 【问题描述】:

我从给定的SemanticModel 获得了一个IMethodSymbol 对象,但随后意识到该符号缺少对其声明语法的引用。

让我们假设我可以轻松地为任何符号创建尊重 SyntaxTree 对象。

如何“刷新”IMethodSymbol 对象?

这是我目前所拥有的:

IMethodSymbol methodSymbol = ...;
if (methodSymbol.DeclaringSyntaxReferences.Length == 0)

    var syntaxTree = ...;
    var compilation = semanticModel.Compilation.AddSyntaxTrees(syntaxTree);
    semanticModel = compilation.GetSemanticModel(semanticModel.SyntaxTree);
    methodSymbol = ???;

新的semanticModel 对象链接到新的compilation 对象,该对象使用相关的语法树扩展了旧对象。我不想重复我最初用来获取methodSymbol 对象的整个过程。

当然,我应该能够利用我已经从语义模型的另一个实例中获得它的事实。但是怎么做呢?

【问题讨论】:

【参考方案1】:

这似乎是一个 hack,但我们可以通过注释 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);

【讨论】:

非常有趣的方法。但它并没有完全回答这个问题。您没有利用链接到语义模型的先前实例的methodSymbol 的存在。相反,您说的是“使用任何算法来查找声明,对其进行注释,然后使用注释第二次找到它”。我理解基本原理 - 找到带注释的节点可能比原始过程更简单。但是你在这里暗示不可能“重用”以前找到的符号。 @mark 据我所知,我们无法在新的语义模型中找到以前存在的引用。缺少诸如全局唯一标识符之类的概念。这就是我提出“注解方式”的原因 问题是注解创建了一个全新的SyntaxTree 实例。这可能是有问题的。因为我猜新树不等于旧树? 它不会创建SyntaxTree 的新实例。我们只替换 same 语法树中的单个节点(可能还有它的子节点)。此外,IsEquivalentTo(...) 方法将返回 true,因为注释被忽略。 哦,那好多了。我将不得不抽出时间来探索它。

以上是关于给定通过不同的 `SemanticModel` 实例获得的匹配 IMethodSymbol 对象,如何获取 IMethodSymbol 对象?的主要内容,如果未能解决你的问题,请参考以下文章

通过分析 JDK 源代码研究 TreeMap 红黑树算法实

#私藏项目实操分享# Angular @HostListener 装饰器的使用笔记

#私藏项目实操分享# Angular @HostListener 装饰器的使用笔记

#私藏项目实操分享#iOS开发:NSSet的使用

跟着动画学Go数据结构之冒泡排序 #私藏项目实操分享#

python 通过给定目录统计所有的不同子文件类型及占用内存