目次

無効な_case_パターン

Dart 3.0で有効なcase式を使用してください。

このルールは現在実験的であり、Dart 3.0以降で使用可能です。

このルールには、クイックフィックスが用意されています。

詳細

#

Dart 2.19以前で有効なcase式の中には、ライブラリが3.0にアップグレードされるとエラーになるか、セマンティクスが変更されるものがあります。 このリントは、Dart 3.0への移行を容易にするために、これらの式にフラグを立てます。

2.19で有効なswitch caseの中には、Dart 3.0ではコンパイルエラーになるものがあります

  • セットリテラル
  • 括弧で囲まれた式
  • identical()の呼び出し。
  • 単項演算子式 `!`、`-`、または `~` (整数リテラルの前にある `-` は有効なパターンであり問題ないため、例外)
  • 二項演算子式 `!=`、`==`、`&`、`|`、`^`、 `~/`、`>>`、 `>>>`、`<<`、`+`、 `-`、 `*`、`/`、`%`、 `<`、`<=`、 `>`、 `>=`、`??`.
  • 条件演算子 `?:`
  • 文字列に対する`.length`呼び出し
  • `is`と`is!`式

すべての例

dart
switch (obj) {
  case {1}: // Set literal.
  case (1): // Parenthesized expression.
  case identical(1, 2): // `identical()` call.
  case -pi: // Unary operator.
  case 1 + 2: // Binary operator.
  case true ? 1 : 2: // Conditional operator.
  case 'hi'.length: // .length call.
  case i is int: // is expression.
}

2.19で有効なswitch caseの中には、構文的には有効なパターンであるが、パターンマッチングの動作が現在の定数等価性動作と異なる場合があります。 それらは以下のとおりです。

リストリテラルとマップリテラル。 リストまたはマップリテラルは、caseの中で定数として現れることができます

dart
switch (obj) {
  case [1, 2]: ...
  case {'k': 'v'}: ...
}

現在、caseは入力値が定数と同じアイデンティティを持っている場合にのみ一致します。 したがって、

dart
test(List<int> list) {
  switch (list) {
    case [1, 2]: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const [1, 2]); // Prints "Matched".
  test([1, 2]); // Prints "Did not match".
}

パターンを使用すると、リストまたはマップリテラルはリストまたはマップパターンになります。 パターンは入力オブジェクトを分解し、サブパターンがすべて一致する場合に一致します。 つまり、リストとマップのパターンは、深い等価性のようなものを使用して一致します。

Dart 3.0では、上記のプログラムは「Matched」を2回出力します。

定数コンストラクタ呼び出し。 コレクションと同様に、caseの中でクラスの定数インスタンスを構築できます

dart
class Point {
  final int x;
  final int y;
  const Point({this.x, this.y});
}

test(Point p) {
  switch (p) {
    case Point(x: 1, y: 2): print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const Point(1, 2)); // Prints "Matched".
  test(Point(1, 2)); // Prints "Did not match".
}

繰り返しますが、コレクションと同様に、caseは現在、入力値が同じアイデンティティを持っている場合にのみ一致します。 パターンを使用すると、`Point(...)`構文はオブジェクトパターンになり、入力ポイントを分解し、`x`ゲッターと`y`ゲッターを呼び出して、それらの結果を対応するサブパターンと照合します。

この例では、「Matched」が2回出力されます。

オブジェクトパターンは名前付きフィールドのみをサポートすることに注意してください。 したがって、現在caseに位置引数を持つ定数コンストラクタは、パターンとして解析されるとコンパイル時エラーになります。 引数のない定数コンストラクタ呼び出しは有効なオブジェクトパターンであり、型テストのみを実行します

dart
class Thing {
  const Thing();
}

test(Thing t) {
  switch (t) {
    case Thing(): print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(const Thing()); // Prints "Matched".
  test(Thing()); // Prints "Did not match".
}

パターンとして解釈すると、「Matched」が2回出力されます。

ワイルドカード。 現在、`_`という名前の定数を使用できます

dart
test(int n) {
  const _ = 3;
  switch (n) {
    case _: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(3); // Prints "Matched".
  test(5); // Prints "Did not match".
}

パターンを使用すると、識別子 `_` はすべての値に一致するパターンとして扱われるため、「Matched」が2回出力されます。

論理演算子。 論理演算子`&&`と `||` は有効な定数式であり、有効なパターンでもあります。 定数式として、それらは式をブール値に評価し、入力値がそのブール値と等しい場合に一致します。 したがって、

dart
test(bool b) {
  switch (b) {
    case true && false: print('Matched'); break;
    default: print('Did not match'); break;
  }
}

main() {
  test(false); // Prints "Matched".
  test(true); // Prints "Did not match".
}

Dart 3.0では、これらはパターンになります。 上記の例では、ブール値はtrueとfalseの両方になることができないため、「Did not match」が2回出力されます。

無効なcaseの多くは、現在のDartとDart 3.0の両方で有効であり、同じ意味を持つように機械的に変更できます。

括弧で囲まれた式:内部式がDart 3.0で壊れていないものである場合、括弧を破棄するだけです。

リストリテラル、マップリテラル、セットリテラル、および定数コンストラクタ呼び出し:リテラルまたは呼び出しの前に `const` を配置します。 これにより、現在の動作を維持する定数パターンに変換されます

悪い例

dart
case [1, 2]:
case {'k': 'v'}:
case {1, 2}:
case Point(1, 2):

良い例

dart
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):
  • ワイルドカード:定数の名前を `_` から別の名前に変更します。 名前はプライベートであるため、他のコードに影響を与えることなくライブラリ内でローカルに変更できます。

  • その他すべて:その他の無効な式については、式を新しい名前付き定数にホイストする必要があります。 たとえば、次のようなコードがある場合

悪い例

dart
switch (n) {
  case 1 + 2: ...
}

次のように変更することで修正できます

良い例

dart
const three = 1 + 2;

switch (n) {
 case three: ...
}

使用方法

#

invalid_case_patternsルールを有効にするには、analysis_options.yamlファイルのlinter > rulesの下に `invalid_case_patterns` を追加します

analysis_options.yaml
yaml
linter:
  rules:
    - invalid_case_patterns