FIDL 样式指南

本部分包含 Fuchsia 接口定义语言文件。

另请参阅 FIDL API 评分准则

姓名

猫咪的名字是件难事,
它不仅仅是您的节日游戏之一;
--- 一般Eliot

FIDL 中定义的名称用于生成每种目标语言的标识符。 有些语言会给各种名称包含语义或常规含义, 表单。例如,在 Go 中,标识符中的首字母是否是 大写用于控制标识符的可见性。因此,许多 语言后端会转换库中的名称, 展示内容。本部分的命名规则采用 在 FIDL 源代码的可读性与每个目标平台的可用性之间取得平衡 确保各目标语言的一致性

请避免使用常用的保留字,例如 goto。语言后端 将保留字转换为非保留标识符,但这些将 降低这些语言的易用性。避免使用常见的保留字可以 应用这些转换的频率。

虽然某些 FIDL 关键字在目标语言中通常也是保留字, (例如 C 和 C++ 中的 struct),因此应避免使用,其他 FIDL 关键字(尤其是requesthandle)通常都是描述性的 您可以酌情使用。

名称的开头或结尾不得包含下划线。开头或结尾 下划线在某些语言中具有语义含义(例如,前导下划线 控件可见性)和其他语言中的常规含义(例如, 结尾的下划线通常用于 C++ 中的成员变量)。 此外,FIDL 编译器会使用前导和尾随下划线来移除 标识符,以避免冲突。

使用 size 一词命名字节数。使用 count 一词来命名 其他一些数量(例如,矢量中项的数量) 结构体)。

支持请求定义

有时,有多种方法可以决定 标识符。我们的样式如下:

  • 请以美式英语的原始短语(例如,“Non-Null HTTP Client”)
  • 请移除标点符号。(“非 Null HTTP 客户端”)
  • 全部小写(“non null http 客户端”)
  • 根据适用于指定样式的样式,执行以下某项操作 标识符: <ph type="x-smartling-placeholder">
      </ph>
    • 将空格替换为下划线(“_”)以表示小写蛇形non_null_http_client)。
    • 将空格大写并替换为下划线(蛇形大写) (NON_NULL_HTTP_CLIENT)。
    • 将每个单词的首字母大写,然后将所有单词连接起来 大驼峰式命名法 (NonNullHttpClient)。

用法

下表列出了用例的用法与元素的对应关系:

元素 大小写 示例
bits 大驼峰式命名法 InfoFeatures
Bitfield 成员 上蛇壳 WLAN_SNOOP
const 上蛇壳 MAX_NAMES
alias 大驼峰式命名法 DeviceId
protocol 大驼峰式命名法 AudioRenderer
协议方法参数 下蛇框 enable_powersave
协议方法 大驼峰式命名法 GetBatteryStatus
struct 大驼峰式命名法 KeyboardEvent
结构体成员 下蛇框 child_pid
table 大驼峰式命名法 ComponentDecl
表成员 下蛇框 num_rx
union 大驼峰式命名法 BufferFormat
联盟成员 下蛇框 vax_primary
enum 大驼峰式命名法 PixelFormat
枚举成员 上蛇壳 RGB_888

库名称是以英文句点分隔的标识符列表。库的部分内容 除最后一个名称之外的其他名称也称为命名空间。每个组件 该名称采用小写形式,并且必须与以下正则表达式匹配: [a-z][a-z0-9]*

我们之所以采用这些限制性规则,是因为不同的目标语言具有不同的 对命名空间、库或软件包的限定方式进行限制。我们有 选择保守型最小公分母,以确保 FIDL 有效 使用我们当前的目标语言和未来可能的目标语言 语言。

标识符名称:首选具有意义的功能角色

首选功能名称(例如,fuchsia.media) 而不是产品或代号 (例如,fuchsia.amberfuchsia.scenic)。产品名称是合适的 当产品在 Fuchsia 之外有一些外部存在,以及 协议。例如,fuchsia.cobalt 是 Cobalt 接口协议的名称要优于 fuchsia.metrics,因为 其他指标实现方式(例如Firebase)不太可能实现相同的 协议。

