.net - 编译器管道如何对应增量源生成?

标签 .net roslyn roslyn-code-analysis csharp-source-generator

我无法理解 Roslyn 文档并将其与我在使用增量源生成器时看到的内容相匹配。

https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/compiler-api-model

它的图片信息非常丰富。

enter image description here

据我了解,语法树是解析器工作的结果(这是正确的吗?)。我可以通过 IncrementalGeneratorInitializationContext.SyntaxProvider 访问语法树。让我困惑的是 GeneratorSyntaxContext 有一个名为 SemanticModel 的属性,它似乎允许访问符号。我认为符号是编译的产物,在处理语法时不应该可用。

这引出了另一个问题。编译器管道的哪一部分对应于编译?是 Binder 吗?

最佳答案

增量生成器和管道没有直接关联。老实说,该图确实应该表述为:

  1. 解析器生成 SyntaxTree 对象。 (那就是深绿色的盒子。)
  2. 多个 SyntaxTree 对象可以粘在一起形成一个 Compilation 对象,该对象提供对符号的访问(灰色框)。
  3. 给定 Compilation 和 SyntaxTree,您可以获得 SemanticModel 来在那里提出进一步的问题(浅绿色框)。
  4. Compilation 有一个您可以使用的发射 API(即浅绿色框。)

不要将其视为管道,而是将其视为数据结构,因为事物指向其他事物,并且您在生成器中说明了您所依赖的数据结构。这个想法是越精确,它就能让我们在 IDE 中运行得更快,这样下次击键时我们就可以减少重新运行的次数。

在 IDE 中实际发生的是击键,我们为您编辑的文件生成一个新的语法树,但我们拥有您未更改的所有现有树。我们生成一个新的编译,并可能重新运行生成器。我们将首先运行增量语法提供程序的“谓词”部分来查找编辑树中的节点,但我们仍然知道其他树的生成器之前运行的节点。这样您就不必重新分析未更改的部分。然后,我们为您提供再次使用语义查看节点的机会,但成本更高。

这样做的真正目标是“遍历每个语法树并找到所有看起来像特定模式的节点”是昂贵的,因此这让我们可以在中间进行缓存,以使从一次运行到下一次运行的成本更便宜。

关于.net - 编译器管道如何对应增量源生成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71607413/

相关文章:

c# - 如何使用 Roslyn 独立分析从别名获取类型

c# - 为什么下面的代码编译没有错误?

c# - 使用 Roslyn 替换方法

asp.net-mvc - VS 2015、C# 6、MVC5、Roslyn — Azure Web 应用程序上出现 502 网关错误

c# - FxCop 分析器不会即时显示警告

.Net 本地化与品牌化

.net - 为什么不从 GridView 的下拉列表中触发 SelectedIndexChanged 事件?

c# - 在 C# 中检索 RETURN @@IDENTITY 的值

.net - 无法构建某些服务 - 在 Worker Service .Net Core 3.1(依赖注入(inject))中验证服务描述符时出错

roslyn - 如何跨 Workspace.TryApplyChanges() 跟踪 SyntaxNodes