Flutter静态代码检查

avatar
@智云健康

作者:Elemen Zhang,未经授权禁止转载。

相关源码

Flutter工程沿用Dart的静态代码检查器dartanalyzer, 并使用内置在Flutter Tools内的终端工具进行代码扫描和分析, 相关代码位于:

flutter/packages/flutter_tools/lib/src/commands/

flutter/packages/flutter_tools/lib/src/dart

基本使用

一般情况下, 在工程文件下配有分析脚本的情况下, 可以直接使用flutter analyze命令进行静态检查, 这和开发工具Android Studio自带的检查插件的效果是一样的, 最终结果会显示在AS下方的Dart Analysis Tab下.

如果工程项目内不包含分析脚本, 检查器会使用Flutter SDK路径下的默认分析脚本进行扫描.
可以使用参数 --watch 来保持持续检查, 或者--write来把检查结果写入文件. 值得注意的是, Flutter官方在Wiki中推荐使用命令: flutter analyze --flutter-repo 来分析代码, 但是这个命令会检查Flutter环境下所有的pub库, 非常耗时.

定制分析脚本

The analysis options file

检查器会根据项目根目录下的分析脚本执行检查, 该文件通常会与pubspec文件处于同一层级.

老版本的分析脚本命名为.analysis_options, 没有yaml后缀, 新版本统一命名为:analysis_options.yaml

检查器会使用#1检查other package和other other package, 使用#2检查my package.

Linter for Dart

Dart的检查器也包括对lint的支持, 具体的支持细节和Lint规则编写见Linter for Dart, 结合需要添加.

Dart文档中提到的lint规则 - close_sinks很有用, 它可以提示你没有正确释放的StreamController, 以免内存泄露.

严格类型检查

静态检查文件中, 开头会配售检查器的模式:

analyzer:
  strong-mode:
    implicit-casts: false
    implicit-dynamic: false

我们知道dart使用语法糖实现了伪动态类型 - dynamic, 可以在编译器不确定类型时, 使用dynamic代替, implicit-dynamic可以阻止这种操作. implicit-casts表示禁止Object类型隐式转换为其他类型.

lint_script

如果嫌一条条配置lint规则麻烦, 可以直接集成Google的开源项目pedantic或者effective dart(二选一).

include: package:pedantic/analysis_options.yaml
or
include: package:effective_dart/analysis_options.yaml

pedantic: GitHub - google/pedantic: How to get the most value from Dart static analysis effective dart: effective_dart | Dart Package

如果使用了pedantic, 需要在pub里添加依赖:

dev_dependencies:
  pedantic: ^1.0.0

如果使用了effect dart, 需要在pub里添加依赖:

dev_dependencies:
  effective_dart: ^1.0.0

可以选择指定版本的pedantic来依赖:

include: 
    package:effective_dart/analysis_options.1.3.0.yaml  

允许/禁止lint规则有两种格式可以选择:

linter:
  rules:
    - annotate_overrides
    - await_only_futures
or
linter:
  rules:
    avoid_shadowing_type_parameters: false
    await_only_futures: true

这两种形式不能混用, 如果必须想要混用, 可以通过include关键字把另一种形式的分析文件导入.

Exclude关键字用来排除不需要扫描的文件.

想要忽略某行代码或者某个文件不需要被检查, 可以使用 //ignore 关键字.

另外可以自定义某条lint规则的严重级别, dart支持3种自定义级别:

  1. info: 只提示.
  2. warning: 警告级别.
  3. error: 错误, 分析不通过.

只有error级别会导致analyze任务失败, 如果你项目中使用了CI, 注意只有此时会阻止任务继续执行.
这里放上Flutter官方在1.22版本默认使用的分析脚本, 可以参考:analysis_options_user.yml

其他

Dart的analyzer十分强大, 用来做静态代码扫描只是其中很小的一个功能, 我们知道dart的语言动态能力支持很弱, flutter直接禁止了所有反射, 但是dart提供了编译期十分强大的AST分析能力, 可以方便的把dart源码翻译成AST, 并提供丰富的接口来对AST操作, 这给在编译期对程序进行干预提供了十分有用的手段, 比如可以动态分析AST文件再生成自定义的DSL文件来实现Flutter的动态化等等.

结尾

感谢你的阅读,日前智云健康大前端正在参加掘金人气团队评选活动。如果你觉得不错的话,那就来 给我们投一票 吧!你的支持是是我们最大的动力。