标识符名称应与参与者扮演的特定角色相关; 请避免将访问控制编码到名称中。基于角色的名称包括 描述性的名称不会像基于访问控制的名称那样快 规定一种由外部定义的关系,该关系会随着 平台不断发展演变。例如,对于涉及 FocusChain 对象的 API, 相应的名称应为 fuchsia.ui.focus,而不是 fuchsia.ui.privileged;如果我们决定扩大 FocusChain 对象的范围, 那么 fuchsia.ui.focus 不是一个有问题的名称。以下 应避免使用示例字词:

  • constrained
  • limited
  • oem
  • private
  • privileged
  • protected
  • special
  • vendor

标识符名称应具有实际含义;避免使用没有意义的名称。如果 fuchsia.foo.barfuchsia.foo.baz有一些共同的概念, 不妨考虑在单独库中定义这些概念 fuchsia.foo,而不是在 fuchsia.foo.common 中。以下示例字词 应避免:

  • common
  • service
  • util
  • base
  • f<letter>l
  • zx<word>

顶级

请避免重复库名称中的名称。例如,在 fuchsia.process 库中,用于启动进程的协议应命名为 Launcher,而不是 ProcessLauncher,因为名称 process 已 会显示在库名称中。对于所有目标语言,顶级名称都是 以某种方式指定库名称来限定作用域。

原初别名

基元别名不得重复封装库中的名称。全部 原语别名会替换为基础原语 因此不会导致名称冲突。

alias vaddr = uint64;

常量

常量名称不得重复封装库中的名称。在所有目标中 常量名称的范围由其所属的库限定。

描述上下限的常量应使用前缀 MIN_MAX_

const MAX_NAMES uint64 = 32;

协议

协议通过 protocol 关键字指定。

协议必须是名词短语。 通常,协议是使用表示操作的名词命名的。对于 例如,AudioRenderer 是一个名词,表示协议与 呈现音频的过程。同样,Launcher 是一个名词,表示 都与发布什么内容相关协议也可以是被动的 尤其是当它们与实现所持有的某个状态有关时。 例如,Directory 是一个名词,表示协议适用于 与实现包含的目录交互。

可以使用面向对象的设计模式命名协议。例如: fuchsia.fonts.Provider 使用 provider 后缀,这表示 协议提供字体(而不是表示字体本身)。同样, fuchsia.tracing.Controller 使用 controller 后缀,这表示 协议控制跟踪系统(而不是表示跟踪记录) 本身)。

名称 Manager 可作为协议 范围很广例如,fuchsia.power.Manager。但请注意 “经理”往往会吸引大量松散相关的 可以更好地纳入多个协议的功能。

协议不得包含名称 service.。所有协议都会定义服务。 这个词没有意义。例如,fuchsia.tts.TtsService 就违反了 评分准则。首先,Tts 前缀对于库是多余的 名称。其次,禁止使用 Service 后缀。

明确的“open/ajar/closed”修饰符

