dart-fix-runtime-errors

dart-fix-runtime-errors

热门

利用 get_runtime_errors 与 lsp 获取实时堆栈信息,定位出错代码行并完成修复,最后通过 hot_reload 验证修复结果。

2792Star
164Fork
更新于 2026/8/5
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.yamlanalyzer: language: 下配置 strict-casts: true,强制要求显式类型转换,从而在编译期捕获隐式向下转型的错误。

空安全

通过正确管理变量初始化与可空性,彻底消除空安全相关的静态分析错误。

  • 修饰符: 可空类型使用 ?,非空断言使用 !,不可为空的命名参数使用 required
  • 延迟初始化(Late Initialization): 对能确保在使用前初始化的非空变量使用 late 关键字。在 Dart 控制流分析无法确切证明初始化的顶级变量或实例变量中,要重点应用此特性。
  • 通配符: 使用 _ 通配符变量(Dart 3.7+)来表示无需绑定的局部变量或参数,避免产生未使用的变量警告。

错误处理

区分可恢复的异常(Exception)与不可恢复的错误(Error)。

  • 捕获(Catching): 仅针对可恢复的故障捕获 Exception 的子类。
  • 错误(Errors): 切勿显式捕获 Error 及其子类(例如 TypeErrorArgumentError)。Error 代表必须修复的代码 Bug,而不是用来捕获的。建议开启 avoid_catching_errors lint 规则来强制执行此约束。
  • 重新抛出(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 testTypeError 失败: 说明引入了无效的显式类型转换(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';
  }
}