メインコンテンツにスキップ

静的解析のカスタマイズ

静的解析により、コードを一行も実行する前に問題を特定できます。これは、バグを防ぎ、コードがスタイル ガイドラインに準拠していることを確認するための強力なツールです。

アナライザーの助けを借りて、単純なタイプミスを見つけることができます。たとえば、誤ってセミコロンが 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

アナライザーは、より微妙な問題を見つけるのにも役立ちます。たとえば、シンク メソッドを閉じるのを忘れた場合などです。

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 言語仕様で指定されたエラーや警告を含む、さまざまな潜在的な問題を探すことができます。また、リンター ルールを設定して、コードが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_package および my_other_other_package のコードを解析し、ファイル #2 を使用して my_package のコードを解析します。

より厳密な型チェックを有効にする

#

strict-castsstrict-inferencestrict-raw-types の言語モードを有効にすることを検討してください。これらは、Dart の型システムが必要とするよりも厳密な静的チェックを提供します。

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

リンター ルールを有効または無効にする

#

analyzer パッケージはコード リンターも提供します。さまざまなリンター ルールが利用可能です。リンターは通常、宗派にとらわれません。ルールはお互いに同意する必要はありません。たとえば、一部のルールは通常の Dart パッケージに適しており、他のルールは Flutter アプリ用に設計されています。リンター ルールは、静的解析とは異なり、偽陽性を持つ可能性があることに注意してください。

Dart チーム推奨のリンター ルールを有効にする

#

Dart チームは、lints パッケージで 2 セットの推奨リンター ルールを提供しています。

コア ルール
Dart コードの実行または使用時に問題を引き起こす可能性のある重大な問題の特定に役立ちます。すべてのコードはこれらのリンター ルールに合格する必要があります。pub.dev にアップロードされたパッケージには、これらのルールに合格することが部分的に基づいたパッケージ スコアがあります。
推奨ルール
Dart コードの実行または使用時に問題を引き起こす可能性のある追加の問題を特定し、単一の、慣用的なスタイルとフォーマットを強制します。すべての Dart コードでこれらのルールを使用することをお勧めします。これらはコア ルールのスーパーセットです。

いずれかのセットのリンツを有効にするには、lints パッケージを開発依存関係として追加します。

dart pub add --dev lints

次に、analysis_options.yaml ファイルを編集して、好みのルールセットを含めます。

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

たとえば、推奨ルールセットを次のように含めることができます。

yaml
include: package:lints/recommended.yaml

個々のルールを有効にする

#

単一のリンター ルールを有効にするには、分析オプションファイルにトップレベルのキーとして linter: を追加し、次にセカンドレベルのキーとして rules: を追加します。後続の行では、ダッシュ(YAML リストの構文)を先頭に付けて、適用したいルールを指定します。例:

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 リンターを有効にする分析オプションファイルの例です。

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.yaml、次に two.yaml、次に three.yaml、最後に analysis_options.yaml で見つかったオプションを適用することによって計算されます。

アナライザー プラグインを有効にする(実験的)

#

アナライザーには、プラグインの実験的なサポートがあります。これらのプラグインはアナライザーと統合され、新しい診断、クイック修正、カスタム コード補完などの機能を追加します。analysis_options.yaml ファイルごとに 1 つのプラグインしか有効にできません。アナライザー プラグインを有効にすると、アナライザーが使用するメモリ量が増加します。

次のいずれかの条件に当てはまる場合は、アナライザー プラグインを使用しないでください。

  • メモリが 16 GB 未満の開発マシンを使用している。
  • 10 個以上の pubspec.yaml および analysis_options.yaml ファイルを持つモノレポを使用している。

pub.dev でいくつかのアナライザー プラグインを見つけることができます。pub.dev

プラグインを有効にするには

  1. プラグインを含むパッケージを開発依存関係として追加します。

    dart pub add --dev <your_favorite_analyzer_plugin_package>
  2. analysis_options.yaml ファイルを編集してプラグインを有効にします。

    yaml
    analyzer:
      plugins:
        - your_favorite_analyzer_plugin_package

    新しい診断などの特定のプラグイン機能を示すには、追加のセットアップが必要になる場合があります。

解析からコードを除外する

#

一部のコードが解析に失敗しても問題ない場合があります。たとえば、所有していないパッケージによって生成されたコードに依存している場合などです。生成されたコードは機能しますが、静的解析中に警告を生成します。または、リンター ルールが抑制したい偽陽性を引き起こす可能性があります。

コードを解析から除外するには、いくつかの方法があります。

  • 解析からファイル全体を除外する。
  • 特定の非エラー ルールが個々のファイルに適用されないようにする。
  • 特定の非エラー ルールが個々のコード行に適用されないようにする。

また、特定のルールを無効にするか、ルールの重大度を変更することもできます。

ファイルを解析から除外する

#

静的解析からファイルを除外するには、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

すべてのリンター ルールを抑制するには、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;

または、無視コメントを適用対象の行に追加します。

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

pubspec ファイルを診断から抑制する

#

pubspec.yaml ファイルで非エラー診断を抑制する必要がある場合は、影響を受ける行の上に ignore コメントを追加します。

次の例では、flutter 依存関係を最初に配置したいので、sort_pub_dependencies リンターを無視しています。

pubspec.yaml
yaml
dependencies:
  flutter:
    sdk: flutter

  # ignore: sort_pub_dependencies
  collection: ^1.19.0

解析ルールのカスタマイズ

#

アナライザー診断リンター ルールにはデフォルトの重大度があります。分析オプションファイルを使用して、個々のルールの重大度を変更したり、一部のルールを常に無視したりできます。

アナライザーは 3 つの重大度レベルをサポートしています。

info
解析を失敗させない情報メッセージ。例:dead_code
warning
アナライザーが警告をエラーとして扱うように設定されていない限り、解析を失敗させない警告。例:invalid_null_aware_operator
error
解析を失敗させるエラー。例:invalid_assignment

ルールを無視する

#

errors: フィールドを使用して、特定のアナライザー診断リンター ルールを無視できます。ルールをリストし、その後に : ignore を付けます。たとえば、次の分析オプションファイルは、TODO ルールを無視するように分析ツールに指示します。

yaml
analyzer:
  errors:
    todo: ignore

ルールの重大度を変更する

#

特定のルールの重大度をグローバルに変更できます。この手法は、通常の分析問題とリンツの両方に機能します。たとえば、次の分析オプションファイルは、無効な代入を警告として扱い、欠落している戻りをエラーとして扱い、デッドコードに関する情報(警告やエラーではない)を提供するように分析ツールに指示します。

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

dart format の設定

#

page_width を指定する formatter セクションを分析オプションファイルに追加することで、dart format の動作を設定できます。

詳細については、「フォーマッターのページ幅の設定」をお読みください。

リソース

#

Dart の静的解析についてさらに詳しく知るには、次のリソースを使用してください。