从零实现增量源生成器 · 第 7 / 17 篇

目标类型发现,为什么不能靠全文扫描

目标发现不是把所有类型扫一遍再碰运气,而是尽早缩小候选集,再把语义判断放进转换阶段。

目标发现阶段决定了生成器的第一层性能上限。你如果一开始就全量扫描所有类型、再慢慢过滤,项目稍微大一点,体验就会开始变差。

当前项目使用的是更明确的发现方式:

context.SyntaxProvider.ForAttributeWithMetadataName(
    "Tutorial.ToStringGenerator.GenerateToStringAttribute",
    static (node, _) => node is ClassDeclarationSyntax,
    static (context, token) => GenerationSpecFactory.Create(context, token))

这里做了哪三件事

  • 先按特性元数据名缩小候选范围
  • 再用语法节点类型做一次快速过滤
  • 最后进入工厂方法,把语法和语义组合成可生成规格

这三步拆开后,思路会清楚很多。发现阶段不直接生成代码,而是只负责回答一个问题:这个目标值不值得进入下一步。

为什么发现后不直接渲染

因为发现阶段解决的是“是不是目标”,渲染阶段解决的是“该怎么生成”。这两个问题揉在一起,排错会非常痛苦。

一旦后续要补:

  • partial 约束
  • static 类型限制
  • 自定义 ToString 冲突
  • 嵌套类型约束

你就会发现,把发现和生成分开是必须的,不是风格问题。

目标发现的核心标准

越早缩小候选集越好,越晚进入复杂逻辑越稳。好的发现阶段不应该承担所有语义判断,但必须把无关输入尽早挡在门外。

教程导航

继续阅读

当前文章已经挂到教程顺序中,建议按相邻章节继续。

上一篇 从入口方法看清主管线:生成器真正做了哪几步 入口方法不只是注册几个 API,它其实把整个生成器拆成了特性准备、目标发现、规格生成和源代码输出四个阶段。 下一篇 从 Symbol 到模型:生成器为什么需要中间层 不要在拿到 Symbol 后直接拼字符串;先抽出目标类型模型、属性模型和声明模型,渲染层才会稳定。
查看系列目录 查看全部文章

标签

分类