Scaladoc

Scaladoc 库作者

语言

Scaladoc 是一个文档系统,存在于 Scala 源代码的注释中,并且与其中编写的代码结构相关。它基于其他基于注释的文档系统,如 Javadoc,但有一些扩展,例如

  • 可以在注释中使用标记。
  • 扩展的 @ 标记(例如 @tparam@see@note@example@usecase@since 等)
  • 宏定义(在 scaladoc 中替换的已定义值)。
  • 从超类/特质自动继承注释(可与宏定义有效结合使用)。

在何处放置 Scaladoc

Scaladoc 注释位于它们在特殊注释块中涉及的项目之前,该块以 /** 开始,以 */ 结束,如下所示

/** Start the comment here
  * and use the left star followed by a
  * white space on every line.
  *
  * Even on empty paragraph-break lines.
  *
  * Note that the * on each line is aligned
  * with the second * in /** so that the
  * left margin is on the same column on the
  * first line and on subsequent ones.
  *
  * The closing Scaladoc tag goes on its own,
  * separate line. E.g.
  *
  * Calculate the square of the given number
  *
  * @param d the Double to square
  * @return the result of squaring d
  */
 def square(d: Double): Double = d * d

在上面的示例中,此 Scaladoc 注释与方法 square 相关联,因为它在源代码中就在其前面。

Scaladoc 注释可以位于字段、方法、类、特质、对象甚至(尤其是)包对象之前。包对象的 Scaladoc 注释是放置特定包或 API 概述的好地方。

对于在 Scala 中与类本身的定义相一致的类主构造函数@constructor 标记用于将注释定位到主构造函数文档而不是类概述上。

标记

Scaladoc 使用 @ 标记在注释中提供特定详细信息字段。这些字段包括

类特定标记

  • @constructor 放置在类注释中,将描述主构造函数。

方法特定标记

  • @return 详细说明方法的返回值(每个方法一个)。

方法、构造函数和/或类标记

  • @throws 方法或构造函数可能抛出的异常(如果有)。
  • @param 详细说明方法或构造函数的值参数,为方法/构造函数的每个参数提供一个。
  • @tparam 详细说明方法、构造函数或类的类型参数。为每个类型参数提供一个。

用法标记

  • @see 引用其他信息来源,如外部文档链接或文档中的相关实体。
  • @note 为前置条件或后置条件添加注释,或任何其他值得注意的限制或预期。
  • @example 用于提供示例代码或相关的示例文档。
  • @usecase 当完整的方法定义过于复杂或混乱时,提供简化的方法定义。一个示例是(在集合 API 中),为省略隐式 canBuildFrom 的方法提供文档。

成员分组标记

这些标记非常适合具有许多成员的大型类型或包。它们允许你将 Scaladoc 页面组织成不同的部分,每个部分单独显示,按你选择的顺序显示。

默认情况下,这些标记不会启用!你必须将 -groups 标记传递给 Scaladoc 才能启用它们。通常,sbt 的情况类似于

scalacOptions in (Compile, doc) ++= Seq(
  "-groups"
)

每个部分都应该有一个单字标识符,用于所有这些标记中,如下所示 <group>。默认情况下,该标识符显示为该文档部分的标题,但你可以使用 @groupname 提供更长的标题。

通常,您应该将 @groupprio(以及可选的 @groupname@groupdesc)放在包/特征/类/对象的 Scaladoc 中,描述所有组及其顺序。然后在每个成员的 Scaladoc 中放置 @group,说明它属于哪个组。

没有 @group 标记的成员将在生成的文档中列为“未分组”。

  • @group <group> - 将实体标记为 <group> 组的成员。
  • @groupname <group> <name> - 为组提供一个可选名称。 <name> 在组描述前显示为组标题。
  • @groupdesc <group> <description> - 添加可选的描述性文本以在组名称下显示。支持多行格式化文本。
  • @groupprio <group> <priority> - 控制组在页面上的顺序。默认为 0。未分组元素的隐式优先级为 1000。使用 0 到 999 之间的值来设置相对于其他组的相对位置。较低的值将出现在较高值之前。

图表标记

  • @contentDiagram - 与特征和类一起使用以包含内容层次结构图,显示包含的类型。该图表内容可以使用从 hideNodeshideOutgoingImplicitshideSubclasseshideEdgeshideIncomingImplicitshideSuperclasseshideInheritedNode 中获取的其他说明符进行微调。如果默认情况下会创建图表,则可以提供 hideDiagram 来防止创建图表。包和对象默认具有内容图表。
  • @inheritanceDiagram - TODO

其他标记

  • @author 为以下实体提供作者信息
  • @version 实体所属的系统或 API 的版本。
  • @since@version 类似,但定义了此实体首次定义的系统或 API。
  • @todo 用于记录未实现的功能或实体的未实现方面。
  • @deprecated 将实体标记为已弃用,同时提供应使用的替换实现以及此实体被弃用的版本/日期。
  • @inheritdoc 如果本地未提供注释,则将超类的注释作为默认值。
  • @documentable 将类型别名和抽象类型展开为完整的模板页面。- TODO:测试“抽象类型”声明 - Scala 代码库中没有此类示例

  • @define <name> <definition> 允许在同一源文件中其他 Scaladoc 注释中使用 $name,该注释将展开为 <definition> 的内容。

2.12 标记 - TODO:将这些标记移到带有 2.12 注释的上述组中

  • @shortDescription ???
  • @hideImplicitConversion ???

注释继承

隐式

