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

ToString 渲染层到底在解决什么问题

代码渲染不只是拼一段字符串,它要负责重新打开命名空间、嵌套类型和目标类型,并保证输出代码可编译。

到了渲染层,很多人会本能地觉得“这部分最简单”。实际上,渲染层虽然不碰复杂语义,但非常容易制造编译级回归。

当前项目的渲染顺序很明确:

  • 先补 #nullable enable
  • 再写命名空间
  • 再逐层重新打开外层嵌套类型
  • 最后在目标类型里输出 ToString()

为什么要重新打开外层类型

因为目标类型如果位于嵌套结构中,生成文件必须在同样的结构里重新声明分部类型,编译器才能把两边合并起来。

这也是为什么当前项目专门维护了 ContainingTypes。如果外层结构丢了,生成代码即使文本上看起来像对的,也会在编译期出问题。

ToString 表达式里真正重要的细节

当前实现对需要空值防护的属性会走:

  • ?.ToString() ?? "null"

而不是一律直接插值。这种处理看起来像小事,但会直接决定引用类型和可空值类型的输出行为是否稳定。

渲染层的目标不是“聪明”

渲染层越机械越好。它只需要忠实消费前面已经整理好的模型,然后生成一份可编译、可读、可测试的文本。真正的判断应该尽量留在前面的发现和建模阶段。

教程导航

继续阅读

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

上一篇 属性怎么选,输出面就怎么长 主案例只选择公开、可读、非索引器、非静态属性,这不是保守,而是在明确生成器的输出面。 下一篇 为什么 hint name 不是随便起一个文件名 hint name 决定生成文件的身份边界;对嵌套类型和多目标输入来说,它不是装饰,而是稳定输出的一部分。
查看系列目录 查看全部文章

标签

分类