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
- 与特征和类一起使用以包含内容层次结构图,显示包含的类型。该图表内容可以使用从hideNodes
、hideOutgoingImplicits
、hideSubclasses
、hideEdges
、hideIncomingImplicits
、hideSuperclasses
和hideInheritedNode
中获取的其他说明符进行微调。如果默认情况下会创建图表,则可以提供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 注释中的歧义链接
当两个方法在词法上无法区分时,可能会导致 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 认为链接已结束并转到其描述。
- 必须完全限定正在使用的任何类型:假设你编写程序时没有使用任何导入语句!
然后,为消除对象和类型之间的歧义,追加 $
以指定术语名称,追加 !
以指定类型名称。术语名称包括不是类型的成员,例如 val
、def
和 object
定义。例如
[[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 样式指南。