对于协议,应始终指定 openajarclosed 而不是依赖于默认值也就是说,始终优先选择 open protocol Foo { ...,而不是仅 protocol Foo { ...

方法

方法必须是动词短语。

例如,GetBatteryStatusCreateSession 是动词短语, 用于指明该方法要执行的操作。

在事件发生时调用的 listenerobserver 协议的方法 应带有 On 前缀,并描述在 。例如,ViewContainerListener 协议有一个 名为 OnChildAttached

事件

类似地,事件(即从服务器发送至客户端的未经请求的消息) 应带有 On 前缀,并描述过去发生的事件 状态。

例如,AudioCapturer 协议有一个名为 OnPacketCaptured

单一方法协议

单个方法协议的方法应该是 协议中定义了这些协议的名词短语,例如Loader.LoadGetter.GetUploader.Upload。对于限定名词短语,例如 JobCreatorProcessStopper,则应使用非限定动词短语,例如 JobCreator.CreateProcessStopper.Stop

属于单一方法但打算随着时间的推移发展为多方法的协议 并不一定需要遵循此命名惯例,例如,如果有 协议的已知扩展,建议的命名并非 那么最好尽早选择其他名称在 因此最好采纳默认建议。

因为替换协议比改进协议更难, 从未打算发展,但最终发现需要改用多种方法 改进现有协议,最好添加一个方法, 并可能重命名现有方法

露骨的“strict/flexible”修饰符

对于方法和事件,应始终指定 strictflexible 而不是依赖于默认值也就是说,始终优先使用 flexible Foo();, 只需要 Foo()

结构体、联合和表

结构体、联合和表必须是名词短语。 例如,Point 是一个结构体,用于定义空间中的位置和 KeyboardEvent 是一个定义键盘相关事件的结构体。

结构体、联合和表成员

在以下情况下,最好使用单个单词的结构体、联合体和表成员名称 切合实际(单字词名称在各种目标语言中的呈现方式更加一致)。 不过,如果一个字词可能不适合您, 含糊不清或令人困惑

成员名称不得重复所属类型(或影视库)中的名称,除非 如果没有属于封闭类型名称,成员名称不明确。对于 例如,包含事件发生时间的 KeyboardEvent 类型的成员 交付项应命名为 time,而不是 event_time,因为其名称 event 已出现在封闭类型的名称中。在所有目标中 成员名称的范围取决于所属类型。

然而,DeviceToRoom 类型会将智能设备与房间相关联 可能需要有device_idroom_name成员,因为 idname 不明确。这两个标记都可能表示 或者房间

枚举

枚举必须是名词短语。

例如,PixelFormat 是一个定义颜色编码方式的枚举 转换为位。

枚举成员

枚举成员名称不得重复所属类型(或库)中的名称。 例如,PixelFormat 枚举的成员应命名为 ARGB,而不是 PIXEL_FORMAT_ARGB,因为名称“PIXEL_FORMAT”已出现在名称中 所属类型在所有目标语言中,枚举成员名称的作用域限定为 所属的类型。

位字段

位字段必须是名词短语。

例如,InfoFeatures 是一个位字段,用于指明哪些特征 都位于以太网接口上

Bitfield 成员

位字段成员不得重复所属类型(或库)中的名称。 例如,InfoFeatures 位字段的成员应命名为 WLAN 而不是 INFO_FEATURES_WLAN,因为名称 INFO_FEATURES 已 。 在所有目标语言中,位字段成员名称都按其 封装类型。

类型

露骨的“strict/flexible”修饰符

对于接受 strict/flexible 修饰符的类型(bitsenumunion),则应始终指定此类修饰符,而不是依赖于 默认值。也就是说,始终优先选择 flexible bits ...,而不是仅 bits ...

组织机构

语法

  • 使用 4 个空格缩进。
  • 一律不使用标签页。
  • 避免尾随空格。
  • bitsenumprotocolstructtable、 以及包含不同声明的其他声明的 union 构造, 一个空白行(两个连续的换行符)。
  • 文件末尾只能包含一个换行符。

评论

注释使用 ///(三个正斜杠)。库中的评论还会 会显示在生成的代码中,以便在针对 库。将评论“流经”目标语言。

在所描述的内容上方添加注释。下列情况除外: 请使用正确的大小写和长度合理的句子, 。评论长度不得超过 80 个字符,但较长的评论除外 不可避免(例如,对于较长的网址)。

注释应使用 Markdown 编写。我们依靠 CommonMark 规范。部分 工具可能会使用其他 Markdown 标准渲染输出;如果您的工具 不使用 CommonMark,因此我们鼓励开发者编写 同时兼容 CommonMark 及其工具。对 FIDL 元素的引用 应始终采用代码字体。

记录的实体是指附加了注释的任何 FIDL 元素。第一个 注释中引用任何已记录的实体时,都应提供其完整 限定名称,格式为 [`<library>/<top level declaration>.<member>`] (例如,[`fuchsia.io/Node.clone`])。在以下情况下,此表单可能会生成超链接: 工具为其提供支持对记录实体的后续引用可以 请使用简写版本,前提是该简写版本清晰明确 (例如,clone)。不带方括号的表单不会生成超链接。

请求参数、响应参数和错误类型应记录为 以下形式的列表:

+ request `param1` <description>
+ request `param2` <description>
- response `param1` <description>
- response `param2` <description>
* error <description>

请求、响应和错误必须按该顺序显示。一组给定的 参数的声明顺序也必须遵循 参数列表。术语“请求”和“response”可能被省略 参数名称只能在请求或响应参数列表之一中找到。

描述变量、字段或类型的文档注释的第一部分应为 简要说明记录实体的预期用途的名词短语; 包含无法从名称和类型推断出来的信息。通过 说明应以句点结尾。广告内容描述不应 重申记录实体的名称或其特定类型的 FIDL 语言元素(例如,structprotocol)。

/// A representation of violins displayed on the screen.
type Widget = struct {
    /// A monotonically increasing id, uniquely identifying the widget.
    id uint64;
    /// Location of the top left corner of the widget.
    location Point;
};

下面列举了一些示例来说明不应该采取的措施:

/// BAD: Widget is a representation of violins displayed on the screen.
/// BAD: struct Widget is a representation of violins displayed on the screen.

协议方法所附文档注释的第一部分应为简短内容 该方法的行为的说明,以动词开头,包括 无法从名称和类型推断出的信息。动词应为 采用现在时时,同意第三人称单数代词;以及 使用陈述语气(这实际上就是假装 “it”并指出您是在陈述事实)。通过 短语应以句点结尾。

完整示例:

/// An abstract representation of a [`fuchsia.io/Node`] whose layout is flat.
protocol File {
    compose Node;

    /// Acquires a [`fuchsia.mem/Buffer`] representing this file, if
    /// there is one, with the requested access rights.
    ///
    /// ## Rights
    ///
    /// This method requires the following rights:
    ///
    /// * [`fuchsia.io/OPEN_RIGHT_WRITABLE`] if `flags` includes
    ///   [`fuchsia.io/VMO_FLAG_WRITE`].
    /// * [`fuchsia.io/OPEN_RIGHT_READABLE`] if `flags` includes
    ///   [`fuchsia.io/VMO_FLAG_READ`] or [`fuchsia.io/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 [`fuchsia.mem/Buffer`]
    /// [`fuchsia.mem/Buffer`]:
    ///    https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/fidl/fuchsia.io/
    GetBuffer(struct {
        flags uint32;
    }) -> (resource struct {
        buffer box<fuchsia.mem.Buffer>;
    }) error zx.Status;
};

应该对由某些外部可信来源定义的类型或值添加注释 并引用外部事物例如,引用 Wi-Fi 描述配置结构的规范同样,如果 结构必须与 C 头文件中定义的 ABI 匹配,请引用 C 头文件。

有关注释应包含的内容的详情,请参阅 API 文档评分准则

引用 FIDL 协议或协议方法

在注释中引用 FIDL 协议或其方法时应遵循 格式:

/// See fuchsia.library/ProtocolName.Method for more information.

当引用与注释位于同一库中的协议时,库 ProtocolName.Method

同样,在使用与注释相同的协议引用方法时, 库名称和协议名称可以省略:Method

库概览

您可以以文档注释的形式提供库概览, library 语句。“库”语句启动 FIDL 文件。例如:

/// Library containing example FIDL used throughout the Fuchsia documentation.
library fuchsia.examples.docs;

库概览应提供定义库的一般文档。 他们还可以详细说明各种讯息, 以及这些消息和协议如何协同使用。

虽然一个库可以细分为多个 FIDL 文件, 只能是单个库概览。建议你参考下面这些有关媒体库的建议 概览:

  • 如果概览很短,并且库由单个文件组成,您可以 将概览放在库文件顶部的 library 语句中。
  • 如果库包含多个文件,请创建一个独立的文件 overview.fidl,用于为库编写文档。“overview.fidl”文件不应 包含任何声明、类型别名或协议定义。

非完整评论

如果您的评论是面向图书馆作者的,请使用更简单的评论 // (两个正斜线),该符号不透过目标语言。

在决定常规 /// 注释和非 flow-through 注释时 请注意以下几点:

常规评论:

  • 形参、实参和函数的说明
  • 使用说明

非完整评论:

  • 内部“待办事项”评论
  • 版权通知
  • 实现细节

这两种评论样式都可以结合使用:

/// A widget displaying violins on the screen.
// TODO -- widgets should use UUIDs instead of sequential ids
type ViolinWidget = struct {
    /// A monotonically increasing id, uniquely identifying the widget.
    id uint64;
    /// Location of the top left corner of the widget.
    location Point;
};

文件

库由一个或多个文件组成。这些文件存储在 目录层次结构:

fidl/<library>/[<dir>/]*<file>.fidl

<library> 目录使用以英文句点分隔的 FIDL 名称进行命名, 库。<dir> 子目录是可选的,通常不用于 包含不到十几个文件的库。此目录结构与 FIDL 文件包含在 Fuchsia SDK 中。

将库拆分为文件不会对 库。声明(包括协议)可以相互引用, 而不管它们显示在什么文件中。 将库拆分为多个文件,以最大限度地提高可读性。

  • 对于库中的文件,首选 DAG 依赖关系图。
  • 更喜欢让相互引用的定义在文字上彼此靠近, 最好在同一个文件中
  • 对于复杂的库,最好在叶中定义纯数据类型或常量 文件,并定义在主干中引用这些类型的协议 文件。