关于 dart-static-analysis
面向 Dart 项目的静态分析配置与执行指南,涵盖严格检查、Lint 规则管理及类型提升失败的处理。
主要功能
- 01配置严格的分析选项
- 02采用推荐的 Lint 规则集
- 03使用 dart fix 自动修复
- 04处理类型提升失败
适用场景
- 01为 Dart 包配置静态分析
- 02检查代码错误与风格问题
- 03修复常见 Lint 违规
- 04解决可空类型提升错误
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dart-lang/ skills --skill dart-static-analysis安装后在 Claude Code 中输入/dart-static-analysis确认已加载。
详细介绍
分析和检查 Dart 代码
目录
配置分析选项
在包的根目录下放置 analysis_options.yaml 文件,以控制静态分析。
- 强制严格类型检查: 始终在
analyzer部分启用strict-casts、strict-inference和strict-raw-types,以便在编译时捕获隐式动态类型转换和未推断出的类型。 - 配置格式化: 在
formatter部分定义dart format规则(例如page_width和trailing_commas)。 - 排除生成的代码: 使用
exclude键忽略生成的文件(例如**/*.g.dart、**/*.freezed.dart),以避免误报。
管理 Linter 规则
使用社区标准的规则集,而不是自行维护一份规则列表。
- 使用标准包: 纯 Dart 项目包含
package:lints/recommended.yaml,Flutter 项目则包含package:flutter_lints/flutter.yaml。 - 避免手动忽略: 除非绝对必要,否则避免手动忽略 lint(例如
// ignore: ...)。优先修复 lint 的根本原因。 - 批量修复: 使用
dart fix --apply自动解决整个代码库中常见的 lint 违规和迁移问题。 - 自定义严重级别: 如果某条规则产生过多提示但仍有价值,可在
errors映射中更改其严重级别(例如todo: info),而不是完全禁用它。
解决类型提升失败问题
当流程分析确认某个可空变量不为 null 时,就会发生类型提升。如果编译器无法保证某个值在检查和使用之间保持稳定,类型提升就会失败。
类型提升失败的常见原因包括:
- 公共或非 final 字段: 外部库可能重写公共字段,而非 final 字段可能被修改。
- Getter: 编译器无法保证 getter 在后续调用时返回相同的值。
- 写入捕获: 在闭包或函数表达式中修改变量会使先前的检查失效。
解决方案: 通过在执行 null 或类型检查之前,将字段、getter 或被捕获的变量赋值给一个局部 final 变量,来解决“无法提升”的原因。局部变量可以保证保持稳定,因此编译器能够安全地提升类型。
工作流:设置和执行静态分析
使用此检查清单在 Dart 项目中初始化并强制执行静态分析。
- 任务进度:设置分析
- 运行
dart pub add --dev lints(或flutter_lints)。 - 在项目根目录下创建
analysis_options.yaml。 - 包含推荐规则集(
include: package:lints/recommended.yaml)。 - 启用严格语言模式(
strict-casts、strict-inference、strict-raw-types)。
- 运行
- 任务进度:执行和修复
- 运行
dart analyze,尽早发现潜在错误和样式违规。 - 运行
dart fix --apply,自动解决机械性的 lint 问题。 - 手动检查剩余错误。运行验证器 -> 检查错误 -> 修复根本原因,不使用
// ignore。
- 运行
工作流:修复类型提升问题
当 dart analyze 报告某个属性或字段无法提升时:
- 任务进度:修复提升问题
- 找出出现问题的变量(例如,公共字段、getter 或被写入捕获的变量)。
- 在条件检查之前立即声明一个局部
final变量。 - 将无法提升的字段/getter 赋给新的局部变量。
- 对局部变量执行
!= null或is Type检查。 - 将条件块内的所有引用更新为使用局部变量。
- 运行
dart analyze,验证提升问题已解决。
示例
高保真 analysis_options.yaml
include: package:lints/recommended.yaml
analyzer:
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
errors:
todo: info
invalid_assignment: error
formatter:
page_width: 80
trailing_commas: preserve
linter:
rules:
# Disable specific rules if they conflict with project architecture
avoid_classes_with_only_static_members: false
# Enable additional strict rules
always_declare_return_types: true
cancel_subscriptions: true
通过局部变量修复类型提升问题
反模式: 直接检查 getter 或公共字段。编译器会报错,因为 _value 是 getter,第二次调用时可能返回不同的结果。
abstract class Example {
int? get _value => Random().nextBool() ? 123 : null;
}
void printParity(Example x) {
if (x._value != null) {
// ERROR: '_value' refers to a getter so it couldn't be promoted.
print(x._value.isEven);
}
}
最佳实践: 赋值给局部 final 变量,以确保其稳定性。
abstract class Example {
int? get _value => Random().nextBool() ? 123 : null;
}
void printParity(Example x) {
final localValue = x._value; // 1. Assign to local final variable
if (localValue != null) { // 2. Check the local variable
print(localValue.isEven); // 3. Use the promoted local variable (OK)
}
}
相关技能:dart-effective-style、dart-api-design
评论
支持 Markdown