RFC-0043:文档注释格式

RFC-0043:文档注释格式
状态已接受
区域
  • FIDL
说明

此 FTP 采用了单一格式来编写文档注释。此格式可供以其他人类可读且可供机器使用的格式(例如HTML、Markdown)。

作者
提交日期(年-月-日)2019-05-06
审核日期(年-月-日)2019-05-30

摘要

此 RFC 标准化了用于编写文档注释的单一格式。此格式可供以其他人类可读且可供机器使用的格式(例如HTML、Markdown)。

设计初衷

我们目前提供了一个 API 文档评分标准,其中明确说明了需要记录 FIDL 代码的哪些方面,包括参数、返回值和错误。我们还鼓励开发者提供 API 使用示例。不过,我们尚未向开发者提供在 FIDL API 文档中清晰表达这些功能的方法。

随着 fidldoc 工具的出现,为开发者提供一种在注释中表达格式的途径变得更加重要。编写注释的开发者应了解如何在输出中设置列表格式,例如。他们还必须知道如何指明某个内容是返回值还是参数,以便在输出中正确显示该内容。

设计

要点:我们希望使用 Markdown 来添加评论。当然,细节决定成败。

此 RFC 修改了 API 文档评分标准,以及我们用于处理 FIDL API 文档的工具。这不会影响 FIDL 语言,因为一组合法的 FIDL 保持不变。

为什么使用 Markdown?

文档注释的解决方案空间可分为两部分:“自行开发解决方案”和“使用现有解决方案”。我们认为,FIDL 的生态系统规模不足以支持为注释语法开发单独的标准。通过使用现有解决方案,开发者将能够利用外部文档和工具(以及可能的现有知识)。此外,通过使用现有解决方案,我们可以节省开发时间。

如果我们决定使用现有解决方案,就必须选择一个。有几种特定于语言的解决方案可以扩展(例如 javadoc 和 Python 文档字符串)。还有一些通用解决方案(例如LaTeX、RST、Markdown)。

我们认为 Markdown 是最佳选择。与特定语言的解决方案不同,有许多工具可将 Markdown 集成到新语言中。Markdown 也广泛为开发者所用和了解:例如,GitHub 就使用 Markdown 编写文档。最后,某些语言(例如Rust 和 Kotlin)正在将其语法标准化为 Markdown,并且它也开始取代其他语言中的现有解决方案(例如,LLVM 将从 RST 迁移到 Markdown)。

什么是 Markdown?

Markdown 有多种实现,行为略有不同。其中任意数量的选项都是合理的选择。我们选择 CommonMark,因为它是最接近标准的。 对于工具需要同时定位到 CommonMark 和其他 Markdown 实现的开发者,我们建议尽可能使其文档与这两者兼容。

Markdown 不可扩展,因此无法帮助您表达语言元素。我们添加了可由 fidldoc(以及其他 API 文档使用工具)处理的 Markdown 专用扩展。

文档注释采用 Markdown 格式编写,位于要记录的元素之前。它包含一个说明,可选地后跟有关参数、错误和“see”(表示读者应查看所引用的 API 以了解详情)的文档。

参数和错误

应记录请求参数:

* request `paramname` Description of parameter

应记录响应参数:

* response `paramname` Description of parameter

我们还将 paramreturninout 视为关键字,而不是 requestresponse

如果该方法不使用相同的标识符作为请求和响应的参数,则 requestresponse 是可选的。

返回无参数值 (Foo() -> ()) 的方法可以使用术语 response,而无需对应的参数来进行文档编写。

错误子句应记录在以下位置:

* error Description of error values

完全限定名称

完全限定名称的格式为:

<library>/<top level declaration>.<member>

这将唯一标识任何成员,因为没有重载。

目前,序数哈希基于采用 <library>.<top level declaration>/<member> 格式的名称(请参阅 RFC-0020),fidlc 使用 <library>.<top level declaration>/<member> 格式报告错误。我们打算让这些内容采用上述明确的格式。我们将修改 RFC-0029:递增方法序数,以使用 <library>/<top level declaration>.<member> 作为经过哈希处理的名称,并修改 fidlc 以一致地报告错误。

通过添加 [`link-target`],可以链接到其他与文档关联的 FIDL 语言元素(或已记录的实体)。例如,[“fidl.io/NodeInfo”] 链接到该库的文档。分辨率规则如下:

  1. 首先,系统会检查嵌套元素。如果您要记录 struct Object,并且它包含成员 event,则可以将其引用为 [`event`]。
  2. 接下来,系统会检查与记录的元素处于同一作用域级别的元素。例如,如果您要记录协议方法 foo(),而同一协议包含方法 bar(),则可以将其称为 [`bar`]。
  3. 接下来,系统会检查封闭作用域的元素(如果有)。例如,如果您要为协议方法 foo() 编写文档,并且同一库中还有另一个名为 Info 的协议,则可以通过 [`Info`] 来引用该协议及其元素。
  4. 在连续封闭的范围中重复 3,直到您到达顶级范围。如果您要记录协议方法 foo(),并编写 [`fuchsia.io/NodeInfo`],则它将引用联合体 fuchsia.io/NodeInfo

