SKILL.md
只读
名称
dart-fix-runtime-errors
描述
利用 get_runtime_errors 与 lsp 获取实时堆栈信息,定位出错代码行并完成修复,最后通过 hot_reload 验证修复结果。
解决 Dart 静态分析错误
Contents
核心概念与规范
类型系统与健全性
贯彻 Dart 的健全类型系统(Sound Type System),防止在运行时出现非法状态。
- 方法重写(Method Overrides): 保持健全的返回值类型(协变)和参数类型(逆变)。切勿在子类中直接收紧参数类型,除非显式使用
covariant关键字标记。 - 泛型与集合(Generics & Collections): 为泛型类显式添加类型注解(例如
List<T>、Map<K, V>)。绝不能把List<dynamic>直接赋值给带具体类型的列表(例如List<Cat>)。 - 向下转型(Downcasting): 避免对
dynamic进行隐式向下转型。必要时使用显式类型转换(例如as List<Cat>),但须确保底层运行时类型匹配,以免触发TypeError异常。 - 严格类型转换(Strict Casts): 在
analysis_options.yaml的analyzer: language:下配置strict-casts: true,强制要求显式类型转换,从而在编译期捕获隐式向下转型的错误。
空安全
通过正确管理变量初始化与可空性,彻底消除空安全相关的静态分析错误。
- 修饰符: 可空类型使用
?,非空断言使用!,不可为空的命名参数使用required。 - 延迟初始化(Late Initialization): 对能确保在使用前初始化的非空变量使用
late关键字。在 Dart 控制流分析无法确切证明初始化的顶级变量或实例变量中,要重点应用此特性。 - 通配符: 使用
_通配符变量(Dart 3.7+)来表示无需绑定的局部变量或参数,避免产生未使用的变量警告。
错误处理
区分可恢复的异常(Exception)与不可恢复的错误(Error)。
- 捕获(Catching): 仅针对可恢复的故障捕获
Exception的子类。 - 错误(Errors): 切勿显式捕获
Error及其子类(例如TypeError、ArgumentError)。Error代表必须修复的代码 Bug,而不是用来捕获的。建议开启avoid_catching_errorslint 规则来强制执行此约束。 - 重新抛出(Rethrowing): 在
catch块内部使用rethrow重新抛出异常,以完整保留其原始堆栈信息。
工作流
工作流:静态分析错误修复
按照以下顺序工作流排查、修复并验证 Dart 项目中的静态分析错误。可以复制清单来记录你的排查进度。
任务进度:
- [ ] 1. 运行静态分析工具
- [ ] 2. 应用自动修复
- [ ] 3. 手动解决剩余错误
- [ ] 4. 验证修复结果(反馈循环)
1. 运行静态分析工具
运行 Dart analyzer 检查目标目录或文件中的所有静态分析错误。
dart analyze . --fatal-infos
2. 应用自动修复
使用 dart fix 工具自动修复常见的 linting 和静态分析问题。
# 预览改动
dart fix --dry-run
# 应用改动
dart fix --apply
3. 手动解决剩余错误
检查分析器输出的剩余错误,并根据错误类型采取相应措施:
- 如果错误是空安全问题(如 "Property cannot be accessed on a nullable receiver"):
- 核实该变量在逻辑上是否可能为 null。
- 如果可能,使用可选链(
?.)或提供默认回退值(??)。 - 如果不可能且能在其它地方确保初始化,请将变量声明标记为
late。
- 如果错误是类型不匹配(如 "The argument type 'List<dynamic>' can't be assigned..."):
- 追踪该变量的初始化位置。
- 在实例化时显式添加泛型类型注解(例如使用
<int>[]代替[])。
- 如果错误是无效的方法重写(如 "The parameter type doesn't match the overridden method"):
- 扩大参数类型以与父类保持一致;或者
- 如果业务逻辑确实需要收紧参数类型,请为该参数显式加上
covariant关键字。
4. 验证修复结果(反馈循环)
运行验证命令。检查错误并继续修复。
dart analyze .
dart test
- 若
dart analyze依然报错: 返回步骤 3 继续处理。 - 若
dart test因TypeError失败: 说明引入了无效的显式类型转换(as T)或访问了未初始化的late变量。定位运行时报错位置,修正类型层级或初始化顺序。
示例
示例:修复动态列表赋值问题
输入(静态分析未通过):
void printInts(List<int> a) => print(a);
void main() {
final list = []; // 被推导为 List<dynamic>
list.add(1);
list.add(2);
printInts(list); // 报错:List<dynamic> 无法赋值给 List<int>
}
输出(静态分析通过):
void printInts(List<int> a) => print(a);
void main() {
final list = <int>[]; // 显式指定类型
list.add(1);
list.add(2);
printInts(list);
}
示例:修复方法重写参数类型问题(逆变)
输入(静态分析未通过):
class Animal {
void chase(Animal a) {}
}
class Cat extends Animal {
@override
void chase(Mouse a) {} // 报错:收紧了参数类型
}
输出(静态分析通过):
class Animal {
void chase(Animal a) {}
}
class Cat extends Animal {
@override
void chase(covariant Mouse a) {} // 显式标记为 covariant
}
示例:使用 late 修复空安全错误
输入(静态分析未通过):
class Thermometer {
String temperature; // 报错:不可空实例字段必须初始化
void read() {
temperature = '20C';
}
}
输出(静态分析通过):
class Thermometer {
late String temperature; // 将初始化检查延迟至运行时
void read() {
temperature = '20C';
}
}






