深入解读 Roc 包文档生成:私有模块与私有类型声明的隐藏机制(Issue 10077) 📅 发布时间:2026/9/17 23:28:21 👁 浏览次数: 深入解读 Roc 包文档生成私有模块与私有类型声明的隐藏机制Issue 10077【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc导读Roc 编译器在为package生成 API 文档时只会暴露包声明中列出的模块而模块内部的私有类型声明、被间接import的辅助模块都会被一并隐藏。本文以仓库中的快照测试文档test/snapshots/docs_package_hides_private_modules.md为骨架结合src/docs/DocModel.zig中PackageDocs的实现完整解读package-docs的 S-expression 输出结构、模块可见性规则以及如何用快照工具复现与验证这一行为。快照文档的三个组成部分该文档位于 test/snapshots/docs_package_hides_private_modules.md采用test/snapshots/目录下所有快照的统一格式由三个区块构成META以 ini 格式声明快照的元信息description说明本条快照验证的目标——Issue 10077包文档会隐藏私有模块与私有类型声明typedocs表明它属于文档生成docs类快照。SOURCE编译器的输入即一组 Roc 源文件main.roc、Date.roc、Time.roc、Util.roc。DOCS期望输出即文档模型序列化后的 S-expressionpackage-docs由src/docs/DocModel.zig中的PackageDocs.writeToSExprIndented生成。descriptionIssue 10077: package docs hide private mods and private type declarations typedocs被测源码一个导出[Date, Time]的最小包SOURCE 部分构造了一个仅导出两个模块的package包入口main.rocpackage [Date, Time] {}这是 Roc 的package头部语法方括号内是对外导出的模块清单{}为包的空配置。这一行是整个可见性规则的总开关——文档生成器只会为清单中的模块生成文档条目。类型模块Date.rocimport Util ## A calendar date. Date :: {}.{ ## Date formatting options. Format :: {} } ## Private implementation details. Help :: {}这里展示了两个关键特性Date是类型模块type module使用::定义。外层{}给出类型的形状一个记录内部{}承载模块成员。Format是嵌套在Date内的嵌套类型声明同样以::定义并附带文档注释在文档输出中会成为Date条目下的子条目。Help是与Date平级的模块级声明文档注释明确标注Private implementation details.私有实现细节。它不在导出行列因此不会出现在生成的文档中。公开类型模块Time.roc## A time of day. Time :: {}Time是被导出的第二个模块::定义了一个空记录形状的类型模块。被间接引用的私有模块Util.roc## Private utilities used by Date. Util :: {}Util被Date.roc通过import Util引用但它不在package的导出清单中。这正是本快照的核心验证点之一即使一个模块被公开模块内部依赖只要它未被导出生成的文档就必须将其完全隐藏。期望输出package-docsS-expression 结构DOCS 区块给出了上述源码对应的期望文档序列化结果(package-docs (name test-app) (mod (name Date) (package mod) (kind type_mod) (entry (name Date) (kind opaque) (type Date :: (record)) (doc A calendar date.) (entry (name Format) (kind opaque) (type Format :: (record)) (doc Date formatting options.) ) ) ) (mod (name Time) (package mod) (kind type_mod) (doc A time of day.) (entry (name Time) (kind opaque) (type Time :: (record)) (doc A time of day.) ) ) )顶层结构(package-docs ...)整个文档模型的根节点对应src/docs/DocModel.zig中的PackageDocs结构DocModel.zig其writeToSExprIndented方法以(package-docs\n起始输出。(name test-app)文档归属的包名。mod节点模块级信息每个模块对应一个mod节点包含字段含义本快照中的取值name模块名Date、Timepackage模块所属包作用域modkind模块种类type_mod类型模块doc模块级文档注释如A time of day.entry模块暴露的条目类型模块本身及其嵌套条目注意test/snapshots/README.md中提到快照后处理会将移除的 header 关键字统一改写为mod因此 S-expression 内部也统一使用mod表示模块节点。entry节点类型与嵌套声明Date模块的entry描述了类型模块Datekind为opaque不透明类型type为Date :: (record)doc为模块文档。Format作为嵌套entry出现在Date条目之下同样为opaque类型type为Format :: (record)。Time模块的entry结构相同doc与模块级doc一致模块文档即类型文档。关键观察什么被隐藏了对照 SOURCE 与 DOCS 可以发现三处隐藏Util模块整体消失尽管Date.roc中import Util由于Util不在导出清单[Date, Time]中整个mod节点都不存在。Date中的Help声明消失Help是模块级私有声明::定义的私有类型尽管有文档注释仍不出现在Date的条目中。Date对Util的 import 关系不体现文档只描述公开 API 形状不记录内部依赖。这与同目录下的兄弟快照互为印证docs_platform_hides_internal_modules.md验证了platform文档只输出exposes中列出的模块如Stdout而内部宿主边界模块Host被隐藏docs_transitive_modules.md则展示了 app 中通过import可达的模块Geometry、Helpers反而会进入文档。二者共同勾勒出 Roc 文档可见性的完整规则package/platform 的暴露清单决定文档边界import 关系不构成暴露依据。源码印证PackageDocs如何承载这些结构文档模型的实现位于 src/docs/DocModel.zigpub const PackageDocs struct { // ... pub fn writeToSExpr(self: *const PackageDocs, writer: anytype) (Allocator.Error || error{WriteFailed})!void { // ... pub fn writeToSExprIndented(self: *const PackageDocs, writer: anytype, depth: usize) (Allocator.Error || error{WriteFailed})!void { try writer.writeAll((package-docs\n);PackageDocs持有name与modules列表mod节点即模块列表中的一项。每个模块条目携带name、package、kind、doc与嵌套entry序列化顺序与快照 DOCS 区块严格一致。writeToSExprIndented负责递归缩进输出快照中的(package-docs根节点即由此产生。同文件中的resolveDocRefs与reshapeBuiltinDocModel.zig负责文档引用解析与内置类型重塑注释还提到由reshapeBuiltin合成的模块具有特殊标记DocModel.zig。从源码结构看文档构建过程只遍历暴露模块树私有模块与私有声明在模型构造阶段即被过滤快照 DOCS 中看不到它们正是该过滤逻辑的端到端证据。序列化后的PackageDocs还会被 src/docs/render_html.zig 消费用于生成独立的 HTML 文档站点说明该 S-expression 是后续多格式文档渲染的统一中间表示。如何复现与更新这条快照快照测试由src/snapshot_tool/main.zig驱动test/snapshots/README.md 给出了完整的操作方式# 生成/刷新所有快照 zig build run-snapshot-tool # 只处理指定快照文件 zig build run-snapshot-tool -- test/snapshots/docs_package_hides_private_modules.md # 用当前编译器输出更新期望结果谨慎使用 zig build run-snapshot-tool -- test/snapshots/docs_package_hides_private_modules.md --update-expected快照机制的价值在于端到端回归检测typedocs快照将编译器实际生成的PackageDocs序列化结果与期望 S-expression 逐字节比对。一旦文档构建逻辑出现改动例如意外泄露了私有模块Util、Help或改变了opaque的呈现方式zig build run-snapshot-tool就会立即报告差异从而守住公开文档只含公开 API这一约定。若要在新的修改中增加类似的可见性用例可在test/snapshots/下仿照本文档创建METASOURCEDOCS三段式文件再运行快照工具生成期望输出。小结docs_package_hides_private_modules.md以最小化的 4 个源文件精准锚定了 Roc 包文档生成中的两条硬规则未列入package导出清单的模块无论是否被 import一律不出现在文档中公开类型模块内部的私有类型声明同样被过滤。配合PackageDocs的 S-expression 输出与快照工具的回归守护Roc 保证了package文档始终与exposes声明严格一致——这对语言工具链的 API 文档可靠性而言是一项值得借鉴的测试设计。【免费下载链接】rocA fast, friendly, functional language.项目地址: https://gitcode.com/GitHub_Trending/ro/roc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考