dart-fix-runtime-errors

dart-fix-runtime-errors

热门

使用 get_runtime_errors 和 lsp 获取活动堆栈跟踪,定位失败行,应用修复,并通过 hot_reload 验证解决。

392Star
25Fork
更新于 2026/7/10
SKILL.md
只读
名称
dart-fix-runtime-errors
描述

使用 get_runtime_errors 和 lsp 获取活动堆栈跟踪,定位失败行,应用修复,并通过 hot_reload 验证解决。

解决 Dart 静态分析错误

目录

核心概念与指南

类型系统与健全性

强制使用 Dart 健全的类型系统,以防止运行时无效状态。

  • 方法重写: 保持返回类型(协变)和参数类型(逆变)的健全性。除非显式使用 covariant 关键字,否则切勿在子类中收紧参数类型。
  • 泛型与集合: 为泛型类(例如 List<T>Map<K, V>)添加显式类型注解。切勿将 List<dynamic> 赋值给类型化列表(例如 List<Cat>)。
  • 向下转型: 避免从 dynamic 进行隐式向下转型。必要时使用显式转型(例如 as List<Cat>),但确保底层运行时类型匹配,以防止 TypeError 异常。
  • 严格转型:analysis_options.yamlanalyzer: language: 下启用 strict-casts: true,以强制显式转型并在编译时捕获隐式向下转型错误。

空安全

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

  • 修饰符: 对可空类型使用 ?,对空断言使用 !,对不能为空的命名参数使用 required
  • 延迟初始化: 对保证在使用前初始化的非空变量使用 late 关键字。特别适用于顶级或实例变量,当 Dart 的控制流分析无法明确证明初始化时。
  • 通配符: 对非绑定局部变量或参数使用 _ 通配符变量(Dart 3.7+),以避免未使用变量警告。

错误处理

区分可恢复的异常和不可恢复的错误。

  • 捕获: 捕获 Exception 子类型以处理可恢复的失败。
  • 错误: 切勿显式捕获 Error 或其子类型(例如 TypeErrorArgumentError)。错误表示编程错误,必须修复,而非捕获。通过启用 avoid_catching_errors lint 规则来强制执行。
  • 重新抛出:catch 块中使用 rethrow 传播异常,同时保留其原始堆栈跟踪。

工作流程

工作流程:静态分析解决

使用此顺序工作流程来识别、修复和验证 Dart 项目中的静态分析错误。复制清单以跟踪进度。

任务进度:

  • [ ] 1. 运行静态分析器。
  • [ ] 2. 应用自动修复。
  • [ ] 3. 手动解决剩余错误。
  • [ ] 4. 验证修复(反馈循环)。

1. 运行静态分析器
执行 Dart 分析器以识别目标目录或文件中的所有静态错误。

dart analyze . --fatal-infos

2. 应用自动修复
使用 dart fix 工具自动解决标准 lint 和分析问题。

# 预览更改
dart fix --dry-run
# 应用更改
dart fix --apply

3. 手动解决剩余错误
审查剩余的分析器输出,并根据错误类型应用条件逻辑:

  • 如果错误是空安全问题(例如,“无法在可空接收器上访问属性”):
    • 验证变量在逻辑上是否可以为空。
    • 如果是,使用可选链式调用(?.)或提供回退值(??)。
    • 如果否,且初始化在其他地方得到保证,则在声明上标记 late
  • 如果错误是类型不匹配(例如,“参数类型 'List<dynamic>' 无法赋值...”):
    • 追踪变量的初始化。
    • 在实例化中添加显式泛型类型注解(例如 <int>[] 而不是 [])。
  • 如果错误是无效重写(例如,“参数类型与重写的方法不匹配”):
    • 放宽参数类型以匹配超类,或者
    • 如果根据领域逻辑有意收紧类型,则在参数上添加 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) {} // 显式标记为协变
}

示例:使用 late 修复空安全

输入(静态分析失败):

class Thermometer {
  String temperature; // 错误:非空实例字段必须初始化

  void read() {
    temperature = '20C';
  }
}

输出(静态分析通过):

class Thermometer {
  late String temperature; // 将初始化检查推迟到运行时

  void read() {
    temperature = '20C';
  }
}