mcpField
D
dart-fix-runtime-errors

dart-fix-runtime-errors

github.com/dhruvanbhalara开发3052 次安装9 周前更新
代码仓库

关于 dart-fix-runtime-errors

面向 Dart 开发者的排错技能,帮助定位静态分析问题和运行时故障。内容涵盖类型安全、空安全、异常处理及验证修复的工作流。

主要功能

  1. 01检查类型与泛型安全
  2. 02处理空安全和变量初始化
  3. 03区分异常与程序错误
  4. 04运行静态分析与自动修复
  5. 05通过测试验证修复

适用场景

  1. 01排查 Dart 类型错误
  2. 02修复空值与延迟初始化故障
  3. 03改进异常捕获和重抛逻辑
  4. 04验证静态分析告警修复

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dhruvanbhalara/skills --skill dart-fix-runtime-errors

安装后在 Claude Code 中输入/dart-fix-runtime-errors确认已加载。

详细介绍

目录

类型系统与健全性

Dart 强制执行健全的类型系统,确保变量在运行时符合其编译时类型。为防止运行时类型错误:

  • 方法重写:确保子类重写时保持协变返回类型和逆变参数类型。除非明确使用 covariant 关键字来覆盖安全检查,否则切勿在子类中收窄参数类型。
  • 泛型与集合类型:避免将未指定类型的集合(如 List<dynamic>)直接赋给强类型目标。初始化列表或映射时,始终提供明确的泛型参数(例如 List<String>)。
  • 显式向下转型:避免对 dynamic 值进行隐式向下转型。只有在确保底层结构匹配时,才使用显式类型转换(例如 as List<Map<String, dynamic>>)。
  • 严格配置:在项目的 analysis_options.yaml 中启用严格的转换配置,以强制进行显式转换,并在代码分析期间发现动态类型错误:
    analyzer:
      language:
        strict-casts: true
    

空安全与变量初始化

妥善管理变量状态,以避免编译时分析器错误和运行时空指针异常:

  • 可空标记:对允许持有空值的类型添加 ?。仅当断定值绝不为空时才使用 !。
  • 延迟初始化:仅当能保证变量在首次访问前完成初始化时,才使用 late 关键字。如果在初始化前访问延迟变量,运行时会抛出 LateInitializationError。
  • 通配符变量:使用单个下划线 _(现代 Dart 版本支持)声明有意不读取的局部参数或变量,以满足未使用变量的 lint 规则。

错误与异常处理

区分可恢复的应用故障(异常)和不可恢复的错误(错误):

  • 捕获异常:实现 try-catch 块,以捕获并处理 Exception 的子类(例如 FormatException、SocketException)。这些表示应用应妥善处理的预期运行时故障。
  • 避免捕获错误:不要捕获 Error 或其子类(例如 TypeError、RangeError)。错误代表必须在开发期间修正的编码缺陷,不应在运行时将其抑制。
  • 重新抛出:捕获异常以进行日志记录或清理时,始终使用 rethrow 关键字,而不要再次抛出捕获到的异常。rethrow 会保留原始堆栈跟踪。

工作流:解决静态分析与运行时故障

按照此检查清单识别、修正并验证静态和运行时错误:

  • 运行静态分析器:在项目根目录执行 dart analyze . --fatal-infos。
  • 应用自动修复:预览并应用机械性调整:
    dart fix --dry-run
    dart fix --apply
    
  • 识别手动修复项:处理复杂警告:
    • 如果报告了空值冲突:评估业务逻辑,使用合并运算符 ?? 指定默认值,或使用空安全链 ?.。
    • 如果报告了协变不匹配:调整子类参数或应用 covariant 修饰符。
  • 测试执行:运行 dart test 或 flutter test,确保运行时健全性。
  • 验证 late 状态变更:如果运行时出现 TypeError 或 LateInitializationError,检查堆栈跟踪并修正初始化流程。

示例

修正动态列表赋值
// Fails Static Analysis due to List<dynamic> assignment:
void printScores(List<int> scores) => print(scores);

void badMain() {
  final scores = []; // Inferred as List<dynamic>
  scores.add(90);
  printScores(scores); // Error: List<dynamic> cannot be assigned to List<int>
}

// Corrected Implementation:
void goodMain() {
  final scores = <int>[]; // Explicitly typed
  scores.add(90);
  printScores(scores); // Compiles and runs safely
}
方法重写与协变
class Worker {
  void performTask(Task t) {}
}

// Fails Static Analysis: Tightening parameter type from Task to CodingTask
class SoftwareEngineer extends Worker {
  @override
  void performTask(CodingTask t) {} 
}

// Corrected Implementation using the covariant keyword:
class LeadSoftwareEngineer extends Worker {
  @override
  void performTask(covariant CodingTask t) {} 
}
安全管理延迟初始化
class DatabaseClient {
  // Late keyword defers null safety checks to runtime
  late final String connectionString;

  void initialize(String url) {
    connectionString = url;
  }

  void connect() {
    // If connect() is called before initialize(), this throws a LateInitializationError
    print('Connecting to $connectionString');
  }
}

评论

支持 Markdown