内容

自定义静态分析

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

在分析器的帮助下,您可以找到简单的拼写错误。例如,一个意外的分号可能出现在 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 语言规范 中指定的错误和警告。您还可以配置 Lint 规则,以确保您的代码符合 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

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

如果分析器无法在包根目录中找到分析选项文件,它会向上遍历目录树,寻找一个文件。如果没有任何文件可用,分析器会默认为标准检查。

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

project root contains analysis_options.yaml (#1) and 3 packages, one of which (my_package) contains an analysis_options.yaml file (#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> 的隐式向下转换,这可能在运行时失败。此模式会报告潜在的错误,要求您添加显式转换或以其他方式调整您的代码。
✗ 静态分析:失败dart
void foo(List<String> lines) {
  ...
}

void bar(String jsonText) {
  foo(jsonDecode(jsonText)); // Implicit cast
}
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,此模式会为此发出一个推断失败提示
✗ 静态分析:失败dart
final lines = {}; // Inference failure
lines['Dart'] = 10000;
lines['C++'] = 'one thousand';
lines['Go'] = 2000;
print('Lines: ${lines.values.reduce((a, b) => a + b)}'); // Runtime error

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

启用和禁用 Lint 规则

#

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

启用 Dart 团队推荐的 Lint 规则

#

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

核心规则
帮助识别在运行或使用 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: 添加到 analysis options 文件作为顶级键,然后将 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 中的那个 analysis options 文件,您可能希望禁用其中的一些规则。禁用单个规则类似于启用它们,但需要使用映射而不是列表作为 rules: 条目的值,因此每一行都应包含规则名称,后跟 : false: true

这是一个 analysis options 文件的示例,它使用 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 规则 都有一个默认严重性。您可以使用 analysis options 文件更改单个规则的严重性,或始终忽略某些规则。

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

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

忽略规则

#

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

yaml
analyzer:
  errors:
    todo: ignore

更改规则的严重性

#

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

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

资源

#

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