目录

自定义静态分析

静态分析允许您在执行任何代码之前发现问题。它是一个强大的工具,用于防止错误并确保代码符合样式指南。

借助分析器,您可以找到简单的拼写错误。例如,一个意外的分号可能出现在 if 语句中:

dart
void increment() {
  if (count < 10) ;
  count++;
}

如果配置正确,分析器会指向分号并产生以下警告:

info - example.dart:9:19 - Unnecessary empty statement. Try removing the empty statement or restructuring the code. - empty_statements

分析器还可以帮助您找到更细微的问题。例如,您可能忘记关闭 sink 方法:

dart
var controller = StreamController<String>();
info - Unclosed instance of 'Sink'. Try invoking 'close' in the function in which the 'Sink' was created. - close_sinks

在 Dart 生态系统中,Dart 分析服务器和其他工具使用 analyzer 包 执行静态分析。

您可以自定义静态分析以查找各种潜在问题,包括 Dart 语言规范 中指定的错误和警告。您还可以配置 linter 规则,以确保您的代码符合 Dart 样式指南 以及 Effective Dart 中的其他建议指南。诸如 dart analyzeflutter analyzeIDE 和编辑器 之类的工具使用 analyzer 包来评估您的代码。

本文档说明如何使用分析选项文件或 Dart 源代码中的注释来自定义分析器的行为。如果您想将静态分析添加到您的工具中,请参阅 analyzer 包 文档和 分析服务器 API 规范

分析选项文件

#

将分析选项文件 analysis_options.yaml 放在包的根目录下,与 pubspec 文件位于同一目录中。

这是一个示例分析选项文件:

analysis_options.yaml
yaml
include: package:lints/recommended.yaml

