自定义静态分析
静态分析允许您在执行任何代码之前发现问题。它是一个强大的工具,用于防止错误并确保代码符合样式指南。
在分析器的帮助下,您可以找到简单的拼写错误。例如,可能不小心在 if
语句中添加了一个分号
dartvoid 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 方法
dartvar controller = StreamController<String>();
info - Unclosed instance of 'Sink'. Try invoking 'close' in the function in which the 'Sink' was created. - close_sinks
在 Dart 生态系统中,Dart 分析服务器和其他工具使用分析器包执行静态分析。
您可以自定义静态分析以查找各种潜在问题,包括 Dart 语言规范中指定的错误和警告。您还可以配置 linter 规则,以确保您的代码符合 Dart 风格指南和 高效 Dart 中建议的其他指南。诸如 dart analyze
、flutter analyze
和 IDE 和编辑器 等工具使用分析器包来评估您的代码。
本文档解释了如何使用分析选项文件或 Dart 源代码中的注释来自定义分析器的行为。如果您想在工具中添加静态分析,请参阅分析器包文档和分析服务器 API 规范。
分析选项文件
#将分析选项文件 analysis_options.yaml
放置在包的根目录中,与 pubspec 文件位于同一目录中。
这是一个分析选项文件的示例
include: package:lints/recommended.yaml
analyzer:
exclude: [build/**]
language:
strict-casts: true
strict-raw-types: true
linter:
rules:
- cancel_subscriptions
该示例说明了最常见的顶级条目
- 使用
include: url
从指定的 URL 引入选项,在本例中是从lints
包中的文件引入。由于 YAML 不允许重复的键,因此您最多可以包含一个文件。 - 使用
analyzer:
条目来自定义静态分析:启用更严格的类型检查、排除文件、忽略特定规则、更改规则的严重程度或启用实验。 - 使用
linter:
条目来配置 linter 规则。
如果分析器在包的根目录中找不到分析选项文件,它会向上遍历目录树,查找该文件。如果没有可用文件,则分析器将默认使用标准检查。
考虑大型项目的以下目录结构
分析器使用文件 #1 来分析 my_other_package
和 my_other_other_package
中的代码,并使用文件 #2 来分析 my_package
中的代码。
启用更严格的类型检查
#如果您需要比 Dart 类型系统要求的更严格的静态检查,请考虑启用 strict-casts
、strict-inference
和 strict-raw-types
语言模式
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
您可以一起或单独使用这些模式;所有模式的默认值均为 false
。
strict-casts: <bool>
- 值为
true
可确保类型推断引擎永远不会从dynamic
隐式转换为更具体的类型。以下有效的 Dart 代码包含从jsonDecode
返回的dynamic
值到List<String>
的隐式向下转换,这可能会在运行时失败。此模式会报告潜在的错误,要求您添加显式转换或以其他方式调整代码。
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
,导致此模式发出推断失败提示
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
变量,导致此模式发出原始类型提示
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
启用和禁用 linter 规则
#分析器包还提供代码 linter。有各种各样的linter 规则可用。Linters 往往是非宗派的 - 规则不必相互一致。例如,某些规则更适用于常规 Dart 包,而其他规则则专为 Flutter 应用而设计。请注意,linter 规则可能会出现误报,这与静态分析不同。
启用 Dart 团队推荐的 linter 规则
#Dart 团队在 lints 包中提供了两组推荐的 linter 规则
- 核心规则
- 帮助识别在运行或使用 Dart 代码时可能导致问题的关键问题。所有代码都应通过这些 lint 规则。上传到 pub.dev 的软件包会有一个 软件包得分,该得分部分基于通过这些规则的情况。
- 推荐规则
- 帮助识别在运行或使用 Dart 代码时可能导致的其他问题,并强制实施单一、惯用的样式和格式。我们建议所有 Dart 代码都使用这些规则,这些规则是核心规则的超集。
要启用任何一组 lint,请将 lints 包 添加为开发依赖项
$ dart pub add --dev lints
然后编辑您的 analysis_options.yaml
文件以包含您首选的规则集
include: package:lints/<RULE_SET>.yaml
例如,您可以像这样包含推荐的规则集
include: package:lints/recommended.yaml
启用单个规则
#要启用单个 linter 规则,请将 linter:
作为顶级键添加到分析选项文件中,后跟 rules:
作为二级键。在后续行中,指定您要应用的规则,并以破折号为前缀(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
include: package:lints/recommended.yaml
linter:
rules:
avoid_shadowing_type_parameters: false
await_only_futures: true
启用分析器插件(实验性)
#分析器对插件有实验性支持。这些插件与分析器集成,以添加诸如新诊断、快速修复和自定义代码完成等功能。每个 analysis_options.yaml
文件只能启用一个插件。启用分析器插件会增加分析器使用的内存量。
如果您的环境符合以下任一条件,请不要使用分析器插件
- 您使用的开发机器内存少于 16 GB。
- 您使用的单仓库(mono-repo)包含超过 10 个
pubspec.yaml
和analysis_options.yaml
文件。
您可以在 pub.dev 上找到一些分析器插件。
要启用插件
将包含插件的软件包添加为开发依赖项。
$ dart pub add --dev <your_favorite_analyzer_plugin_package>
编辑您的
analysis_options.yaml
文件以启用该插件。yamlanalyzer: plugins: - your_favorite_analyzer_plugin_package
要指示要启用的特定插件功能(例如新的诊断),可能需要进行额外的设置。
从分析中排除代码
#有时,某些代码无法通过分析是可以接受的。例如,您可能依赖于您不拥有的软件包生成的代码,该生成的代码可以工作,但在静态分析期间会产生警告。或者,linter 规则可能会导致您想要抑制的误报。
您可以通过几种方式将代码排除在分析之外
- 将整个文件排除在分析之外。
- 阻止特定非错误规则应用于单个文件。
- 阻止特定非错误规则应用于单行代码。
排除文件
#要将文件排除在静态分析之外,请使用 exclude:
分析器选项。您可以列出单个文件,或使用 glob 模式语法。所有 glob 模式的使用都应相对于包含 analysis_options.yaml
文件的目录。
analyzer:
exclude:
- lib/client.dart
- lib/server/*.g.dart
- test/_data/**
禁止显示文件的诊断信息
#要忽略特定文件的特定非错误诊断,请将 ignore_for_file
注释添加到文件中
// ignore_for_file: unused_local_variable
这适用于整个文件,注释之前或之后,并且对于生成的代码特别有用。
要抑制多个诊断,请使用逗号分隔的列表
// ignore_for_file: unused_local_variable, duplicate_ignore, dead_code
要抑制所有 linter 规则,请添加 type=lint
说明符
// ignore_for_file: type=lint
禁止显示一行的代码的诊断信息
#要在特定的 Dart 代码行上抑制特定的非错误诊断,请将 ignore
注释放在代码行上方。这是一个忽略导致运行时错误的代码的示例,您可能会在语言测试中这样做
// ignore: invalid_assignment
int x = '';
要抑制多个诊断,请提供一个逗号分隔的列表
// ignore: invalid_assignment, const_initialized_with_non_constant_value
const x = y;
或者,将忽略注释附加到它所适用的行
int x = ''; // ignore: invalid_assignment
禁止显示 pubspec 文件中的诊断信息
#如果您需要在 pubspec.yaml
文件中抑制来自分析器的非错误诊断,请在受影响的行上方添加一个 ignore
注释。
以下示例忽略了 sort_pub_dependencies
lint,因为它想将 flutter
依赖项放在首位
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 规则
analyzer:
errors:
todo: ignore
更改规则的严重程度
#您可以全局更改特定规则的严重性。此技术适用于常规分析问题以及 lint。例如,以下分析选项文件指示分析工具将无效赋值视为警告,将缺少返回视为错误,并提供有关无效代码的信息(但不是警告或错误)
analyzer:
errors:
invalid_assignment: warning
missing_return: error
dead_code: info
资源
#使用以下资源了解有关 Dart 中静态分析的更多信息
除非另有说明,否则本网站上的文档反映了 Dart 3.6.0。页面上次更新时间为 2024-12-10。 查看源代码 或 报告问题。