Guidedog 手册 0.2.0
语言
本页内容
Guidedog / 文档 0.2.0

为 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 层 &&、|| 和 !,更长则视为未求值。