为 Odin 生成文档¶
Odin 域为包、过程、类型和成员提供命名目标。Guidedog 也能解析 Odin 源码生成 API 页面,不调用编译器,也不执行包。生成的签名仍需有用的契约。
描述对象¶
包为后续内容提供上下文,如同 Python 模块:
.. odin:package:: core:strings
:synopsis: Procedures to manipulate UTF-8 encoded strings.
:imports: rt=base:runtime
.. odin:procedure:: @(require_results) clone :: proc(s: string, allocator := context.allocator) -> (res: string, err: rt.Allocator_Error) #optional_allocator_error
Clones a string.
:param s: The string to be cloned.
:result res: The cloned string.
:result err: An allocator error, or ``nil``.
.. odin:struct:: Builder :: struct
A dynamic byte buffer.
.. odin:field:: buf: [dynamic]byte
签名按 Odin 声明形式写在一行中,显示也相同。以下示例的效果如下:
- shapes.Kind :: enum u8
-
- Circle = 1
- @(require_results) shapes.area :: proc(side: f32, scale: f32 = 1) -> (a: f32, ok: bool) #optional_ok
-
测量一个正方形。
- 参数:
side – 边长。
- 返回:
a – 面积。
ok – 类型是否已知。
指令及其接受的签名:
odin:package和odin:currentpackage-
可写
core:fmt,或项目根目录下的路径,如readers/sphinx。对象名称使用包导入路径:core:fmt.println。odin:currentpackage只改变上下文、不生成目标;None清空上下文。选项有:synopsis:、:platform:、:deprecated:、:no-index:和:imports:。后者按alias=package列出签名使用的导入别名,如gd=core rst=readers/rst,使gd.Node_Id链接到core.Node_Id。:private:列出私有类型及过程组的私有成员,如State Rules catalog_text;签名将其显示为文本,因为没有描述可链接。生成页面自动列出它们。 odin:procedure(或odin:proc)-
name :: proc(params) -> results,支持名称前属性(@(require_results))、proc前的#force_inline、调用约定(proc "c" (...))、默认参数(x := 1、x: int = 1)、$T多态参数、..可变参数、using、#c_vararg、命名结果、标签(#optional_ok)和where子句。name(params) -> results是简写。 odin:procgroup-
name :: proc{a, b}:每个成员链接到对应过程。 odin:struct,odin:union,odin:enum,odin:bitset,odin:bitfield,odin:type-
Name :: struct($T: typeid) #packed、Name :: union #no_nil {A, B}、Name :: enum u8、Name :: bit_set[Flag; u8]、Name :: bit_field u32。odin:type支持独立类型和别名(Handle :: distinct uintptr、Callback :: proc(x: int) -> bool)。类型内容包含其成员。 odin:field和odin:enumerator-
类型内部使用
name: Type,可带标签(name: string `json:"n"`)或位宽(low: u8 | 3);枚举成员使用Name或Name = 3。其名称为Type.member。 odin:const,odin:var,odin:foreign-
NAME :: 64或NAME : int : 64;name: Type、name := value或name: Type = value;外部导入使用libc "system:c"。
所有对象支持 Sphinx 域选项::no-index:、:no-index-entry:、:no-contents-entry:、:no-typesetting:。另有 :package:(在其他包中描述)、:private: 和 :deprecated: message(签名未含时显示为 @(private) 和 @(deprecated="message"))、:availability: Windows, Linux(内容首行说明可用平台)、:foreign: libc(外部块过程)。多行签名描述同一对象在不同目标上的形式,只有第一行获得 ID 和索引条目。
类型位置的名称链接到对应类型,先在签名所属包和类型中查找,再按原名称查找。内置类型(int、string、rawptr、typeid、any 等)、关键字、多态名称($T 及后续 T,包括外层类型中的名称)、数组长度、默认值、常量、标签和 where 子句均原样显示,不生成链接。
角色与标识符¶
:odin:pkg:、:odin:proc:、:odin:type:(结构体、联合体、枚举、位集合、位字段等类型)、:odin:const:、:odin:var:、:odin:field:、:odin:enumerator: 和 :odin:obj:(任意对象)用于链接。与 Python 域一样,~ 只显示末段(:odin:proc:`~core:fmt.println` 显示 println),前导 . 匹配任意对象名称的末尾。查找先在引用所属类型和包中,再按原名,再取包路径 : 或 / 之后部分;因此 fmt.println 找到 core:fmt.println,sphinx.Config 找到 readers/sphinx.Config,符合 Odin 使用包路径末段命名的方式。当前包 :imports: 的别名优先解析。设置 default-domain:: odin 或 primary_domain = "odin" 后,角色无需 odin: 前缀。
对象 ID 用 Sphinx 的 make_id 处理 odin- 与全名:odin-core-fmt.println、odin-readers-sphinx.Config.docname。与 Python ID 一样保留大小写和点;导入路径中的 : 和 / 变为连字符。ID 可读、构建间稳定,也区分末段同名的包。包 ID 为 odin-package- 加路径。索引如“println (procedure in core:fmt)”。objects.inv 按 odin 域和类型(odin:procedure、odin:struct、odin:field 等)列出所有对象,包排在前面,如 Sphinx 的模块。
内容中的信息字段与其他域一样分组::param name:(配合 :type name:)、命名结果的 :result name:、:returns: 和 :rtype:。
从源码生成¶
指定包相对于源目录的位置:
odin_autoapi_dirs = ["../src"]
odin_collections = {core = "/usr/local/lib/odin/core"} # optional
odin_autoapi_dirs 下的包按相对路径命名(src/shapes/round 为 shapes/round);集合内的包按 Odin 导入名称命名(core:strings)。生成指令随后按 autodoc 的方式工作:
.. odin:autopackage:: shapes
:members:
:undoc-members:
:member-order: groupwise
.. odin:autoproc:: shapes.area
.. odin:autotype:: Shape
odin:autopackage 输出包及文档注释,带 :members: 时也输出声明(全部或指定项)。odin:autoproc、odin:autoprocgroup、odin:autotype、odin:autoconst、odin:autovar 各输出一个声明,可用当前包名称或 package.name。选项::members:、:undoc-members:、:private-members:(默认省略的 @(private) 声明)、:exclude-members:、:member-order:,其值为 source(默认,先文件名后位置)、alphabetical、groupwise(分为“Types”“Procedures”“Procedure groups”“Constants”“Variables”“Foreign imports”),以及 :no-index:。
文档注释是声明正上方的 // 行或 /* */ 块,以及字段或枚举成员的行尾注释。它们是纯文本,按以下规则转为 reStructuredText:
- 段落仍是段落;由
- item行组成的列表仍是列表。 - 空行之后,或以冒号结尾的行(
Example:)之后,缩进块(制表符或空格)转为code-block:: odin;Output:后转为text。若某行比紧接段落行的文本缩进更深,则续接该段落。 Inputs:后的- name: text列表转为:param name:字段;Returns:条目转为:result name:,无名称则转为:returns:。这与 Odin 核心库的注释形式一致。- 以
NOTE:或WARNING:开头的行成为注释或警告。 `code`是字面文本。其他会被 reStructuredText 解释为标记的字符(*、|、词尾_等)都进行转义,因此注释按原样显示,不产生警告。
API 页面¶
设置 odin_autoapi_dirs 后,其中每个包也获得独立页面,在构建读取时生成,类似 sphinx-autoapi。api/shapes 使用 odin_autoapi_options 包含 odin:autopackage:: shapes;api/index 列出各包和简介。页面属于项目文档,可进入 toctree、搜索、总索引、singlehtml 和 PDF,但不写入源目录。设置如下:
odin_autoapi_dirs-
需要生成页面的包目录,相对于源目录。只读取这些目录及
odin_collections内的文件;指向外部的链接会被拒绝。 odin_collections-
集合名称与目录的表,用于
core:strings等指令参数。这些包不生成页面。 odin_autoapi_root-
页面目录,默认
"api"。若源文档已占用某页面名称,则保留源文档并发出警告。 odin_autoapi_options-
默认
["members", "undoc-members"];可加入private-members。 odin_autoapi_member_order-
"source"(默认)、"alphabetical"或"groupwise"。 odin_autoapi_add_toctree_entry-
true(默认):api/index加入根文档的第一个 toctree。 odin_autoapi_generate_api_docs-
true(默认);false时只为指令读取目录。
未记录包的类型(core:io.Writer)无法链接。使用 -n 时,可用 nitpick_ignore_regex = [["odin:type", "(core|base):.*"]] 抑制这类警告。Guidedog 的 docs/api 也采用此设置。
平台¶
按 Odin 对文件的判断,为包的各构建目标生成文档。*_windows.odin、*_linux_arm64.odin、*_amd64.odin 只适用于对应目标;#+build linux, darwin、#+build !windows(及旧式 //+build)进一步限制。文件级 when ODIN_OS == .Windows 若只比较 ODIN_OS 和 ODIN_ARCH,其分支归对应目标,else 归其余目标。省略 *_test.odin 和 #+ignore 文件。所有目标共有的声明只显示一次;部分目标的声明标明平台,如“Availability: Windows”;签名不同时每种签名显示一次并标明目标,仅第一种有 ID。只支持部分目标的包用 :platform: 说明。
重新构建¶
页面读取的每个 Odin 文件都成为该页依赖。修改包源码后,下次构建只重读记录该包的页面。包新增、删除或简介改变时,重读包索引。guidedog serve 在提供 HTML 页面前检查 odin_autoapi_dirs 和 odin_collections 的修改时间;编辑后刷新浏览器。
限制¶
- 源码仅解析,不编译或类型检查:类型和常量值按原样显示,常量值超过 100 字符则省略,不做推断。
A :: B是类型还是常量由名称判断:首字母大写但非全大写的名称,或内置类型,按类型处理。 when中除ODIN_OS和ODIN_ARCH比较之外的条件不求值,两分支都会记录。- 声明引用私有类型时显示为文本,因为除非指定
:private-members:,私有声明没有条目。生成的包通过:private:列出它们,因此-n不会报告这类引用。 core:odin/parser拒绝同时带#optional_ok和where子句的过程。此类文件会被报告,能读取的部分仍生成文档。- Odin 解析器处理深度嵌套需要大量栈,数百层括号可使线程栈溢出。远超实际代码深度的文件(约 50 层括号或类型,或同一链约千个
else)会以odin.autodoc.nesting警告省略,其余包内容照常记录。when条件最多求值 64 层&&、||和!,更长则视为未求值。