完全限定名称采用 <library>/<top level declaration>.<member> 格式,请参阅上文中的详细信息

对于其他链接快捷方式,您可以指定链接目标,例如:

[fuchsia-concepts]: https://fuchsia.dev/fuchsia-src/concepts

该行不会显示在工具输出中。

如果工具在运行时知道给定的 FIDL 目标类型,则无需指定位置。例如,在同一工具调用中,系统可能会生成 fuchsia.sys/ComponentControllerfuchsia.sys/EnvironmentController 的文档。该工具会了解它们之间的关联。

开发者还可以使用以下方式指明存在相关 API:

* see [`fidl.io`]

(如果适用)。

实施策略

实现包括将其添加到 FIDL 评分标准、对其进行公开以及将特殊注解纳入 fidldoc 工具。我们还可以为 fidldoc 语法添加 lint 检查,将其添加到 fidl-lint 工具或单独的工具中。

文档和示例

完整示例如下所示。 请注意,此 API 目前并非如此;我们已将状态更改为“错误”以作说明。

library fuchsia.io;

protocol File {
    /// Acquires a [`fuchsia.mem/Buffer`] representing this file, if
    /// there is one, with the requested access rights.
    ///
    /// ## Rights
    ///
    /// This method requires the following rights:
    ///
    /// * [`OPEN_RIGHT_WRITABLE`] if `flags` includes
    ///   [`VMO_FLAG_WRITE`].
    /// * [`OPEN_RIGHT_READABLE`] if `flags` includes
    ///   [`VMO_FLAG_READ`] or [`VMO_FLAG_EXEC`].
    ///
    /// + request `flags` a bit field composing any of
    ///   `VMO_FLAG_READ`, `VMO_FLAG_WRITE`, or `VMO_FLAG_EXEC`.
    /// - response `buffer` the requested [`fuchsia.mem/Buffer`], or
    ///     null if there was an error, or the buffer does not exist.
    /// * error a `zx.status` value indicating success or failure.
    /// * see [Filesystem architecture][fs-arch] for further details.
    ///
    /// [fs-arch]: https://fuchsia.dev/fuchsia-src/concepts/filesystems/filesystems
    GetBuffer(uint32 flags) ->
        (fuchsia.mem.Buffer? buffer) error zx.status;
};

请注意,按照惯例,您只需在给定文档注释中链接到元素的第一个引用即可。上述对 VMO_FLAG_READ 的第一个引用已关联,而第二个引用未关联。

向后兼容性

没有重大的向后兼容性问题。当前文档使用 C++ 风格的 |param| 表示法来指明参数和返回值。这相对来说比较容易更改。

性能

这会增加开发者输入的字符数,进而影响开发速度,但同时也会让开发者了解更多。

缺点、替代方案和未知情况

假设采用格式比不采用格式要好得多。因此,缺点很少。

替代方案可能包括其他 API 文档格式。Java 使用 Javadoc,它非常详尽且依赖于内嵌 HTML。开发者会觉得很痛苦。其他语言使用 RST。不过,这种方式越来越不受欢迎;开发者更熟悉 Markdown。值得注意的是,LLVM 项目正在从 RST 迁移到 Markdown。

我们考虑过使用 Markdown 的其他变体。我们之所以选择使用 CommonMark,是因为它是经过最完善规范的 Markdown 实现。如果开发者需要其代码在其他 Markdown 渲染系统中正常运行,则应尝试编写符合 CommonMark 和目标系统的文档注释。

我们考虑过不为关联记录的实体发明新的语法。 我们考虑的替代方案包括:

  • 自动检测。 在其他情境中使用自动检测机制的经验表明,它们很少检测到开发者预期的内容。此外,自动检测功能还可防止工具显示链接错误这一事实。因此,我们将自动检测功能的相关工作推迟到日后。
  • 使用现有语法。这与自动检测有相同的问题,但症状略有缓解。如果我们使用 fuchsia.io/NodeInfo 作为语法,那么如果拼写有误,则不会显示链接,而只会显示代码字体。我们希望工具能够检测损坏的链接,而不是采用回退行为。

我们日后应考虑但不在本 RFC 范围内的事项包括:

  • 将图片或流程图嵌入到生成的文档中的方法。
  • 将自动检查的示例嵌入到文档中的方法。

在先技术和参考文档

此提案深受 Rust 和 Kotlin 文档样式的启发。