analyzer:
  exclude: [build/**]
  language:
    strict-casts: true
    strict-raw-types: true

linter:
  rules:
    - cancel_subscriptions

该示例说明了最常见的顶级条目:

如果分析器找不到包根目录下的分析选项文件,它会向上遍历目录树,查找该文件。如果没有可用文件,分析器将默认为标准检查。

考虑大型项目的以下目录结构:

项目根目录包含 analysis_options.yaml (#1) 和 3 个包,其中一个 (my_package) 包含一个 analysis_options.yaml 文件 (#2)。

分析器使用文件 #1 来分析 my_other_packagemy_other_other_package 中的代码,并使用文件 #2 来分析 my_package 中的代码。

启用更严格的类型检查

#

如果您想要比 Dart 类型系统 所要求的更严格的静态检查, 请考虑启用 strict-castsstrict-inferencestrict-raw-types 语言模式:

analysis_options.yaml
yaml
analyzer:
  language:
    strict-casts: true
    strict-inference: true
    strict-raw-types: true

您可以一起或单独使用这些模式;所有模式都默认为 false

strict-casts: <bool>
true 值确保类型推断引擎绝不会隐式地从 dynamic 类型转换为更具体的类型。以下有效的 Dart 代码包含从 jsonDecode 返回的 dynamic 值到 List<String> 的隐式向下转换,这在运行时可能会失败。此模式会报告潜在的错误,要求您添加显式转换或以其他方式调整代码。
✗ static analysis: failuredart
void foo(List<String> lines) {
  ...
}

void bar(String jsonText) {
  foo(jsonDecode(jsonText)); // 隐式转换
}
error - The argument type 'dynamic' can't be assigned to the parameter type 'List<String>'. - argument_type_not_assignable
strict-inference: <bool>
true 值确保类型推断引擎绝不会在无法确定静态类型时选择 dynamic 类型。以下有效的 Dart 代码创建一个其类型参数无法推断的 Map ,此模式会提示推断失败:
✗ static analysis: failuredart
final lines = {}; // 推断失败
lines['Dart'] = 10000;
lines['C++'] = 'one thousand';
lines['Go'] = 2000;
print('Lines: ${lines.values.reduce((a, b) => a + b)}'); // 运行时错误

warning - The type argument(s) of 'Map' can't be inferred - inference_failure_on_collection_literal
strict-raw-types: <bool>
true 值确保类型推断引擎绝不会在由于省略类型参数而无法确定静态类型时选择 dynamic 类型。以下有效的 Dart 代码具有一个原始类型的 List 变量,此模式会提示原始类型:
✗ static analysis: failuredart
List numbers = [1, 2, 3]; // 原始类型的 List
for (final n in numbers) {
  print(n.length); // 运行时错误
}
warning - The generic type 'List<dynamic>' should have explicit type arguments but doesn't - strict_raw_type

启用和禁用 linter 规则

#

analyzer 包还提供了一个代码 linter。有各种各样的 linter 规则 可用。Linter 往往是非教派的——规则不必相互一致。例如,某些规则更适合常规 Dart 包,而其他规则则专为 Flutter 应用而设计。请注意,与静态分析不同,linter 规则可能会出现误报。

启用 Dart 团队推荐的 linter 规则

#

Dart 团队在 lints 包 中提供了两套推荐的 linter 规则:

核心规则
帮助识别可能在运行或使用 Dart 代码时导致问题的关键问题。所有代码都应该通过这些 linter 规则。上传到 pub.dev 的包具有一个 包评分 ,该评分部分基于通过这些规则。
推荐规则
帮助识别可能在运行或使用 Dart 代码时导致问题的其他问题,并强制执行单一、惯用的样式和格式。我们建议所有 Dart 代码都使用这些规则,这些规则是核心规则的超集。

要启用任一套 lint,请将 lints 包 添加为开发依赖项:

$ dart pub add --dev lints

然后编辑您的 analysis_options.yaml 文件以包含您首选的规则集:

yaml
include: package:lints/<RULE_SET>.yaml

例如,您可以这样包含推荐的规则集:

yaml
include: package:lints/recommended.yaml

启用单个规则

#

要启用单个 linter 规则,请将 linter: 添加到分析选项文件作为顶级键,然后将 rules: 添加为二级键。在后续行中,指定要应用的规则,前面加上短划线(YAML 列表的语法)。例如:

yaml
linter:
  rules:
    - always_declare_return_types
    - cancel_subscriptions
    - close_sinks
    - combinators_ordering
    - comment_references
    - invalid_case_patterns
    - one_member_abstracts
    - only_throw_errors
    - prefer_single_quotes

禁用单个规则

#

如果您包含像 lints 中的那个分析选项文件,

您可能希望禁用某些包含的规则。禁用单个规则类似于启用它们,但是需要使用映射而不是列表作为 rules: 条目的值,因此每一行都应该包含规则名称后跟 : false: true

这是一个分析选项文件的示例,它使用 lints 中的所有推荐规则,除了 avoid_shadowing_type_parameters 。它还启用了 lint await_only_futures

analysis_options.yaml
yaml
include: package:lints/recommended.yaml

linter:
  rules:
    avoid_shadowing_type_parameters: false
    await_only_futures: true

启用分析器插件(实验性)

#

分析器对插件具有实验性支持。这些插件与分析器集成,以添加功能,例如新的诊断信息、快速修复和自定义代码补全。您每个 analysis_options.yaml 文件只能启用一个插件。启用分析器插件会增加分析器使用的内存量。

如果您的情况符合以下任一条件,请不要使用分析器插件:

  • 您使用的开发机器内存少于 16 GB。
  • 您使用的是包含 10 个以上 pubspec.yamlanalysis_options.yaml 文件的单体仓库。

您可以在 pub.dev 上找到一些分析器插件。

要启用插件:

  1. 将包含插件的包添加为开发依赖项。

    $ dart pub add --dev <your_favorite_analyzer_plugin_package>
  2. 编辑您的 analysis_options.yaml 文件以启用插件。

    yaml
    analyzer:
      plugins:
        - your_favorite_analyzer_plugin_package

    要指示要启用的特定插件功能,例如新的诊断信息,可能需要额外的设置。

从分析中排除代码

#

有时,某些代码无法通过分析是可以的。例如,您可能依赖于您不拥有的包生成的代码——生成的代码有效,但在静态分析期间会产生警告。或者 linter 规则可能会导致您想要抑制的误报。

您可以通过几种方法从分析中排除代码:

  • 从分析中排除整个文件。
  • 阻止将特定非错误规则应用于单个文件。
  • 阻止将特定非错误规则应用于代码的单个行。

您还可以 禁用特定规则 用于所有文件或 更改规则的严重性

排除文件

#

要从静态分析中排除文件,请使用 exclude: 分析器选项。您可以列出单个文件,或使用 glob 模式语法。所有 glob 模式的用法都应相对于包含 analysis_options.yaml 文件的目录。

yaml
analyzer:
  exclude:
    - lib/client.dart
    - lib/server/*.g.dart
    - test/_data/**

抑制文件的诊断信息

#

要忽略特定文件的特定非错误诊断信息,请向该文件添加 ignore_for_file 注释:

dart
// ignore_for_file: unused_local_variable

这会作用于整个文件,在注释之前或之后,对于生成的代码特别有用。

要抑制多个诊断信息,请使用逗号分隔的列表:

dart
// ignore_for_file: unused_local_variable, duplicate_ignore, dead_code

要抑制所有 linter 规则,请添加 type=lint 说明符:

dart
// ignore_for_file: type=lint

抑制代码行的诊断信息

#

要抑制 Dart 代码特定行上的特定非错误诊断信息,请在代码行上方放置 ignore 注释。这是一个忽略导致运行时错误的代码的示例,就像您在语言测试中可能做的那样:

dart
// ignore: invalid_assignment
int x = '';

要抑制多个诊断信息,请提供逗号分隔的列表:

dart
// ignore: invalid_assignment, const_initialized_with_non_constant_value
const x = y;

或者,将 ignore 注释附加到它适用的行:

dart
int x = ''; // ignore: invalid_assignment

在 pubspec 文件中抑制诊断信息

#

如果您需要从 pubspec.yaml 文件中的分析器中抑制非错误诊断信息,请在受影响的行上方添加 ignore 注释。

以下示例忽略了 sort_pub_dependencies lint,因为它希望首先放置 flutter 依赖项:

pubspec.yaml
yaml
dependencies:
  flutter:
    sdk: flutter

  # ignore: sort_pub_dependencies
  collection: ^1.19.0

自定义分析规则

#

每个 分析器诊断信息linter 规则 都有默认严重性。您可以使用分析选项文件来更改单个规则的严重性,或始终忽略某些规则。

分析器支持三个严重性级别:

info
一条不会导致分析失败的信息消息。 示例: dead_code
warning
一条警告,除非分析器配置为将警告视为错误,否则不会导致分析失败。 示例: invalid_null_aware_operator
error
一个导致分析失败的错误。 示例: invalid_assignment

忽略规则

#

您可以使用 errors: 字段忽略特定的 分析器诊断信息linter 规则 。列出规则,后跟 : ignore。例如,以下分析选项文件指示分析工具忽略 TODO 规则:

yaml
analyzer:
  errors:
    todo: ignore

更改规则的严重性

#

您可以全局更改特定规则的严重性。此技术适用于常规分析问题以及 lint。例如,以下分析选项文件指示分析工具将无效赋值视为警告,将缺少返回值视为错误,并提供有关死代码的信息(而不是警告或错误):

yaml
analyzer:
  errors:
    invalid_assignment: warning
    missing_return: error
    dead_code: info

资源

#

使用以下资源来了解有关 Dart 中静态分析的更多信息: