跳到主要內容

自訂靜態分析

靜態分析可讓您在執行單行程式碼之前找到問題。它是一個強大的工具,用於預防錯誤並確保程式碼符合樣式指南。

借助分析器的協助,您可以找到簡單的錯字。例如,可能不小心在 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 Analysis Server 和其他工具使用analyzer 套件來執行靜態分析。

您可以自訂靜態分析以尋找各種潛在問題,包括Dart 語言規格中指定的錯誤和警告。您還可以設定 Linter 規則,以確保您的程式碼符合Dart 風格指南以及Effective Dart中建議的其他指南。dart analyzeflutter analyzeIDE 和編輯器等工具使用 analyzer 套件來評估您的程式碼。

本文檔說明如何使用分析選項檔案或 Dart 原始碼中的註解來自訂分析器的行為。如果您想將靜態分析新增至您的工具,請參閱analyzer 套件文件和Analysis Server 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

啟用和停用 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 中的檔案),您可能想要停用某些包含的規則。停用個別規則與啟用它們類似,但需要使用 Map 而不是清單作為 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

包含共用選項

#

分析選項檔案可以包含在另一個選項檔案中指定的選項,甚至是其他選項檔案的清單。您可以使用頂層 include: 欄位來指定此類檔案

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

可以使用 package: 路徑或相對路徑來指定包含的選項檔案。可以在清單中指定多個分析選項檔案

analysis_options.yaml
yaml
include:
  - package:flutter_lints/recommended.yaml
  - ../team_options.yaml

包含檔案中的選項可以被包含檔案以及後續包含的檔案覆寫。換句話說,分析選項檔案指定的選項是通過首先應用每個包含檔案中指定的選項 (通過遞迴應用此演算法),按照它們在清單中出現的順序,然後使用任何本地定義的選項覆寫它們來計算的。

例如,假設有以下選項檔案

three.yaml
yaml
include: two.yaml
# ...

以及包含這些檔案的最終選項檔案

analysis_options.yaml
yaml
include:
  - one.yaml
  - three.yaml
# ...

然後,組合的分析選項是通過應用在 one.yamltwo.yamlthree.yaml 和最終 analysis_options.yaml 中找到的選項來計算的。

啟用分析器外掛程式 (實驗性)

#

分析器具有對外掛程式的實驗性支援。這些外掛程式與分析器整合,以新增功能,例如新的診斷訊息、快速修復和自訂程式碼完成。每個 analysis_options.yaml 檔案只能啟用一個外掛程式。啟用分析器外掛程式會增加分析器使用的記憶體量。

如果您的情況符合以下任一條件,請勿使用分析器外掛程式

  • 您使用的開發機器記憶體小於 16 GB。
  • 您使用具有超過 10 個 pubspec.yamlanalysis_options.yaml 檔案的 Mono-repo。

您可以在 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 format

#

您可以通過將 formatter 區段新增至分析選項檔案並指定您偏好的 page_width 來設定 dart format 的行為。

如需更多資訊,請閱讀設定格式器頁面寬度

資源

#

使用以下資源來瞭解有關 Dart 中靜態分析的更多資訊