笨办法学 Dart: dartdoc.dart 源码分析
Flutter SDK 的 dartdoc.dart 脚本不仅可以演示了 dartdoc
各参数的用法,它也是学习 Dart 编程语言的绝好参考资料。
Dart SDK 中的 dartdoc
命令用于从 Dart 源码生成文档。使用过程中遇到问题,一番搜索后发现 Flutter SDK 的 dartdoc.dart
脚本是对该命令的封装。这个脚本用于生成 Flutter 文档。我发现从 dartdoc.dart
中不仅能学习到 dartdoc
各参数的用法,它还是学习 Dart 编程语言的绝好参考资料。学习并记录一下。(看似挺笨的学习方法,但感觉有效)
一方面是 Dart 语言相关的知识:
- 第三方简单用法
- argParser
- path
- process
- 文件操作
- 文件生成和读写
- 切换及遍历目录
- 进程操作
- Dart 语言特性
- Synchronous generator
- 扩展操作符
- 字符串操作
- 正则表达式
另一方面是 Dart dartdoc 的用法。
dartdoc.dart 脚本见 Github。另外注意区分 dartdoc.dart 和 Dart dartdoc
,前者是 Flutter SDK 中用于生成文档的脚本,是对后者的封装;后者则是 Dart SDK 的内置命令。
Dart 语言
dartdoc.dart
函数了以下内容。
args 库
首先要引入 args库,在 pubspec.yaml
中添加如下依赖:
1 | dependencies: |
arg 库的基本用法包括:
- 创建 ArgParser -
ArgParser()
- 添加 flag -
ArgParser.addFlag()
- 生成 ArgResults -
ArgParser.parse()
- 访问
ArgResults
- 显示当前程序的用法 -
ArgResults.usage
- 访问传给当前程序的参数 -
[]
- 显示当前程序的用法 -
示例代码如下:
1 | ArgParser _createArgsParser() { |
Flag 支持的选项包括:
negatable
- 是否可忽略abbr
- 缩写命令,比如--help
的短命令是-h
defaultsTo
- 缺省值
path 库
首先要引入 path库,在 pubspec.yaml
中添加如下依赖:
1 | dependencies: |
Dart 中使用 Directory
类可获取当前目录,通过 path 库可获取到目录名和文件名。示例代码如下:
1 | // 获取当前目录 |
process 库
dartdoc.dart
脚本中有这样一段代码:
1 | final ProcessResult flutter = Process.runSync('flutter', <String>[]); |
这段代码的功能包括:
- 使用
Process.runSync()
启动flutter
命令并检查是否运行成功 - 使用
File.existsSync()
检查<FLUTTER DIR>/version
文件是否存在
引入 path库,在 pubspec.yaml
中添加如下依赖:
1 | dependencies: |
process 库 的 ProcessWrapper
是对 Dart Process
的包装,以提供更方便的方法。其用法如下:
1 | // Run pub. |
文件操作
dartdoc.dart
脚本中用到几种基本的文件操作,
- 写文件
- 读文件
- 创建目录
- 遍历目录
File.writeAsStringSync(String)
方法用于将字符串写入文件。用法如下:
1 | // Create the pubspec.yaml file. |
Directory.createSync()
方法用于创建目录。用法如下:
1 | // Create the library file. |
dartdoc.dart
包含的一个功能是遍历 Flutter SDK packages
目录来找到所有的库路径:
1 | /// Returns import or on-disk paths for all libraries in the Flutter SDK. |
从这段代码可以学到两个知识点:
- 首先,注意
libraryRefs()
方法中用到的sync*
和yield
的用法。实际上这里返回的Iterable
是 synchronous generator - 其次,
Directory.listSync()
返回当前目录中的所有文件和目录。该方法的参数recursive
用于支持递归遍历
正则式
dartdoc.dart
中用到了正则式。限于篇幅,这里不展开。
1 | printStream(process.stdout, prefix: args['json'] ? '' : 'dartdoc:stdout: ', |
其他
这里来看一些小的语言特性。小则小,用起来确实方便。
一,可以将 if
表达式用于 List 字面量的创建。
1 | final List<String> dartdocBaseArgs = <String>[ |
二,Dart 提供 ...
扩展操作符。用法如下:
1 | final List<String> dartdocBaseArgs = <String>[ |
Dart dartdoc 命令
Use dartdoc to generate HTML documentaton for your Dart package.
Dart dartdoc 是 Dart SDK 中用于为 Dart package 生成 HTML 文档的命令行工具。
要正确使用这个工具,建议先简单了解以下内容:
最简单的 Dart package 目录结构如下:
- pubspec file
- lib directory
- lib 目录下可以创建任意目录结构
- lib/src 目录下的代码是私有的,通常是具体实现
- lib 目录下的代码是公开的
- 可以通过 lib 目录下的文件导出 lib/src 为公开代码
更完整的代码结构可以参考 shelf。
使用
Dart SDK 自带 dartdoc,不用另外安装。
- 生成文档 - 在根目录下运行
dartdoc
- 查看文档
dhttpd --path doc/api
启动服务http://localhost:8080
查看
参数
Dart dartdoc 命令支持相当多的参数。以 Flutter 为例,生成文档时的参数如下:
1 | dartdoc |
实际使用时可以参考 dart-lang/dartdoc: API documentation tool for Dart.。
dartdoc_options.yaml
可以通过在根目录下创建 dartdoc_options.yaml
来控制调整生成的文档。
1 | dartdoc: |
详细参数见 Github
简单例子
这里用一个简单的例子演示 dartdoc 的用法。代码结构和 dartdoc_options.yaml
分别如下:
我们在 exclude
中排除了 hello.dart
和 bar.dart
两个文件,而 lib/src
下的代码为私有的,所以最终仅为 hello2.dart
生成了文档。
浏览器中看到了文档是这样的: