目次

静的解析のカスタマイズ

静的解析を使用すると、コードを1行も実行する前に問題を見つけることができます。これは、バグを防ぎ、コードがスタイルガイドラインに準拠するようにするための強力なツールです。

アナライザーの助けを借りて、単純なタイプミスを見つけることができます。たとえば、誤ってセミコロンが 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 スタイルガイドおよび 効果的な Dart で提案されているその他のガイドラインに準拠していることを確認できます。dart analyzeflutter analyze、および IDE とエディターなどのツールは、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-inference、および strict-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 コードには、このモードによる raw 型のヒントが発生する、raw 型の 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:を、2番目のレベルのキーとして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にあるような解析オプションファイルを含める場合は、含まれているルールの一部を無効にしたい場合があります。個別のルールを無効にするのは、ルールを有効にするのと似ていますが、rules:エントリの値としてリストではなくマップを使用する必要があります。そのため、各行にルール名と、その後に: falseまたは: trueを指定する必要があります。

以下は、avoid_shadowing_type_parametersを除く、lintsの推奨ルールをすべて使用し、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ファイルごとに有効にできるプラグインは1つだけです。アナライザープラグインを有効にすると、アナライザーが使用するメモリが増加します。

状況が次のいずれかの条件を満たす場合は、アナライザープラグインを使用しないでください。

  • 16 GB未満のメモリを搭載した開発マシンを使用している。
  • 10個以上のpubspec.yamlファイルとanalysis_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

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

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

#

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

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

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

また、すべてのファイルに対して特定のルールを無効にするか、ルールの重大度を変更することもできます。

ファイルを除外する

#

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

または、適用される行にignoreコメントを追加します。

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

pubspec ファイル内の診断を抑制する

#

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

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

pubspec.yaml
yaml
dependencies:
  flutter:
    sdk: flutter

  # ignore: sort_pub_dependencies
  collection: ^1.19.0

解析規則のカスタマイズ

#

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

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

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

規則の無視

#

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

yaml
analyzer:
  errors:
    todo: ignore

規則の重大度の変更

#

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

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

リソース

#

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