如果在当前继承级别未为实体提供注释,但在继承层次结构中较高级别的覆盖实体中提供了注释,则将使用超类的注释。

同样,如果省略了 @param@tparam@return 和其他实体标记,但可以从超类中获取,则将使用这些注释。

显式

对于显式注释继承,请使用 @inheritdoc 标记。

标记

仍然可以在 Scaladoc 中嵌入 HTML 标记(如 Javadoc),但大多数情况下没有必要,因为可以使用标记。

一些可用的标记类型

`monospace`
''italic text''
'''bold text'''
__underline__
^superscript^
,,subscript,,
[[entity link]], e.g. [[scala.collection.Seq]]
[[https://external.link External Link]],
  e.g. [[https://scala-lang.org.cn Scala Language Site]]

其他格式化注释

  • 段落以一个(或多个)空行开头。注释中边距的 * 有效(且应包含),但该行应为空白。
  • 代码块包含在 {{{ this }}} 中,并且可以是多行的。缩进相对于注释的起始 *
  • 标题用周围的 = 字符定义,更多的 = 表示子标题。例如 =Heading===Sub-Heading== 等。
  • 表格使用 | 定义,以分隔行中的元素,如 博客 中所述。
  • 列表块是具有相同样式和级别的列表项序列,不会被其他块样式中断。无序列表可以使用 - 进行项目符号标记;有序列表可以使用 1.i.I.a. 来表示不同的编号样式。在这两种情况下,前面都必须有额外的空格,更多的空格表示子级别。

列表块的标记如下所示

/** Here is an unordered list:
  *
  *   - First item
  *   - Second item
  *     - Sub-item to the second
  *     - Another sub-item
  *   - Third item
  *
  * Here is an ordered list:
  *
  *   1. First numbered item
  *   1. Second numbered item
  *     i. Sub-item to the second
  *     i. Another sub-item
  *   1. Third item
  */

编写 Scaladoc 注释的一般注意事项

  • 简洁明了!快速切入正题,人们在你的文档上花费的时间有限,明智地利用它。
  • 省略不必要的词语。优先使用 returns X 而不是 this method returns X,以及 does X,Y & Z 而不是 this method does X, Y and Z
  • DRY - 不要重复自己。避免在 @return 标记和其他形式的重复注释中重复方法描述。

当两个方法在词法上无法区分时,可能会导致 Scaladoc 报告存在歧义方法。例如

import scala.collection.mutable.ListBuffer
class bar {
    def foo(x: Int): Boolean = ???
    def foo(x: ListBuffer[Int], y: String): Int = ???
}

如果通过 [[foo]] 引用 foo,则 Scaladoc 将会抱怨并提供两个备选方案。解决此问题的方法是详细说明签名,使其明确无歧义。总体而言,需要注意以下几点

  • 不得在签名的描述中使用空格:这会导致 Scaladoc 认为链接已结束并转到其描述。
  • 必须完全限定正在使用的任何类型:假设你编写程序时没有使用任何导入语句!

然后,为消除对象和类型之间的歧义,追加 $ 以指定术语名称,追加 ! 以指定类型名称。术语名称包括不是类型的成员,例如 valdefobject 定义。例如

  • [[scala.collection.immutable.List!.apply class List's apply method]]
  • [[scala.collection.immutable.List$.apply object List's apply method]]

然而,在处理模棱两可的重载时,情况会变得更复杂

  • 您必须使用 * 完成签名(完整或其他方式),它用作通配符,使您可以在签名明确时将其截断。
  • 您必须指定参数的名称,并且它们必须完全与函数定义中所写的一致
    • [[bar.foo(Int)*]]非法的(没有名称)
    • [[bar.foo(y:Int)*]]非法的(名称错误)
    • [[bar.foo(x: Int)*]]非法的(空格!Scaladoc 将其视为 bar.foo(x:
    • [[bar.foo(x:Int):Boolean]]非法的(没有 *
    • [[bar.foo(x:Int)*]]合法的且明确的
    • [[bar.foo(x:Int*]]合法的Int 足以消除歧义,因此不需要闭合括号
  • 方法的封闭范围(包/类/对象等)必须使用 .,但在参数和返回类型中,必须使用 \. 来完全限定类型
    • [[bar.foo(x:ListBuffer[Int],y:String)*]]非法的ListBuffer 上没有限定)
    • [[bar.foo(x:scala.collection.mutable.ListBuffer[Int],y:String)*]]非法的(未转义点!)
    • [[bar\.foo(x:scala\.collection\.mutable\.ListBuffer[Int],y:String)*]]非法的(不能转义前缀中的点)
    • [[bar.foo(x:scala\.collection\.mutable\.ListBuffer[Int],y:String)*]]合法的
    • [[bar.foo(x:scala\.collection\.mutable\.ListBuffer[Int]*]]合法的,第一个参数足以消除歧义。
  • 涉及泛型时,可以使用额外的方括号来避免签名意外关闭链接。从本质上讲,前导左括号的数量决定了完成链接所需的右括号的数量
    • [[baz(x:List[List[A]])*]]非法的(它被读取为 baz(x:List[List[A)
    • [[[baz(x:List[List[A]])*]]]合法的]] 不再是终止符,]]] 是)

已知限制

  • # 语法似乎不支持参数和返回类型。
  • 空格不能用 \ 转义,因此 implicit 参数似乎也不受支持。

有关编写 Scaladoc 的更多详细信息

有关格式和样式建议的更多信息,请参阅 Scala-lang scaladoc 样式指南

此页面的贡献者