自定義靜態分析
靜態分析允許你在執行任何一行程式碼之前發現問題。它是一個強大的工具,用於防止 bug 並確保程式碼符合風格指南。
藉助分析器,你可以發現簡單的拼寫錯誤。例如,一個意外的分號可能進入了 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 Analysis Server 和其他工具使用 analyzer 包來執行靜態分析。
你可以自定義靜態分析以查詢各種潛在問題,包括 Dart 語言規範中指定的錯誤和警告。你還可以配置 Linter 規則,以確保你的程式碼符合 Dart 風格指南和 Effective Dart 中建議的其他準則。像 dart analyze、flutter analyze 以及 IDE 和編輯器這樣的工具使用 analyzer 包來評估你的程式碼。
本文件解釋瞭如何使用分析選項檔案或 Dart 原始碼中的註釋來自定義分析器的行為。如果你想在你的工具中新增靜態分析,請參閱 analyzer 包文件和 Analysis Server 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_assignablestrict-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 errorwarning - The type argument(s) of 'Map' can't be inferred - inference_failure_on_collection_literalstrict-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 規則
#analyzer 包還提供了一個程式碼 Linter。提供了各種各樣的Linter 規則。Linter 往往是非宗派的——規則之間不必相互一致。例如,有些規則更適合常規 Dart 包,而另一些規則則專為 Flutter 應用設計。請注意,與靜態分析不同,Linter 規則可能會產生誤報。
啟用 Dart 團隊推薦的 Linter 規則
#Dart 團隊在 lints 包中提供了兩套推薦的 Linter 規則
- 核心規則
- 幫助識別在使用或執行 Dart 程式碼時可能導致問題的關鍵問題。所有程式碼都應透過這些 Linter 規則。上傳到 pub.dev 的包會有一個包評分,該評分部分基於透過這些規則的情況。
- 推薦規則
- 幫助識別在使用或執行 Dart 程式碼時可能導致的其他問題,並強制執行單一、慣用的風格和格式。我們建議所有 Dart 程式碼都使用這些規則,它們是核心規則的超集。
要啟用任一組 Lints,請將 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
- annotate_redeclares
- cancel_subscriptions
- close_sinks
- combinators_ordering
- comment_references
- invalid_case_patterns
- one_member_abstracts
- only_throw_errors停用單個規則
#如果你包含一個分析選項檔案,例如 lints 中的檔案,你可能想停用一些包含的規則。停用單個規則與啟用它們類似,但需要使用對映而不是列表作為 rules: 條目的值,因此每行應包含規則名稱,後跟 : false 或 : true。
這是一個分析選項檔案的示例,它使用了 lints 中除 avoid_shadowing_type_parameters 外的所有推薦規則。它還啟用了 await_only_futures 規則
include: package:lints/recommended.yaml
linter:
rules:
avoid_shadowing_type_parameters: false
await_only_futures: true包含共享選項
#分析選項檔案可以包含在其他選項檔案或甚至其他選項檔案列表中指定的選項。你可以使用頂層 include: 欄位來指定這些檔案
include: package:flutter_lints/recommended.yaml包含的選項檔案可以透過 package: 路徑或相對路徑指定。可以在列表中指定多個分析選項檔案
include:
- package:flutter_lints/recommended.yaml
- ../team_options.yaml包含檔案中的選項可以在包含檔案中被覆蓋,也可以被後續包含的檔案覆蓋。換句話說,分析選項檔案指定的選項是透過首先按列表中出現的順序應用每個包含檔案(透過遞迴應用此演算法)中指定的選項,然後用本地定義的任何選項覆蓋它們來計算的。
例如,給定以下選項檔案
include: two.yaml
# ...以及一個包含這些選項檔案的最終選項檔案
include:
- one.yaml
- three.yaml
# ...然後,透過依次應用 one.yaml、two.yaml、three.yaml 中找到的選項,最後應用 analysis_options.yaml 中的選項來計算組合的分析選項。
啟用分析器外掛 (實驗性)
#分析器對外掛提供實驗性支援。這些外掛與分析器整合,以新增新診斷、快速修復和自定義程式碼補全等功能。每個 analysis_options.yaml 檔案只能啟用一個外掛。啟用分析器外掛會增加分析器使用的記憶體。
如果你的情況符合以下任一條件,請不要使用分析器外掛
- 你的開發機器記憶體少於 16 GB。
- 你使用包含超過 10 個
pubspec.yaml和analysis_options.yaml檔案的 mono-repo。
你可以在 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;或者,將 ignore 註釋附加到它應用的行
int x = ''; // ignore: invalid_assignment抑制 pubspec 檔案中的診斷
#如果你需要在 pubspec.yaml 檔案中抑制分析器報告的非錯誤診斷,請在受影響的行上方新增 ignore 註釋。
以下示例忽略了 sort_pub_dependencies 規則,因為它想把 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更改規則的嚴重性
#你可以全域性更改特定規則的嚴重性。此技術適用於常規分析問題和 Lints。例如,以下分析選項檔案指示分析工具將無效賦值視為警告,將缺少返回值視為錯誤,並提供關於死程式碼的資訊(但不是警告或錯誤)
analyzer:
errors:
invalid_assignment: warning
missing_return: error
dead_code: info配置 dart format
#你可以透過在分析選項檔案中新增 formatter 部分並指定你偏好的 page_width 來配置 dart format 的行為。
有關更多資訊,請閱讀配置格式化程式頁面寬度。
資源
#使用以下資源瞭解有關 Dart 中靜態分析的更多資訊