跳到主要内容
目录

诊断消息

目录 keyboard_arrow_down keyboard_arrow_up
更多水平方向的空白

此页面列出了 Dart 分析器生成的诊断消息,其中详细说明了这些消息的含义以及如何修复代码。有关分析器的更多信息,请参阅自定义静态分析

诊断

#

分析器针对不符合语言规范或可能以意外方式工作的代码生成以下诊断消息。

abi_specific_integer_invalid

#

扩展 'AbiSpecificInteger' 的类必须只有一个 const 构造函数,没有其他成员,也没有类型参数。

描述

#

当扩展 AbiSpecificInteger 的类不满足以下所有要求时,分析器会生成此诊断消息:

  • 必须只有一个构造函数
  • 构造函数必须标记为 const
  • 除了一个构造函数外,不能有任何其他成员
  • 不能有任何类型参数

示例

#

以下代码生成此诊断消息,因为类 C 没有定义 const 构造函数

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
}

以下代码生成此诊断消息,因为构造函数不是 const 构造函数

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  C();
}

以下代码生成此诊断消息,因为类 C 定义了多个构造函数

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  const C.zero();
  const C.one();
}

以下代码生成此诊断消息,因为类 C 定义了一个字段

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  final int i;

  const C(this.i);
}

以下代码生成此诊断消息,因为类 C 有一个类型参数

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C<T> extends AbiSpecificInteger { // type parameters
  const C();
}

常见修复方法

#

更改类,使其满足没有类型参数且只有一个成员(即 const 构造函数)的要求

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  const C();
}

abi_specific_integer_mapping_extra

#

扩展 'AbiSpecificInteger' 的类必须只有一个 'AbiSpecificIntegerMapping' 注解,指定从 ABI 到具有固定大小的 'NativeType' 整数的映射。

描述

#

当扩展 AbiSpecificInteger 的类具有多个 AbiSpecificIntegerMapping 注解时,分析器会生成此诊断消息。

示例

#

以下代码生成此诊断消息,因为类 C 上有两个 AbiSpecificIntegerMapping 注解

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
@AbiSpecificIntegerMapping({Abi.linuxX64 : Uint16()})
final class C extends AbiSpecificInteger {
  const C();
}

常见修复方法

#

删除除一个之外的所有注解,并根据需要合并参数

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8(), Abi.linuxX64 : Uint16()})
final class C extends AbiSpecificInteger {
  const C();
}

abi_specific_integer_mapping_missing

#

扩展 'AbiSpecificInteger' 的类必须只有一个 'AbiSpecificIntegerMapping' 注解,指定从 ABI 到具有固定大小的 'NativeType' 整数的映射。

描述

#

当扩展 AbiSpecificInteger 的类没有 AbiSpecificIntegerMapping 注解时,分析器会生成此诊断消息。

示例

#

以下代码生成此诊断消息,因为类 C 上没有 AbiSpecificIntegerMapping 注解

dart
import 'dart:ffi';

final class C extends AbiSpecificInteger {
  const C();
}

常见修复方法

#

向类添加 AbiSpecificIntegerMapping 注解

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  const C();
}

abi_specific_integer_mapping_unsupported

#

到 '{0}' 的映射无效;仅支持到 'Int8'、'Int16'、'Int32'、'Int64'、'Uint8'、'Uint16'、'UInt32' 和 'Uint64' 的映射。

描述

#

AbiSpecificIntegerMapping 注解的 map 参数中的值不是以下整数类型之一时,分析器会生成此诊断消息:

  • Int8
  • Int16
  • Int32
  • Int64
  • Uint8
  • Uint16
  • UInt32
  • Uint64

示例

#

以下代码生成此诊断消息,因为 map 条目的值是 Array<Uint8>,这不是有效的整数类型

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Array<Uint8>(4)})
final class C extends AbiSpecificInteger {
  const C();
}

常见修复方法

#

使用有效的类型之一作为 map 中的值

dart
import 'dart:ffi';

@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
  const C();
}

abstract_field_initializer

#

抽象字段不能有初始化器。

描述

#

当具有 abstract 修饰符的字段也有初始化器时,分析器会生成此诊断消息。

示例

#

以下代码生成此诊断消息,因为 f 被标记为 abstract 并且具有初始化器

dart
abstract class C {
  abstract int f = 0;
}

以下代码生成此诊断消息,因为 f 被标记为 abstract 并且构造函数中有一个初始化器

dart
abstract class C {
  abstract int f;

  C() : f = 0;
}

常见修复方法

#

如果字段必须是抽象的,则删除初始化器

dart
abstract class C {
  abstract int f;
}

如果字段不需要是抽象的,则删除 abstract 关键字

dart
abstract class C {
  int f = 0;
}

abstract_sealed_class

#

'sealed' 类不能标记为 'abstract',因为它已经是隐式抽象的。

描述

#

当类同时使用 abstractsealed 修饰符声明时,分析器会生成此诊断消息。Sealed 类是隐式抽象的,因此不允许显式使用这两个修饰符。

示例

#

以下代码生成此诊断消息,因为类 C 同时使用 abstractsealed 声明

dart
abstract sealed class C {}

常见修复方法

#

如果类应该是抽象的但不是 sealed 的,则删除 sealed 修饰符

dart
abstract class C {}

如果类应该既是抽象的又是 sealed 的,则删除 abstract 修饰符

dart
sealed class C {}

abstract_super_member_reference

#

超类型中 {0} '{1}' 始终是抽象的。

描述

#

当使用 super 引用继承的成员,但超类链中没有该成员的具体实现时,分析器会生成此诊断消息。抽象成员不能被调用。

示例

#

以下代码生成此诊断消息,因为 B 没有继承 a 的具体实现

dart
abstract class A {
  int get a;
}
class B extends A {
  int get a => super.a;
}

常见修复方法

#

删除抽象成员的调用,可以将其替换为对具体成员的调用。

ambiguous_export

#

名称 '{0}' 在库 '{1}' 和 '{2}' 中定义。

描述

#

当两个或多个导出指令导致同一个名称从多个库导出时,分析器会生成此诊断消息。

示例

#

给定一个包含以下内容的文件 a.dart

dart
class C {}

以及一个包含以下内容的文件 b.dart

dart
class C {}

以下代码生成此诊断消息,因为名称 C 正从 a.dartb.dart 导出

dart
export 'a.dart';
export 'b.dart';

常见修复方法

#

如果其中一个库中的任何名称都不需要导出,则删除不必要的导出指令

dart
export 'a.dart';

如果所有导出指令都是必需的,则在除一个指令之外的所有指令中隐藏该名称

dart
export 'a.dart';
export 'b.dart' hide C;

ambiguous_extension_member_access

#

名为 '{0}' 的成员在 '{1}' 和 '{2}' 中定义,并且没有一个是更具体的。

名为 '{0}' 的成员在 {1} 中定义,并且没有一个是更具体的。

描述

#

当代码引用对象的成员(例如,o.m()o.mo[i]),而 o 的静态类型没有声明该成员(例如 m[])时,分析器会尝试在扩展中查找该成员。例如,如果成员是 m,则分析器会查找声明名为 m 的成员并且扩展类型可以赋值给 o 的静态类型的扩展。当作用域内存在多个此类扩展时,将选择扩展类型最具体的扩展。

当所有其他扩展的扩展类型中没有一个扩展的扩展类型比所有其他扩展的扩展类型更具体时,分析器会生成此诊断消息,从而使对成员的引用变得模棱两可。

示例

#

以下代码生成此诊断消息,因为无法在 E1 中的成员和 E2 中的成员之间做出选择

dart
extension E1 on String {
  int get charCount => 1;
}

extension E2 on String {
  int get charCount => 2;
}

void f(String s) {
  print(s.charCount);
}

常见修复方法

#

如果不需要两个扩展,则可以删除或隐藏其中一个。

如果需要两个扩展,则通过使用扩展覆盖显式选择要使用的扩展

dart
extension E1 on String {
  int get charCount => length;
}

extension E2 on String {
  int get charCount => length;
}

void f(String s) {
  print(E2(s).charCount);
}

ambiguous_import

#

名称 '{0}' 在库 {1} 中定义。

描述

#

当引用的名称在两个或多个导入的库中声明时,分析器会生成此诊断消息。

示例

#

给定一个库 (a.dart) 定义了一个类(本例中为 C):

dart
class A {}
class C {}

以及一个库 (b.dart) 定义了同名的不同类:

dart
class B {}
class C {}

以下代码生成此诊断消息:

dart
import 'a.dart';
import 'b.dart';

void f(C c1, C c2) {}

常见修复方法

#

如果任何库是不需要的,则删除它们的导入指令

dart
import 'a.dart';

void f(C c1, C c2) {}

如果名称仍然由多个库定义,则为除一个库之外的所有库的导入指令添加 hide 子句

dart
import 'a.dart' hide C;
import 'b.dart';

void f(C c1, C c2) {}

如果必须能够引用这些类型中的多个类型,则为每个导入指令添加前缀,并使用适当的前缀限定引用

dart
import 'a.dart' as a;
import 'b.dart' as b;

void f(a.C c1, b.C c2) {}

ambiguous_set_or_map_literal_both

#

字面量不能是 Map 或 Set,因为它包含至少一个字面量 Map 条目或展开 'Map' 的展开运算符,以及至少一个既不是这两者之一的元素。

描述

#

由于 Map 和 Set 字面量使用相同的分隔符({}),因此分析器会查看类型参数和元素来确定您想要的字面量类型。当没有类型参数时,分析器使用元素的类型。如果所有元素都是字面量 Map 条目,并且所有展开运算符都在展开 Map,则它是 Map。如果没有任何元素是字面量 Map 条目,并且所有展开运算符都在展开 Iterable,则它是 Set。如果两者都不是真的,则它是模棱两可的。

当至少一个元素是字面量 Map 条目或展开 'Map' 的展开运算符,并且至少一个元素既不是这两者之一时,分析器会生成此诊断消息,这使得分析器无法确定您是在编写 Map 字面量还是 Set 字面量。

示例

#

以下代码生成此诊断消息:

dart
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
    {...a, ...b, ...c};

列表 b 只能展开到 Set 中,而 Map ac 只能展开到 Map 中,并且字面量不能两者都是。

常见修复方法

#

有两种常见的解决方法。第一种是删除所有同类型或不同类型的展开元素,以便元素保持一致。在这种情况下,这可能意味着删除列表并决定如何处理现在未使用的参数

dart
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
    {...a, ...c};

第二种解决方法是将一种类型的元素更改为与另一种元素一致的元素。例如,您可以将列表的元素添加为映射到自身的键

dart
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
    {...a, for (String s in b) s: s, ...c};

ambiguous_set_or_map_literal_either

#

此字面量必须是 Map 或 Set,但元素没有足够的类型推断信息。

描述

#

由于 Map 和 Set 字面量使用相同的分隔符({}),因此分析器会查看类型参数和元素来确定您想要的字面量类型。当没有类型参数并且所有元素都是展开元素(在两种字面量类型中都允许)时,分析器使用正在展开的表达式的类型。如果所有表达式都具有 Iterable 类型,则它是 Set 字面量;如果它们都具有 Map 类型,则它是 Map 字面量。

当正在展开的表达式都没有允许分析器确定您是在编写 Map 字面量还是 Set 字面量的类型时,会生成此诊断消息。

示例

#

以下代码生成此诊断消息:

dart
union(a, b) => {...a, ...b};

出现此问题的原因是没有类型参数,并且没有关于 ab 类型的信息。

常见修复方法

#

有三种常见的解决方法。第一种是向字面量添加类型参数。例如,如果字面量旨在成为 Map 字面量,则您可以编写如下代码:

dart
union(a, b) => <String, String>{...a, ...b};

第二种解决方法是添加类型信息,以便表达式具有 Iterable 类型或 Map 类型。您可以添加显式强制转换,或者在本例中,为两个参数的声明添加类型

dart
union(List<int> a, List<int> b) => {...a, ...b};

第三种解决方法是添加上下文信息。在这种情况下,这意味着为函数添加返回类型

dart
Set<String> union(a, b) => {...a, ...b};

在其他情况下,您可能在其他位置添加类型。例如,假设原始代码如下所示

dart
union(a, b) {
  var x = {...a, ...b};
  return x;
}

您可以在 x 上添加类型注解,如下所示

dart
union(a, b) {
  Map<String, String> x = {...a, ...b};
  return x;
}

annotation_on_pointer_field

#

struct 类中类型为 'Pointer' 的字段不应有任何注解。

描述

#

当在 Struct 的子类中声明且类型为 Pointer 的字段也具有与之关联的注解时,分析器会生成此诊断消息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码生成此诊断消息,因为字段 p 的类型为 Pointer,并且在 Struct 的子类中声明,并带有注解 @Double()

dart
import 'dart:ffi';

final class C extends Struct {
  @Double()
  external Pointer<Int8> p;
}

常见修复方法

#

从字段中删除注解

dart
import 'dart:ffi';

final class C extends Struct {
  external Pointer<Int8> p;
}

argument_must_be_a_constant

#

参数 '{0}' 必须是常量。

描述

#

Pointer.asFunctionDynamicLibrary.lookupFunction 的调用具有 isLeaf 参数,且其值不是常量表达式时,分析器会生成此诊断消息。

Pointer.fromFunctionNativeCallable.isolateLocal 的调用具有 exceptionalReturn 参数,且其值不是常量表达式时,分析器也会生成此诊断消息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码生成此诊断消息,因为 isLeaf 参数的值是参数,因此不是常量

dart
import 'dart:ffi';

int Function(int) fromPointer(
    Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
  return p.asFunction(isLeaf: isLeaf);
}

常见修复方法

#

如果有合适的常量可以使用,则将参数替换为常量

dart
import 'dart:ffi';

const isLeaf = false;

int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
  return p.asFunction(isLeaf: isLeaf);
}

如果没有合适的常量,则将参数替换为布尔字面量

dart
import 'dart:ffi';

int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
  return p.asFunction(isLeaf: true);
}

argument_must_be_native

#

'Native.addressOf' 的参数必须使用 @Native 注解

描述

#

当传递给 Native.addressOf 的参数未使用 Native 注解进行注解时,分析器会生成此诊断消息。

示例

#

以下代码生成此诊断消息,因为 addressOf 的参数是一个字符串,而不是字段,并且字符串不能被注解

dart
import 'dart:ffi';

@Native<Void Function()>()
external void f();

void g() {
  print(Native.addressOf('f'));
}

以下代码生成此诊断消息,因为函数 f 正在传递给 addressOf,但未注解为 Native

dart
import 'dart:ffi';

external void f();

void g() {
  print(Native.addressOf<NativeFunction<Void Function()>>(f));
}

常见修复方法

#

如果参数既不是字段也不是函数,则将参数替换为使用 Native 注解的字段或函数

dart
import 'dart:ffi';

@Native<Void Function()>()
external void f();

void g() {
  print(Native.addressOf<NativeFunction<Void Function()>>(f));
}

如果参数是字段或函数,则使用 Native 注解字段或函数

dart
import 'dart:ffi';

@Native<Void Function()>()
external void f();

void g() {
  print(Native.addressOf<NativeFunction<Void Function()>>(f));
}

argument_type_not_assignable

#

参数类型 '{0}' 不能赋值给参数类型 '{1}'。{2}

描述

#

当参数的静态类型不能赋值给相应参数的静态类型时,分析器会生成此诊断消息。

示例

#

以下代码生成此诊断消息,因为 num 不能赋值给 String

dart
String f(String x) => x;
String g(num y) => f(y);

常见修复方法

#

如果可能,请重写代码,使静态类型可赋值。在上面的示例中,您或许可以更改参数 y 的类型

dart
String f(String x) => x;
String g(String y) => f(y);

如果无法进行此修复,则添加代码以处理参数值不是所需类型的情况。一种方法是将其他类型强制转换为所需类型

dart
String f(String x) => x;
String g(num y) => f(y.toString());

另一种方法是添加显式类型测试和回退代码

dart
String f(String x) => x;
String g(Object y) => f(y is String ? y : '');

如果您认为参数的运行时类型将始终与参数的静态类型相同,并且您愿意承担在运行时出现异常的风险(如果您错了),则添加显式强制转换

dart
String f(String x) => x;
String g(num y) => f(y as String);

argument_type_not_assignable_to_error_handler

#

参数类型 '{0}' 不能赋值给参数类型 '{1} Function(Object)' 或 '{1} Function(Object, StackTrace)'。

描述

#

Future.catchError 的调用具有一个参数,该参数是一个函数,其参数与调用该函数时将传递给该函数的参数不兼容时,分析器会生成此诊断消息。catchError 的第一个参数的静态类型只是 Function,即使传入的函数应具有类型为 Object 的单个参数,或类型为 ObjectStackTrace 的两个参数。

示例

#

以下代码生成此诊断消息,因为传递给 catchError 的闭包不接受任何参数,但该函数必须接受至少一个参数

dart
void f(Future<int> f) {
  f.catchError(() => 0);
}

以下代码产生此诊断,因为传递给 catchError 的闭包接受三个参数,但它不能有超过两个必需参数

dart
void f(Future<int> f) {
  f.catchError((one, two, three) => 0);
}

以下代码产生此诊断,因为即使传递给 catchError 的闭包接受一个参数,该闭包的类型也与 Object 不兼容

dart
void f(Future<int> f) {
  f.catchError((String error) => 0);
}

常见修复方法

#

更改传递给 catchError 的函数,使其具有一个或两个必需参数,并且参数具有必需的类型

dart
void f(Future<int> f) {
  f.catchError((Object error) => 0);
}

assert_in_redirecting_constructor

#

重定向构造函数不能有 'assert' 初始化列表。

描述

#

当重定向构造函数(重定向到同一类中的另一个构造函数的构造函数)的初始化列表中包含 assert 时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为未命名构造函数是一个重定向构造函数,并且还在初始化列表中包含 assert

dart
class C {
  C(int x) : assert(x > 0), this.name();
  C.name() {}
}

常见修复方法

#

如果不需要 assert,则删除它

dart
class C {
  C(int x) : this.name();
  C.name() {}
}

如果需要 assert,则将构造函数转换为工厂构造函数

dart
class C {
  factory C(int x) {
    assert(x > 0);
    return C.name();
  }
  C.name() {}
}

asset_directory_does_not_exist

#

资源目录“{0}”不存在。

描述

#

当资源列表包含引用不存在目录的值时,分析器会产生此诊断。

示例

#

假设目录 assets 不存在,以下代码会产生此诊断,因为它被列为包含资源的目录

yaml
name: example
flutter:
  assets:
    - assets/

常见修复方法

#

如果路径正确,则在该路径下创建一个目录。

如果路径不正确,则更改路径以匹配包含资源的目录的路径。

asset_does_not_exist

#

资源文件“{0}”不存在。

描述

#

当资源列表包含引用不存在文件的值时,分析器会产生此诊断。

示例

#

假设文件 doesNotExist.gif 不存在,以下代码会产生此诊断,因为它被列为资源

yaml
name: example
flutter:
  assets:
    - doesNotExist.gif

常见修复方法

#

如果路径正确,则在该路径下创建一个文件。

如果路径不正确,则更改路径以匹配包含资源的文件路径。

asset_field_not_list

#

'assets' 字段的值应为相对文件路径列表。

描述

#

assets 键的值不是列表时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 assets 键的值是一个字符串,但应为列表

yaml
name: example
flutter:
  assets: assets/

常见修复方法

#

更改资源列表的值,使其成为列表

yaml
name: example
flutter:
  assets:
    - assets/

asset_missing_path

#

资源映射条目必须包含 'path' 字段。

描述

#

当资源映射缺少 path 值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为资源映射缺少 path

yaml
name: example
flutter:
  assets:
    - flavors:
      - premium

常见修复方法

#

更改资源映射,使其包含一个带有字符串值(有效的 POSIX 风格文件路径)的 path 字段

yaml
name: example
flutter:
  assets:
    - path: assets/image.gif
      flavors:
      - premium

asset_not_string

#

资源必须是文件路径(字符串)。

描述

#

assets 列表包含不是字符串的值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 assets 列表包含一个映射

yaml
name: example
flutter:
  assets:
    - image.gif: true

常见修复方法

#

更改 assets 列表,使其仅包含有效的 POSIX 风格文件路径

yaml
name: example
flutter:
  assets:
    - assets/image.gif

asset_not_string_or_map

#

资源值必须是文件路径(字符串)或映射。

描述

#

当资源值不是字符串或映射时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为资源值是一个列表

yaml
name: example
flutter:
  assets:
    - [one, two, three]

常见修复方法

#

如果需要指定不仅仅是资源路径的信息,则将该值替换为一个带有 path 键(有效的 POSIX 风格文件路径)的映射

yaml
name: example
flutter:
  assets:
    - path: assets/image.gif
      flavors:
      - premium

如果只需要指定路径,则将该值替换为资源的路径(有效的 POSIX 风格文件路径)

yaml
name: example
flutter:
  assets:
    - assets/image.gif

asset_path_not_string

#

资源路径必须是文件路径(字符串)。

描述

#

当资源映射包含一个不是字符串的 path 值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为资源映射包含一个列表类型的 path

yaml
name: example
flutter:
  assets:
    - path: [one, two, three]
      flavors:
      - premium

常见修复方法

#

更改 asset 映射,使其包含一个字符串类型的 path 值(有效的 POSIX 风格文件路径)

yaml
name: example
flutter:
  assets:
    - path: image.gif
      flavors:
      - premium

assignment_of_do_not_store

#

“{0}”被标记为“doNotStore”,不应赋值给字段或顶层变量。

描述

#

当显式或隐式地被 doNotStore 注解标记的函数(包括方法和 getter)的值存储在字段或顶层变量中时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为函数 f 的值正在被存储在顶层变量 x

dart
import 'package:meta/meta.dart';

@doNotStore
int f() => 1;

var x = f();

常见修复方法

#

将对字段或变量的引用替换为对产生该值的函数的调用。

assignment_to_const

#

常量变量在初始化后不能被赋值。

描述

#

当分析器找到对具有 const 修饰符的顶层变量、静态字段或局部变量的赋值时,会产生此诊断。编译时常量的值在运行时不能被更改。

示例

#

以下代码产生此诊断,因为 c 即使带有 const 修饰符,也正在被赋值

dart
const c = 0;

void f() {
  c = 1;
  print(c);
}

常见修复方法

#

如果变量必须是可赋值的,则删除 const 修饰符

dart
var c = 0;

void f() {
  c = 1;
  print(c);
}

如果常量不应被更改,则删除赋值或使用局部变量代替对常量的引用

dart
const c = 0;

void f() {
  var v = 1;
  print(v);
}

assignment_to_final

#

“{0}”不能用作 setter,因为它被声明为 final。

描述

#

当分析器找到对 setter 的调用时,如果因为同名的字段被声明为 finalconst 而不存在 setter,则会产生此诊断。

示例

#

以下代码产生此诊断,因为 v 是 final 的

dart
class C {
  final v = 0;
}

f(C c) {
  c.v = 1;
}

常见修复方法

#

如果需要能够设置字段的值,则从字段中删除修饰符 final

dart
class C {
  int v = 0;
}

f(C c) {
  c.v = 1;
}

assignment_to_final_local

#

final 变量“{0}”只能设置一次。

描述

#

当声明为 final 的局部变量在初始化后被赋值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 x 是 final 的,因此在初始化后不能再被赋值

dart
void f() {
  final x = 0;
  x = 3;
  print(x);
}

常见修复方法

#

删除关键字 final,如果没有任何类型注解,则将其替换为 var

dart
void f() {
  var x = 0;
  x = 3;
  print(x);
}

assignment_to_final_no_setter

#

类“{1}”中没有名为“{0}”的 setter。

描述

#

当找到对 setter 的引用时,如果该类型没有定义 setter,但定义了同名的 getter,则分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 C 中没有名为 x 的 setter,但有一个名为 x 的 getter

dart
class C {
  int get x => 0;
  set y(int p) {}
}

void f(C c) {
  c.x = 1;
}

常见修复方法

#

如果要调用现有的 setter,则更正名称

dart
class C {
  int get x => 0;
  set y(int p) {}
}

void f(C c) {
  c.y = 1;
}

如果要调用 setter 但它尚不存在,则声明它

dart
class C {
  int get x => 0;
  set x(int p) {}
  set y(int p) {}
}

void f(C c) {
  c.x = 1;
}

assignment_to_function

#

函数不能被赋值。

描述

#

当函数名称出现在赋值表达式的左侧时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为对函数 f 的赋值无效

dart
void f() {}

void g() {
  f = () {};
}

常见修复方法

#

如果右侧应赋值给其他内容(例如局部变量),则更改左侧

dart
void f() {}

void g() {
  var x = () {};
  print(x);
}

如果目的是更改函数的实现,则定义一个函数值变量而不是函数

dart
void Function() f = () {};

void g() {
  f = () {};
}

assignment_to_method

#

方法不能被赋值。

描述

#

当赋值的目标是方法时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 f 不能被赋值,因为它是一个方法

dart
class C {
  void f() {}

  void g() {
    f = null;
  }
}

常见修复方法

#

重写代码,使其不包含对方法的赋值。

assignment_to_type

#

类型不能被赋值。

描述

#

当类型名称出现在赋值表达式的左侧时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为对类 C 的赋值无效

dart
class C {}

void f() {
  C = null;
}

常见修复方法

#

如果右侧应赋值给其他内容(例如局部变量),则更改左侧

dart
void f() {}

void g() {
  var c = null;
  print(c);
}

async_for_in_wrong_context

#

async for-in 循环只能在 async 函数中使用。

描述

#

当在函数或方法体中找到 async for-in 循环,但该函数或方法体未标记为 asyncasync* 时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 f 的主体未标记为 asyncasync*,但 f 包含一个 async for-in 循环

dart
void f(list) {
  await for (var e in list) {
    print(e);
  }
}

常见修复方法

#

如果函数应返回 Future,则将主体标记为 async

dart
Future<void> f(list) async {
  await for (var e in list) {
    print(e);
  }
}

如果函数应返回值的 Stream,则将主体标记为 async*

dart
Stream<void> f(list) async* {
  await for (var e in list) {
    print(e);
  }
}

如果函数应该是同步的,则删除循环之前的 await

dart
void f(list) {
  for (var e in list) {
    print(e);
  }
}

await_in_late_local_variable_initializer

#

'await' 表达式不能用于 'late' 局部变量的初始化器。

描述

#

当具有 late 修饰符的局部变量在其初始化器中使用 await 表达式时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 await 表达式用于 v 的初始化器中,而 v 是一个标记为 late 的局部变量

dart
Future<int> f() async {
  late var v = await 42;
  return v;
}

常见修复方法

#

如果可以重写初始化器以不使用 await,则重写它

dart
Future<int> f() async {
  late var v = 42;
  return v;
}

如果无法重写初始化器,则删除 late 修饰符

dart
Future<int> f() async {
  var v = await 42;
  return v;
}

await_of_incompatible_type

#

'await' 表达式不能用于扩展类型表达式,除非该扩展类型是 'Future' 的子类型。

描述

#

await 表达式中表达式的类型是扩展类型,并且该扩展类型不是 Future 的子类时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为扩展类型 E 不是 Future 的子类

dart
extension type E(int i) {}

void f(E e) async {
  await e;
}

常见修复方法

#

如果扩展类型定义正确,则删除 await

dart
extension type E(int i) {}

void f(E e) {
  e;
}

如果扩展类型旨在是可等待的,则将 Future(或 Future 的子类型)添加到 implements 子句中(如果尚无 implements 子句,则添加一个),并使表示类型匹配

dart
extension type E(Future<int> i) implements Future<int> {}

void f(E e) async {
  await e;
}

body_might_complete_normally

#

主体可能会正常完成,导致返回 'null',但返回类型“{0}”是潜在的非可空类型。

描述

#

当方法或函数的返回类型是潜在的非可空类型,但如果控制流到达函数末尾,则会隐式返回 null 时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为方法 m 在方法末尾插入了一个隐式返回 null,但该方法被声明为不返回 null

dart
class C {
  int m(int t) {
    print(t);
  }
}

以下代码产生此诊断,因为方法 m 在方法末尾插入了一个隐式返回 null,但由于类 C 可以用非可空类型参数实例化,因此该方法实际上被声明为不返回 null

dart
class C<T> {
  T m(T t) {
    print(t);
  }
}

常见修复方法

#

如果存在可以返回的合理值,则在方法末尾添加 return 语句

dart
class C<T> {
  T m(T t) {
    print(t);
    return t;
  }
}

如果方法不会到达隐式返回,则在方法末尾添加 throw

dart
class C<T> {
  T m(T t) {
    print(t);
    throw '';
  }
}

如果方法有意在末尾返回 null,则在方法末尾添加显式的 null 返回,并更改返回类型,使其可以有效返回 null

dart
class C<T> {
  T? m(T t) {
    print(t);
    return null;
  }
}

body_might_complete_normally_catch_error

#

此 'onError' 处理程序必须返回可赋值给“{0}”的值,但结束时未返回值。

描述

#

当传递给 Future.catchError 方法的 onError 参数的闭包需要返回一个非 null 值(因为 Future 的类型参数),但可能会隐式返回 null 时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为传递给 catchError 方法的闭包需要返回一个 int,但没有以显式的 return 结尾,导致它隐式返回 null

dart
void g(Future<int> f) {
  f.catchError((e, st) {});
}

常见修复方法

#

如果闭包有时应返回非 null 值,则向闭包添加显式的 return

dart
void g(Future<int> f) {
  f.catchError((e, st) {
    return -1;
  });
}

如果闭包应始终返回 null,则将 Future 的类型参数更改为 voidNull

dart
void g(Future<void> f) {
  f.catchError((e, st) {});
}

body_might_complete_normally_nullable

#

此函数具有可空返回类型“{0}”,但结束时未返回值。

描述

#

当方法或函数可以通过到达末尾而隐式返回 null 时,分析器会产生此诊断。虽然这是有效的 Dart 代码,但最好显式返回 null

示例

#

以下代码产生此诊断,因为函数 f 隐式返回 null

dart
String? f() {}

常见修复方法

#

如果有意返回 null,则使其显式化

dart
String? f() {
  return null;
}

如果函数应沿该路径返回非 null 值,则添加缺少的 return 语句

dart
String? f() {
  return '';
}

switch 成员上的 break 标签

#

break 标签解析为 'case' 或 'default' 语句。

描述

#

当 switch 语句内 case 子句中的 break 语句具有与另一个 case 子句关联的标签时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为标签 l0 的 case 子句关联

dart
void f(int i) {
  switch (i) {
    l: case 0:
      break;
    case 1:
      break l;
  }
}

常见修复方法

#

如果目的是将控制权转移到 switch 语句之后的语句,则从 break 语句中删除标签

dart
void f(int i) {
  switch (i) {
    case 0:
      break;
    case 1:
      break;
  }
}

如果目的是将控制权转移到不同的 case 代码块,则使用 continue 而不是 break

dart
void f(int i) {
  switch (i) {
    l: case 0:
      break;
    case 1:
      continue l;
  }
}

内置标识符作为类型

#

内置标识符“{0}”不能用作类型。

描述

#

当在期望类型名称的位置使用内置标识符时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 import 不能用作类型,因为它是一个内置标识符

dart
import<int> x;

常见修复方法

#

将内置标识符替换为有效类型的名称

dart
List<int> x;

声明中的内置标识符

#

内置标识符“{0}”不能用作前缀名称。

内置标识符“{0}”不能用作类型名称。

内置标识符“{0}”不能用作类型参数名称。

内置标识符“{0}”不能用作 typedef 名称。

内置标识符“{0}”不能用作扩展名称。

内置标识符“{0}”不能用作扩展类型名称。

描述

#

当类、扩展、mixin、typedef、类型参数或导入前缀的声明中使用的名称是内置标识符时,分析器会产生此诊断。内置标识符不能用于命名任何这些类型的声明。

示例

#

以下代码产生此诊断,因为 mixin 是一个内置标识符

dart
extension mixin on int {}

常见修复方法

#

为声明选择不同的名称。

case 代码块未终止

#

'case' 的最后一个语句应为 'break'、'continue'、'rethrow'、'return' 或 'throw'。

描述

#

case 代码块中的最后一个语句不是必需的终止符之一时,分析器会产生此诊断:breakcontinuerethrowreturnthrow

示例

#

以下代码产生此诊断,因为 case 代码块以赋值结尾

dart
void f(int x) {
  switch (x) {
    case 0:
      x += 2;
    default:
      x += 1;
  }
}

常见修复方法

#

添加必需的终止符之一

dart
void f(int x) {
  switch (x) {
    case 0:
      x += 2;
      break;
    default:
      x += 1;
  }
}

case 表达式类型实现了 equals 方法

#

switch case 表达式类型“{0}”不能重写 '==' 运算符。

描述

#

当关键字 case 后面的表达式类型具有 == 运算符的实现,而不是 Object 中的实现时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为关键字 case 后面的表达式 (C(0)) 的类型为 C,并且类 C 重写了 == 运算符

dart
class C {
  final int value;

  const C(this.value);

  bool operator ==(Object other) {
    return false;
  }
}

void f(C c) {
  switch (c) {
    case C(0):
      break;
  }
}

常见修复方法

#

如果没有充分的理由不这样做,则重写代码以使用 if-else 结构

dart
class C {
  final int value;

  const C(this.value);

  bool operator ==(Object other) {
    return false;
  }
}

void f(C c) {
  if (c == C(0)) {
    // ...
  }
}

如果无法重写 switch 语句,并且 == 的实现不是必需的,则删除它

dart
class C {
  final int value;

  const C(this.value);
}

void f(C c) {
  switch (c) {
    case C(0):
      break;
  }
}

如果无法重写 switch 语句,并且无法删除 == 的定义,则找到一些其他可以用来控制 switch 的值

dart
class C {
  final int value;

  const C(this.value);

  bool operator ==(Object other) {
    return false;
  }
}

void f(C c) {
  switch (c.value) {
    case 0:
      break;
  }
}

case 表达式类型不是 switch 表达式子类型

#

switch case 表达式类型“{0}”必须是 switch 表达式类型“{1}”的子类型。

描述

#

switch 语句中 case 后面的表达式的静态类型不是 switch 后面的表达式的静态类型的子类型时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 1int 类型,它不是 Strings 的类型)的子类型

dart
void f(String s) {
  switch (s) {
    case 1:
      break;
  }
}

常见修复方法

#

如果 case 表达式的值不正确,则更改 case 表达式,使其具有所需的类型

dart
void f(String s) {
  switch (s) {
    case '1':
      break;
  }
}

如果 case 表达式的值正确,则更改 switch 表达式以具有所需的类型

dart
void f(int s) {
  switch (s) {
    case 1:
      break;
  }
}

从可空类型到非空类型的强制转换总是失败

#

此类型转换将始终抛出异常,因为可空局部变量“{0}”未赋值。

描述

#

当具有可空类型的局部变量尚未赋值并被强制转换为非可空类型时,分析器会产生此诊断。由于变量尚未赋值,因此它具有默认值 null,从而导致类型转换抛出异常。

示例

#

以下代码产生此诊断,因为变量 x 在已知值为 null 时被强制转换为非可空类型 (int)

dart
void f() {
  num? x;
  x as int;
  print(x);
}

常见修复方法

#

如果希望变量在类型转换之前具有值,则添加初始化器或赋值

dart
void f() {
  num? x = 3;
  x as int;
  print(x);
}

如果变量不应被赋值,则删除类型转换

dart
void f() {
  num? x;
  print(x);
}

从 null 到非空类型的强制转换总是失败

#

此类型转换始终抛出异常,因为表达式始终求值为 'null'。

描述

#

当类型为 Null 的表达式被强制转换为非可空类型时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为已知 n 始终为 null,但它正在被强制转换为非可空类型

dart
void f(Null n) {
  n as int;
}

常见修复方法

#

删除不必要的类型转换

dart
void f(Null n) {
  n;
}

强制转换为非类型

#

名称“{0}”不是类型,因此不能在 'as' 表达式中使用。

描述

#

当强制转换表达式中 as 后面的名称被定义为类型以外的其他内容时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 x 是一个变量,而不是类型

dart
num x = 0;
int y = x as x;

常见修复方法

#

将名称替换为类型的名称

dart
num x = 0;
int y = x as int;

类用作 mixin

#

类“{0}”不能用作 mixin,因为它既不是 mixin 类也不是 mixin。

描述

#

当既不是 mixin class 也不是 mixin 的类在 with 子句中使用时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为类 M 正在用作 mixin,但它未定义为 mixin class

dart
class M {}
class C with M {}

常见修复方法

#

如果该类可以是纯 mixin,则将 class 更改为 mixin

dart
mixin M {}
class C with M {}

如果该类需要既是类又是 mixin,则添加 mixin

dart
mixin class M {}
class C with M {}

来自延迟库的集合元素

#

来自延迟库的常量值不能用作 'const' 映射字面量中的键。

来自延迟库的常量值不能用作 'const' 构造函数中的值。

来自延迟库的常量值不能用作 'const' 列表字面量中的值。

来自延迟库的常量值不能用作 'const' 映射字面量中的值。

来自延迟库的常量值不能用作 'const' set 字面量中的值。

描述

#

当显式(因为它以 const 关键字为前缀)或隐式(因为它出现在常量上下文中)为常量的集合字面量包含的值在延迟导入的库中声明时,分析器会产生此诊断。常量在编译时求值,而来自延迟库的值在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

给定一个文件 a.dart,其中定义了常量 zero

dart
const zero = 0;

以下代码产生此诊断,因为常量列表字面量包含使用 deferred 导入的 a.zero

dart
import 'a.dart' deferred as a;

var l = const [a.zero];

常见修复方法

#

如果集合字面量不需要是常量,则删除 const 关键字

dart
import 'a.dart' deferred as a;

var l = [a.zero];

如果集合需要是常量,并且必须引用导入的常量,则从导入中删除关键字 deferred

dart
import 'a.dart' as a;

var l = const [a.zero];

如果不需要引用常量,则将其替换为合适的值

dart
var l = const [0];

复合类型实现了 Finalizable 接口

#

类“{0}”不能实现 Finalizable。

描述

#

StructUnion 的子类实现 Finalizable 时,分析器会产生此诊断。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码产生此诊断,因为类 S 实现了 Finalizable

dart
import 'dart:ffi';

final class S extends Struct implements Finalizable {
  external Pointer notEmpty;
}

常见修复方法

#

尝试从类中删除 implements 子句

dart
import 'dart:ffi';

final class S extends Struct {
  external Pointer notEmpty;
}

具体类具有枚举超接口

#

具体类不能将 'Enum' 作为超接口。

描述

#

当具体类间接将类 Enum 作为超接口时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为具体类 B 由于实现了 A 而将 Enum 作为超接口

dart
abstract class A implements Enum {}

class B implements A {}

常见修复方法

#

如果实现的类不是您想要实现的类,则更改它

dart
abstract class A implements Enum {}

class B implements C {}

class C {}

如果可以将实现的类更改为不实现 Enum,则这样做

dart
abstract class A {}

class B implements A {}

如果无法将实现的类更改为不实现 Enum,则从 implements 子句中删除它

dart
abstract class A implements Enum {}

class B {}

具有抽象成员的具体类

#

“{0}”必须有方法体,因为“{1}”不是抽象的。

描述

#

当在具体类中找到没有具体实现的成员时,分析器会产生此诊断。具体类不允许包含抽象成员。

示例

#

以下代码产生此诊断,因为 m 是一个抽象方法,但 C 不是一个抽象类

dart
class C {
  void m();
}

常见修复方法

#

如果创建类的实例是有效的,请为成员提供实现

dart
class C {
  void m() {}
}

如果创建类的实例无效,则将类标记为抽象类

dart
abstract class C {
  void m();
}

构造函数和静态成员冲突

#

“{0}”不能同时用作此类中的构造函数和静态字段的名称。

“{0}”不能同时用作此类中的构造函数和静态 getter 的名称。

“{0}”不能同时用作此类中的构造函数和静态方法的名称。

“{0}”不能同时用作此类中的构造函数和静态 setter 的名称。

描述

#

当命名构造函数和静态方法或静态字段具有相同的名称时,分析器会产生此诊断。两者都使用类的名称访问,因此具有相同的名称会使引用变得模糊不清。

示例

#

以下代码产生此诊断,因为静态字段 foo 和命名构造函数 foo 具有相同的名称

dart
class C {
  C.foo();
  static int foo = 0;
}

以下代码产生此诊断,因为静态方法 foo 和命名构造函数 foo 具有相同的名称

dart
class C {
  C.foo();
  static void foo() {}
}

常见修复方法

#

重命名成员或构造函数。

泛型接口冲突

#

{0}“{1}”不能同时实现“{2}”和“{3}”,因为类型参数不同。

描述

#

当一个类尝试多次实现泛型接口,并且类型参数的值不相同时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 C 被定义为同时实现 I<int>(因为它扩展了 A)和 I<String>(因为它实现了 B),但 intString 不是相同的类型

dart
class I<T> {}
class A implements I<int> {}
class B implements I<String> {}
class C extends A implements B {}

常见修复方法

#

重新设计类型层次结构以避免这种情况。例如,您可以使一个或两个继承的类型成为泛型,以便 C 可以为两个类型参数指定相同的类型

dart
class I<T> {}
class A<S> implements I<S> {}
class B implements I<String> {}
class C extends A<String> implements B {}

类型变量和容器冲突

#

“{0}”不能同时用作类型参数和定义类型参数的类的名称。

“{0}”不能同时用作类型参数和定义类型参数的枚举的名称。

“{0}”不能同时用作类型参数和定义类型参数的扩展的名称。

“{0}”不能同时用作类型参数和定义类型参数的扩展类型的名称。

“{0}”不能同时用作类型参数和定义类型参数的 mixin 的名称。

描述

#

当类、mixin 或扩展声明声明的类型参数与声明它的类、mixin 或扩展的名称相同时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为类型参数 C 与它所属的类 C 具有相同的名称

dart
class C<C> {}

常见修复方法

#

重命名类型参数,或类、mixin 或扩展

dart
class C<T> {}

类型变量和成员冲突

#

“{0}”不能同时用作类型参数和此类中成员的名称。

“{0}”不能同时用作类型参数和此枚举中成员的名称。

“{0}”不能同时用作类型参数和此扩展类型中成员的名称。

“{0}”不能同时用作类型参数和此扩展中成员的名称。

“{0}”不能同时用作类型参数和此 mixin 中成员的名称。

描述

#

当类、mixin 或扩展声明声明的类型参数与声明它的类、mixin 或扩展的成员之一的名称相同时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为类型参数 T 与字段 T 具有相同的名称

dart
class C<T> {
  int T = 0;
}

常见修复方法

#

重命名类型参数或与其冲突的成员

dart
class C<T> {
  int total = 0;
}

常量模式永远不匹配值类型

#

匹配的值类型“{0}”永远不能等于此类型为“{1}”的常量。

描述

#

当常量模式永远无法匹配它正在测试的值时,分析器会产生此诊断,因为已知常量的类型永远无法匹配值的类型。

示例

#

以下代码产生此诊断,因为常量模式 (true) 的类型为 bool,而被匹配的值 (x) 的类型为 int,并且布尔值永远不能匹配整数

dart
void f(int x) {
  if (x case true) {}
}

常见修复方法

#

如果值的类型正确,则重写模式以使其兼容

dart
void f(int x) {
  if (x case 3) {}
}

如果常量的类型正确,则重写值以使其兼容

dart
void f(bool x) {
  if (x case true) {}
}

带有非常量表达式的常量模式

#

常量模式的表达式必须是有效的常量。

描述

#

当常量模式的表达式不是有效的常量时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为常量模式 i 不是常量

dart
void f(int e, int i) {
  switch (e) {
    case i:
      break;
  }
}

常见修复方法

#

如果应该匹配的值是已知的,则将表达式替换为常量

dart
void f(int e, int i) {
  switch (e) {
    case 0:
      break;
  }
}

如果应该匹配的值是未知的,则重写代码以不使用模式

dart
void f(int e, int i) {
  if (e == i) {}
}

const 构造函数参数类型不匹配

#

类型为“{0}”的值不能赋值给 const 构造函数中类型为“{1}”的参数。

描述

#

当常量值的运行时类型不能赋值给常量构造函数参数的静态类型时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 i 的运行时类型为 int,它不能赋值给 s 的静态类型

dart
class C {
  final String s;

  const C(this.s);
}

const dynamic i = 0;

void f() {
  const C(i);
}

常见修复方法

#

将正确类型的值传递给构造函数

dart
class C {
  final String s;

  const C(this.s);
}

const dynamic i = 0;

void f() {
  const C('$i');
}

const 构造函数,字段由非常量值初始化

#

无法定义 'const' 构造函数,因为字段“{0}”是用非常量值初始化的。

描述

#

当构造函数具有关键字 const,但类中的字段被初始化为非常量值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为字段 s 被初始化为非常量值

dart
String x = '3';
class C {
  final String s = x;
  const C();
}

常见修复方法

#

如果字段可以初始化为常量值,则将初始化器更改为常量表达式

dart
class C {
  final String s = '3';
  const C();
}

如果字段无法初始化为常量值,则从构造函数中删除关键字 const

dart
String x = '3';
class C {
  final String s = x;
  C();
}

带有非常量 super 调用的 const 构造函数

#

常量构造函数不能调用“{0}”的非常量超类构造函数。

描述

#

当标记为 const 的构造函数调用其超类中未标记为 const 的构造函数时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 B 中的 const 构造函数调用了类 A 中的构造函数 nonConst,而超类构造函数不是 const 构造函数

dart
class A {
  const A();
  A.nonConst();
}

class B extends A {
  const B() : super.nonConst();
}

常见修复方法

#

如果调用当前正在调用的超类构造函数不是必要的,则调用超类中的常量构造函数

dart
class A {
  const A();
  A.nonConst();
}

class B extends A {
  const B() : super();
}

如果当前构造函数必须被调用,并且您可以修改它,则将 const 添加到超类中的构造函数

dart
class A {
  const A();
  const A.nonConst();
}

class B extends A {
  const B() : super.nonConst();
}

如果当前构造函数必须被调用,并且您无法修改它,则从子类中的构造函数中删除 const

dart
class A {
  const A();
  A.nonConst();
}

class B extends A {
  B() : super.nonConst();
}

带有非 final 字段的 const 构造函数

#

无法为具有非 final 字段的类定义 const 构造函数。

描述

#

当构造函数被标记为 const 构造函数,但该构造函数定义在至少有一个非 final 实例字段(直接或通过继承)的类中时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为字段 x 不是 final 的

dart
class C {
  int x;

  const C(this.x);
}

常见修复方法

#

如果可以将所有字段标记为 final,则这样做

dart
class C {
  final int x;

  const C(this.x);
}

如果无法将所有字段标记为 final,则从构造函数中删除关键字 const

dart
class C {
  int x;

  C(this.x);
}

const 延迟类

#

延迟类不能使用 'const' 创建。

描述

#

当使用延迟导入的库中的类来创建 const 对象时,分析器会生成此诊断。常量在编译时求值,而来自延迟库的类在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

以下代码会生成此诊断,因为它尝试创建来自延迟库的类的 const 实例

dart
import 'dart:convert' deferred as convert;

const json2 = convert.JsonCodec();

常见修复方法

#

如果对象不需要是常量,则更改代码,以便创建非常量实例

dart
import 'dart:convert' deferred as convert;

final json2 = convert.JsonCodec();

如果对象必须是常量,则从导入指令中删除 deferred

dart
import 'dart:convert' as convert;

const json2 = convert.JsonCodec();

const 值用非常量值初始化

#

Const 变量必须使用常量值初始化。

描述

#

当将一个静态未知为常量的值分配给声明为 const 变量的变量时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 x 未声明为 const

dart
var x = 0;
const y = x;

常见修复方法

#

如果被赋值的值可以声明为 const,则更改声明

dart
const x = 0;
const y = x;

如果该值不能声明为 const,则从变量中删除 const 修饰符,可以考虑使用 final 代替

dart
var x = 0;
final y = x;

const 值用来自延迟库的非常量值初始化

#

来自延迟库的常量值不能用于初始化 'const' 变量。

描述

#

当使用从延迟导入的库中的 const 变量初始化 const 变量时,分析器会生成此诊断。常量在编译时求值,而来自延迟库的值在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

以下代码会生成此诊断,因为变量 pi 正在使用来自库 dart:math 的常量 math.pi 进行初始化,而 dart:math 被作为延迟库导入

dart
import 'dart:math' deferred as math;

const pi = math.pi;

常见修复方法

#

如果您需要引用来自导入库的常量的值,则删除关键字 deferred

dart
import 'dart:math' as math;

const pi = math.pi;

如果您不需要引用导入的常量,则删除引用

dart
const pi = 3.14;

const 实例字段

#

只有静态字段可以声明为 const。

描述

#

当实例字段被标记为 const 时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 f 是一个实例字段

dart
class C {
  const int f = 3;
}

常见修复方法

#

如果该字段需要是实例字段,则删除关键字 const,或将其替换为 final

dart
class C {
  final int f = 3;
}

如果该字段确实应该是 const 字段,则将其设为静态字段

dart
class C {
  static const int f = 3;
}

const Map 键不是原始相等性

#

常量 Map 中键的类型不能重写 '==' 运算符或 'hashCode',但类 '{0}' 却重写了。

描述

#

当用作常量 Map 字面量中键的对象的类实现了 == 运算符、getter hashCode 或两者都实现时,分析器会生成此诊断。常量 Map 的实现同时使用 == 运算符和 hashCode getter,因此除从 Object 继承的实现之外的任何实现都需要在编译时执行任意代码,这是不支持的。

示例

#

以下代码会生成此诊断,因为常量 Map 包含一个键,其类型为 C,并且类 C 重写了 == 的实现

dart
class C {
  const C();

  bool operator ==(Object other) => true;
}

const map = {C() : 0};

以下代码会生成此诊断,因为常量 Map 包含一个键,其类型为 C,并且类 C 重写了 hashCode 的实现

dart
class C {
  const C();

  int get hashCode => 3;
}

const map = {C() : 0};

常见修复方法

#

如果可以从类中删除 ==hashCode 的实现,请这样做

dart
class C {
  const C();
}

const map = {C() : 0};

如果无法从类中删除 ==hashCode 的实现,则使 Map 变为非常量

dart
class C {
  const C();

  bool operator ==(Object other) => true;
}

final map = {C() : 0};

const 未初始化

#

常量 '{0}' 必须被初始化。

描述

#

当声明为常量的变量没有初始化器时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 c 未被初始化

dart
const c;

常见修复方法

#

添加一个初始化器

dart
const c = 'c';

const Set 元素不是原始相等性

#

(之前称为 const_set_element_type_implements_equals)

常量 Set 中的元素不能重写 '==' 运算符或 'hashCode',但类型 '{0}' 却重写了。

描述

#

当用作常量 Set 字面量中元素的对象的类实现了 == 运算符、getter hashCode 或两者都实现时,分析器会生成此诊断。常量 Set 的实现同时使用 == 运算符和 hashCode getter,因此除从 Object 继承的实现之外的任何实现都需要在编译时执行任意代码,这是不支持的。

示例

#

以下代码会生成此诊断,因为常量 Set 包含一个元素,其类型为 C,并且类 C 重写了 == 的实现

dart
class C {
  const C();

  bool operator ==(Object other) => true;
}

const set = {C()};

以下代码会生成此诊断,因为常量 Set 包含一个元素,其类型为 C,并且类 C 重写了 hashCode 的实现

dart
class C {
  const C();

  int get hashCode => 3;
}

const map = {C()};

常见修复方法

#

如果可以从类中删除 ==hashCode 的实现,请这样做

dart
class C {
  const C();
}

const set = {C()};

如果无法从类中删除 ==hashCode 的实现,则使 Set 变为非常量

dart
class C {
  const C();

  bool operator ==(Object other) => true;
}

final set = {C()};

const 展开应为 List 或 Set

#

在此扩展中应为 List 或 Set。

描述

#

当常量 List 或 Set 中扩展运算符的表达式求值为 List 或 Set 以外的其他内容时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 list1 的值为 null,它既不是 List 也不是 Set

dart
const dynamic list1 = 42;
const List<int> list2 = [...list1];

常见修复方法

#

将表达式更改为求值为常量 List 或常量 Set 的内容

dart
const dynamic list1 = [42];
const List<int> list2 = [...list1];

const 展开应为 Map

#

在此扩展中应为 Map。

描述

#

当常量 Map 中扩展运算符的表达式求值为 Map 以外的其他内容时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 map1 的值为 null,它不是 Map

dart
const dynamic map1 = 42;
const Map<String, int> map2 = {...map1};

常见修复方法

#

将表达式更改为求值为常量 Map 的内容

dart
const dynamic map1 = {'answer': 42};
const Map<String, int> map2 = {...map1};

const 中使用了非常量值

#

被调用的构造函数不是 const 构造函数。

描述

#

当使用关键字 const 调用未标记为 const 的构造函数时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 A 中的构造函数不是 const 构造函数

dart
class A {
  A();
}

A f() => const A();

常见修复方法

#

如果希望并且可能使类成为常量类(通过使该类的所有字段,包括继承的字段,都为 final),则将关键字 const 添加到构造函数

dart
class A {
  const A();
}

A f() => const A();

否则,删除关键字 const

dart
class A {
  A();
}

A f() => A();

const 中使用了非常量参数

#

常量创建的参数必须是常量表达式。

描述

#

当使用非常量表达式的参数调用 const 构造函数时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 i 不是常量

dart
class C {
  final int i;
  const C(this.i);
}
C f(int i) => const C(i);

常见修复方法

#

要么使所有参数都成为常量表达式,要么删除 const 关键字以使用构造函数的非常量形式

dart
class C {
  final int i;
  const C(this.i);
}
C f(int i) => C(i);

带有类型参数的 const

#

常量构造函数拆分不能使用类型形参作为类型实参。

常量创建不能使用类型形参作为类型实参。

常量函数拆分不能使用类型形参作为类型实参。

描述

#

当在构造函数的 const 调用中使用类型形参作为类型实参时,分析器会生成此诊断。这是不允许的,因为类型形参的值(运行时将使用的实际类型)在编译时是未知的。

示例

#

以下代码会生成此诊断,因为在创建常量时,类型形参 T 被用作类型实参

dart
class C<T> {
  const C();
}

C<T> newC<T>() => const C<T>();

常见修复方法

#

如果将用于类型形参的类型可以在编译时知道,则删除类型形参的使用

dart
class C<T> {
  const C();
}

C<int> newC() => const C<int>();

如果将用于类型形参的类型在运行时才能知道,则删除关键字 const

dart
class C<T> {
  const C();
}

C<T> newC<T>() => C<T>();

continue 标签无效

#

(之前称为 continue_label_on_switch)

'continue' 语句中使用的标签必须在循环或 switch 成员上定义。

描述

#

continue 语句中的标签解析为 switch 语句上的标签时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为用于标记 switch 语句的标签 lcontinue 语句中使用

dart
void f(int i) {
  l: switch (i) {
    case 0:
      continue l;
  }
}

常见修复方法

#

寻找实现所需控制流的不同方法;例如,通过引入一个重新执行 switch 语句的循环。

创建 struct 或 union

#

'Struct' 和 'Union' 的子类由本机内存支持,不能通过生成构造函数实例化。

描述

#

当使用生成构造函数实例化 StructUnion 的子类时,分析器会生成此诊断。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断,因为类 C 正在使用生成构造函数实例化

dart
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  external int a;
}

void f() {
  C();
}

常见修复方法

#

如果需要分配类描述的结构,请使用 ffi 包来执行此操作

dart
import 'dart:ffi';
import 'package:ffi/ffi.dart';

final class C extends Struct {
  @Int32()
  external int a;
}

void f() {
  final pointer = calloc.allocate<C>(4);
  final c = pointer.ref;
  print(c);
  calloc.free(pointer);
}

使用非类型创建

#

名称 '{0}' 不是类。

描述

#

当使用 newconst 的实例创建指定了未定义为类的名称时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 f 是函数而不是类

dart
int f() => 0;

void g() {
  new f();
}

常见修复方法

#

如果应创建类,则将无效名称替换为有效类的名称

dart
int f() => 0;

void g() {
  new Object();
}

如果该名称是函数的名称,并且您希望调用该函数,则删除 newconst 关键字

dart
int f() => 0;

void g() {
  f();
}

死代码

#

死代码。

死代码:已赋值的通配符变量被标记为 late 且永远不会被引用,因此该初始化器将永远不会被求值。

描述

#

当找到将不会被执行的代码时,分析器会生成此诊断,因为执行永远不会到达该代码。

示例

#

以下代码会生成此诊断,因为 print 的调用发生在函数返回之后

dart
void f() {
  return;
  print('here');
}

常见修复方法

#

如果不需要该代码,则将其删除

dart
void f() {
  return;
}

如果代码需要被执行,则将代码移动到将被执行的位置

dart
void f() {
  print('here');
  return;
}

或者,重写之前的代码,使其可以被到达

dart
void f({bool skipPrinting = true}) {
  if (skipPrinting) {
    return;
  }
  print('here');
}

跟随 catch 代码块的死代码 catch 代码块

#

死代码:在 'catch (e)' 或 'on Object catch (e)' 之后的 Catch 子句永远不会被到达。

描述

#

当找到无法执行的 catch 子句时,分析器会生成此诊断,因为它在 catch (e)on Object catch (e) 形式的 catch 子句之后。将选择与抛出的对象匹配的第一个 catch 子句,并且这两种形式都将匹配任何对象,因此不会选择它们之后的任何 catch 子句。

示例

#

以下代码生成此诊断消息:

dart
void f() {
  try {
  } catch (e) {
  } on String {
  }
}

常见修复方法

#

如果该子句应该是可选择的,则将该子句移动到通用子句之前

dart
void f() {
  try {
  } on String {
  } catch (e) {
  }
}

如果该子句不需要是可选择的,则将其删除

dart
void f() {
  try {
  } catch (e) {
  }
}

catch 子类型上的死代码

#

死代码:此 on-catch 代码块将不会被执行,因为 '{0}' 是 '{1}' 的子类型,因此已被捕获。

描述

#

当找到无法执行的 catch 子句时,分析器会生成此诊断,因为它在捕获相同类型或子句类型超类型的 catch 子句之后。将选择与抛出的对象匹配的第一个 catch 子句,并且较早的子句始终匹配高亮显示的子句可匹配的任何内容,因此永远不会选择高亮显示的子句。

示例

#

以下代码生成此诊断消息:

dart
void f() {
  try {
  } on num {
  } on int {
  }
}

常见修复方法

#

如果该子句应该是可选择的,则将该子句移动到通用子句之前

dart
void f() {
  try {
  } on int {
  } on num {
  }
}

如果该子句不需要是可选择的,则将其删除

dart
void f() {
  try {
  } on num {
  }
}

死的空感知表达式

#

左操作数不能为 null,因此永远不会执行右操作数。

描述

#

分析器在两种情况下会生成此诊断。

第一种情况是当 ?? 运算符的左操作数不能为 null 时。仅当左操作数的值为 null 时,才会对右操作数求值,并且由于左操作数不能为 null,因此永远不会对右操作数求值。

第二种情况是当使用 ??= 运算符的赋值的左侧不能为 null 时。仅当左侧的值为 null 时,才会对右侧求值,并且由于左侧不能为 null,因此永远不会对右侧求值。

示例

#

以下代码会生成此诊断,因为 x 不能为 null

dart
int f(int x) {
  return x ?? 0;
}

以下代码会生成此诊断,因为 f 不能为 null

dart
class C {
  int f = -1;

  void m(int x) {
    f ??= x;
  }
}

常见修复方法

#

如果针对 ?? 运算符报告了诊断,则删除 ?? 运算符和右操作数

dart
int f(int x) {
  return x;
}

如果针对赋值报告了诊断,并且不需要赋值,则删除赋值

dart
class C {
  int f = -1;

  void m(int x) {
  }
}

如果需要赋值,但应基于不同的条件,则重写代码以使用 = 和不同的条件

dart
class C {
  int f = -1;

  void m(int x) {
    if (f < 0) {
      f = x;
    }
  }
}

默认 List 构造函数

#

启用空安全时,默认的 'List' 构造函数不可用。

描述

#

当分析器在已选择加入空安全的代码中找到对类 List 的默认构造函数的使用时,会生成此诊断。

示例

#

假设以下代码已选择加入空安全,则它会生成此诊断,因为它使用了默认的 List 构造函数

dart
var l = List<int>();

常见修复方法

#

如果未提供初始大小,则将代码转换为使用 List 字面量

dart
var l = <int>[];

如果需要提供初始大小,并且元素有一个合理的初始值,则使用 List.filled

dart
var l = List.filled(3, 0);

如果需要提供初始大小,但每个元素都需要计算,则使用 List.generate

dart
var l = List.generate(3, (i) => i);

函数类型中的默认值

#

函数类型中的参数不能具有默认值。

描述

#

当与参数关联的函数类型包含具有默认值的可选参数时,分析器会生成此诊断。这是不允许的,因为参数的默认值不是函数类型的一部分,因此包含它们不会提供任何价值。

示例

#

以下代码会生成此诊断,因为参数 p 具有默认值,即使它是参数 g 类型的一部分

dart
void f(void Function([int p = 0]) g) {
}

常见修复方法

#

从函数类型的参数中删除默认值

dart
void f(void Function([int p]) g) {
}

重定向工厂构造函数中的默认值

#

在重定向到另一个构造函数的工厂构造函数中,不允许使用默认值。

描述

#

当重定向到另一个构造函数的工厂构造函数为可选参数指定默认值时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 A 中的工厂构造函数的可选参数 x 具有默认值

dart
class A {
  factory A([int x = 0]) = B;
}

class B implements A {
  B([int x = 1]) {}
}

常见修复方法

#

从工厂构造函数中删除默认值

dart
class A {
  factory A([int x]) = B;
}

class B implements A {
  B([int x = 1]) {}
}

请注意,此修复可能会更改省略可选参数时使用的值。如果发生这种情况,并且如果该更改有问题,请考虑使工厂方法中的可选参数成为必需参数

dart
class A {
 factory A(int x) = B;
}

class B implements A {
  B([int x = 1]) {}
}

必需参数上的默认值

#

必需的命名参数不能具有默认值。

描述

#

当命名参数同时具有 required 修饰符和默认值时,分析器会生成此诊断。如果参数是必需的,则始终在调用站点提供参数的值,因此永远不会使用默认值。

示例

#

以下代码会生成此诊断

dart
void log({required String message = 'no message'}) {}

常见修复方法

#

如果参数确实是必需的,则删除默认值

dart
void log({required String message}) {}

如果参数不是始终必需的,则删除 required 修饰符

dart
void log({String message = 'no message'}) {}

扩展的延迟导入

#

延迟库的导入必须隐藏所有扩展。

描述

#

当使用延迟导入的库声明了在导入库中可见的扩展时,分析器会生成此诊断。扩展方法在编译时解析,并且来自延迟库的扩展在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

给定一个定义了命名扩展的文件 a.dart

dart
class C {}

extension E on String {
  int get size => length;
}

以下代码会生成此诊断,因为命名扩展对库可见

dart
import 'a.dart' deferred as a;

void f() {
  a.C();
}

常见修复方法

#

如果库必须作为 deferred 导入,则添加一个列出被引用名称的 show 子句,或添加一个列出所有命名扩展的 hide 子句。添加 show 子句看起来像这样

dart
import 'a.dart' deferred as a show C;

void f() {
  a.C();
}

添加 hide 子句看起来像这样

dart
import 'a.dart' deferred as a hide E;

void f() {
  a.C();
}

使用第一个修复,好处是如果将新扩展添加到导入的库中,则这些扩展不会导致生成诊断。

如果库不需要作为 deferred 导入,或者如果需要使用其中声明的扩展方法,则删除关键字 deferred

dart
import 'a.dart' as a;

void f() {
  a.C();
}

明确未赋值的 late 局部变量

#

此时,late 局部变量 '{0}' 肯定是未赋值的。

描述

#

确定性赋值分析显示标记为 late 的局部变量在赋值之前被读取时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 x 在读取之前未被赋值

dart
void f(bool b) {
  late int x;
  print(x);
}

常见修复方法

#

在从变量读取之前为其赋值

dart
void f(bool b) {
  late int x;
  x = b ? 1 : 0;
  print(x);
}

dependencies 字段不是 Map

#

'{0}' 字段的值应为 Map。

描述

#

dependenciesdev_dependencies 键的值不是 Map 时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为顶级 dependencies 键的值是 List

yaml
name: example
dependencies:
  - meta

常见修复方法

#

使用 Map 作为 dependencies 键的值

yaml
name: example
dependencies:
  meta: ^1.0.2

已弃用的冒号用于默认值

#

使用冒号作为默认值之前的分隔符已弃用,并且在语言版本 3.0 及更高版本中将不再支持。

描述

#

当使用冒号 (:) 作为可选命名参数的默认值之前的分隔符时,分析器会生成此诊断。虽然允许使用此语法,但它已被弃用,建议使用等号 (=) 代替。

示例

#

以下代码会生成此诊断,因为在可选参数 i 的默认值之前使用了冒号

dart
void f({int i : 0}) {}

常见修复方法

#

将冒号替换为等号。

dart
void f({int i = 0}) {}

已弃用的导出使用

#

间接导入 '{0}' 的能力已弃用。

描述

#

当一个库从第二个库导入名称,而第二个库从第三个库导出该名称但已指示将来不会导出第三个库时,分析器会生成此诊断。

示例

#

给定一个定义了类 A 的库 a.dart

dart
class A {}

以及第二个库 b.dart,它导出了 a.dart,但已将导出标记为已弃用

dart
import 'a.dart';

@deprecated
export 'a.dart';

以下代码会生成此诊断,因为类 A 在未来的某个版本中将不会从 b.dart 导出

dart
import 'b.dart';

A? a;

常见修复方法

#

如果该名称可以从您可以导入的不同库中获得,则将现有导入替换为该库的导入(或者如果您仍然需要旧的导入,则为定义库添加导入)

dart
import 'a.dart';

A? a;

如果该名称不可用,请查找库作者的说明或直接与他们联系,以了解如何更新您的代码。

已弃用的字段

#

'{0}' 字段不再使用,可以删除。

描述

#

当在 pubspec.yaml 文件中使用已弃用的键时,分析器会生成此诊断。未使用的键会占用空间,并且可能暗示不再有效的语义。

示例

#

以下代码会生成此诊断,因为 author 键不再使用

dart
name: example
author: 'Dash'

常见修复方法

#

删除已弃用的键

dart
name: example

已弃用的成员使用

#

'{0}' 已弃用,不应使用。

'{0}' 已弃用,不应使用。 {1}

描述

#

当在不同的包中使用已弃用的库或类成员时,分析器会生成此诊断。

示例

#

如果类 C 中的方法 m 使用 @deprecated 注释,则以下代码会生成此诊断

dart
void f(C c) {
  c.m();
}

常见修复方法

#

使用 @deprecated 注释的声明的文档应指示使用什么代码来代替已弃用的代码。

来自同一包的已弃用的成员使用

#

'{0}' 已弃用,不应使用。

'{0}' 已弃用,不应使用。 {1}

描述

#

当在声明已弃用的库成员或类成员的同一包中使用它时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 x 已弃用

dart
@deprecated
var x = 0;
var y = x;

常见修复方法

#

修复方法取决于已弃用的内容以及替换项是什么。已弃用声明的文档应指示使用什么代码来代替已弃用的代码。

注释引用中已弃用的 new 关键字

#

在注释引用中使用 'new' 关键字已弃用。

描述

#

当注释引用(文档注释中方括号括起来的声明名称)使用关键字 new 来引用构造函数时,分析器会生成此诊断。这种形式已被弃用。

示例

#

以下代码会生成此诊断,因为正在使用 new C 引用未命名的构造函数

dart
/// See [new C].
class C {
  C();
}

以下代码会生成此诊断,因为正在使用 new C.c 引用名为 c 的构造函数

dart
/// See [new C.c].
class C {
  C.c();
}

常见修复方法

#

如果您正在引用命名构造函数,请删除关键字 new

dart
/// See [C.c].
class C {
  C.c();
}

如果您正在引用未命名的构造函数,请删除关键字 new 并在类名后附加 .new

dart
/// See [C.new].
class C {
  C.c();
}

已弃用的函数子类型

#

扩展 'Function' 已弃用。

实现 'Function' 没有效果。

混入 'Function' 已弃用。

描述

#

当类 Function 在类或 mixin 的 extendsimplementswith 子句中使用时,分析器会生成此诊断。以这种方式使用类 Function 没有语义价值,因此它实际上是死代码。

示例

#

以下代码会生成此诊断,因为 Function 被用作 F 的超类

dart
class F extends Function {}

常见修复方法

#

Function 所在的任何子句中删除类 Function,如果 Function 是子句中唯一的类型,则删除整个子句

dart
class F {}

不允许的类型实例化表达式

#

只有泛型类型、泛型函数、泛型实例方法或泛型构造函数可以具有类型实参。

描述

#

当具有值(该值不是允许值类型之一)的表达式后跟类型实参时,分析器会生成此诊断。允许的值类型为

  • 泛型类型,
  • 泛型构造函数,以及
  • 泛型函数,包括顶级函数、静态和实例成员以及局部函数。

示例

#

以下代码会生成此诊断,因为 i 是一个顶级变量,它不是允许的情况之一

dart
int i = 1;

void f() {
  print(i<int>);
}

常见修复方法

#

如果引用的值是正确的,则删除类型实参

dart
int i = 1;

void f() {
  print(i);
}

除法优化

#

运算符 x ~/ y 比 (x / y).toInt() 更有效。

描述

#

当使用 toInt 将两个数字的除法结果转换为整数时,分析器会生成此诊断。Dart 有一个内置的整数除法运算符,它既更有效又更简洁。

示例

#

以下代码会生成此诊断,因为使用 toIntxy 相除的结果转换为整数

dart
int divide(int x, int y) => (x / y).toInt();

常见修复方法

#

使用整数除法运算符 (~/)

dart
int divide(int x, int y) => x ~/ y;

重复的构造函数

#

名称为 '{0}' 的构造函数已定义。

未命名的构造函数已定义。

描述

#

当一个类声明了多个未命名的构造函数,或者当它声明了多个同名的构造函数时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为未命名的构造函数有两个声明

dart
class C {
  C();

  C();
}

以下代码会生成此诊断,因为名为 m 的构造函数有两个声明

dart
class C {
  C.m();

  C.m();
}

常见修复方法

#

如果有多个未命名的构造函数并且所有构造函数都是必需的,则为所有构造函数或除其中一个以外的所有构造函数命名

dart
class C {
  C();

  C.n();
}

如果有多个未命名的构造函数并且除其中一个以外的所有构造函数都是不需要的,则删除不需要的构造函数

dart
class C {
  C();
}

如果有多个命名的构造函数并且所有构造函数都是必需的,则重命名除其中一个以外的所有构造函数

dart
class C {
  C.m();

  C.n();
}

如果有多个命名的构造函数并且除其中一个以外的所有构造函数都是不需要的,则删除不需要的构造函数

dart
class C {
  C.m();
}

重复的定义

#

名称 '{0}' 已定义。

描述

#

当声明一个名称时,并且在同一作用域中存在具有相同名称的先前声明时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为名称 x 被声明了两次

dart
int x = 0;
int x = 1;

常见修复方法

#

为其中一个声明选择不同的名称。

dart
int x = 0;
int y = 1;

重复的导出

#

重复导出。

描述

#

当找到与文件中之前的导出相同的导出指令时,分析器会生成此诊断。第二个导出没有增加价值,应将其删除。

示例

#

以下代码会生成此诊断,因为同一个库被导出了两次

dart
export 'package:meta/meta.dart';
export 'package:meta/meta.dart';

常见修复方法

#

删除不必要的导出

dart
export 'package:meta/meta.dart';

重复的字段形式参数

#

字段 '{0}' 不能由同一构造函数中的多个参数初始化。

描述

#

当构造函数的参数列表中同一字段有多个初始化形式参数时,分析器会生成此诊断。分配一个将立即被覆盖的值是没有用的。

示例

#

以下代码会生成此诊断,因为 this.f 在参数列表中出现了两次

dart
class C {
  int f;

  C(this.f, this.f) {}
}

常见修复方法

#

删除其中一个初始化形式参数

dart
class C {
  int f;

  C(this.f) {}
}

重复的字段名称

#

字段名称 '{0}' 已在此记录中使用。

描述

#

当记录字面量或记录类型注释包含一个字段,该字段的名称与同一字面量或类型中先前声明的字段的名称相同时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为记录字面量有两个名为 a 的字段

dart
var r = (a: 1, a: 2);

以下代码会生成此诊断,因为记录类型注释有两个名为 a 的字段,一个位置字段,另一个命名字段

dart
void f((int a, {int a}) r) {}

常见修复方法

#

重命名其中一个或两个字段

dart
var r = (a: 1, b: 2);

重复的隐藏名称

#

重复隐藏的名称。

描述

#

当一个名称在 hide 子句中多次出现时,分析器会生成此诊断。重复该名称是不必要的。

示例

#

以下代码会生成此诊断,因为名称 min 被隐藏了多次

dart
import 'dart:math' hide min, min;

var x = pi;

常见修复方法

#

如果名称在一个或多个地方被错误键入,则更正错误键入的名称

dart
import 'dart:math' hide max, min;

var x = pi;

如果名称没有被错误键入,则从列表中删除不必要的名称

dart
import 'dart:math' hide min;

var x = pi;

重复的 ignore

#

诊断 '{0}' 在这里不需要被忽略,因为它已经被忽略了。

描述

#

当诊断名称出现在 ignore 注释中,但该诊断已经被忽略时,分析器会生成此诊断,原因可能是它已经包含在同一个 ignore 注释中,或者因为它出现在 ignore-in-file 注释中。

示例

#

以下代码会生成此诊断,因为名为 unused_local_variable 的诊断已经被忽略了整个文件,因此不需要在特定行上忽略它

dart
// ignore_for_file: unused_local_variable
void f() {
  // ignore: unused_local_variable
  var x = 0;
}

以下代码会生成此诊断,因为名为 unused_local_variable 的诊断在同一行上被忽略了两次

dart
void f() {
  // ignore: unused_local_variable, unused_local_variable
  var x = 0;
}

常见修复方法

#

删除 ignore 注释,或者如果 ignore 注释忽略了多个诊断,则删除不必要的诊断名称

dart
// ignore_for_file: unused_local_variable
void f() {
  var x = 0;
}

重复的导入

#

重复导入。

描述

#

当找到与文件中之前的导入相同的导入指令时,分析器会生成此诊断。第二个导入没有增加价值,应将其删除。

示例

#

以下代码生成此诊断消息:

dart
import 'package:meta/meta.dart';
import 'package:meta/meta.dart';

@sealed class C {}

常见修复方法

#

删除不必要的导入

dart
import 'package:meta/meta.dart';

@sealed class C {}

重复的命名参数

#

已指定命名参数 '{0}' 的参数。

描述

#

当调用具有两个或多个同名的命名参数时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为有两个名称为 a 的参数

dart
void f(C c) {
  c.m(a: 0, a: 1);
}

class C {
  void m({int? a, int? b}) {}
}

常见修复方法

#

如果其中一个参数应具有不同的名称,则更改名称

dart
void f(C c) {
  c.m(a: 0, b: 1);
}

class C {
  void m({int? a, int? b}) {}
}

如果其中一个参数是错误的,则将其删除

dart
void f(C c) {
  c.m(a: 1);
}

class C {
  void m({int? a, int? b}) {}
}

重复的 part 指令

#

库已包含 URI 为 '{0}' 的 part。

描述

#

当单个文件在多个 part 指令中被引用时,分析器会生成此诊断。

示例

#

给定一个包含以下内容的文件 part.dart

dart
part of 'test.dart';

以下代码会生成此诊断,因为文件 part.dart 被多次包含

dart
part 'part.dart';
part 'part.dart';

常见修复方法

#

删除除第一个重复的 part 指令之外的所有指令

dart
part 'part.dart';

重复的模式赋值变量

#

变量 '{0}' 已在此模式中赋值。

描述

#

当单个模式变量在同一模式赋值中被多次赋值时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为变量 a 在模式 (a, a) 中被赋值了两次

dart
int f((int, int) r) {
  int a;
  (a, a) = r;
  return a;
}

常见修复方法

#

如果需要捕获所有值,则为要匹配的每个子模式使用唯一的变量

dart
int f((int, int) r) {
  int a, b;
  (a, b) = r;
  return a + b;
}

如果某些值不需要捕获,则使用通配符模式 _ 以避免将值绑定到变量

dart
int f((int, int) r) {
  int a;
  (_, a) = r;
  return a;
}

重复的模式字段

#

字段 '{0}' 已在此模式中匹配。

描述

#

当记录模式多次匹配同一字段,或者当对象模式多次匹配同一 getter 时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为记录字段 a 在同一记录模式中被匹配了两次

dart
void f(({int a, int b}) r) {
  switch (r) {
    case (a: 1, a: 2):
      return;
  }
}

以下代码会生成此诊断,因为 getter f 在同一对象模式中被匹配了两次

dart
void f(Object o) {
  switch (o) {
    case C(f: 1, f: 2):
      return;
  }
}
class C {
  int? f;
}

常见修复方法

#

如果模式应针对重复字段的多个值进行匹配,则使用逻辑或模式

dart
void f(({int a, int b}) r) {
  switch (r) {
    case (a: 1, b: _) || (a: 2, b: _):
      break;
  }
}

如果模式应与多个字段匹配,则更改其中一个字段的名称

dart
void f(({int a, int b}) r) {
  switch (r) {
    case (a: 1, b: 2):
      return;
  }
}

模式中重复的 rest 元素

#

在 List 或 Map 模式中最多允许一个 rest 元素。

描述

#

当 List 或 Map 模式中存在多个 rest 模式时,分析器会生成此诊断。rest 模式将捕获其他子模式未匹配的任何值,从而使后续的 rest 模式变得不必要,因为没有剩余要捕获的内容。

示例

#

以下代码会生成此诊断,因为 List 模式中有两个 rest 模式

dart
void f(List<int> x) {
  if (x case [0, ..., ...]) {}
}

常见修复方法

#

删除除其中一个 rest 模式之外的所有模式

dart
void f(List<int> x) {
  if (x case [0, ...]) {}
}

重复的显示名称

#

重复显示的名称。

描述

#

当一个名称在 show 子句中多次出现时,分析器会生成此诊断。重复该名称是不必要的。

示例

#

以下代码会生成此诊断,因为名称 min 被显示了多次

dart
import 'dart:math' show min, min;

var x = min(2, min(0, 1));

常见修复方法

#

如果名称在一个或多个地方被错误键入,则更正错误键入的名称

dart
import 'dart:math' show max, min;

var x = max(2, min(0, 1));

如果名称没有被错误键入,则从列表中删除不必要的名称

dart
import 'dart:math' show min;

var x = min(2, min(0, 1));

重复的变量模式

#

变量 '{0}' 已在此模式中定义。

描述

#

当逻辑与模式的分支声明了一个变量,该变量已在同一模式的较早分支中声明时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为变量 a 在逻辑与模式的两个分支中都声明了

dart
void f((int, int) r) {
  if (r case (var a, 0) && (0, var a)) {
    print(a);
  }
}

常见修复方法

#

如果需要在多个分支中捕获匹配的值,则更改变量的名称,使其唯一

dart
void f((int, int) r) {
  if (r case (var a, 0) && (0, var b)) {
    print(a + b);
  }
}

如果只需要在一个分支上捕获匹配的值,则从除一个分支以外的所有分支中删除变量模式

dart
void f((int, int) r) {
  if (r case (var a, 0) && (0, _)) {
    print(a);
  }
}

空 Map 模式

#

Map 模式必须至少有一个条目。

描述

#

当 Map 模式为空时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为 Map 模式为空

dart
void f(Map<int, String> x) {
  if (x case {}) {}
}

常见修复方法

#

如果模式应匹配任何 Map,则将其替换为对象模式

dart
void f(Map<int, String> x) {
  if (x case Map()) {}
}

如果模式应仅匹配空 Map,则在模式中检查长度

dart
void f(Map<int, String> x) {
  if (x case Map(isEmpty: true)) {}
}

带有逗号的空记录字面量

#

没有字段的记录字面量不能有尾随逗号。

描述

#

当没有字段的记录字面量具有尾随逗号时,分析器会生成此诊断。空记录字面量不能包含逗号。

示例

#

以下代码会生成此诊断,因为空记录字面量具有尾随逗号

dart
var r = (,);

常见修复方法

#

如果记录旨在为空,则删除逗号

dart
var r = ();

如果记录旨在具有一个或多个字段,则添加用于计算这些字段值的表达式

dart
var r = (3, 4);

空记录类型命名字段列表

#

记录类型中命名字段的列表不能为空。

描述

#

当记录类型具有空的命名字段列表时,分析器会生成此诊断。

示例

#

以下代码会生成此诊断,因为记录类型具有空的命名字段列表

dart
void f((int, int, {}) r) {}

常见修复方法

#

如果记录旨在具有命名字段,则添加字段的类型和名称

dart
void f((int, int, {int z}) r) {}

如果记录不旨在具有命名字段,则删除花括号

dart
void f((int, int) r) {}

带有逗号的空记录类型

#

没有字段的记录类型不能有尾随逗号。

描述

#

当没有字段的记录类型具有尾随逗号时,分析器会生成此诊断。空记录类型不能包含逗号。

示例

#

以下代码会生成此诊断,因为空记录类型具有尾随逗号

dart
void f((,) r) {}

常见修复方法

#

如果记录类型旨在为空,则删除逗号

dart
void f(() r) {}

如果记录类型旨在具有一个或多个字段,则添加这些字段的类型

dart
void f((int, int) r) {}

空 struct

#

类“{0}”不能为空,因为它是一个“{1}”的子类。

描述

#

StructUnion 的子类没有任何字段时,分析器会生成此诊断信息。不支持使用空的 StructUnion

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类 C 扩展了 Struct,但未声明任何字段

dart
import 'dart:ffi';

final class C extends Struct {}

常见修复方法

#

如果该类旨在作为结构体,则声明一个或多个字段

dart
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  external int x;
}

如果该类旨在用作 Pointer 的类型参数,则使其成为 Opaque 的子类

dart
import 'dart:ffi';

final class C extends Opaque {}

如果该类不打算作为结构体使用,则删除或更改 extends 子句

dart
class C {}

枚举常量与封闭类型同名

#

枚举值的名称不能与枚举的名称相同。

描述

#

当枚举值与其声明所在的枚举具有相同的名称时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为枚举值 E 与封闭枚举 E 具有相同的名称

dart
enum E {
  E
}

常见修复方法

#

如果枚举的名称是正确的,则重命名常量

dart
enum E {
  e
}

如果常量的名称是正确的,则重命名枚举

dart
enum F {
  E
}

带有非常量构造函数的枚举常量

#

调用的构造函数不是“const”构造函数。

描述

#

当使用工厂构造函数或未标记为 const 的生成构造函数创建枚举值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为枚举值 e 正在由工厂构造函数初始化

dart
enum E {
  e();

  factory E() => e;
}

常见修复方法

#

使用标记为 const 的生成构造函数

dart
enum E {
  e._();

  factory E() => e;

  const E._();
}

带有实例变量的枚举 mixin

#

应用于枚举的混入不能有实例变量。

描述

#

当应用于枚举的混入声明了一个或多个实例变量时,分析器会生成此诊断信息。这是不允许的,因为枚举值是常量,并且枚举中的构造函数无法初始化任何混入的字段。

示例

#

以下代码会生成此诊断信息,因为混入 M 定义了实例字段 x

dart
mixin M {
  int x = 0;
}

enum E with M {
  a
}

常见修复方法

#

如果需要应用混入,则将所有实例字段更改为 getter 和 setter 对,并在必要时在枚举中实现它们

dart
mixin M {
  int get x => 0;
}

enum E with M {
  a
}

如果不需要应用混入,则删除它

dart
enum E {
  a
}

带有抽象成员的枚举

#

“{0}”必须有方法体,因为“{1}”是一个枚举。

描述

#

当找到枚举的成员没有具体实现时,分析器会生成此诊断信息。枚举不允许包含抽象成员。

示例

#

以下代码会生成此诊断信息,因为 m 是一个抽象方法,而 E 是一个枚举

dart
enum E {
  e;

  void m();
}

常见修复方法

#

为成员提供实现

dart
enum E {
  e;

  void m() {}
}

带有 nameValues 的枚举

#

名称“values”不是枚举的有效名称。

描述

#

当声明的枚举名称为 values 时,分析器会生成此诊断信息。这是不允许的,因为枚举有一个隐式的静态字段名为 values,两者会冲突。

示例

#

以下代码会生成此诊断信息,因为存在一个枚举声明,其名称为 values

dart
enum values {
  c
}

常见修复方法

#

将枚举重命名为 values 以外的名称。

const Set 中相等的元素

#

常量 set 字面量中的两个元素不能相等。

描述

#

当常量 set 字面量中的两个元素具有相同的值时,分析器会生成此诊断信息。set 只能包含每个值一次,这意味着其中一个值是不必要的。

示例

#

以下代码会生成此诊断信息,因为字符串 'a' 被指定了两次

dart
const Set<String> set = {'a', 'a'};

常见修复方法

#

删除其中一个重复的值

dart
const Set<String> set = {'a'};

请注意,字面量 set 保留其元素的顺序,因此选择删除哪个元素可能会影响迭代器返回元素的顺序。

Set 中相等的元素

#

Set 字面量中的两个元素不应相等。

描述

#

当非常量 set 中的元素与同一 set 中的前一个元素相同时,分析器会生成此诊断信息。如果两个元素相同,则第二个值将被忽略,这使得同时拥有这两个元素变得毫无意义,并且可能预示着一个 bug。

示例

#

以下代码会生成此诊断信息,因为元素 1 出现了两次

dart
const a = 1;
const b = 1;
var s = <int>{a, b};

常见修复方法

#

如果两个元素都应包含在 set 中,则更改其中一个元素

dart
const a = 1;
const b = 2;
var s = <int>{a, b};

如果只需要其中一个元素,则删除不需要的那个

dart
const a = 1;
var s = <int>{a};

请注意,字面量 set 保留其元素的顺序,因此选择删除哪个元素可能会影响迭代器返回元素的顺序。

const Map 中相等的键

#

常量 map 字面量中的两个键不能相等。

描述

#

当常量 map 中的键与同一 map 中的前一个键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得同时拥有这两个键值对变得毫无意义。

示例

#

以下代码会生成此诊断信息,因为键 1 被使用了两次

dart
const map = <int, String>{1: 'a', 2: 'b', 1: 'c', 4: 'd'};

常见修复方法

#

如果两个条目都应包含在 map 中,则将其中一个键更改为不同的键

dart
const map = <int, String>{1: 'a', 2: 'b', 3: 'c', 4: 'd'};

如果只需要其中一个条目,则删除不需要的那个

dart
const map = <int, String>{1: 'a', 2: 'b', 4: 'd'};

请注意,字面量 map 保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。

Map 中相等的键

#

Map 字面量中的两个键不应相等。

描述

#

当非常量 map 中的键与同一 map 中的前一个键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得同时拥有这两个键值对变得毫无意义,并且可能预示着一个 bug。

示例

#

以下代码会生成此诊断信息,因为键 ab 具有相同的值

dart
const a = 1;
const b = 1;
var m = <int, String>{a: 'a', b: 'b'};

常见修复方法

#

如果两个条目都应包含在 map 中,则更改其中一个键

dart
const a = 1;
const b = 2;
var m = <int, String>{a: 'a', b: 'b'};

如果只需要其中一个条目,则删除不需要的那个

dart
const a = 1;
var m = <int, String>{a: 'a'};

请注意,字面量 map 保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。

Map 模式中相等的键

#

Map 模式中的两个键不能相等。

描述

#

当 map 模式包含多个同名键时,分析器会生成此诊断信息。同一个键不能匹配两次。

示例

#

以下代码会生成此诊断信息,因为键 'a' 出现了两次

dart
void f(Map<String, int> x) {
  if (x case {'a': 1, 'a': 2}) {}
}

常见修复方法

#

如果您尝试匹配两个不同的键,则更改模式中的其中一个键

dart
void f(Map<String, int> x) {
  if (x case {'a': 1, 'b': 2}) {}
}

如果您尝试匹配同一个键,但允许多个模式中的任何一个匹配,则使用逻辑或模式

dart
void f(Map<String, int> x) {
  if (x case {'a': 1 || 2}) {}
}

应为一个 List 模式类型参数

#

List 模式需要一个或零个类型参数,但找到了 {0} 个。

描述

#

当 list 模式具有多个类型参数时,分析器会生成此诊断信息。List 模式可以有零个或一个类型参数,但不能有多个。

示例

#

以下代码会生成此诊断信息,因为 list 模式 ([0]) 有两个类型参数

dart
void f(Object x) {
  if (x case <int, int>[0]) {}
}

常见修复方法

#

删除除一个之外的所有类型参数

dart
void f(Object x) {
  if (x case <int>[0]) {}
}

应为一个 List 类型参数

#

List 字面量需要一个或零个类型参数,但找到了 {0} 个。

描述

#

当 list 字面量具有多个类型参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 list 字面量有两个类型参数,但它最多只能有一个

dart
var l = <int, int>[];

常见修复方法

#

删除除一个之外的所有类型参数

dart
var l = <int>[];

应为一个 Set 类型参数

#

Set 字面量需要一个或零个类型参数,但找到了 {0} 个。

描述

#

当 set 字面量具有多个类型参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 set 字面量有三个类型参数,但它最多只能有一个

dart
var s = <int, String, int>{0, 'a', 1};

常见修复方法

#

删除除一个之外的所有类型参数

dart
var s = <int>{0, 1};

应为两个 Map 模式类型参数

#

Map 模式需要两个或零个类型参数,但找到了 {0} 个。

描述

#

当 map 模式具有一个类型参数或多于两个类型参数时,分析器会生成此诊断信息。Map 模式可以有零个或两个类型参数,但不能有任何其他数量。

示例

#

以下代码会生成此诊断信息,因为 map 模式 (<int>{}) 有一个类型参数

dart
void f(Object x) {
  if (x case <int>{0: _}) {}
}

常见修复方法

#

添加或删除类型参数,直到有两个或没有

dart
void f(Object x) {
  if (x case <int, int>{0: _}) {}
}

应为两个 Map 类型参数

#

Map 字面量需要两个或零个类型参数,但找到了 {0} 个。

描述

#

当 map 字面量具有一个或多于两个类型参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 map 字面量有三个类型参数,但它只能有两个或零个

dart
var m = <int, String, int>{};

常见修复方法

#

删除除两个之外的所有类型参数

dart
var m = <int, String>{};

导出内部库

#

库“{0}”是内部库,无法导出。

描述

#

当分析器找到一个导出,其 dart: URI 引用了一个内部库时,会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 _interceptors 是一个内部库

dart
export 'dart:_interceptors';

常见修复方法

#

删除 export 指令。

导出旧式符号

#

符号“{0}”在旧版库中定义,无法从启用了空安全性的库中重新导出。

描述

#

当选择加入空安全性的库导出另一个库,而导出的库选择退出空安全性时,分析器会生成此诊断信息。

示例

#

给定一个选择退出空安全性的库

dart
// @dart = 2.8
String s;

以下代码会生成此诊断信息,因为它正在从选择退出的库中导出符号

dart
export 'optedOut.dart';

class C {}

常见修复方法

#

如果可以,请迁移导出的库,使其不需要选择退出

dart
String? s;

如果无法迁移库,则删除 export

dart
class C {}

如果导出的库(选择退出的库)本身导出了一个选择加入的库,那么您的库间接导出选择加入库中的符号是有效的。您可以通过在库的 export 指令中添加 hide 组合器来隐藏选择退出库中声明的所有名称,从而做到这一点。

导出非库文件

#

导出的库“{0}”不能有 part-of 指令。

描述

#

当 export 指令引用一个 part 而不是库时,分析器会生成此诊断信息。

示例

#

给定一个包含以下内容的文件 part.dart

dart
part of lib;

以下代码会生成此诊断信息,因为文件 part.dart 是一个 part,而只有库才能被导出

dart
library lib;

export 'part.dart';

常见修复方法

#

删除 export 指令,或将 URI 更改为包含该 part 的库的 URI。

Map 中的表达式

#

表达式不能在 map 字面量中使用。

描述

#

当分析器在看似 map 字面量中找到表达式而不是 map 条目时,会生成此诊断信息。

示例

#

以下代码生成此诊断消息:

dart
var map = <String, int>{'a': 0, 'b': 1, 'c'};

常见修复方法

#

如果该表达式旨在计算条目中的键或值,请通过将表达式替换为键或值来修复此问题。例如

dart
var map = <String, int>{'a': 0, 'b': 1, 'c': 2};

扩展非类

#

类只能扩展其他类。

描述

#

extends 子句包含的名称被声明为类以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 被声明为一个函数

dart
void f() {}

class C extends f {}

常见修复方法

#

如果您希望类扩展 Object 以外的类,则将 extends 子句中的名称替换为该类的名称

dart
void f() {}

class C extends B {}

class B {}

如果您希望类扩展 Object,则删除 extends 子句

dart
void f() {}

class C {}

扩展作为表达式

#

扩展“{0}”不能用作表达式。

描述

#

当扩展的名称在表达式中使用,而不是在扩展覆盖中或限定对扩展的静态成员的访问时,分析器会生成此诊断信息。由于类定义了一种类型,因此可以使用类的名称来引用表示类类型的 Type 实例。另一方面,扩展不定义类型,也不能用作类型字面量。

示例

#

以下代码会生成此诊断信息,因为 E 是一个扩展

dart
extension E on int {
  static String m() => '';
}

var x = E;

常见修复方法

#

将扩展的名称替换为可以引用的名称,例如扩展上定义的静态成员

dart
extension E on int {
  static String m() => '';
}

var x = E.m();

扩展中静态成员和实例成员冲突

#

扩展不能定义静态成员“{0}”和同名的实例成员。

描述

#

当扩展声明同时包含具有相同名称的实例成员和静态成员时,分析器会生成此诊断信息。实例成员和静态成员不能具有相同的名称,因为不清楚在扩展主体内不限定地使用该名称时,引用的是哪个成员。

示例

#

以下代码会生成此诊断信息,因为名称 a 被用于两个不同的成员

dart
extension E on Object {
  int get a => 0;
  static int a() => 0;
}

常见修复方法

#

重命名或删除其中一个成员

dart
extension E on Object {
  int get a => 0;
  static int b() => 0;
}

扩展声明抽象成员

#

扩展不能声明抽象成员。

描述

#

当在扩展中声明抽象声明时,分析器会生成此诊断信息。扩展只能声明具体成员。

示例

#

以下代码会生成此诊断信息,因为方法 a 没有方法体

dart
extension E on String {
  int a();
}

常见修复方法

#

为成员提供实现或删除它。

扩展声明构造函数

#

扩展不能声明构造函数。

描述

#

当在扩展中找到构造函数声明时,分析器会生成此诊断信息。定义构造函数是无效的,因为扩展不是类,并且不可能创建扩展的实例。

示例

#

以下代码会生成此诊断信息,因为 E 中有一个构造函数声明

dart
extension E on String {
  E() : super();
}

常见修复方法

#

删除构造函数或将其替换为静态方法。

扩展声明实例字段

#

扩展不能声明实例字段。

描述

#

当在扩展中找到实例字段声明时,分析器会生成此诊断信息。定义实例字段是无效的,因为扩展只能添加行为,而不能添加状态。

示例

#

以下代码会生成此诊断信息,因为 s 是一个实例字段

dart
extension E on String {
  String s;
}

常见修复方法

#

如果可以在不将其存储在字段中的情况下计算值,则尝试使用 getter 或方法

dart
extension E on String {
  String get s => '';

  void s(String value) => print(s);
}

如果必须存储该值,但对于每个实例都相同,则尝试使用静态字段

dart
extension E on String {
  static String s = '';
}

如果每个实例都需要存储其自己的值,则尝试使用由静态 Expando 支持的 getter 和 setter 对

dart
extension E on SomeType {
  static final _s = Expando<String>();

  String get s => _s[this] ?? '';
  set s(String value) => _s[this] = value;
}

扩展声明 Object 的成员

#

扩展不能声明与“Object”声明的成员同名的成员。

描述

#

当扩展声明声明的成员与类 Object 中声明的成员同名时,分析器会生成此诊断信息。这样的成员永远无法使用,因为总是首先找到 Object 中的成员。

示例

#

以下代码会生成此诊断信息,因为 toStringObject 定义

dart
extension E on String {
  String toString() => this;
}

常见修复方法

#

删除该成员或重命名它,使其名称与 Object 中的成员不冲突

dart
extension E on String {
  String displayString() => this;
}

扩展覆盖访问静态成员

#

扩展覆盖不能用于访问扩展中的静态成员。

描述

#

当扩展覆盖是静态成员调用的接收者时,分析器会生成此诊断信息。与类中的静态成员类似,扩展的静态成员应使用扩展的名称而不是扩展覆盖来访问。

示例

#

以下代码会生成此诊断信息,因为 m 是静态的

dart
extension E on String {
  static void m() {}
}

void f() {
  E('').m();
}

常见修复方法

#

将扩展覆盖替换为扩展的名称

dart
extension E on String {
  static void m() {}
}

void f() {
  E.m();
}

扩展覆盖参数不可赋值

#

扩展覆盖“{0}”的参数类型无法赋值给扩展类型“{1}”。

描述

#

当扩展覆盖的参数无法赋值给扩展所扩展的类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 3 不是 String

dart
extension E on String {
  void method() {}
}

void f() {
  E(3).method();
}

常见修复方法

#

如果您使用的是正确的扩展,则更新参数以使其具有正确的类型

dart
extension E on String {
  void method() {}
}

void f() {
  E(3.toString()).method();
}

如果存在另一个对参数类型有效的扩展,则替换扩展的名称或解包参数,以便找到正确的扩展。

扩展覆盖没有访问权限

#

扩展覆盖只能用于访问实例成员。

描述

#

当找到未用于访问扩展成员之一的扩展覆盖时,分析器会生成此诊断信息。扩展覆盖语法没有任何运行时语义;它仅控制在编译时选择哪个成员。

示例

#

以下代码会生成此诊断信息,因为 E(i) 不是表达式

dart
extension E on int {
  int get a => 0;
}

void f(int i) {
  print(E(i));
}

常见修复方法

#

如果您想调用扩展的成员之一,则添加调用

dart
extension E on int {
  int get a => 0;
}

void f(int i) {
  print(E(i).a);
}

如果您不想调用成员,则解包参数

dart
extension E on int {
  int get a => 0;
}

void f(int i) {
  print(i);
}

带有级联调用的扩展覆盖

#

扩展覆盖没有值,因此不能用作级联表达式的接收者。

描述

#

当扩展覆盖用作级联表达式的接收者时,分析器会生成此诊断信息。级联表达式 e..m 的值是接收者 e 的值,但扩展覆盖不是表达式,也没有值。

示例

#

以下代码会生成此诊断信息,因为 E(3) 不是表达式

dart
extension E on int {
  void m() {}
}
f() {
  E(3)..m();
}

常见修复方法

#

使用 . 而不是 ..

dart
extension E on int {
  void m() {}
}
f() {
  E(3).m();
}

如果存在多个级联访问,则需要为每个访问复制扩展覆盖。

带有 super 形式参数的扩展类型构造函数

#

扩展类型构造函数不能声明 super 形参。

描述

#

当扩展类型中的构造函数具有 super 参数时,分析器会生成此诊断信息。Super 参数无效,因为扩展类型没有超类。

示例

#

以下代码会生成此诊断信息,因为命名构造函数 n 包含 super 参数

dart
extension type E(int i) {
  E.n(this.i, super.foo);
}

常见修复方法

#

如果您需要该参数,请将 super 参数替换为普通参数

dart
extension type E(int i) {
  E.n(this.i, String foo);
}

如果您不需要该参数,请删除 super 参数

dart
extension type E(int i) {
  E.n(this.i);
}

带有 super 调用的扩展类型构造函数

#

扩展类型构造函数不能包含 super 初始化列表。

描述

#

当扩展类型中的构造函数在其初始化列表中包含对 super 构造函数的调用时,分析器会生成此诊断信息。由于扩展类型没有超类,因此没有构造函数可以调用。

示例

#

以下代码会生成此诊断信息,因为构造函数 E.n 在其初始化列表中调用了 super 构造函数

dart
extension type E(int i) {
  E.n() : i = 0, super.n();
}

常见修复方法

#

删除对 super 构造函数的调用

dart
extension type E(int i) {
  E.n() : i = 0;
}

扩展类型声明实例字段

#

扩展类型不能声明实例字段。

描述

#

当扩展类型声明的主体中存在字段声明时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 E 声明了一个名为 f 的字段

dart
extension type E(int i) {
  final int f = 0;
}

常见修复方法

#

如果您不需要该字段,则删除它或将其替换为 getter 和/或 setter

dart
extension type E(int i) {
  int get f => 0;
}

如果您需要该字段,则将扩展类型转换为类

dart
class E {
  final int i;

  final int f = 0;

  E(this.i);
}

扩展类型声明 Object 的成员

#

扩展类型不能声明与“Object”声明的成员同名的成员。

描述

#

当扩展类型声明的主体包含与 Object 声明的成员之一同名的成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类 Object 已经定义了一个名为 hashCode 的成员

dart
extension type E(int i) {
  int get hashCode => 0;
}

常见修复方法

#

如果您需要具有已实现语义的成员,则重命名该成员

dart
extension type E(int i) {
  int get myHashCode => 0;
}

如果您不需要具有已实现语义的成员,则删除该成员

dart
extension type E(int i) {}

扩展类型实现不允许的类型

#

扩展类型不能实现“{0}”。

描述

#

当扩展类型实现了一个它不允许实现的类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型不能实现类型 dynamic

dart
extension type A(int i) implements dynamic {}

常见修复方法

#

从 implements 子句中删除不允许的类型

dart
extension type A(int i) {}

扩展类型实现自身

#

扩展类型不能实现自身。

描述

#

当扩展类型直接或间接地实现自身时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 A 直接实现了自身

dart
extension type A(int i) implements A {}

以下代码会生成此诊断信息,因为扩展类型 A 间接实现了自身(通过 B

dart
extension type A(int i) implements B {}

extension type B(int i) implements A {}

常见修复方法

#

通过从循环中涉及的至少一个类型的 implements 子句中删除类型来打破循环

dart
extension type A(int i) implements B {}

extension type B(int i) {}

扩展类型实现非超类型

#

“{0}”不是“{1}”的超类型,即表示类型。

描述

#

当扩展类型实现了一个不是表示类型的超类型的类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 A 实现了 String,但 String 不是表示类型 int 的超类型

dart
extension type A(int i) implements String {}

常见修复方法

#

如果表示类型是正确的,则删除或替换 implements 子句中的类型

dart
extension type A(int i) {}

如果表示类型不正确,则将其替换为正确的类型

dart
extension type A(String s) implements String {}

扩展类型实现表示类型非超类型

#

“{0}”(“{1}”的表示类型)不是“{2}”(“{3}”的表示类型)的超类型。

描述

#

当一个扩展类型实现另一个扩展类型,并且被实现扩展类型的表示类型不是实现扩展类型的表示类型的子类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 B 实现了 A,但 A 的表示类型 (num) 不是 B 的表示类型 (String) 的子类型

dart
extension type A(num i) {}

extension type B(String s) implements A {}

常见修复方法

#

更改两个扩展类型的表示类型,使被实现类型的表示类型成为实现类型的表示类型的超类型

dart
extension type A(num i) {}

extension type B(int n) implements A {}

或者从 implements 子句中删除被实现类型

dart
extension type A(num i) {}

extension type B(String s) {}

扩展类型继承的成员冲突

#

扩展类型“{0}”从已实现的类型中具有多个名为“{1}”的不同成员。

描述

#

当扩展类型实现了两个或多个其他类型,并且其中至少有两个类型声明了同名成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 C 同时实现了 AB,并且两者都声明了一个名为 m 的成员

dart
class A {
  void m() {}
}

extension type B(A a) {
  void m() {}
}

extension type C(A a) implements A, B {}

常见修复方法

#

如果扩展类型不需要实现所有列出的类型,则删除除引入冲突成员的类型之外的所有类型

dart
class A {
  void m() {}
}

extension type B(A a) {
  void m() {}
}

extension type C(A a) implements A {}

如果扩展类型需要实现所有列出的类型,但您可以重命名这些类型中的成员,则为冲突的成员提供唯一的名称

dart
class A {
  void m() {}
}

extension type B(A a) {
  void n() {}
}

extension type C(A a) implements A, B {}

扩展类型表示类型依赖于自身

#

扩展类型表示不能依赖于自身。

描述

#

当扩展类型的表示类型依赖于扩展类型自身(直接或间接)时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 A 的表示类型直接依赖于 A

dart
extension type A(A a) {}

以下两个代码示例会生成此诊断信息,因为扩展类型 A 的表示类型通过扩展类型 B 间接依赖于 A

dart
extension type A(B b) {}

extension type B(A a) {}
dart
extension type A(List<B> b) {}

extension type B(List<A> a) {}

常见修复方法

#

通过为循环中的至少一个类型选择不同的表示类型来消除依赖关系

dart
extension type A(String s) {}

扩展类型表示类型为 Bottom

#

表示类型不能是 bottom 类型。

描述

#

当扩展类型的表示类型是 bottom 类型 Never 时,分析器会生成此诊断信息。类型 Never 不能作为扩展类型的表示类型,因为没有可以扩展的值。

示例

#

以下代码会生成此诊断信息,因为扩展类型 E 的表示类型是 Never

dart
extension type E(Never n) {}

常见修复方法

#

将扩展类型替换为其他类型

dart
extension type E(String s) {}

带有抽象成员的扩展类型

#

“{0}”必须有方法体,因为“{1}”是一个扩展类型。

描述

#

当扩展类型声明了一个抽象成员时,分析器会生成此诊断信息。由于扩展类型成员引用是静态解析的,因此扩展类型中的抽象成员永远无法执行。

示例

#

以下代码会生成此诊断信息,因为扩展类型 E 中的方法 m 是抽象的

dart
extension type E(String s) {
  void m();
}

常见修复方法

#

如果该成员旨在可执行,则为该成员提供实现

dart
extension type E(String s) {
  void m() {}
}

如果该成员不旨在可执行,则删除它

dart
extension type E(String s) {}

带有初始化器的 external 声明

#

外部字段不能有初始化器。

外部变量不能有初始化器。

描述

#

当标记为关键字 external 的字段或变量具有初始化器,或者当外部字段在构造函数中初始化时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为外部字段 x 在初始化列表中被赋值

dart
class C {
  external int x;
  C() : x = 0;
}

以下代码会生成此诊断信息,因为外部字段 x 具有初始化器

dart
class C {
  external final int x = 0;
}

以下代码会生成此诊断信息,因为外部顶级变量 x 具有初始化器

dart
external final int x = 0;

常见修复方法

#

删除初始化器

dart
class C {
  external final int x;
}

struct 字段上额外的注解

#

struct 类中的字段必须恰好有一个指示 native 类型的注解。

描述

#

Struct 的子类中的字段具有多个描述字段的 native 类型的注解时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 x 有两个描述字段的 native 类型的注解

dart
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  @Int16()
  external int x;
}

常见修复方法

#

删除除一个之外的所有注解

dart
import 'dart:ffi';
final class C extends Struct {
  @Int32()
  external int x;
}

额外的位置参数

#

位置参数过多:应为 {0} 个,但找到了 {1} 个。

描述

#

当方法或函数调用具有的位置参数多于方法或函数允许的位置参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 定义了 2 个参数,但使用 3 个参数调用了它

dart
void f(int a, int b) {}
void g() {
  f(1, 2, 3);
}

常见修复方法

#

删除与参数不对应的参数

dart
void f(int a, int b) {}
void g() {
  f(1, 2);
}

额外的的位置参数可以命名

#

位置参数过多:应为 {0} 个,但找到了 {1} 个。

描述

#

当方法或函数调用具有的位置参数多于方法或函数允许的位置参数时,但方法或函数定义了命名参数,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 定义了 2 个位置参数,但有一个命名参数可以用于第三个参数

dart
void f(int a, int b, {int? c}) {}
void g() {
  f(1, 2, 3);
}

常见修复方法

#

如果某些参数应该是命名参数的值,则在参数前添加名称

dart
void f(int a, int b, {int? c}) {}
void g() {
  f(1, 2, c: 3);
}

否则,删除与位置参数不对应的参数

dart
void f(int a, int b, {int? c}) {}
void g() {
  f(1, 2);
}

C 数组上额外的大小注解

#

“Array”必须恰好有一个“Array”注解。

描述

#

Struct 的子类中的字段具有多个描述 native 数组大小的注解时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 a0 有两个指定 native 数组大小的注解

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(4)
  @Array(8)
  external Array<Uint8> a0;
}

常见修复方法

#

删除除一个之外的所有注解

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8)
  external Array<Uint8> a0;
}

ffi_native 无效的重复默认资源

#

一个库最多只能有一个 @DefaultAsset 注解。

描述

#

当库指令具有多个与之关联的 DefaultAsset 注解时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为库指令具有两个与之关联的 DefaultAsset 注解

dart
@DefaultAsset('a')
@DefaultAsset('b')
library;

import 'dart:ffi';

常见修复方法

#

删除除一个之外的所有 DefaultAsset 注解

dart
@DefaultAsset('a')
library;

import 'dart:ffi';

ffi_native 无效的多个注解

#

Native 函数和字段必须恰好有一个 @Native 注解。

描述

#

当单个声明上有多个 Native 注解时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数 f 有两个与之关联的 Native 注解

dart
import 'dart:ffi';

@Native<Int32 Function(Int32)>()
@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);

常见修复方法

#

删除除一个之外的所有注解

dart
import 'dart:ffi';

@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);

ffi_native 必须是 external 声明

#

Native 函数必须声明为 external。

描述

#

当标记为 @Native 的函数未标记为 external 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数 free 被标记为 @Native,但该函数未标记为 external

dart
import 'dart:ffi';

@Native<Void Function(Pointer<Void>)>()
void free(Pointer<Void> ptr) {}

常见修复方法

#

如果该函数是 native 函数,则在返回类型前添加修饰符 external

dart
import 'dart:ffi';

@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);

ffi_native 参数数量意外

#

Native 注解参数的数量意外。应为 {0} 个,但有 {1} 个。

描述

#

当用作 @Native 注解的类型参数的函数类型中的参数数量与被注解函数中的参数数量不匹配时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为用作 @Native 注解的类型参数的函数类型 (Void Function(Double)) 有一个参数,而被注解函数的类型 (void f(double, double)) 有两个参数

dart
import 'dart:ffi';

@Native<Void Function(Double)>(symbol: 'f')
external void f(double x, double y);

常见修复方法

#

如果被注解函数是正确的,则更新 @Native 注解中的函数类型以匹配

dart
import 'dart:ffi';

@Native<Void Function(Double, Double)>(symbol: 'f')
external void f(double x, double y);

如果 @Native 注解中的函数类型是正确的,则更新被注解函数以匹配

dart
import 'dart:ffi';

@Native<Void Function(Double)>(symbol: 'f')
external void f(double x);

ffi_native 带有接收者的参数数量意外

#

Native 注解参数的数量意外。应为 {0} 个,但有 {1} 个。Native 实例方法注解必须将接收者作为第一个参数。

描述

#

当 native 方法的 @Native 注解上使用的类型参数不包含方法接收者的类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 @Native 注解上的类型参数 (Void Function(Double)) 不包含方法接收者的类型

dart
import 'dart:ffi';

class C {
  @Native<Void Function(Double)>()
  external void f(double x);
}

常见修复方法

#

添加一个初始参数,其类型与声明 native 方法的类相同

dart
import 'dart:ffi';

class C {
  @Native<Void Function(C, Double)>()
  external void f(double x);
}

字段被多个初始化器初始化

#

字段“{0}”不能在同一个构造函数中初始化两次。

描述

#

当构造函数的初始化列表多次初始化一个字段时,分析器会生成此诊断信息。允许两个初始化器没有价值,因为只保留最后一个值。

示例

#

以下代码会生成此诊断信息,因为字段 f 被初始化了两次

dart
class C {
  int f;

  C() : f = 0, f = 1;
}

常见修复方法

#

删除其中一个初始化器

dart
class C {
  int f;

  C() : f = 0;
}

字段在初始化器和声明中都进行了初始化

#

如果字段是 final 并且已经在声明时初始化,则不能在构造函数中初始化字段。

描述

#

当 final 字段在字段声明和构造函数中的初始化列表中都初始化时,分析器会生成此诊断信息。Final 字段只能赋值一次,因此不能在两个地方都初始化。

示例

#

以下代码会生成此诊断信息,因为 f

dart
class C {
  final int f = 0;
  C() : f = 1;
}

常见修复方法

#

如果初始化不依赖于传递给构造函数的任何值,并且如果所有构造函数都需要将字段初始化为相同的值,则从构造函数中删除初始化器

dart
class C {
  final int f = 0;
  C();
}

如果初始化依赖于传递给构造函数的值,或者如果不同的构造函数需要以不同的方式初始化字段,则删除字段声明中的初始化器

dart
class C {
  final int f;
  C() : f = 1;
}

字段在参数和初始化器中都进行了初始化

#

字段不能在参数列表和初始化列表中都初始化。

描述

#

当字段在参数列表和构造函数的初始化列表中都初始化时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字段 f 同时被初始化形参和初始化列表初始化

dart
class C {
  int f;

  C(this.f) : f = 0;
}

常见修复方法

#

如果应由参数初始化字段,则删除初始化列表中的初始化

dart
class C {
  int f;

  C(this.f);
}

如果应在初始化列表中初始化字段并且不需要参数,则删除参数

dart
class C {
  int f;

  C() : f = 0;
}

如果应在初始化列表中初始化字段并且需要参数,则将其设为普通参数

dart
class C {
  int f;

  C(int g) : f = g * 2;
}

字段初始化器在工厂构造函数中

#

初始化形参不能在工厂构造函数中使用。

描述

#

当工厂构造函数具有初始化形参时,分析器会生成此诊断信息。工厂构造函数不能为字段赋值,因为没有创建实例;因此,没有字段可以赋值。

示例

#

以下代码会生成此诊断信息,因为工厂构造函数使用了初始化形参

dart
class C {
  int? f;

  factory C(this.f) => throw 0;
}

常见修复方法

#

将初始化形参替换为普通参数

dart
class C {
  int? f;

  factory C(int f) => throw 0;
}

struct 中的字段初始化器

#

“Struct”和“Union”的子类中的构造函数不能有字段初始化列表。

描述

#

StructUnion 的子类中的构造函数具有一个或多个字段初始化列表时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类 C 有一个构造函数,其中包含字段 f 的初始化列表

dart
// @dart = 2.9
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  int f;

  C() : f = 0;
}

常见修复方法

#

删除字段初始化列表

dart
// @dart = 2.9
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  int f;

  C();
}

字段初始化器不可赋值

#

常量构造函数中,初始化器类型“{0}”无法赋值给字段类型“{1}”。

初始化器类型“{0}”无法赋值给字段类型“{1}”。

描述

#

当构造函数的初始化列表将字段初始化为无法赋值给字段的值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 0 的类型为 int,而 int 无法赋值给类型为 String 的字段

dart
class C {
  String s;

  C() : s = 0;
}

常见修复方法

#

如果字段的类型是正确的,则更改分配给它的值,使该值具有有效的类型

dart
class C {
  String s;

  C() : s = '0';
}

如果值的类型是正确的,则更改字段的类型以允许赋值

dart
class C {
  int s;

  C() : s = 0;
}

字段初始化器在构造函数外部

#

字段形参只能在构造函数中使用。

初始化形参只能在构造函数中使用。

描述

#

当初始化形参在构造函数以外的任何参数列表中使用时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为初始化形参 this.x 正在方法 m 中使用

dart
class A {
  int x = 0;

  m([this.x = 0]) {}
}

常见修复方法

#

将初始化形参替换为普通形参,并在方法体中赋值给字段

dart
class A {
  int x = 0;

  m([int x = 0]) {
    this.x = x;
  }
}

字段初始化器在重定向构造函数中

#

重定向构造函数不能有字段初始化器。

描述

#

当重定向构造函数初始化对象中的字段时,分析器会生成此诊断信息。这是不允许的,因为拥有该字段的实例在应该初始化时尚未创建。

示例

#

以下代码会产生此诊断信息,因为重定向到构造函数 C 的构造函数 C.zero 具有初始化字段 f 的初始化形参

dart
class C {
  int f;

  C(this.f);

  C.zero(this.f) : this(f);
}

以下代码会产生此诊断信息,因为重定向到构造函数 C 的构造函数 C.zero 具有初始化字段 f 的初始化器

dart
class C {
  int f;

  C(this.f);

  C.zero() : f = 0, this(1);
}

常见修复方法

#

如果初始化是通过初始化形参完成的,则使用普通形参

dart
class C {
  int f;

  C(this.f);

  C.zero(int f) : this(f);
}

如果初始化是在初始化器中完成的,则删除初始化器

dart
class C {
  int f;

  C(this.f);

  C.zero() : this(0);
}

字段初始化形式参数不可赋值

#

形参类型“{0}”与字段类型“{1}”不兼容。

描述

#

当初始化形参的类型不能赋值给被初始化的字段的类型时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为初始化形参的类型为 String,但字段的类型为 int。形参的类型必须是字段类型的子类型。

dart
class C {
  int f;

  C(String this.f);
}

常见修复方法

#

如果字段的类型不正确,则更改字段的类型以匹配形参的类型,并考虑从形参中删除类型

dart
class C {
  String f;

  C(this.f);
}

如果形参的类型不正确,则删除形参的类型

dart
class C {
  int f;

  C(this.f);
}

如果字段和形参的类型都正确,则使用初始化器而不是初始化形参来将形参值转换为正确类型的值

dart
class C {
  int f;

  C(String s) : f = int.parse(s);
}

带有初始化器的 struct 中的字段

#

“Struct”和“Union”子类中的字段不能有初始化器。

描述

#

Struct 子类中的字段具有初始化器时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会产生此诊断信息,因为字段 p 具有初始化器

dart
// @dart = 2.9
import 'dart:ffi';

final class C extends Struct {
  Pointer p = nullptr;
}

常见修复方法

#

删除初始化器

dart
// @dart = 2.9
import 'dart:ffi';

final class C extends Struct {
  Pointer p;
}

struct 中的字段必须是 external 声明

#

“Struct”和“Union”子类的字段必须标记为 external。

描述

#

StructUnion 子类中的字段未标记为 external 时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会产生此诊断信息,因为字段 a 未标记为 external

dart
import 'dart:ffi';

final class C extends Struct {
  @Int16()
  int a;
}

常见修复方法

#

添加所需的 external 修饰符

dart
import 'dart:ffi';

final class C extends Struct {
  @Int16()
  external int a;
}

final 字段在声明和构造函数中都进行了初始化

#

“{0}”是 final 的,并且在声明时已赋值,因此无法设置为新值。

描述

#

当 final 字段被初始化两次时,分析器会生成此诊断信息:一次在声明时,一次通过构造函数的形参。

示例

#

以下代码会产生此诊断信息,因为字段 f 被初始化了两次

dart
class C {
  final int f = 0;

  C(this.f);
}

常见修复方法

#

如果该字段对于所有实例应具有相同的值,则删除形参列表中的初始化

dart
class C {
  final int f = 0;

  C();
}

如果该字段在不同的实例中可以具有不同的值,则删除声明中的初始化

dart
class C {
  final int f;

  C(this.f);
}

final 未初始化

#

final 变量“{0}”必须被初始化。

描述

#

当 final 字段或变量未初始化时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 x 没有初始化器

dart
final x;

常见修复方法

#

对于变量和静态字段,您可以添加初始化器

dart
final x = 0;

对于实例字段,您可以添加初始化器,如前面的示例所示,或者您可以在每个构造函数中初始化该字段。您可以使用初始化形参来初始化该字段

dart
class C {
  final int x;
  C(this.x);
}

您也可以在构造函数中使用初始化器列表来初始化该字段

dart
class C {
  final int x;
  C(int y) : x = y * 2;
}

构造函数中 final 未初始化

#

所有 final 变量都必须初始化,但“{0}”和“{1}”未初始化。

所有 final 变量都必须初始化,但“{0}”未初始化。

所有 final 变量都必须初始化,但“{0}”、“{1}”和另外 {2} 个未初始化。

描述

#

当一个类定义了一个或多个没有初始化器的 final 实例字段,并且至少有一个构造函数没有初始化这些字段时,分析器会生成此诊断信息。所有 final 实例字段都必须在创建实例时初始化,可以通过字段的初始化器或构造函数来完成。

示例

#

以下代码生成此诊断消息:

dart
class C {
  final String value;

  C();
}

常见修复方法

#

如果该值应直接传递到构造函数中,则使用初始化形参来初始化字段 value

dart
class C {
  final String value;

  C(this.value);
}

如果该值应从调用者提供的值间接计算得出,则添加一个形参并包含一个初始化器

dart
class C {
  final String value;

  C(Object o) : value = o.toString();
}

如果字段的值不依赖于可以传递给构造函数的值,则在字段声明中为该字段添加一个初始化器

dart
class C {
  final String value = '';

  C();
}

如果字段的值不依赖于可以传递给构造函数的值,但不同的构造函数需要将其初始化为不同的值,则在初始化器列表中为该字段添加一个初始化器

dart
class C {
  final String value;

  C() : value = '';

  C.named() : value = 'c';
}

但是,如果该值对于所有实例都相同,则考虑使用静态字段而不是实例字段

dart
class C {
  static const String value = '';

  C();
}

Flutter 字段不是 Map

#

“flutter”字段的值应为 map。

描述

#

flutter 键的值不是 map 时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为顶层 flutter 键的值是字符串

yaml
name: example
flutter: true

常见修复方法

#

如果您需要指定 Flutter 特定的选项,则将值更改为 map

yaml
name: example
flutter:
  uses-material-design: true

如果您不需要指定 Flutter 特定的选项,则删除 flutter

yaml
name: example

for-in 循环的元素类型无效

#

“for”循环中使用的类型“{0}”必须实现“{1}”,且类型参数可赋值给“{2}”。

描述

#

当 for-in 循环中的 IterableStream 的元素类型不能赋值给循环变量时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 <String>[] 的元素类型为 String,而 String 不能赋值给 e 的类型 (int)

dart
void f() {
  for (int e in <String>[]) {
    print(e);
  }
}

常见修复方法

#

如果循环变量的类型正确,则更新 iterable 的类型

dart
void f() {
  for (int e in <int>[]) {
    print(e);
  }
}

如果 iterable 的类型正确,则更新循环变量的类型

dart
void f() {
  for (String e in <String>[]) {
    print(e);
  }
}

for-in 循环的类型无效

#

“for”循环中使用的类型“{0}”必须实现“{1}”。

描述

#

当 for-in 循环中 in 后面的表达式的类型不是 Iterable 的子类时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 mMap,而 Map 不是 Iterable 的子类

dart
void f(Map<String, String> m) {
  for (String s in m) {
    print(s);
  }
}

常见修复方法

#

将表达式替换为生成 iterable 值的表达式

dart
void f(Map<String, String> m) {
  for (String s in m.values) {
    print(s);
  }
}

带有 const 变量的 for-in 循环

#

for-in 循环变量不能是“const”。

描述

#

当 for-in 循环中声明的循环变量被声明为 const 时,分析器会生成此诊断信息。变量不能是 const,因为该值无法在编译时计算。

示例

#

以下代码会产生此诊断信息,因为循环变量 x 被声明为 const

dart
void f() {
  for (const x in [0, 1, 2]) {
    print(x);
  }
}

常见修复方法

#

如果存在类型注解,则从声明中删除 const 修饰符。

如果不存在类型,则将 const 修饰符替换为 finalvar 或类型注解

dart
void f() {
  for (final x in [0, 1, 2]) {
    print(x);
  }
}

dynamic 上的泛型方法类型实例化

#

接收器类型为“dynamic”的方法拆分不能有类型参数。

描述

#

当从类型为 dynamic 的接收器中拆分实例方法,并且拆分包含类型参数时,分析器会生成此诊断信息。由于分析器无法知道该方法有多少个类型参数,或者它是否具有任何类型参数,因此无法验证类型参数是否正确。因此,不允许使用类型参数。

示例

#

以下代码会产生此诊断信息,因为 p 的类型为 dynamic,而 m 的拆分具有类型参数

dart
void f(dynamic list) {
  list.fold<int>;
}

常见修复方法

#

如果可以使用比 dynamic 更具体的类型,则更改接收器的类型

dart
void f(List<Object> list) {
  list.fold<int>;
}

如果无法使用更具体的类型,则删除类型参数

dart
void f(dynamic list) {
  list.cast;
}

泛型 struct 子类

#

类“{0}”不能扩展“Struct”或“Union”,因为“{0}”是泛型类。

描述

#

StructUnion 的子类具有类型参数时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会产生此诊断信息,因为类 S 定义了类型参数 T

dart
import 'dart:ffi';

final class S<T> extends Struct {
  external Pointer notEmpty;
}

常见修复方法

#

从类中删除类型参数

dart
import 'dart:ffi';

final class S extends Struct {
  external Pointer notEmpty;
}

getter 类型不是 setter 类型的子类型

#

getter “{0}”的返回类型为“{1}”,它不是其 setter “{3}”的类型“{2}”的子类型。

描述

#

当 getter 的返回类型不是与它同名的 setter 的形参类型的子类型时,分析器会生成此诊断信息。

子类型关系是必要条件,无论 getter 和 setter 是否在同一个类中,或者其中一个是否在另一个的超类中。

示例

#

以下代码会产生此诊断信息,因为 getter x 的返回类型为 num,setter x 的形参类型为 int,而 num 不是 int 的子类型

dart
class C {
  num get x => 0;

  set x(int y) {}
}

常见修复方法

#

如果 getter 的类型正确,则更改 setter 的类型

dart
class C {
  num get x => 0;

  set x(num y) {}
}

如果 setter 的类型正确,则更改 getter 的类型

dart
class C {
  int get x => 0;

  set x(int y) {}
}

非法的异步生成器返回类型

#

标记为“async*”的函数必须具有作为“Stream”的超类型的返回类型,其中“T”为某种类型。

描述

#

当函数的函数体具有 async* 修饰符,即使函数的返回类型不是 StreamStream 的超类型时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为函数 f 的函数体具有“async*”修饰符,即使返回类型 int 不是 Stream 的超类型

dart
int f() async* {}

常见修复方法

#

如果函数应为异步的,则将返回类型更改为 StreamStream 的超类型

dart
Stream<int> f() async* {}

如果函数应为同步的,则删除 async* 修饰符

dart
int f() => 0;

非法的异步返回类型

#

标记为“async”的函数必须具有作为“Future”的超类型的返回类型。

描述

#

当函数的函数体具有 async 修饰符,即使函数的返回类型不能赋值给 Future 时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为函数 f 的函数体具有 async 修饰符,即使返回类型不能赋值给 Future

dart
int f() async {
  return 0;
}

常见修复方法

#

如果函数应为异步的,则将返回类型更改为可赋值给 Future 的类型

dart
Future<int> f() async {
  return 0;
}

如果函数应为同步的,则删除 async 修饰符

dart
int f() => 0;

非法的具体枚举成员

#

名为“{0}”的具体实例成员不能在实现“Enum”的类中声明。

名为“{0}”的具体实例成员不能从实现“Enum”的类中的“{1}”继承。

描述

#

当枚举声明、实现 Enum 的类或具有 Enum 的超类约束的 mixin 声明或继承了名为 indexhashCode== 的具体实例成员时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为枚举 E 声明了一个名为 index 的实例 getter

dart
enum E {
  v;

  int get index => 0;
}

以下代码会产生此诊断信息,因为实现 Enum 的类 C 声明了一个名为 hashCode 的实例字段

dart
abstract class C implements Enum {
  int hashCode = 0;
}

以下代码会产生此诊断信息,因为通过类 A 间接实现 Enum 的类 C 声明了一个名为 hashCode 的实例 getter

dart
abstract class A implements Enum {}

abstract class C implements A {
  int get hashCode => 0;
}

以下代码会产生此诊断信息,因为在 on 子句中具有 Enum 的 mixin M 声明了一个显式运算符 ==

dart
mixin M on Enum {
  bool operator ==(Object other) => false;
}

常见修复方法

#

重命名冲突的成员

dart
enum E {
  v;

  int get getIndex => 0;
}

非法的枚举 values

#

名为“values”的实例成员不能在实现“Enum”的类中声明。

名为“values”的实例成员不能从实现“Enum”的类中的“{0}”继承。

描述

#

当实现 Enum 的类或具有 Enum 的超类约束的 mixin 具有名为 values 的实例成员时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为实现 Enum 的类 C 声明了一个名为 values 的实例字段

dart
abstract class C implements Enum {
  int get values => 0;
}

以下代码会产生此诊断信息,因为实现 Enum 的类 BA 继承了一个名为 values 的实例方法

dart
abstract class A {
  int values() => 0;
}

abstract class B extends A implements Enum {}

常见修复方法

#

更改冲突成员的名称

dart
abstract class C implements Enum {
  int get value => 0;
}

非法的同步生成器返回类型

#

标记为“sync*”的函数必须具有作为“Iterable”的超类型的返回类型,其中“T”为某种类型。

描述

#

分析器会生成此诊断信息,当函数的函数体具有 sync* 修饰符,即使函数的返回类型不是 IterableIterable 的超类型时。

示例

#

以下代码会产生此诊断信息,因为函数 f 的函数体具有“sync*”修饰符,即使返回类型 int 不是 Iterable 的超类型

dart
int f() sync* {}

常见修复方法

#

如果函数应返回 iterable,则将返回类型更改为 IterableIterable 的超类型

dart
Iterable<int> f() sync* {}

如果函数应返回单个值,则删除 sync* 修饰符

dart
int f() => 0;

实现非类

#

类和 mixin 只能实现其他类和 mixin。

描述

#

当在类或 mixin 声明的 implements 子句中使用的名称被定义为类或 mixin 以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 x 是变量而不是类或 mixin

dart
var x;
class C implements x {}

常见修复方法

#

如果该名称是已导入的现有类或 mixin 的名称,则为导入添加前缀,以便名称的本地定义不会遮蔽导入的名称。

如果该名称是未导入的现有类或 mixin 的名称,则为声明它的库添加一个带前缀的导入。

否则,将 implements 子句中的名称替换为现有类或 mixin 的名称,或从 implements 子句中删除该名称。

重复实现

#

“{0}”只能实现一次。

描述

#

当在 implements 子句中多次指定同一个类时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 A 在列表中出现了两次

dart
class A {}
class B implements A, A {}

常见修复方法

#

删除除一个类名之外的所有类名

dart
class A {}
class B implements A {}

实现超类

#

“{0}”不能同时在“extends”和“implements”子句中使用。

“{0}”不能同时在“extends”和“with”子句中使用。

描述

#

当一个类在类声明的 extends 子句中列出,并且同时在同一声明的 implementswith 子句中列出时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为类 A 同时在类 Bextendsimplements 子句中使用

dart
class A {}

class B extends A implements A {}

以下代码会产生此诊断信息,因为类 A 同时在类 Bextendswith 子句中使用

dart
mixin class A {}

class B extends A with A {}

常见修复方法

#

如果想要从类继承实现,则从 implements 子句中删除该类

dart
class A {}

class B extends A {}

如果不想要从类继承实现,则删除 extends 子句

dart
class A {}

class B implements A {}

隐式 super 初始化器缺少参数

#

从“{0}”隐式调用的未命名构造函数具有必需的形参。

描述

#

当构造函数隐式调用超类的未命名构造函数,超类的未命名构造函数具有必需的形参,并且没有与必需的形参对应的 super 形参时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为类 B 中的未命名构造函数隐式调用类 A 中的未命名构造函数,但 A 中的构造函数具有名为 x 的必需位置形参

dart
class A {
  A(int x);
}

class B extends A {
  B();
}

以下代码会产生此诊断信息,因为类 B 中的未命名构造函数隐式调用类 A 中的未命名构造函数,但 A 中的构造函数具有名为 x 的必需命名形参

dart
class A {
  A({required int x});
}

class B extends A {
  B();
}

常见修复方法

#

如果可以向子类中的构造函数添加形参,则添加与超类构造函数中必需的形参对应的 super 形参。新形参可以是必需的

dart
class A {
  A({required int x});
}

class B extends A {
  B({required super.x});
}

或者它可以是可选的

dart
class A {
  A({required int x});
}

class B extends A {
  B({super.x = 0});
}

如果不能向子类中的构造函数添加形参,则添加带有必需参数的显式 super 构造函数调用

dart
class A {
  A(int x);
}

class B extends A {
  B() : super(0);
}

初始化器中隐式的 this 引用

#

实例成员“{0}”不能在初始化器中访问。

描述

#

当分析器在构造函数的初始化器列表中找到对实例成员的引用时,会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 defaultX 是实例成员

dart
class C {
  int x;

  C() : x = defaultX;

  int get defaultX => 0;
}

常见修复方法

#

如果可以将成员设为静态成员,则这样做

dart
class C {
  int x;

  C() : x = defaultX;

  static int get defaultX => 0;
}

否则,将初始化器中的引用替换为不使用实例成员的不同表达式

dart
class C {
  int x;

  C() : x = 0;

  int get defaultX => 0;
}

导入带有 load 函数的延迟库

#

导入的库定义了一个名为“loadLibrary”的顶层函数,该函数被延迟此库而隐藏。

描述

#

当使用延迟导入导入声明了名为 loadLibrary 的函数的库时,分析器会生成此诊断信息。延迟导入引入了一个名为 loadLibrary 的隐式函数。此函数用于加载延迟库的内容,并且隐式函数隐藏了延迟库中的显式声明。

有关更多信息,请查看 延迟加载库

示例

#

给定一个定义了名为 loadLibrary 的函数的文件 a.dart

dart
void loadLibrary(Library library) {}

class Library {}

以下代码会产生此诊断信息,因为 a.loadLibrary 的隐式声明正在隐藏 a.dartloadLibrary 的显式声明

dart
import 'a.dart' deferred as a;

void f() {
  a.Library();
}

常见修复方法

#

如果不需要延迟导入导入的库,则删除关键字 deferred

dart
import 'a.dart' as a;

void f() {
  a.Library();
}

如果需要延迟导入导入的库,并且需要引用导入的函数,则重命名导入的库中的函数

dart
void populateLibrary(Library library) {}

class Library {}

如果需要延迟导入导入的库,并且不需要引用导入的函数,则添加 hide 子句

dart
import 'a.dart' deferred as a hide loadLibrary;

void f() {
  a.Library();
}

导入内部库

#

库“{0}”是内部库,无法导入。

描述

#

当分析器发现 dart: URI 引用内部库的导入时,会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 _interceptors 是一个内部库

dart
import 'dart:_interceptors';

常见修复方法

#

删除导入指令。

将旧式库导入到空安全代码中

#

库“{0}”是旧版库,不应导入到空安全库中。

描述

#

当空安全库导入非空安全库时,分析器会生成此诊断信息。

示例

#

给定一个包含以下内容的文件 a.dart

dart
// @dart = 2.9

class A {}

以下代码会产生此诊断信息,因为空安全库正在导入非空安全库

dart
import 'a.dart';

A? f() => null;

常见修复方法

#

如果可以将导入的库迁移到空安全,则迁移它并更新或删除迁移库的语言版本。

如果无法迁移导入的库,则导入库需要具有 2.12 之前的语言版本,那时默认启用空安全。

导入非库文件

#

导入的库“{0}”不能有 part-of 指令。

描述

#

part 文件 被导入到库中时,分析器会生成此诊断信息。

示例

#

给定一个名为 part.dartpart 文件,其中包含以下内容

dart
part of lib;

以下代码会产生此诊断信息,因为导入的文件不能有 part-of 指令

dart
library lib;

import 'part.dart';

常见修复方法

#

导入包含 part 文件 的库,而不是 part 文件 本身。

不一致的继承

#

超接口对于“{0}”没有有效的重写:{1}。

描述

#

当一个类为一个成员继承了两个或多个冲突的签名,并且没有提供满足所有继承签名的实现时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 C 正在从 A 继承 m 的声明,并且该实现与从 B 继承的 m 的签名不一致

dart
class A {
  void m({int? a}) {}
}

class B {
  void m({int? b}) {}
}

class C extends A implements B {
}

常见修复方法

#

添加一个满足所有继承签名的方法的实现

dart
class A {
  void m({int? a}) {}
}

class B {
  void m({int? b}) {}
}

class C extends A implements B {
  void m({int? a, int? b}) {}
}

不一致的语言版本覆盖

#

Part 文件必须与库具有完全相同的语言版本覆盖。

描述

#

part 文件 具有语言版本覆盖注释,该注释指定的语言版本与用于 part 文件所属库的语言版本不同时,分析器会生成此诊断信息。

示例

#

给定一个名为 part.dartpart 文件,其中包含以下内容

dart
// @dart = 2.14
part of 'test.dart';

以下代码会产生此诊断信息,因为库的 part 文件必须与定义编译单元具有相同的语言版本

dart
// @dart = 2.15
part 'part.dart';

常见修复方法

#

part 文件 中删除语言版本覆盖,以便它隐式地使用与定义编译单元相同的版本

dart
part of 'test.dart';

如有必要,调整定义编译单元中的语言版本覆盖以适合 part 文件中的代码,或迁移 part 文件 中的代码以与新的语言版本保持一致。

不一致的模式变量逻辑或

#

变量“{0}”在此逻辑或模式的分支中具有不同的类型和/或 final 性。

描述

#

当在逻辑或模式的所有分支上声明的模式变量在每个分支上没有相同的类型时,分析器会生成此诊断信息。当变量在不同分支上具有不同的 final 性时,也会生成此诊断信息。在逻辑或模式的多个分支上声明的模式变量需要在每个分支中具有相同的类型和 final 性,以便可以在受逻辑或模式保护的代码中知道变量的类型和 final 性。

示例

#

以下代码会产生此诊断信息,因为变量 a 在一个分支中定义为 int,而在另一个分支中定义为 double

dart
void f(Object? x) {
  if (x case (int a) || (double a)) {
    print(a);
  }
}

以下代码会产生此诊断信息,因为变量 a 在第一个分支中是 final,而在第二个分支中不是 final

dart
void f(Object? x) {
  if (x case (final int a) || (int a)) {
    print(a);
  }
}

常见修复方法

#

如果变量的 final 性不同,请决定它应该是 final 还是非 final,并使情况保持一致

dart
void f(Object? x) {
  if (x case (int a) || (int a)) {
    print(a);
  }
}

如果变量的类型不同,并且该类型对于要匹配的条件并不重要,则确保该变量在两个分支上都具有相同的类型

dart
void f(Object? x) {
  if (x case (num a) || (num a)) {
    print(a);
  }
}

如果变量的类型不同,并且该类型对于要匹配的条件至关重要,则考虑将条件分解为多个 if 语句或 case 子句

dart
void f(Object? x) {
  if (x case int a) {
    print(a);
  } else if (x case double a) {
    print(a);
  }
}

不存在的字段的初始化器

#

“{0}”不是封闭类中的字段。

描述

#

当构造函数初始化一个未在包含该构造函数的类中声明的字段时,分析器会生成此诊断信息。构造函数无法初始化未声明的字段和从超类继承的字段。

示例

#

以下代码会产生此诊断信息,因为初始化器正在初始化 x,但 x 不是类中的字段

dart
class C {
  int? y;

  C() : x = 0;
}

常见修复方法

#

如果要初始化不同的字段,则将名称更改为字段的名称

dart
class C {
  int? y;

  C() : y = 0;
}

如果必须声明该字段,则添加声明

dart
class C {
  int? x;
  int? y;

  C() : x = 0;
}

静态字段的初始化器

#

“{0}”是封闭类中的静态字段。在构造函数中初始化的字段不能是静态的。

描述

#

当静态字段在构造函数中使用初始化形参或初始化器列表中的赋值进行初始化时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为静态字段 a 正在被初始化形参 this.a 初始化

dart
class C {
  static int? a;
  C(this.a);
}

常见修复方法

#

如果该字段应为实例字段,则删除关键字 static

dart
class C {
  int? a;
  C(this.a);
}

如果您打算初始化实例字段并输入了错误的名称,请更正要初始化的字段的名称

dart
class C {
  static int? a;
  int? b;
  C(this.b);
}

如果确实要初始化静态字段,则将初始化移到构造函数体中

dart
class C {
  static int? a;
  C(int? c) {
    a = c;
  }
}

不存在的字段的初始化形式参数

#

“{0}”不是封闭类中的字段。

描述

#

当在未声明要初始化的字段的类中的构造函数中找到初始化形参时,分析器会生成此诊断信息。构造函数无法初始化未声明的字段和从超类继承的字段。

示例

#

以下代码会产生此诊断信息,因为字段 x 未定义

dart
class C {
  int? y;

  C(this.x);
}

常见修复方法

#

如果字段名称错误,则将其更改为现有字段的名称

dart
class C {
  int? y;

  C(this.y);
}

如果字段名称正确但尚未定义,则声明该字段

dart
class C {
  int? x;
  int? y;

  C(this.x);
}

如果需要该形参但不应初始化字段,则将其转换为普通形参并使用它

dart
class C {
  int y;

  C(int x) : y = x * 2;
}

如果不需要该形参,则删除它

dart
class C {
  int? y;

  C();
}

实例访问静态成员

#

无法通过实例访问静态 {1} “{0}”。

描述

#

当使用访问运算符通过类的实例访问静态成员时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 zero 是静态字段,但它被访问为实例字段

dart
void f(C c) {
  c.zero;
}

class C {
  static int zero = 0;
}

常见修复方法

#

使用类来访问静态成员

dart
void f(C c) {
  C.zero;
}

class C {
  static int zero = 0;
}

从工厂构造函数访问实例成员

#

无法从工厂构造函数访问实例成员。

描述

#

当工厂构造函数包含对实例成员的非限定引用时,分析器会生成此诊断信息。在生成构造函数中,类的实例在执行构造函数体之前创建和初始化,因此可以将实例绑定到 this 并像在实例方法中一样访问它。但是,在工厂构造函数中,实例在执行函数体之前不会创建,因此 this 不能用于引用它。

示例

#

以下代码会产生此诊断信息,因为 x 在工厂构造函数中不在作用域内

dart
class C {
  int x;
  factory C() {
    return C._(x);
  }
  C._(this.x);
}

常见修复方法

#

重写代码,使其不引用实例成员

dart
class C {
  int x;
  factory C() {
    return C._(0);
  }
  C._(this.x);
}

从静态成员访问实例成员

#

无法从静态方法访问实例成员。

描述

#

当静态方法包含对实例成员的非限定引用时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为实例字段 x 正在静态方法中被引用

dart
class C {
  int x = 0;

  static int m() {
    return x;
  }
}

常见修复方法

#

如果该方法必须引用实例成员,则它不能是静态的,因此删除关键字

dart
class C {
  int x = 0;

  int m() {
    return x;
  }
}

如果该方法不能设为实例方法,则添加一个形参,以便可以传入类的实例

dart
class C {
  int x = 0;

  static int m(C c) {
    return c.x;
  }
}

实例化抽象类

#

抽象类不能被实例化。

描述

#

当分析器找到构造函数调用并且构造函数在抽象类中声明时,分析器会生成此诊断信息。即使您无法创建抽象类的实例,抽象类也可以声明可以被子类调用的构造函数。

示例

#

以下代码会产生此诊断信息,因为 C 是一个抽象类

dart
abstract class C {}

var c = new C();

常见修复方法

#

如果存在可以使用的抽象类的具体子类,则创建具体子类的实例。

实例化枚举

#

枚举不能被实例化。

描述

#

当枚举被实例化时,分析器会生成此诊断信息。通过调用构造函数来创建枚举的实例是无效的;只能存在枚举声明中命名的实例。

示例

#

以下代码会产生此诊断信息,因为枚举 E 正在被实例化

dart
// @dart = 2.16
enum E {a}

var e = E();

常见修复方法

#

如果您打算使用枚举的实例,则引用枚举中定义的常量之一

dart
// @dart = 2.16
enum E {a}

var e = E.a;

如果您打算使用类的实例,则使用该类的名称代替枚举的名称。

实例化扩展为类型参数的类型别名

#

扩展为类型参数的类型别名不能被实例化。

描述

#

当找到构造函数调用,其中要实例化的类型是类型别名的类型参数之一的类型别名时,分析器会生成此诊断信息。这是不允许的,因为类型参数的值是类型而不是类。

示例

#

以下代码会产生此诊断信息,因为它创建了 A 的实例,即使 A 是定义为等效于类型参数的类型别名

dart
typedef A<T> = T;

void f() {
  const A<int>();
}

常见修复方法

#

使用类名或定义为类的类型别名,而不是定义为类型参数的类型别名

dart
typedef A<T> = C<T>;

void f() {
  const A<int>();
}

class C<T> {
  const C();
}

整数字面量作为 double 类型不精确

#

整数文字被用作 double,但无法在不溢出或丢失精度的情况下表示为 64 位 double:“{0}”。

描述

#

当整数文字被隐式转换为 double,但无法在不溢出或丢失精度的情况下表示为 64 位 double 时,分析器会生成此诊断信息。如果上下文需要 double 类型,则整数文字会被隐式转换为 double。

示例

#

以下代码会产生此诊断信息,因为整数值 9223372036854775807 无法精确地表示为 double

dart
double x = 9223372036854775807;

常见修复方法

#

如果您需要使用精确值,则使用类 BigInt 来表示该值

dart
var x = BigInt.parse('9223372036854775807');

如果您需要使用 double,则将值更改为可以精确表示的值

dart
double x = 9223372036854775808;

整数字面量超出范围

#

整数文字 {0} 无法用 64 位表示。

描述

#

当整数文字的值太大(正数)或太小(负数)而无法用 64 位字表示时,分析器会生成此诊断信息。

示例

#

以下代码会产生此诊断信息,因为该值无法用 64 位表示

dart
var x = 9223372036854775810;

常见修复方法

#

如果您需要表示当前值,则将其包装在类 BigInt 的实例中

dart
var x = BigInt.parse('9223372036854775810');

无效的注解

#

注解必须是 const 变量引用或 const 构造函数调用。

描述

#

当找到的注解正在使用既不是标记为 const 的变量也不是 const 构造函数的调用时,分析器会生成此诊断信息。

Getter 不能用作注解。

示例

#

以下代码会产生此诊断信息,因为变量 v 不是 const 变量

dart
var v = 0;

@v
void f() {
}

以下代码会产生此诊断信息,因为 f 不是变量

dart
@f
void f() {
}

以下代码会产生此诊断信息,因为 f 不是构造函数

dart
@f()
void f() {
}

以下代码会产生此诊断信息,因为 g 是一个 getter

dart
@g
int get g => 0;

常见修复方法

#

如果注解正在引用不是 const 构造函数的变量,则将关键字 const 添加到变量的声明中

dart
const v = 0;

@v
void f() {
}

如果注解没有引用变量,则删除它

dart
int v = 0;

void f() {
}

来自延迟库的无效注解常量值

#

延迟库中的常量值不能在注解中使用。

描述

#

当延迟导入的库中定义的常量在注解的参数列表中被引用时,分析器会生成此诊断信息。注解在编译时求值,而延迟库中的值在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

以下代码会产生此诊断,因为常量 pi 在注解的参数列表中被引用,即使定义它的库是以延迟库的形式导入的。

dart
import 'dart:math' deferred as math;

class C {
  const C(double d);
}

@C(math.pi)
void f () {}

常见修复方法

#

如果需要引用导入的常量,请删除 deferred 关键字。

dart
import 'dart:math' as math;

class C {
  const C(double d);
}

@C(math.pi)
void f () {}

如果导入需要延迟,并且有另一个合适的常量,则使用该常量代替延迟库中的常量。

来自延迟库的无效注解

#

来自延迟库的常量值不能用作注解。

描述

#

当来自使用延迟导入的库的常量被用作注解时,分析器会产生此诊断。注解在编译时求值,而来自延迟库的常量在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

以下代码会产生此诊断,因为常量 pi 在库 dart:mathdeferred 形式导入时被用作注解。

dart
import 'dart:math' deferred as math;

@math.pi
void f() {}

常见修复方法

#

如果需要将常量作为注解引用,请从导入中删除关键字 deferred

dart
import 'dart:math' as math;

@math.pi
void f() {}

如果可以使用不同的常量作为注解,则将注解替换为不同的常量。

dart
@deprecated
void f() {}

无效的注解目标

#

注解 '{0}' 只能用于 {1}。

描述

#

当注解应用于它不支持的声明类型时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 optionalTypeArgs 注解未定义为对顶级变量有效。

dart
import 'package:meta/meta.dart';

@optionalTypeArgs
int x = 0;

常见修复方法

#

从声明中删除注解。

无效的赋值

#

类型为 '{0}' 的值不能赋给类型为 '{1}' 的变量。

描述

#

当赋值给变量的表达式的静态类型与变量的类型不兼容时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为初始化器 (int) 的类型与变量 (String) 的类型不兼容。

dart
int i = 0;
String s = i;

常见修复方法

#

如果被赋值的值在运行时始终兼容,即使静态类型没有反映这一点,则添加显式类型转换。

否则,更改被赋值的值,使其具有预期的类型。在前面的示例中,可能如下所示:

dart
int i = 0;
String s = i.toString();

如果无法更改值,则更改变量的类型以使其与被赋值的值的类型兼容。

dart
int i = 0;
int s = i;

无效的依赖

#

可发布的软件包不能有 '{0}' 依赖项。

描述

#

当可发布的软件包在其 pubspec.yaml 文件的 dependencies 列表中包含一个不是 pub 托管的依赖项时,分析器会产生此诊断。

要了解有关不同类型的依赖项来源的更多信息,请查看 软件包依赖项

示例

#

以下代码会产生此诊断,因为对软件包 transmogrify 的依赖项不是 pub 托管的依赖项。

yaml
name: example
dependencies:
  transmogrify:
    path: ../transmogrify

常见修复方法

#

如果要将软件包发布到 pub.dev,则将依赖项更改为在 pub.dev 上发布的托管软件包。

如果软件包不打算在 pub.dev 上发布,则在其 pubspec.yaml 文件中添加 publish_to: none 条目,将其标记为不打算发布。

yaml
name: example
publish_to: none
dependencies:
  transmogrify:
    path: ../transmogrify

无效的异常值

#

当函数的返回类型为 'void'、'Handle' 或 'Pointer' 时,方法 {0} 不能具有异常返回值(第二个参数)。

描述

#

当调用 Pointer.fromFunctionNativeCallable.isolateLocal 方法时,如果具有第二个参数(异常返回值),并且要从调用返回的类型为 voidHandlePointer,则分析器会产生此诊断。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会产生此诊断,因为当 f 的返回类型为 void 时,提供了第二个参数。

dart
import 'dart:ffi';

typedef T = Void Function(Int8);

void f(int i) {}

void g() {
  Pointer.fromFunction<T>(f, 42);
}

常见修复方法

#

删除异常值。

dart
import 'dart:ffi';

typedef T = Void Function(Int8);

void f(int i) {}

void g() {
  Pointer.fromFunction<T>(f);
}

无效地导出内部元素

#

成员 '{0}' 不能作为软件包公共 API 的一部分导出。

描述

#

公共库 导出使用 internal 注解标记的声明时,分析器会产生此诊断。

示例

#

给定 src 目录中的文件 a.dart,其中包含:

dart
import 'package:meta/meta.dart';

@internal class One {}

以下代码在 公共库 中找到时,会产生此诊断,因为 export 指令正在导出仅供内部使用的名称。

dart
export 'src/a.dart';

常见修复方法

#

如果需要导出,则添加 hide 子句以隐藏内部名称。

dart
export 'src/a.dart' hide One;

如果不需要导出,则删除它。

无效地间接导出内部元素

#

成员 '{0}' 不能作为软件包公共 API 的一部分导出,但作为 '{1}' 的签名的一部分间接导出。

描述

#

公共库 导出一个顶级函数,其返回类型或至少一个参数类型使用 internal 注解标记时,分析器会产生此诊断。

示例

#

给定 src 目录中的文件 a.dart,其中包含以下内容:

dart
import 'package:meta/meta.dart';

@internal
typedef IntFunction = int Function();

int f(IntFunction g) => g();

以下代码会产生此诊断,因为函数 f 具有类型为 IntFunction 的参数,而 IntFunction 仅供内部使用。

dart
export 'src/a.dart' show f;

常见修复方法

#

如果函数必须是公共的,则使函数签名中的所有类型都成为公共类型。

如果函数不需要导出,则停止导出它,可以通过从 show 子句中删除它、将其添加到 hide 子句或删除导出。

无效的扩展参数计数

#

扩展覆盖必须只有一个参数:扩展方法中 'this' 的值。

描述

#

当扩展覆盖没有正好一个参数时,分析器会产生此诊断。该参数是用于计算扩展方法中 this 值的表达式,因此必须有一个参数。

示例

#

以下代码会产生此诊断,因为没有参数。

dart
extension E on String {
  String join(String other) => '$this $other';
}

void f() {
  E().join('b');
}

并且,以下代码会产生此诊断,因为有多个参数。

dart
extension E on String {
  String join(String other) => '$this $other';
}

void f() {
  E('a', 'b').join('c');
}

常见修复方法

#

为扩展覆盖提供一个参数。

dart
extension E on String {
  String join(String other) => '$this $other';
}

void f() {
  E('a').join('b');
}

无效的工厂方法声明

#

工厂方法 '{0}' 必须具有返回类型。

描述

#

当使用 factory 注解注解的方法的返回类型为 void 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为方法 createC 使用 factory 注解进行注解,但未返回任何值。

dart
import 'package:meta/meta.dart';

class Factory {
  @factory
  void createC() {}
}

class C {}

常见修复方法

#

将返回类型更改为 void 以外的类型。

dart
import 'package:meta/meta.dart';

class Factory {
  @factory
  C createC() => C();
}

class C {}

无效的工厂方法实现

#

工厂方法 '{0}' 未返回新分配的对象。

描述

#

当使用 factory 注解注解的方法未返回新分配的对象时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为方法 createC 返回字段的值,而不是 C 的新创建实例。

dart
import 'package:meta/meta.dart';

class Factory {
  C c = C();

  @factory
  C createC() => c;
}

class C {}

常见修复方法

#

更改方法以返回返回类型的新创建实例。

dart
import 'package:meta/meta.dart';

class Factory {
  @factory
  C createC() => C();
}

class C {}

无效的工厂名称,不是类

#

工厂构造函数的名称必须与直接封闭类的名称相同。

描述

#

当工厂构造函数的名称与周围类的名称不同时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为工厂构造函数 (A) 的名称与周围类 (C) 的名称不同。

dart
class A {}

class C {
  factory A() => throw 0;
}

常见修复方法

#

如果工厂返回周围类的实例,并且您打算使其成为未命名的工厂构造函数,则重命名工厂。

dart
class A {}

class C {
  factory C() => throw 0;
}

如果工厂返回周围类的实例,并且您打算使其成为命名的工厂构造函数,则在工厂构造函数的名称前加上周围类的名称。

dart
class A {}

class C {
  factory C.a() => throw 0;
}

如果工厂返回不同类的实例,则将工厂移动到该类。

dart
class A {
  factory A() => throw 0;
}

class C {}

如果工厂返回不同类的实例,但您无法修改该类或不想移动工厂,则将其转换为静态方法。

dart
class A {}

class C {
  static A a() => throw 0;
}

无效的字段名称

#

当整数是位置字段的索引时,记录字段名称不能是以美元符号后跟整数开头。

记录字段名称不能是私有的。

记录字段名称不能与 'Object' 中的成员相同。

描述

#

当记录字面量或记录类型注解具有字段名称无效时,分析器会产生此诊断。如果名称是以下情况,则无效:

  • 私有的(以 _ 开头)
  • Object 上定义的成员之一相同
  • 与位置字段的名称相同(如果字段是具有指定名称的位置字段,则会例外)

示例

#

以下代码会产生此诊断,因为记录字面量具有名为 toString 的字段,它是 Object 上定义的方法。

dart
var r = (a: 1, toString: 4);

以下代码会产生此诊断,因为记录类型注解具有名为 hashCode 的字段,它是 Object 上定义的 getter。

dart
void f(({int a, int hashCode}) r) {}

以下代码会产生此诊断,因为记录字面量具有名为 _a 的私有字段。

dart
var r = (_a: 1, b: 2);

以下代码会产生此诊断,因为记录类型注解具有名为 _a 的私有字段。

dart
void f(({int _a, int b}) r) {}

以下代码会产生此诊断,因为记录字面量具有名为 $1 的字段,它也是不同位置参数的名称。

dart
var r = (2, $1: 1);

以下代码会产生此诊断,因为记录类型注解具有名为 $1 的字段,它也是不同位置参数的名称。

dart
void f((int, String, {int $1}) r) {}

常见修复方法

#

重命名字段。

dart
var r = (a: 1, d: 4);

struct 中无效的字段类型

#

结构类中的字段不能具有类型 '{0}'。它们只能声明为 'int'、'double'、'Array'、'Pointer' 或 'Struct' 或 'Union' 的子类型。

描述

#

Struct 子类中的字段的类型不是 intdoubleArrayPointerStructUnion 的子类型时,分析器会产生此诊断。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会产生此诊断,因为字段 str 的类型为 String,这不是 Struct 子类中字段的允许类型之一。

dart
import 'dart:ffi';

final class C extends Struct {
  external String s;

  @Int32()
  external int i;
}

常见修复方法

#

为字段使用允许的类型之一。

dart
import 'dart:ffi';
import 'package:ffi/ffi.dart';

final class C extends Struct {
  external Pointer<Utf8> s;

  @Int32()
  external int i;
}

无效的实现覆盖

#

'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效具体实现。

Setter '{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效具体实现。

描述

#

当以下所有条件都为真时,分析器会产生此诊断:

  • 类定义了一个抽象成员。
  • 超类中存在该成员的具体实现。
  • 具体实现不是抽象方法的有效实现。

具体实现可能由于返回类型、方法参数类型或类型参数的不兼容而无效。

示例

#

以下代码会产生此诊断,因为方法 A.add 具有类型为 int 的参数,而重写方法 B.add 具有类型为 num 的相应参数。

dart
class A {
  int add(int a) => a;
}
class B extends A {
  int add(num a);
}

这是一个问题,因为在像下面这样的 B.add 调用中:

dart
void f(B b) {
  b.add(3.4);
}

B.add 期望能够接受例如 double,但是当方法 A.add 被执行时(因为它是 add 的唯一具体实现),会抛出运行时异常,因为 double 不能赋值给类型为 int 的参数。

常见修复方法

#

如果子类中的方法可以符合超类中的实现,则更改子类中的声明(如果相同,则删除它)。

dart
class A {
  int add(int a) => a;
}
class B	extends A {
  int add(int a);
}

如果可以泛化超类中的方法以使其成为子类中方法的有效实现,则更改超类方法。

dart
class A {
  int add(num a) => a.floor();
}
class B	extends A {
  int add(num a);
}

如果超类中的方法和子类中的方法都无法更改,则在子类中提供该方法的具体实现。

dart
class A {
  int add(int a) => a;
}
class B	extends A {
  int add(num a) => a.floor();
}

无效的内联函数类型

#

内联函数类型不能用于泛型函数类型中的参数。

描述

#

当泛型函数类型具有使用较旧的内联函数类型语法编写的函数值参数时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为用于定义 F 的泛型函数类型中的参数 f 使用了内联函数类型语法。

dart
typedef F = int Function(int f(String s));

常见修复方法

#

对参数的类型使用泛型函数语法。

dart
typedef F = int Function(int Function(String));

无效的内部注解

#

软件包私有 API 中的公共元素只能注解为内部的。

描述

#

当声明使用 internal 注解进行注解,并且该声明位于 公共库 中或具有私有名称时,分析器会产生此诊断。

示例

#

以下代码在 公共库 中时,会产生此诊断,因为 internal 注解不能应用于 公共库 中的声明。

dart
import 'package:meta/meta.dart';

@internal
class C {}

以下代码,无论是在公共库还是内部库中,都会产生此诊断,因为 internal 注解不能应用于具有私有名称的声明。

dart
import 'package:meta/meta.dart';

@internal
class _C {}

void f(_C c) {}

常见修复方法

#

如果声明具有私有名称,则删除注解。

dart
class _C {}

void f(_C c) {}

如果声明具有公共名称并且 intended 为软件包内部的,则将带注解的声明移动到内部库(换句话说,src 目录内的库)。

否则,删除注解的使用。

dart
class C {}

无效的语言版本覆盖

#

Dart 语言版本覆盖注释后不能跟任何非空白字符。

Dart 语言版本覆盖注释必须在 '=' 字符后指定版本号,例如 '2.0'。

Dart 语言版本覆盖注释必须使用 '=' 字符指定。

Dart 语言版本覆盖注释必须使用正好两个斜杠指定。

Dart 语言版本覆盖注释必须使用全小写字母 'dart' 指定。

Dart 语言版本覆盖号不能以字母为前缀。

Dart 语言版本覆盖号必须以 '@dart' 开头。

语言版本覆盖不能指定大于最新已知语言版本的版本:{0}.{1}。

语言版本覆盖必须在任何声明或指令之前指定。

描述

#

当看起来是尝试指定语言版本覆盖的注释不符合此类注释的要求时,分析器会产生此诊断。有关更多信息,请参阅 按库语言版本选择

示例

#

以下代码会产生此诊断,因为单词 dart 在此类注释中必须是小写的,并且单词 dart 和版本号之间没有等号。

dart
// @Dart 2.13

常见修复方法

#

如果注释 intended 为语言版本覆盖,则更改注释以遵循正确的格式。

dart
// @dart = 2.13

无效的字面量注解

#

只有常量构造函数才能具有 @literal 注解。

描述

#

literal 注解应用于常量构造函数以外的任何内容时,分析器会产生此诊断。

示例

#

以下代码生成此诊断消息,因为构造函数不是 const 构造函数

dart
import 'package:meta/meta.dart';

class C {
  @literal
  C();
}

以下代码会产生此诊断,因为 x 不是构造函数。

dart
import 'package:meta/meta.dart';

@literal
var x;

常见修复方法

#

如果注解在构造函数上,并且构造函数应尽可能始终使用 const 调用,则使用 const 关键字标记构造函数。

dart
import 'package:meta/meta.dart';

class C {
  @literal
  const C();
}

如果构造函数不能标记为 const,则删除注解。

如果注解在构造函数以外的任何内容上,则删除注解。

dart
var x;

构造函数上无效的修饰符

#

修饰符 '{0}' 不能应用于构造函数的主体。

描述

#

当构造函数的主体以以下修饰符之一为前缀时,分析器会产生此诊断:asyncasync*sync*。构造函数主体必须是同步的。

示例

#

以下代码会产生此诊断,因为 C 的构造函数主体被标记为 async

dart
class C {
  C() async {}
}

常见修复方法

#

如果构造函数可以是同步的,则删除修饰符。

dart
class C {
  C();
}

如果构造函数不能是同步的,则使用静态方法来创建实例。

dart
class C {
  C();
  static Future<C> c() async {
    return C();
  }
}

setter 上无效的修饰符

#

Setter 不能使用 'async'、'async*' 或 'sync*'。

描述

#

当 setter 的主体以以下修饰符之一为前缀时,分析器会产生此诊断:asyncasync*sync*。Setter 主体必须是同步的。

示例

#

以下代码会产生此诊断,因为 setter x 的主体被标记为 async

dart
class C {
  set x(int i) async {}
}

常见修复方法

#

如果 setter 可以是同步的,则删除修饰符。

dart
class C {
  set x(int i) {}
}

如果 setter 不能是同步的,则使用方法来设置值。

dart
class C {
  void x(int i) async {}
}

无效的非 virtual 注解

#

注解 '@nonVirtual' 只能应用于具体实例成员。

描述

#

当在类、mixin 或 枚举的成员以外的声明上找到 nonVirtual 注解,或者如果成员不是具体实例成员时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为注解在类声明上,而不是类内的成员上。

dart
import 'package:meta/meta.dart';

@nonVirtual
class C {}

以下代码会产生此诊断,因为方法 m 是抽象方法。

dart
import 'package:meta/meta.dart';

abstract class C {
  @nonVirtual
  void m();
}

以下代码会产生此诊断,因为方法 m 是静态方法。

dart
import 'package:meta/meta.dart';

abstract class C {
  @nonVirtual
  static void m() {}
}

常见修复方法

#

如果声明不是类、mixin 或 枚举的成员,则删除注解。

dart
class C {}

如果成员 intended 为具体实例成员,则使其成为具体实例成员。

dart
import 'package:meta/meta.dart';

abstract class C {
  @nonVirtual
  void m() {}
}

如果成员不 intended 为具体实例成员,则删除注解。

dart
abstract class C {
  static void m() {}
}

无效的空感知运算符

#

元素不能为空,因此空感知运算符 '?' 是不必要的。

映射条目键不能为空,因此空感知运算符 '?' 是不必要的。

映射条目值不能为空,因此空感知运算符 '?' 是不必要的。

由于短路,接收器不能为 'null',因此不能使用空感知运算符 '{0}'。

接收器不能为空,因此空感知运算符 '{0}' 是不必要的。

描述

#

当在已知为非可空的接收器上使用空感知运算符(?.?..?[?..[...?)时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 s 不能为 null

dart
int? getLength(String s) {
  return s?.length;
}

以下代码会产生此诊断,因为 a 不能为 null

dart
var a = [];
var b = [...?a];

以下代码会产生此诊断,因为 s?.length 不能返回 null

dart
void f(String? s) {
  s?.length?.isEven;
}

s?.length 不能返回 null 的原因是,如果 snull,则在 s 之后的空感知运算符会短路 lengthisEven 的求值。换句话说,如果 snull,则既不会调用 length 也不会调用 isEven,如果 s 为非 null,则 length 不能返回 null 值。无论哪种方式,都不能在 null 值上调用 isEven,因此空感知运算符是不必要的。有关更多详细信息,请参阅 了解空安全

以下代码会产生此诊断,因为 s 不能为 null

dart
void f(Object? o) {
  var s = o as String;
  s?.length;
}

s 不能为 null 的原因是,尽管 o 可以为 null,但由于强制转换为 String,这是一个非可空类型。如果 o 曾经具有值 null,则强制转换将失败,并且 length 的调用将不会发生。

以下代码会产生此诊断,因为 s 不能为 null

dart
List<String> makeSingletonList(String s) {
  return <String>[?s];
}

常见修复方法

#

将空感知运算符替换为非空感知等效项;例如,将 ?. 更改为 .

dart
int getLength(String s) {
  return s.length;
}

(请注意,返回类型也已更改为非可空,这在某些情况下可能不合适。)

无效的覆盖

#

'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效覆盖。

Setter '{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效覆盖。

描述

#

当找到一个类的成员,该成员覆盖了超类型的成员,并且覆盖无效时,分析器会产生此诊断。如果以下所有条件都为真,则覆盖有效:

  • 它允许被覆盖成员允许的所有参数。
  • 它不需要被覆盖成员不需要的任何参数。
  • 被覆盖成员的每个参数的类型都可赋值给覆盖的相应参数。
  • 覆盖的返回类型可赋值给被覆盖成员的返回类型。

示例

#

以下代码会产生此诊断,因为参数 s (String) 的类型不可赋值给参数 i (int) 的类型。

dart
class A {
  void m(int i) {}
}

class B extends A {
  void m(String s) {}
}

常见修复方法

#

如果无效方法 intended 为覆盖超类中的方法,则更改它以使其符合。

dart
class A {
  void m(int i) {}
}

class B extends A {
  void m(int i) {}
}

如果它不 intended 为覆盖超类中的方法,则重命名它。

dart
class A {
  void m(int i) {}
}

class B extends A {
  void m2(String s) {}
}

无效地覆盖非 virtual 成员

#

成员 '{0}' 在 '{1}' 中声明为非虚拟的,并且不能在子类中覆盖。

描述

#

当类、mixin 或 枚举的成员覆盖了具有 @nonVirtual 注解的成员时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 B 中的方法 m 覆盖了 A 中的方法 m,并且 A 中的方法 m 使用 @nonVirtual 注解进行注解。

dart
import 'package:meta/meta.dart';

class A {
  @nonVirtual
  void m() {}
}

class B extends A {
  @override
  void m() {}
}

常见修复方法

#

如果超类中方法的注解是正确的(超类中的方法不 intended 为被覆盖),则删除或重命名覆盖方法。

dart
import 'package:meta/meta.dart';

class A {
  @nonVirtual
  void m() {}
}

class B extends A {}

如果超类中的方法 intended 为被覆盖,则删除 @nonVirtual 注解。

dart
class A {
  void m() {}
}

class B extends A {
  @override
  void m() {}
}

共享 case 作用域中无效的模式变量

#

变量 '{0}' 在共享此主体的所有情况下的类型和/或终结性不相同。

变量 '{0}' 在共享此主体的某些情况下可用,但在并非所有情况下都可用。

变量 '{0}' 不可用,因为存在标签或 'default' case。

描述

#

当 switch 语句中的多个 case 子句共享一个主体,并且至少其中一个声明了一个在共享语句中引用的变量,但该变量要么未在所有 case 子句中声明,要么以不一致的方式声明时,分析器会产生此诊断。

如果变量未在所有 case 子句中声明,则如果未声明变量的子句之一是匹配并执行主体的子句,则它将没有值。这包括其中一个 case 子句是 default 子句的情况。

如果变量以不一致的方式声明,要么在某些情况下为 final 而在其他情况下不为 final,要么在不同情况下具有不同的类型,则未定义变量的类型或终结性应具有的语义。

示例

#

以下代码会产生此诊断,因为变量 a 仅在一个 case 子句中声明,并且如果第二个子句是匹配 x 的子句,则将没有值。

dart
void f(Object? x) {
  switch (x) {
    case int a when a > 0:
    case 0:
      a;
  }
}

以下代码会产生此诊断,因为变量 a 未在 default 子句中声明,并且如果主体因没有其他子句匹配 x 而执行,则将没有值。

dart
void f(Object? x) {
  switch (x) {
    case int a when a > 0:
    default:
      a;
  }
}

以下代码会产生此诊断,因为如果主体因一组不同的 case 导致控制权在标签处继续,则变量 a 将没有值。

dart
void f(Object? x) {
  switch (x) {
    someLabel:
    case int a when a > 0:
      a;
    case int b when b < 0:
      continue someLabel;
  }
}

以下代码会产生此诊断,因为变量 a 虽然在所有 case 子句中都已赋值,但在每个子句中关联的类型都不相同。

dart
void f(Object? x) {
  switch (x) {
    case int a when a < 0:
    case num a when a > 0:
      a;
  }
}

以下代码会产生此诊断,因为变量 a 在第一个 case 子句中是 final,而在第二个 case 子句中不是 final

dart
void f(Object? x) {
  switch (x) {
    case final int a when a < 0:
    case int a when a > 0:
      a;
  }
}

常见修复方法

#

如果变量未在所有 case 中声明,并且需要在语句中引用它,则在其他 case 中声明它。

dart
void f(Object? x) {
  switch (x) {
    case int a when a > 0:
    case int a when a == 0:
      a;
  }
}

如果变量未在所有 case 中声明,并且不需要在语句中引用它,则删除对其的引用,并从其他 case 中删除声明。

dart
void f(int x) {
  switch (x) {
    case > 0:
    case 0:
  }
}

如果变量的类型不同,请确定变量应具有的类型,并使 case 保持一致。

dart
void f(Object? x) {
  switch (x) {
    case num a when a < 0:
    case num a when a > 0:
      a;
  }
}

如果变量的 final 性不同,请决定它应该是 final 还是非 final,并使情况保持一致

dart
void f(Object? x) {
  switch (x) {
    case final int a when a < 0:
    case final int a when a > 0:
      a;
  }
}

无效的 platforms 字段

#

'platforms' 字段必须是一个以平台作为键的映射。

描述

#

当指定了顶级 platforms 字段,但其值不是以键为键的映射时,分析器会产生此诊断。要了解有关指定软件包支持的平台的更多信息,请查看 有关平台声明的文档

示例

#

以下 pubspec.yaml 会产生此诊断,因为 platforms 应该是一个映射。

yaml
name: example
platforms:
  - android
  - web
  - ios

常见修复方法

#

如果可以依赖自动平台检测,则省略顶级 platforms 字段。

yaml
name: example

如果需要手动指定受支持平台的列表,则将 platforms 字段编写为以平台名称作为键的映射。

yaml
name: example
platforms:
  android:
  web:
  ios:

对生成枚举构造函数的无效引用

#

生成式枚举构造函数只能用作重定向的目标。

描述

#

当在枚举上定义的生成式构造函数用于创建枚举常量之一以外的任何地方,或者用作来自同一枚举中另一个构造函数的重定向目标时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 E 的构造函数正在函数 f 中用于创建实例。

dart
enum E {
  a(0);

  const E(int x);
}

E f() => const E(2);

常见修复方法

#

如果存在具有相同值的枚举值,或者如果添加了此类常量,则直接引用该常量。

dart
enum E {
  a(0), b(2);

  const E(int x);
}

E f() => E.b;

如果需要使用构造函数调用,则使用工厂构造函数。

dart
enum E {
  a(0);

  const E(int x);

  factory E.c(int x) => a;
}

E f() => E.c(2);

对 this 的无效引用

#

对 'this' 表达式的无效引用。

描述

#

this 在实例方法或生成式构造函数之外使用时,分析器会产生此诊断。保留字 this 仅在实例方法、生成式构造函数或延迟实例字段声明的初始化器的上下文中定义。

示例

#

以下代码会产生此诊断,因为 v 是顶级变量。

dart
C f() => this;

class C {}

常见修复方法

#

使用适当类型的变量代替 this,并在必要时声明它。

dart
C f(C c) => c;

class C {}

catchError 的无效返回类型

#

类型为 '{0}' 的值不能由 'onError' 处理程序返回,因为它必须可赋值给 '{1}'。

返回类型 '{0}' 不可赋值给 '{1}',这是 'Future.catchError' 所要求的。

描述

#

Future.catchError 的调用具有一个参数,其返回类型与 Future 实例返回的类型不兼容时,分析器会产生此诊断。在运行时,方法 catchError 尝试返回来自回调的值作为 future 的结果,这会导致抛出另一个异常。

示例

#

以下代码会产生此诊断,因为 future 被声明为返回 int,而 callback 被声明为返回 String,并且 String 不是 int 的子类型。

dart
void f(Future<int> future, String Function(dynamic, StackTrace) callback) {
  future.catchError(callback);
}

以下代码会产生此诊断,因为传递给 catchError 的闭包返回 int,而 future 被声明为返回 String

dart
void f(Future<String> future) {
  future.catchError((error, stackTrace) => 3);
}

常见修复方法

#

如果 Future 的实例声明正确,则更改回调以匹配。

dart
void f(Future<int> future, int Function(dynamic, StackTrace) callback) {
  future.catchError(callback);
}

如果 Future 的实例声明错误,则更改它以匹配回调。

dart
void f(Future<String> future, String Function(dynamic, StackTrace) callback) {
  future.catchError(callback);
}

无效的 sealed 注解

#

注解 '@sealed' 只能应用于类。

描述

#

当类声明以外的声明具有 @sealed 注解时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 @sealed 注解在方法声明上。

dart
import 'package:meta/meta.dart';

class A {
  @sealed
  void m() {}
}

常见修复方法

#

删除注解。

dart
class A {
  void m() {}
}

无效的 super 形式参数位置

#

Super 参数只能在非重定向生成式构造函数中使用。

描述

#

当 super 参数在非重定向生成式构造函数以外的任何地方使用时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 super 参数 x 在重定向生成式构造函数中。

dart
class A {
  A(int x);
}

class B extends A {
  B.b(super.x) : this._();
  B._() : super(0);
}

以下代码会产生此诊断,因为 super 参数 x 不在生成式构造函数中。

dart
class A {
  A(int x);
}

class C extends A {
  factory C.c(super.x) => C._();
  C._() : super(0);
}

以下代码会产生此诊断,因为 super 参数 x 在方法中。

dart
class A {
  A(int x);
}

class D extends A {
  D() : super(0);

  void m(super.x) {}
}

常见修复方法

#

如果包含 super 参数的函数可以更改为非重定向生成式构造函数,则执行此操作。

dart
class A {
  A(int x);
}

class B extends A {
  B.b(super.x);
}

如果包含 super 参数的函数不能更改为非重定向生成式构造函数,则删除 super

dart
class A {
  A(int x);
}

class D extends A {
  D() : super(0);

  void m(int x) {}
}

const 字面量中无效的类型参数

#

常量列表字面量不能在类型参数中使用类型参数,例如 '{0}'。

常量映射字面量不能在类型参数中使用类型参数,例如 '{0}'。

常量 Set 字面量不能在类型参数中使用类型参数,例如 '{0}'。

描述

#

当在以 const 为前缀的列表、映射或 Set 字面量中的类型参数中使用类型参数时,分析器会产生此诊断。这是不允许的,因为类型参数的值(运行时将使用的实际类型)在编译时无法知道。

示例

#

以下代码会产生此诊断,因为类型参数 T 在创建常量列表时用作类型参数。

dart
List<T> newList<T>() => const <T>[];

以下代码会产生此诊断,因为类型参数 T 在创建常量映射时用作类型参数。

dart
Map<String, T> newSet<T>() => const <String, T>{};

以下代码会产生此诊断,因为类型参数 T 在创建常量 Set 时用作类型参数。

dart
Set<T> newSet<T>() => const <T>{};

常见修复方法

#

如果用于类型参数的类型可以在编译时知道,则删除类型参数。

dart
List<int> newList() => const <int>[];

如果将用于类型形参的类型在运行时才能知道,则删除关键字 const

dart
List<T> newList<T>() => <T>[];

无效的 URI

#

无效的 URI 语法:'{0}'。

描述

#

当指令中的 URI 不符合有效 URI 的语法时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 '#' 不是有效的 URI。

dart
import '#';

常见修复方法

#

将无效的 URI 替换为有效的 URI。

在扩展中无效地使用 covariant

#

扩展中不能有修饰符 '{0}'。

描述

#

当在扩展内部声明的成员在参数声明中使用关键字 covariant 时,分析器会产生此诊断。扩展不是类,也没有子类,因此关键字没有任何作用。

示例

#

以下代码会产生此诊断,因为 i 被标记为协变的。

dart
extension E on String {
  void a(covariant int i) {}
}

常见修复方法

#

删除 covariant 关键字。

dart
extension E on String {
  void a(int i) {}
}

无效地使用内部成员

#

成员 '{0}' 只能在其软件包内使用。

描述

#

当在包含声明的软件包外部找到对使用 internal 注解进行注解的声明的引用时,分析器会产生此诊断。

示例

#

给定一个软件包 p,它定义了一个包含使用 internal 注解标记的声明的库:

dart
import 'package:meta/meta.dart';

@internal
class C {}

以下代码会产生此诊断,因为它引用了类 C,该类不 intended 为在软件包 p 外部使用。

dart
import 'package:p/src/p.dart';

void f(C c) {}

常见修复方法

#

删除对内部声明的引用。

无效地使用 null 值

#

无法取消引用其值始终为“null”的表达式。

描述

#

当取消引用其值始终为 null 的表达式时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 x 将始终为 null

dart
int f(Null x) {
  return x.length;
}

常见修复方法

#

如果允许该值不是 null,则更改表达式的类型

dart
int f(String? x) {
  return x!.length;
}

无效地使用库外部的类型

#

类“{0}”不能在其库外部扩展,因为它是一个 final 类。

类“{0}”不能在其库外部扩展,因为它是一个接口类。

类“{0}”不能在其库外部扩展、实现或混入,因为它是一个 sealed 类。

类“{0}”不能在其库外部实现,因为它是一个 base 类。

类“{0}”不能在其库外部实现,因为它是一个 final 类。

类“{0}”不能用作其库外部的 mixin 超类约束,因为它是一个 final 类。

Mixin “{0}”不能在其库外部实现,因为它是一个 base mixin。

描述

#

extendsimplementswithon 子句以不允许的方式使用类或 mixin 时,并且考虑到该类或 mixin 声明上的修饰符,分析器会生成此诊断信息。

该消息指定了声明的使用方式以及不允许的原因。

示例

#

给定一个文件 a.dart,它定义了一个 base 类 A

dart
base class A {}

以下代码会生成此诊断信息,因为类 B 实现了类 A,但 base 修饰符阻止了 A 在其定义库外部被实现

dart
import 'a.dart';

final class B implements A {}

常见修复方法

#

此类型的使用在其声明库外部受到限制。如果有其他可用的、不受限制的类型可以提供类似的功能,则替换该类型

dart
class B implements C {}
class C {}

如果没有合适的其他类型,则删除该类型,并可能删除整个子句

dart
class B {}

无效地使用 visibleForOverriding 成员

#

成员“{0}”只能用于重写。

描述

#

当在声明它的库外部引用使用 visibleForOverriding 注释的实例成员时,分析器会生成此诊断信息,但用于重写的情况除外。

示例

#

给定一个文件 a.dart,其中包含以下声明

dart
import 'package:meta/meta.dart';

class A {
  @visibleForOverriding
  void a() {}
}

以下代码会生成此诊断信息,因为即使方法 m 仅因允许被重写而公开,它仍被调用

dart
import 'a.dart';

class B extends A {
  void b() {
    a();
  }
}

常见修复方法

#

删除成员的无效使用。

无效地使用 visibleForTesting 成员

#

成员“{0}”只能在“{1}”或测试中使用。

描述

#

当在声明它的库或 test 目录中的库之外的任何地方引用使用 @visibleForTesting 注释的成员时,分析器会生成此诊断信息。

示例

#

给定一个文件 c.dart,其中包含以下内容

dart
import 'package:meta/meta.dart';

class C {
  @visibleForTesting
  void m() {}
}

以下代码在不在 test 目录中时会生成此诊断信息,因为方法 m 被标记为仅在测试中可见

dart
import 'c.dart';

void f(C c) {
  c.m();
}

常见修复方法

#

如果带注释的成员不应在测试之外被引用,则删除引用

dart
import 'c.dart';

void f(C c) {}

如果可以在测试之外引用带注释的成员,则删除注释

dart
class C {
  void m() {}
}

无效的可见性注解

#

成员“{0}”使用“{1}”进行了注释,但此注释仅对公共成员的声明有意义。

描述

#

visibleForTemplatevisibleForTesting 注释应用于非公共声明时,分析器会生成此诊断信息。

示例

#

以下代码生成此诊断消息:

dart
import 'package:meta/meta.dart';

@visibleForTesting
void _someFunction() {}

void f() => _someFunction();

常见修复方法

#

如果声明不需要被测试代码使用,则删除注释

dart
void _someFunction() {}

void f() => _someFunction();

如果需要,则使其公开

dart
import 'package:meta/meta.dart';

@visibleForTesting
void someFunction() {}

void f() => someFunction();

无效的 visibleForOverriding 注解

#

注释“visibleForOverriding”只能应用于可以被重写的公共实例成员。

描述

#

当类中的公共实例成员之外的任何内容使用 visibleForOverriding 进行注释时,分析器会生成此诊断信息。因为只有公共实例成员才能在定义库外部被重写,所以注释任何其他声明都没有价值。

示例

#

以下代码会生成此诊断信息,因为注释位于类上,而类无法被重写

dart
import 'package:meta/meta.dart';

@visibleForOverriding
class C {}

常见修复方法

#

删除注解。

dart
class C {}

无效的 visibleOutsideTemplate 注解

#

注释“visibleOutsideTemplate”只能应用于使用“visibleForTemplate”注释的类、枚举或 mixin 的成员。

描述

#

@visibleOutsideTemplate 注释使用不正确时,分析器会生成此诊断信息。此注释仅用于注释具有 @visibleForTemplate 注释的类、枚举或 mixin 的成员,以使这些成员选择退出 @visibleForTemplate 施加的可见性限制。

示例

#

以下代码会生成此诊断信息,因为类级别没有 @visibleForTemplate 注释

dart
import 'package:angular_meta/angular_meta.dart';

class C {
  @visibleOutsideTemplate
  int m() {
    return 1;
  }
}

以下代码会生成此诊断信息,因为注释位于类声明上,而不是类、枚举或 mixin 的成员上

dart
import 'package:angular_meta/angular_meta.dart';

@visibleOutsideTemplate
class C {}

常见修复方法

#

如果类仅为了模板可以引用它而可见,则将 @visibleForTemplate 注释添加到类中

dart
import 'package:angular_meta/angular_meta.dart';

@visibleForTemplate
class C {
  @visibleOutsideTemplate
  int m() {
    return 1;
  }
}

如果 @visibleOutsideTemplate 注释位于没有 @visibleForTemplate 注释的类、枚举或 mixin 的成员之外的任何内容上,则删除该注释

dart
class C {}

调用没有 call 方法的扩展

#

扩展“{0}”未定义“call”方法,因此不能在调用中使用重写。

描述

#

当扩展重写用于调用函数,但扩展未声明 call 方法时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展 E 未定义 call 方法

dart
extension E on String {}

void f() {
  E('')();
}

常见修复方法

#

如果扩展旨在定义 call 方法,则声明它

dart
extension E on String {
  int call() => 0;
}

void f() {
  E('')();
}

如果扩展类型定义了 call 方法,则删除扩展重写。

如果未定义 call 方法,则重写代码,使其不调用 call 方法。

调用非函数

#

“{0}”不是一个函数。

描述

#

当分析器发现函数调用,但被调用函数的名称被定义为函数以外的其他内容时,它会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 Binary 是函数类型的名称,而不是函数

dart
typedef Binary = int Function(int, int);

int f() {
  return Binary(1, 2);
}

常见修复方法

#

将名称替换为函数的名称。

调用非函数表达式

#

表达式未求值为函数,因此无法调用它。

描述

#

当找到函数调用,但被引用的名称不是函数的名称,或者当计算函数的表达式未计算出函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 x 不是一个函数

dart
int x = 0;

int f() => x;

var y = x();

以下代码会生成此诊断信息,因为 f() 未返回函数

dart
int x = 0;

int f() => x;

var y = f()();

常见修复方法

#

如果需要调用函数,则将参数列表之前的代码替换为函数的名称或计算函数的表达式

dart
int x = 0;

int f() => x;

var y = f();

外层作用域中的标签

#

无法引用在外部方法中声明的标签“{0}”。

描述

#

breakcontinue 语句引用在包含 breakcontinue 语句出现的函数的函数或方法中声明的标签时,分析器会生成此诊断信息。breakcontinue 语句不能用于将控制权转移到包含它们的函数之外。

示例

#

以下代码会生成此诊断信息,因为标签 loop 在局部函数 g 外部声明

dart
void f() {
  loop:
  while (true) {
    void g() {
      break loop;
    }

    g();
  }
}

常见修复方法

#

尝试重写代码,使其不需要将控制权转移到局部函数之外,可能通过内联局部函数

dart
void f() {
  loop:
  while (true) {
    break loop;
  }
}

如果这不可能,则尝试重写局部函数,以便可以使用函数返回的值来确定是否转移了控制权

dart
void f() {
  loop:
  while (true) {
    bool g() {
      return true;
    }

    if (g()) {
      break loop;
    }
  }
}

未定义的标签

#

无法引用未定义的标签“{0}”。

描述

#

当分析器发现对未在引用它的 breakcontinue 语句的作用域中定义的标签的引用时,它会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为标签 loop 在任何地方都未定义

dart
void f() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (j != 0) {
        break loop;
      }
    }
  }
}

常见修复方法

#

如果标签应位于最内层的封闭 doforswitchwhile 语句上,则删除标签

dart
void f() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (j != 0) {
        break;
      }
    }
  }
}

如果标签应位于其他语句上,则添加标签

dart
void f() {
  loop: for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      if (j != 0) {
        break loop;
      }
    }
  }
}

带有 const 构造函数的 late final 字段

#

带有生成式 const 构造函数的类中不能有 late final 字段。

描述

#

当具有至少一个 const 构造函数的类也具有标记为 latefinal 的字段时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类 A 具有 const 构造函数,并且 final 字段 f 被标记为 late

dart
class A {
  late final int f;

  const A();
}

常见修复方法

#

如果字段不需要标记为 late,则从字段中删除 late 修饰符

dart
class A {
  final int f = 0;

  const A();
}

如果字段必须标记为 late,则从构造函数中删除 const 修饰符

dart
class A {
  late final int f;

  A();
}

late final 局部变量已被赋值

#

late final 局部变量已赋值。

描述

#

当分析器可以证明标记为 latefinal 的局部变量在发生另一次赋值时已赋值时,分析器会生成此诊断信息。

因为 final 变量只能赋值一次,所以后续赋值保证会失败,因此会被标记。

示例

#

以下代码会生成此诊断信息,因为 final 变量 v 在两个位置被赋值

dart
int f() {
  late final int v;
  v = 0;
  v += 1;
  return v;
}

常见修复方法

#

如果需要能够重新赋值变量,则删除 final 关键字

dart
int f() {
  late int v;
  v = 0;
  v += 1;
  return v;
}

如果不需要重新赋值变量,则删除除第一个赋值之外的所有赋值

dart
int f() {
  late final int v;
  v = 0;
  return v;
}

叶子调用不能返回句柄

#

FFI 叶子调用不能返回“Handle”。

描述

#

当调用 Pointer.asFunctionDynamicLibrary.lookupFunction 时,isLeaf 参数的值为 true,并且将返回的函数的返回类型为 Handle 时,分析器会生成此诊断信息。

Native 注释中 isLeaf 参数的值为 true,并且注释上的类型参数是返回类型为 Handle 的函数类型时,分析器也会生成此诊断信息。

在所有这些情况下,叶子调用仅支持类型 boolintfloatdouble 以及作为返回类型的 void

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为函数 p 返回 Handle,但 isLeaf 参数为 true

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Handle Function()>> p) {
  p.asFunction<Object Function()>(isLeaf: true);
}

常见修复方法

#

如果函数返回句柄,则删除 isLeaf 参数

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Handle Function()>> p) {
  p.asFunction<Object Function()>();
}

如果函数返回受支持的类型之一,则更正类型信息

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Int32 Function()>> p) {
  p.asFunction<int Function()>(isLeaf: true);
}

叶子调用不能接受句柄

#

FFI 叶子调用不能接受“Handle”类型的参数。

描述

#

当调用 Pointer.asFunctionDynamicLibrary.lookupFunction 时,isLeaf 参数的值为 true,并且将返回的函数的参数类型为 Handle 时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为函数 p 具有 Handle 类型的参数,但 isLeaf 参数为 true

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
  p.asFunction<void Function(Object)>(isLeaf: true);
}

常见修复方法

#

如果函数至少有一个 Handle 类型的参数,则删除 isLeaf 参数

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
  p.asFunction<void Function(Object)>();
}

如果函数的参数都不是 Handle,则更正类型信息

dart
import 'dart:ffi';

void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
  p.asFunction<void Function(int)>(isLeaf: true);
}

List 元素类型不可赋值

#

元素类型“{0}”不能赋值给列表类型“{1}”。

描述

#

当列表字面量中的元素的类型不可赋值给列表的元素类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 2.5 是 double 类型,而列表只能容纳整数

dart
List<int> x = [1, 2.5, 3];

常见修复方法

#

如果打算向列表中添加不同的对象,则将元素替换为计算预期对象的表达式

dart
List<int> x = [1, 2, 3];

如果对象不应在列表中,则删除该元素

dart
List<int> x = [1, 3];

如果正在计算的对象是正确的,则扩大列表的元素类型,以允许它需要包含的所有不同类型的对象

dart
List<num> x = [1, 2.5, 3];

main 函数的第一个位置参数类型

#

“main”函数的第一个位置参数的类型必须是“List<String>”的超类型'.

描述

#

当名为 main 的函数的第一个位置参数不是 List<String> 的超类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 List<int> 不是 List<String> 的超类型

dart
void main(List<int> args) {}

常见修复方法

#

如果该函数是入口点,则将第一个位置参数的类型更改为 List<String> 的超类型

dart
void main(List<String> args) {}

如果该函数不是入口点,则更改函数的名称

dart
void f(List<int> args) {}

main 函数具有必需的命名参数

#

函数“main”不能有任何必需的命名参数。

描述

#

当名为 main 的函数具有一个或多个必需的命名参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为名为 main 的函数具有必需的命名参数 (x)

dart
void main({required int x}) {}

常见修复方法

#

如果该函数是入口点,则删除 required 关键字

dart
void main({int? x}) {}

如果该函数不是入口点,则更改函数的名称

dart
void f({required int x}) {}

main 函数具有过多必需的位置参数

#

函数“main”不能有超过两个必需的位置参数。

描述

#

当名为 main 的函数具有超过两个必需的位置参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数 main 具有三个必需的位置参数

dart
void main(List<String> args, int x, int y) {}

常见修复方法

#

如果该函数是入口点,并且未使用的额外参数,则删除它们

dart
void main(List<String> args, int x) {}

如果该函数是入口点,但使用的额外参数用于函数未用作入口点时,则使额外参数成为可选参数

dart
void main(List<String> args, int x, [int y = 0]) {}

如果该函数不是入口点,则更改函数的名称

dart
void f(List<String> args, int x, int y) {}

main 不是函数

#

名为“main”的声明必须是一个函数。

描述

#

当库包含名称为 main 的声明,但该声明不是顶层函数的声明时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为名称 main 正用于声明顶层变量

dart
var main = 3;

常见修复方法

#

为声明使用不同的名称

dart
var mainIndex = 3;

Map 条目不在 Map 中

#

映射条目只能在映射字面量中使用。

描述

#

当在集合字面量中找到映射条目(键/值对)时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字面量具有映射条目,即使它是一个集合字面量

dart
var collection = <String>{'a' : 'b'};

常见修复方法

#

如果打算让集合成为映射,则更改代码使其成为映射。在前面的示例中,可以通过添加另一个类型参数来执行此操作

dart
var collection = <String, String>{'a' : 'b'};

在其他情况下,您可能需要将显式类型从 Set 更改为 Map

如果打算让集合成为集合,则删除映射条目,如果两个值都应包含在集合中,则可能将冒号替换为逗号

dart
var collection = <String>{'a', 'b'};

Map 键类型不可赋值

#

元素类型“{0}”不能赋值给映射键类型“{1}”。

描述

#

当映射字面量中的键值对的键具有的类型不可赋值给映射的键类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 2int 类型,但映射的键需要是 String 类型

dart
var m = <String, String>{2 : 'a'};

常见修复方法

#

如果映射的类型正确,则将键更改为具有正确的类型

dart
var m = <String, String>{'2' : 'a'};

如果键的类型正确,则更改映射的键类型

dart
var m = <int, String>{2 : 'a'};

Map 值类型不可赋值

#

元素类型“{0}”不能赋值给映射值类型“{1}”。

描述

#

当映射字面量中的键值对的值具有的类型不可赋值给映射的值类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 2int 类型,但是/映射的值需要是 String 类型

dart
var m = <String, String>{'a' : 2};

常见修复方法

#

如果映射的类型正确,则将值更改为具有正确的类型

dart
var m = <String, String>{'a' : '2'};

如果值的类型正确,则更改映射的值类型

dart
var m = <String, int>{'a' : 2};

struct 字段上不匹配的注解

#

注释与字段的声明类型不匹配。

描述

#

StructUnion 子类中的字段上的注释与字段的 Dart 类型不匹配时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为注释 Double 与 Dart 类型 int 不匹配

dart
import 'dart:ffi';

final class C extends Struct {
  @Double()
  external int x;
}

常见修复方法

#

如果字段的类型正确,则更改注释以匹配

dart
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  external int x;
}

如果注释正确,则更改字段的类型以匹配

dart
import 'dart:ffi';

final class C extends Struct {
  @Double()
  external double x;
}

struct 字段上缺少注解

#

“{1}”子类中类型为“{0}”的字段必须具有指示本机类型的注释。

描述

#

StructUnion 子类中类型需要注释的字段没有注释时,分析器会生成此诊断信息。Dart 类型 intdoubleArray 用于表示多个 C 类型,注释指定字段表示的兼容 C 类型。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 x 没有注释指示整数值的底层宽度

dart
import 'dart:ffi';

final class C extends Struct {
  external int x;
}

常见修复方法

#

向字段添加适当的注释

dart
import 'dart:ffi';

final class C extends Struct {
  @Int64()
  external int x;
}

缺少 Dart 库

#

缺少必需的库“{0}”。

描述

#

当 Dart 或 Flutter SDK 未正确安装,因此找不到 dart: 库之一时,分析器会生成此诊断信息。

常见修复方法

#

重新安装 Dart 或 Flutter SDK。

参数缺少默认值

#

参数“{0}”由于其类型而不能具有值“null”,但隐式默认值为“null”。

使用空安全时,请使用“required”关键字,而不是“@required”注释。

描述

#

当可选参数(无论是位置参数还是命名参数)具有可能为非空的类型,并且未指定默认值时,分析器会生成此诊断信息。没有显式默认值的可选参数具有 null 的隐式默认值。如果参数的类型不允许参数具有 null 值,则隐式默认值无效。

示例

#

以下代码会生成此诊断信息,因为 x 不能为 null,并且未指定非 null 默认值

dart
void f([int x]) {}

以下代码也一样

dart
void g({int x}) {}

常见修复方法

#

如果想要使用 null 来指示未提供值,则需要使类型可为空

dart
void f([int? x]) {}
void g({int? x}) {}

如果参数不能为 null,则提供默认值

dart
void f([int x = 1]) {}
void g({int x = 2}) {}

或使参数成为必需参数

dart
void f(int x) {}
void g({required int x}) {}

缺少依赖

#

缺少对导入的包“{0}”的依赖。

描述

#

当源代码中导入了一个包,但该包未列为导入包的依赖项时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为包 path 未列为依赖项,而导入包 example 的源代码中存在带有包 path 的导入语句

yaml
name: example
dependencies:
  meta: ^1.0.2

常见修复方法

#

将缺少的包 path 添加到 dependencies 字段

yaml
name: example
dependencies:
  meta: ^1.0.2
  path: any

switch 语句中缺少枚举常量

#

缺少“{0}”的 case 子句。

描述

#

当枚举的 switch 语句不包含枚举中某个值的选项时,分析器会生成此诊断信息。

请注意,null 始终是枚举的可能值,因此也必须处理。

示例

#

以下代码会生成此诊断信息,因为枚举值 e2 未处理

dart
enum E { e1, e2 }

void f(E e) {
  switch (e) {
    case E.e1:
      break;
  }
}

常见修复方法

#

如果缺少的值有特殊的处理方式,则为每个缺少的值添加 case 子句

dart
enum E { e1, e2 }

void f(E e) {
  switch (e) {
    case E.e1:
      break;
    case E.e2:
      break;
  }
}

如果缺少的值应以相同的方式处理,则添加 default 子句

dart
enum E { e1, e2 }

void f(E e) {
  switch (e) {
    case E.e1:
      break;
    default:
      break;
  }
}

缺少异常值

#

当函数的返回类型既不是“void”、“Handle”也不是“Pointer”时,方法 {0} 必须具有异常返回值(第二个参数)。

描述

#

当方法 Pointer.fromFunctionNativeCallable.isolateLocal 的调用在要从调用返回的类型既不是 voidHandle 也不是 Pointer 时,没有第二个参数(异常返回值)时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为 f 返回的类型应为 8 位整数,但对 fromFunction 的调用不包含异常返回参数

dart
import 'dart:ffi';

int f(int i) => i * 2;

void g() {
  Pointer.fromFunction<Int8 Function(Int8)>(f);
}

常见修复方法

#

添加异常返回类型

dart
import 'dart:ffi';

int f(int i) => i * 2;

void g() {
  Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
}

struct 中缺少字段类型

#

struct 类中的字段必须具有显式声明的“int”、“double”或“Pointer”类型。

描述

#

StructUnion 子类中的字段没有类型注释时,分析器会生成此诊断信息。每个字段都必须具有显式类型,并且该类型必须是 intdoublePointerStructUnion 的子类。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 str 没有类型注释

dart
import 'dart:ffi';

final class C extends Struct {
  external var str;

  @Int32()
  external int i;
}

常见修复方法

#

显式指定字段的类型

dart
import 'dart:ffi';
import 'package:ffi/ffi.dart';

final class C extends Struct {
  external Pointer<Utf8> str;

  @Int32()
  external int i;
}

缺少名称

#

“name”字段是必需的,但缺失。

描述

#

当没有顶层 name 键时,分析器会生成此诊断信息。name 键提供包的名称,这是必需的。

示例

#

以下代码会生成此诊断信息,因为包没有名称

yaml
dependencies:
  meta: ^1.0.2

常见修复方法

#

添加顶层键 name,其值为包的名称

yaml
name: example
dependencies:
  meta: ^1.0.2

缺少命名模式字段名称

#

getter 名称未显式指定,并且模式不是变量。

描述

#

当在对象模式中,属性的规范和用于匹配属性值的模式既没有

  • 冒号前的 getter 名称
  • 也没有可以从中推断 getter 名称的变量模式

示例

#

以下代码会生成此诊断信息,因为在对象模式 (C(:0)) 中,冒号前没有 getter 名称,冒号后也没有变量模式

dart
abstract class C {
  int get f;
}

void f(C c) {
  switch (c) {
    case C(:0):
      break;
  }
}

常见修复方法

#

如果需要在模式的作用域内使用属性的实际值,则添加一个变量模式,其中变量的名称与要匹配的属性的名称相同

dart
abstract class C {
  int get f;
}

void f(C c) {
  switch (c) {
    case C(:var f) when f == 0:
      print(f);
  }
}

如果不需要在模式的作用域内使用属性的实际值,则在冒号前添加要匹配的属性的名称

dart
abstract class C {
  int get f;
}

void f(C c) {
  switch (c) {
    case C(f: 0):
      break;
  }
}

缺少对 mustBeOverridden 成员的覆盖

#

缺少“{0}”的具体实现。

缺少“{0}”和“{1}”的具体实现。

缺少“{0}”、“{1}”和另外 {2} 个的具体实现。

描述

#

当具有 @mustBeOverridden 注释的实例成员未在子类中重写时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为当 A.m 使用 @mustBeOverridden 注释时,类 B 没有继承的方法 A.m 的重写

dart
import 'package:meta/meta.dart';

class A {
  @mustBeOverridden
  void m() {}
}

class B extends A {}

常见修复方法

#

如果注释适合该成员,则在子类中重写该成员

dart
import 'package:meta/meta.dart';

class A {
  @mustBeOverridden
  void m() {}
}

class B extends A {
  @override
  void m() {}
}

如果注释不适合该成员,则删除该注释

dart
class A {
  void m() {}
}

class B extends A {}

缺少必需的参数

#

命名参数“{0}”是必需的,但没有相应的参数。

描述

#

当函数的调用缺少必需的命名参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为对 f 的调用不包含必需的命名参数 end 的值

dart
void f(int start, {required int end}) {}
void g() {
  f(3);
}

常见修复方法

#

添加与缺少的必需参数对应的命名参数

dart
void f(int start, {required int end}) {}
void g() {
  f(3, end: 5);
}

缺少必需的形参

#

参数“{0}”是必需的。

参数“{0}”是必需的。{1}。

描述

#

当调用具有标记为必需的命名参数的方法或函数,但未提供参数值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为命名参数 x 是必需的

dart
import 'package:meta/meta.dart';

void f({@required int? x}) {}

void g() {
  f();
}

常见修复方法

#

提供所需的值

dart
import 'package:meta/meta.dart';

void f({@required int? x}) {}

void g() {
  f(x: 2);
}

缺少 return 语句

#

此函数的返回类型为“{0}”,但不以 return 语句结尾。

描述

#

任何不以显式 return 或 throw 结尾的函数或方法都隐式返回 null。这很少是期望的行为。当分析器发现隐式返回时,它会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 不以 return 结尾

dart
int f(int x) {
  if (x < 0) {
    return 0;
  }
}

常见修复方法

#

添加一个 return 语句,使返回值显式化,即使 null 是适当的值。

C 数组缺少大小注解

#

类型为“Array”的字段必须恰好有一个“Array”注释。

描述

#

StructUnion 的子类中的字段类型为 Array,但没有单个 Array 注释指示数组的维度时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 a0 没有 Array 注释

dart
import 'dart:ffi';

final class C extends Struct {
  external Array<Uint8> a0;
}

常见修复方法

#

确保字段上恰好有一个 Array 注释

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8)
  external Array<Uint8> a0;
}

缺少变量模式

#

逻辑或模式的此分支中缺少变量模式“{0}”。

描述

#

当逻辑或模式的一个分支未声明在同一模式的另一个分支上声明的变量时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为逻辑或模式的右侧未声明变量 a

dart
void f((int, int) r) {
  if (r case (var a, 0) || (0, _)) {
    print(a);
  }
}

常见修复方法

#

如果需要在受控语句中引用变量,则将变量的声明添加到逻辑或模式的每个分支

dart
void f((int, int) r) {
  if (r case (var a, 0) || (0, var a)) {
    print(a);
  }
}

如果不需要在受控语句中引用变量,则从逻辑或模式的每个分支中删除变量的声明

dart
void f((int, int) r) {
  if (r case (_, 0) || (0, _)) {
    print('found a zero');
  }
}

如果仅当模式的一个分支匹配时才需要引用变量,但在另一个分支匹配时不引用变量,则将模式分成两部分

dart
void f((int, int) r) {
  switch (r) {
    case (var a, 0):
      print(a);
    case (0, _):
      print('found a zero');
  }
}

mixin 应用具体超类调用的成员类型

#

超级调用的成员“{0}”的类型为“{1}”,而类中的具体成员的类型为“{2}”。

描述

#

当在类中使用通过 super 调用方法的 mixin,并且该方法在 mixin 的 on 类型中定义的签名与该方法在类中的具体实现的签名不同时,分析器会生成此诊断信息。这是一个错误的原因是因为 mixin 中的调用可能以与实际执行的方法不兼容的方式调用该方法。

示例

#

以下代码会生成此诊断信息,因为类 C 使用 mixin M,mixin M 使用 super 调用 foo,并且在 I(mixin 的 on 类型)中声明的抽象版本 foo 与在 A 中声明的具体版本 foo 的签名不同

dart
class I {
  void foo([int? p]) {}
}

class A {
  void foo(int p) {}
}

abstract class B extends A implements I {
  @override
  void foo([int? p]);
}

mixin M on I {
  void bar() {
    super.foo(42);
  }
}

abstract class C extends B with M {}

常见修复方法

#

如果类不需要使用 mixin,则从 with 子句中删除它

dart
class I {
  void foo([int? p]) {}
}

class A {
  void foo(int? p) {}
}

abstract class B extends A implements I {
  @override
  void foo([int? p]);
}

mixin M on I {
  void bar() {
    super.foo(42);
  }
}

abstract class C extends B {}

如果类需要使用 mixin,则确保存在符合 mixin 期望的签名的方法的具体实现

dart
class I {
  void foo([int? p]) {}
}

class A {
  void foo(int? p) {}
}

abstract class B extends A implements I {
  @override
  void foo([int? p]) {
    super.foo(p);
  }
}

mixin M on I {
  void bar() {
    super.foo(42);
  }
}

abstract class C extends B with M {}

mixin 应用未实现接口

#

“{0}”不能混入到“{1}”中,因为“{1}”未实现“{2}”。

描述

#

当具有超类约束的 mixin 在mixin 应用中使用时,分析器会生成此诊断信息,但超类未实现所需的约束。

示例

#

以下代码会生成此诊断信息,因为 mixin M 要求应用它的类是 A 的子类,但 Object 不是 A 的子类

dart
class A {}

mixin M on A {}

class X = Object with M;

常见修复方法

#

如果需要使用 mixin,则将超类更改为与超类约束相同或超类约束的子类

dart
class A {}

mixin M on A {}

class X = A with M;

mixin 应用没有具体超类调用的成员

#

该类没有超级调用成员“{0}”的具体实现。

该类没有超级调用 setter “{0}”的具体实现。

描述

#

mixin 应用包含对其超类成员的调用,并且在 mixin 应用的超类中没有该名称的具体成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 mixin M 包含调用 super.m(),并且作为 mixin 应用 A+M 的超类的类 A 未定义 m 的具体实现

dart
abstract class A {
  void m();
}

mixin M on A {
  void bar() {
    super.m();
  }
}

abstract class B extends A with M {}

常见修复方法

#

如果打算将 mixin M 应用于不同的类,即具有 m 的具体实现的类,则将 B 的超类更改为该类

dart
abstract class A {
  void m();
}

mixin M on A {
  void bar() {
    super.m();
  }
}

class C implements A {
  void m() {}
}

abstract class B extends C with M {}

如果需要使 B 成为 A 的子类,则在 A 中添加 m 的具体实现

dart
abstract class A {
  void m() {}
}

mixin M on A {
  void bar() {
    super.m();
  }
}

abstract class B extends A with M {}

mixin 类声明扩展了非 Object 类

#

类“{0}”不能声明为 mixin,因为它扩展了“Object”以外的类。

描述

#

当标记有 mixin 修饰符的类扩展了 Object 以外的类时,分析器会生成此诊断信息。Mixin 类不能具有 Object 以外的超类。

示例

#

以下代码会生成此诊断信息,因为具有修饰符 mixin 的类 B 扩展了 A

dart
class A {}

mixin class B extends A {}

常见修复方法

#

如果希望将该类用作 mixin,则将超类更改为 Object,显式更改或删除 extends 子句

dart
class A {}

mixin class B {}

如果该类需要具有 Object 以外的超类,则删除 mixin 修饰符

dart
class A {}

class B extends A {}

如果既需要 mixin 又需要 Object 以外的类的子类,则将子类的成员移动到新的 mixin,从子类中删除 mixin 修饰符,并将新的 mixin 应用于子类

dart
class A {}

class B extends A with M {}

mixin M {}

根据子类的成员,这可能需要向 mixin 添加 on 子句。

mixin 类声明构造函数

#

类“{0}”不能用作 mixin,因为它声明了一个构造函数。

描述

#

当类用作 mixin 并且混入的类定义了构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为定义了构造函数的类 A 正用作 mixin

dart
//@dart=2.19
class A {
  A();
}

class B with A {}

常见修复方法

#

如果可以将类转换为 mixin,则执行此操作

dart
mixin A {
}

class B with A {}

如果类不能是 mixin 并且可以删除构造函数,则执行此操作

dart
//@dart=2.19
class A {
}

class B with A {}

如果类不能是 mixin 并且无法删除构造函数,则尝试扩展或实现该类,而不是混入它

dart
class A {
  A();
}

class B extends A {}

mixin 继承自非 Object 类

#

类“{0}”不能用作 mixin,因为它扩展了“Object”以外的类。

描述

#

当扩展了 Object 以外的类的类用作 mixin 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展了 A 的类 B 正被 C 用作 mixin

dart
//@dart=2.19
class A {}

class B extends A {}

class C with B {}

常见修复方法

#

如果用作 mixin 的类可以更改为扩展 Object,则更改它

dart
//@dart=2.19
class A {}

class B {}

class C with B {}

如果用作 mixin 的类无法更改,并且使用它的类扩展了 Object,则扩展用作 mixin 的类

dart
class A {}

class B extends A {}

class C extends B {}

如果类未扩展 Object,或者如果您希望能够在其他位置混入来自 B 的行为,则创建一个真正的 mixin

dart
class A {}

mixin M on A {}

class B extends A with M {}

class C extends A with M {}

实例化 mixin

#

Mixin 不能被实例化。

描述

#

当 mixin 被实例化时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 mixin M 正在被实例化

dart
mixin M {}

var m = M();

常见修复方法

#

如果打算使用类的实例,则使用该类的名称代替 mixin 的名称。

mixin of 非类

#

类只能混入 mixin 和类。

描述

#

with 子句中的名称被定义为 mixin 或类以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 F 被定义为函数类型

dart
typedef F = int Function(String);

class C with F {}

常见修复方法

#

从列表中删除无效名称,可能会将其替换为预期的 mixin 或类的名称

dart
typedef F = int Function(String);

class C {}

mixin on sealed 类

#

类“{0}”不应被用作 mixin 约束,因为它是 sealed 类,并且任何混入此 mixin 的类都必须以“{0}”作为超类。

描述

#

分析器在 mixin 的超类约束是来自不同包的类,且该类被标记为 sealed 时,会生成此诊断信息。被标记为 sealed 的类不能被扩展、实现、混入或用作超类约束。

示例

#

如果包 p 定义了一个 sealed 类

dart
import 'package:meta/meta.dart';

@sealed
class C {}

那么,以下代码在非 p 包中时,会生成此诊断信息

dart
import 'package:p/p.dart';

mixin M on C {}

常见修复方法

#

如果使用 mixin 的类不需要是 sealed 类的子类,则可以考虑添加一个字段并将操作委托给 sealed 类的包装实例。

mixin 超类约束延迟类

#

延迟加载的类不能用作超类约束。

描述

#

当 mixin 的超类约束是从延迟加载的库导入时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 math.Random 的超类约束是从延迟加载的库导入的

dart
import 'dart:async' deferred as async;

mixin M<T> on async.Stream<T> {}

常见修复方法

#

如果不需要延迟加载导入,则删除 deferred 关键字

dart
import 'dart:async' as async;

mixin M<T> on async.Stream<T> {}

如果确实需要延迟加载导入,则删除超类约束

dart
mixin M<T> {}

mixin 超类约束非接口

#

只有类和 mixin 可以用作超类约束。

描述

#

当 mixin 声明中 on 关键字后面的类型既不是类也不是 mixin 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 F 既不是类也不是 mixin

dart
typedef F = void Function();

mixin M on F {}

常见修复方法

#

如果该类型本意是类但输入错误,则替换名称。

否则,从 on 子句中删除该类型。

多次重定向构造函数调用

#

构造函数最多只能有一个 'this' 重定向。

描述

#

当一个构造函数重定向到同一个类中的多个其他构造函数(使用 this)时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 C 中的未命名构造函数同时重定向到 this.athis.b

dart
class C {
  C() : this.a(), this.b();
  C.a();
  C.b();
}

常见修复方法

#

删除除一个之外的所有重定向

dart
class C {
  C() : this.a();
  C.a();
  C.b();
}

多个 super 初始化器

#

一个构造函数最多只能有一个 'super' 初始化器。

描述

#

当构造函数的初始化列表中包含多个来自超类的构造函数的调用时,分析器会生成此诊断信息。初始化列表必须恰好有一个这样的调用,可以是显式的也可以是隐式的。

示例

#

以下代码会生成此诊断信息,因为 B 的构造函数的初始化列表同时调用了来自超类 A 的构造函数 one 和构造函数 two

dart
class A {
  int? x;
  String? s;
  A.one(this.x);
  A.two(this.s);
}

class B extends A {
  B() : super.one(0), super.two('');
}

常见修复方法

#

如果其中一个 super 构造函数将完全初始化实例,则删除另一个

dart
class A {
  int? x;
  String? s;
  A.one(this.x);
  A.two(this.s);
}

class B extends A {
  B() : super.one(0);
}

如果其中一个 super 构造函数实现的初始化可以在构造函数的主体中执行,则删除其 super 调用并在主体中执行初始化

dart
class A {
  int? x;
  String? s;
  A.one(this.x);
  A.two(this.s);
}

class B extends A {
  B() : super.one(0) {
    s = '';
  }
}

如果初始化只能在超类中的构造函数中执行,则添加一个新的构造函数或修改现有构造函数之一,以便存在一个允许在单个调用中发生所有必需初始化的构造函数

dart
class A {
  int? x;
  String? s;
  A.one(this.x);
  A.two(this.s);
  A.three(this.x, this.s);
}

class B extends A {
  B() : super.three(0, '');
}

必须是 native 函数类型

#

赋予 '{1}' 的类型 '{0}' 必须是有效的 'dart:ffi' 原生函数类型。

描述

#

当调用 Pointer.fromFunctionDynamicLibrary.lookupFunctionNativeCallable 构造函数时,如果类型参数(显式或推断)不是原生函数类型,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类型 T 可以是 Function 的任何子类,但 fromFunction 的类型参数必须是原生函数类型

dart
import 'dart:ffi';

int f(int i) => i * 2;

class C<T extends Function> {
  void g() {
    Pointer.fromFunction<T>(f, 0);
  }
}

常见修复方法

#

使用原生函数类型作为调用的类型参数

dart
import 'dart:ffi';

int f(int i) => i * 2;

class C<T extends Function> {
  void g() {
    Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
  }
}

必须是子类型

#

对于 '{2}',类型 '{0}' 必须是 '{1}' 的子类型。

描述

#

分析器在两种情况下会生成此诊断信息

  • 在调用 Pointer.fromFunctionNativeCallable 构造函数时,如果类型参数(显式或推断)不是作为第一个参数传递给该方法的函数的类型的超类型。
  • 在调用 DynamicLibrary.lookupFunction 时,如果第一个类型参数不是第二个类型参数的超类型。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为函数 f 的类型 (String Function(int)) 不是类型参数 T (Int8 Function(Int8)) 的子类型

dart
import 'dart:ffi';

typedef T = Int8 Function(Int8);

double f(double i) => i;

void g() {
  Pointer.fromFunction<T>(f, 5.0);
}

常见修复方法

#

如果函数是正确的,则更改类型参数以匹配

dart
import 'dart:ffi';

typedef T = Float Function(Float);

double f(double i) => i;

void g() {
  Pointer.fromFunction<T>(f, 5.0);
}

如果类型参数是正确的,则更改函数以匹配

dart
import 'dart:ffi';

typedef T = Int8 Function(Int8);

int f(int i) => i;

void g() {
  Pointer.fromFunction<T>(f, 5);
}

必须是不可变的

#

此类(或此类继承自的类)被标记为 '@immutable',但其一个或多个实例字段不是 final:{0}

描述

#

当一个不可变类定义了一个或多个非 final 的实例字段时,分析器会生成此诊断信息。如果一个类使用注解 immutable 标记为不可变,或者如果它是不可变类的子类,则该类是不可变的。

示例

#

以下代码产生此诊断,因为字段 x 不是 final 的

dart
import 'package:meta/meta.dart';

@immutable
class C {
  int x;

  C(this.x);
}

常见修复方法

#

如果该类的实例应该是不可变的,则将关键字 final 添加到所有非 final 字段声明中

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final int x;

  C(this.x);
}

如果该类的实例应该是可变的,则删除注解,或者如果注解是继承的,则选择不同的超类

dart
class C {
  int x;

  C(this.x);
}

必须调用 super

#

此方法覆盖了 '{0}' 中注解为 '@mustCallSuper' 的方法,但未调用被覆盖的方法。

描述

#

当一个方法覆盖了一个注解为 mustCallSuper 的方法,但未按要求调用被覆盖的方法时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 B 中的方法 m 未调用 A 中被覆盖的方法 m

dart
import 'package:meta/meta.dart';

class A {
  @mustCallSuper
  m() {}
}

class B extends A {
  @override
  m() {}
}

常见修复方法

#

在覆盖方法中添加对被覆盖方法的调用

dart
import 'package:meta/meta.dart';

class A {
  @mustCallSuper
  m() {}
}

class B extends A {
  @override
  m() {
    super.m();
  }
}

必须返回 void

#

传递给 'NativeCallable.listener' 的函数的返回类型必须是 'void' 而不是 '{0}'。

描述

#

当您将一个不返回 void 的函数传递给 NativeCallable.listener 构造函数时,分析器会生成此诊断信息。

NativeCallable.listener 创建一个可以从任何线程调用的原生可调用对象。调用该可调用对象的原生代码会向创建该可调用对象的隔离区发送一条消息,并且不等待响应。因此,不可能从可调用对象返回结果。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为函数 f 返回 int 而不是 void

dart
import 'dart:ffi';

int f(int i) => i * 2;

void g() {
  NativeCallable<Int32 Function(Int32)>.listener(f);
}

常见修复方法

#

将函数的返回类型更改为 void

dart
import 'dart:ffi';

void f(int i) => print(i * 2);

void g() {
  NativeCallable<Void Function(Int32)>.listener(f);
}

名称不是字符串

#

'name' 字段的值必须是字符串。

描述

#

当顶层 name 键的值不是字符串时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 name 键后面的值是一个列表

yaml
name:
  - example

常见修复方法

#

将值替换为字符串

yaml
name: example

native 字段类型无效

#

'{0}' 是原生字段不支持的类型。原生字段仅支持指针、数组或数值和复合类型。

描述

#

当一个带有 @Native 注解的字段具有原生字段不支持的类型时,分析器会生成此诊断信息。

原生字段支持指针、数组、数值类型以及 Compound(即,结构体或联合体)的子类型。NativeType 的其他子类型,例如 HandleNativeFunction,不允许作为原生字段。

原生函数应该与外部函数一起使用,而不是外部字段。

不支持 Handle,因为没有办法透明地将 Dart 对象加载和存储到指针中。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 free 使用了不支持的原生类型 NativeFunction

dart
import 'dart:ffi';

@Native<NativeFunction<Void Function()>>()
external void Function() free;

常见修复方法

#

如果您打算绑定到具有 NativeFunction 字段的现有原生函数,请改用 @Native 方法

dart
import 'dart:ffi';

@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);

要绑定到 C 中存储函数指针的字段,请对 Dart 字段使用指针类型

dart
import 'dart:ffi';

@Native()
external Pointer<NativeFunction<Void Function(Pointer<Void>)>> free;

native 字段缺少类型

#

此字段的原生类型无法推断,必须在注解中指定。

描述

#

当带有 @Native 注解的字段需要在注解上使用类型提示才能推断原生类型时,分析器会生成此诊断信息。

Dart 类型(如 intdouble)具有多种可能的原生表示形式。由于原生类型需要在编译时已知,以便在访问字段时生成正确的加载和存储操作,因此必须给出显式类型。

示例

#

以下代码会生成此诊断信息,因为字段 f 的类型为 int(存在多种原生表示形式),但在 Native 注解上没有显式的类型参数

dart
import 'dart:ffi';

@Native()
external int f;

常见修复方法

#

要修复此诊断信息,请从字段的原生声明中找出正确的原生表示形式。然后,将相应的类型添加到注解中。例如,如果 f 在 C 中声明为 uint8_t,则 Dart 字段应声明为

dart
import 'dart:ffi';

@Native<Uint8>()
external int f;

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

native 字段不是静态的

#

原生字段必须是静态的。

描述

#

当类中的实例字段被注解为 @Native 时,分析器会生成此诊断信息。原生字段引用 C、C++ 或其他原生语言中的全局变量,而 Dart 中的实例字段特定于该类的实例。因此,原生字段必须是静态的。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类 C 中的字段 f@Native,但不是 static

dart
import 'dart:ffi';

class C {
  @Native<Int>()
  external int f;
}

常见修复方法

#

要么使字段成为静态的

dart
import 'dart:ffi';

class C {
  @Native<Int>()
  external static int f;
}

要么将其移出类,在这种情况下,不需要显式的 static 修饰符

dart
import 'dart:ffi';

class C {
}

@Native<Int>()
external int f;

如果您打算注解应该成为结构体一部分的实例字段,请省略 @Native 注解

dart
import 'dart:ffi';

final class C extends Struct {
  @Int()
  external int f;
}

native 函数缺少类型

#

此函数的原生类型无法推断,因此必须在注解中指定。

描述

#

当带有 @Native 注解的函数需要在注解上使用类型提示才能推断原生函数类型时,分析器会生成此诊断信息。

Dart 类型(如 intdouble)具有多种可能的原生表示形式。由于原生类型需要在编译时已知,以便为函数生成正确的绑定和调用指令,因此必须给出显式类型。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为函数 f() 的返回类型为 int,但在 Native 注解上没有显式的类型参数

dart
import 'dart:ffi';

@Native()
external int f();

常见修复方法

#

将相应的类型添加到注解中。例如,如果 f() 被声明为在 C 中返回 int32_t,则 Dart 函数应声明为

dart
import 'dart:ffi';

@Native<Int32 Function()>()
external int f();

负变量维度

#

可变长度数组的变量维度必须是非负数。

描述

#

分析器在两种情况下会生成此诊断。

第一种情况是 Array.variableWithVariableDimension 注解中给出的变量维度为负数。变量维度是注解中的第一个参数。

第二种情况是 Array.variableMulti 注解中给出的变量维度为负数。变量维度在注解的 variableDimension 参数中指定。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为在 Array.variableWithVariableDimension 注解中提供了 -1 的变量维度

dart
import 'dart:ffi';

final class MyStruct extends Struct {
  @Array.variableWithVariableDimension(-1)
  external Array<Uint8> a0;
}

以下代码会生成此诊断信息,因为在 Array.variableMulti 注解中提供了 -1 的变量维度

dart
import 'dart:ffi';

final class MyStruct2 extends Struct {
  @Array.variableMulti(variableDimension: -1, [1, 2])
  external Array<Array<Array<Uint8>>> a0;
}

常见修复方法

#

将变量维度更改为零 (0) 或正数

dart
import 'dart:ffi';

final class MyStruct extends Struct {
  @Array.variableWithVariableDimension(1)
  external Array<Uint8> a0;
}

将变量维度更改为零 (0) 或正数

dart
import 'dart:ffi';

final class MyStruct2 extends Struct {
  @Array.variableMulti(variableDimension: 1, [1, 2])
  external Array<Array<Array<Uint8>>> a0;
}

使用未定义的构造函数默认值的 new 表达式

#

类 '{0}' 没有未命名的构造函数。

描述

#

当在定义了命名构造函数的类上调用未命名的构造函数,但该类没有未命名的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 A 没有定义未命名的构造函数

dart
class A {
  A.a();
}

A f() => A();

常见修复方法

#

如果其中一个命名构造函数可以满足您的需求,则使用它

dart
class A {
  A.a();
}

A f() => A.a();

如果所有命名构造函数都不能满足您的需求,并且您可以添加未命名的构造函数,则添加该构造函数

dart
class A {
  A();
  A.a();
}

A f() => A();

非抽象类继承抽象成员

#

缺少“{0}”的具体实现。

缺少“{0}”和“{1}”的具体实现。

缺少 '{0}'、'{1}'、'{2}'、'{3}' 和其他 {4} 个的具体的实现。

缺少 '{0}'、'{1}'、'{2}' 和 '{3}' 的具体的实现。

缺少 '{0}'、'{1}' 和 '{2}' 的具体的实现。

描述

#

当具体类继承了一个或多个抽象成员,并且没有为至少一个抽象成员提供或继承实现时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类 B 没有 m 的具体实现

dart
abstract class A {
  void m();
}

class B extends A {}

常见修复方法

#

如果子类可以为某些或全部继承的抽象成员提供具体实现,则添加具体实现

dart
abstract class A {
  void m();
}

class B extends A {
  void m() {}
}

如果存在提供继承方法的实现的 mixin,则将 mixin 应用于子类

dart
abstract class A {
  void m();
}

class B extends A with M {}

mixin M {
  void m() {}
}

如果子类无法为所有继承的抽象成员提供具体实现,则将子类标记为抽象类

dart
abstract class A {
  void m();
}

abstract class B extends A {}

非 bool 条件

#

条件表达式的静态类型必须是 'bool'。

描述

#

当条件表达式(例如 ifwhile 循环)的静态类型不是 bool 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 x 的静态类型是 int

dart
void f(int x) {
  if (x) {
    // ...
  }
}

常见修复方法

#

更改条件表达式,使其产生布尔值

dart
void f(int x) {
  if (x == 0) {
    // ...
  }
}

非 bool 表达式

#

断言中的表达式的类型必须为 'bool'。

描述

#

当断言中的第一个表达式的类型不是 bool 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 p 的类型是 int,但需要 bool

dart
void f(int p) {
  assert(p);
}

常见修复方法

#

更改表达式,使其类型为 bool

dart
void f(int p) {
  assert(p > 0);
}

非 bool 取反表达式

#

取反运算符的操作数必须具有 'bool' 静态类型。

描述

#

当一元取反运算符 (!) 的操作数不具有 bool 类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 xint,但它必须是 bool

dart
int x = 0;
bool y = !x;

常见修复方法

#

将操作数替换为类型为 bool 的表达式

dart
int x = 0;
bool y = !(x > 0);

非 bool 操作数

#

运算符 '{0}' 的操作数必须可赋值给 'bool'。

描述

#

&&|| 运算符的操作数之一不具有 bool 类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 a 不是布尔值

dart
int a = 3;
bool b = a || a > 1;

常见修复方法

#

将操作数更改为布尔值

dart
int a = 3;
bool b = a == 0 || a > 1;

非常量注解构造函数

#

注解创建只能调用 const 构造函数。

描述

#

当注解是对现有构造函数的调用,即使被调用的构造函数不是 const 构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 C 的构造函数不是 const 构造函数

dart
@C()
void f() {
}

class C {
  C();
}

常见修复方法

#

如果类可以具有 const 构造函数,则创建一个可用于注解的 const 构造函数

dart
@C()
void f() {
}

class C {
  const C();
}

如果类不能具有 const 构造函数,则删除注解或使用不同的类作为注解。

非常量 case 表达式

#

case 表达式必须是常量。

描述

#

case 子句中的表达式不是常量表达式时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 j 不是常量

dart
void f(int i, int j) {
  switch (i) {
    case j:
      // ...
      break;
  }
}

常见修复方法

#

要么使表达式成为常量表达式,要么将 switch 语句重写为 if 语句序列

dart
void f(int i, int j) {
  if (i == j) {
    // ...
  }
}

来自延迟库的非常量 case 表达式

#

来自延迟加载库的常量值不能用作 case 表达式。

描述

#

当 case 子句中的表达式引用了使用延迟加载导入的库中的常量时,分析器会生成此诊断信息。为了使 switch 语句能够高效编译,case 子句中引用的常量需要在编译时可用,而来自延迟加载库的常量在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

给定一个文件 a.dart,其中定义了常量 zero

dart
const zero = 0;

以下代码会生成此诊断信息,因为库 a.dart 使用 deferred 导入,并且在 case 子句中使用了导入库中声明的常量 a.zero

dart
import 'a.dart' deferred as a;

void f(int x) {
  switch (x) {
    case a.zero:
      // ...
      break;
  }
}

常见修复方法

#

如果您需要引用导入库中的常量,则删除 deferred 关键字

dart
import 'a.dart' as a;

void f(int x) {
  switch (x) {
    case a.zero:
      // ...
      break;
  }
}

如果您需要引用导入库中的常量,并且还需要延迟加载导入库,则将 switch 语句重写为 if 语句序列

dart
import 'a.dart' deferred as a;

void f(int x) {
  if (x == a.zero) {
    // ...
  }
}

如果您不需要引用该常量,则替换 case 表达式

dart
void f(int x) {
  switch (x) {
    case 0:
      // ...
      break;
  }
}

非常量默认值

#

可选参数的默认值必须是常量。

描述

#

当可选参数(命名参数或位置参数)的默认值不是编译时常量时,分析器会生成此诊断信息。

示例

#

以下代码生成此诊断消息:

dart
var defaultValue = 3;

void f([int value = defaultValue]) {}

常见修复方法

#

如果默认值可以转换为常量,则将其转换

dart
const defaultValue = 3;

void f([int value = defaultValue]) {}

如果默认值需要随时间变化,则在函数内部应用默认值

dart
var defaultValue = 3;

void f([int? value]) {
  value ??= defaultValue;
}

来自延迟库的非常量默认值

#

来自延迟加载库的常量值不能用作默认参数值。

描述

#

当可选参数的默认值使用从使用延迟加载导入的库中导入的常量时,分析器会生成此诊断信息。默认值需要在编译时可用,而来自延迟加载库的常量在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

给定一个文件 a.dart,其中定义了常量 zero

dart
const zero = 0;

以下代码会生成此诊断信息,因为 zero 在使用延迟加载导入的库中声明

dart
import 'a.dart' deferred as a;

void f({int x = a.zero}) {}

常见修复方法

#

如果您需要引用导入库中的常量,则删除 deferred 关键字

dart
import 'a.dart' as a;

void f({int x = a.zero}) {}

如果您不需要引用该常量,则替换默认值

dart
void f({int x = 0}) {}

非常量 List 元素

#

const 列表字面量中的值必须是常量。

描述

#

当常量列表字面量中的元素不是常量值时,分析器会生成此诊断信息。列表字面量可以是显式的常量(因为它以 const 关键字为前缀)或隐式的常量(因为它出现在 常量上下文 中)。

示例

#

以下代码会生成此诊断信息,因为 x 不是常量,即使它出现在隐式常量列表字面量中

dart
var x = 2;
var y = const <int>[0, 1, x];

常见修复方法

#

如果列表需要是常量列表,则将元素转换为常量。在上面的示例中,您可以在 x 的声明中添加 const 关键字

dart
const x = 2;
var y = const <int>[0, 1, x];

如果表达式不能变为常量,则列表也不能是常量,因此您必须更改代码,使列表不是常量。在上面的示例中,这意味着删除列表字面量之前的 const 关键字

dart
var x = 2;
var y = <int>[0, 1, x];

非常量 Map 元素

#

const map 字面量中的元素必须是常量。

描述

#

当 const map 中的 if 元素或 spread 元素不是常量元素时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为它试图 spread 一个非 const map

dart
var notConst = <int, int>{};
var map = const <int, int>{...notConst};

类似地,以下代码会生成此诊断信息,因为 if 元素中的条件不是常量表达式

dart
bool notConst = true;
var map = const <int, int>{if (notConst) 1 : 2};

常见修复方法

#

如果 map 需要是 const map,则使元素成为常量。在 spread 示例中,您可以通过使被 spread 的集合成为常量来实现这一点

dart
const notConst = <int, int>{};
var map = const <int, int>{...notConst};

如果 map 不需要是 const map,则删除 const 关键字

dart
bool notConst = true;
var map = <int, int>{if (notConst) 1 : 2};

非常量 Map 键

#

const map 字面量中的键必须是常量。

描述

#

当 const map 字面量中的键不是常量值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 a 不是常量

dart
var a = 'a';
var m = const {a: 0};

常见修复方法

#

如果 map 需要是 const map,则使键成为常量

dart
const a = 'a';
var m = const {a: 0};

如果 map 不需要是 const map,则删除 const 关键字

dart
var a = 'a';
var m = {a: 0};

非常量 Map 模式键

#

Map 模式中的键表达式必须是常量。

描述

#

当 map 模式中的键不是常量表达式时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为键 A() 不是常量

dart
void f(Object x) {
  if (x case {A(): 0}) {}
}

class A {
  const A();
}

常见修复方法

#

为键使用常量

dart
void f(Object x) {
  if (x case {const A(): 0}) {}
}

class A {
  const A();
}

非常量 Map 值

#

const map 字面量中的值必须是常量。

描述

#

当 const map 字面量中的值不是常量值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 a 不是常量

dart
var a = 'a';
var m = const {0: a};

常见修复方法

#

如果 map 需要是 const map,则使键成为常量

dart
const a = 'a';
var m = const {0: a};

如果 map 不需要是 const map,则删除 const 关键字

dart
var a = 'a';
var m = {0: a};

非常量关系模式表达式

#

关系模式表达式必须是常量。

描述

#

当关系模式表达式中的值不是常量表达式时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 > 运算符的操作数 a 不是常量

dart
final a = 0;

void f(int x) {
  if (x case > a) {}
}

常见修复方法

#

将值替换为常量表达式

dart
const a = 0;

void f(int x) {
  if (x case > a) {}
}

非常量 Set 元素

#

const set 字面量中的值必须是常量。

描述

#

当常量 set 字面量包含不是编译时常量的元素时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断,因为 i 不是常量

dart
var i = 0;

var s = const {i};

常见修复方法

#

如果元素可以更改为常量,则更改它

dart
const i = 0;

var s = const {i};

如果元素不能是常量,则删除关键字 const

dart
var i = 0;

var s = {i};

非常量类型参数

#

'{0}' 的类型实参必须在编译时已知,因此它们不能是类型参数。

描述

#

当方法的类型实参需要在编译时已知,但类型参数(其值在编译时无法得知)被用作类型实参时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为 Pointer.asFunction 的类型实参必须在编译时已知,但类型参数 R(在编译时未知)被用作类型实参

dart
import 'dart:ffi';

typedef T = int Function(int);

class C<R extends T> {
  void m(Pointer<NativeFunction<T>> p) {
    p.asFunction<R>();
  }
}

常见修复方法

#

删除对类型参数的所有使用

dart
import 'dart:ffi';

class C {
  void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
    p.asFunction<int Function(int)>();
  }
}

const 参数使用了非常量参数

#

参数 '{0}' 必须是常量。

描述

#

当参数使用 mustBeConst 注解进行注解,但相应的实参不是常量表达式时,分析器会生成此诊断信息。

示例

#

以下代码在调用函数 f 时会生成此诊断信息,因为传递给函数 g 的实参的值不是常量

dart
import 'package:meta/meta.dart' show mustBeConst;

int f(int value) => g(value);

int g(@mustBeConst int value) => value + 1;

常见修复方法

#

如果有合适的常量可用,则将实参替换为常量

dart
import 'package:meta/meta.dart' show mustBeConst;

const v = 3;

int f() => g(v);

int g(@mustBeConst int value) => value + 1;

对字面量构造函数的非常量调用

#

此实例创建必须是 'const',因为 {0} 构造函数被标记为 '@literal'。

描述

#

当具有 literal 注解的构造函数在未使用 const 关键字的情况下被调用,但构造函数的所有实参都是常量时,分析器会生成此诊断信息。该注解表明,只要有可能,就应该使用该构造函数来创建常量值。

示例

#

以下代码生成此诊断消息:

dart
import 'package:meta/meta.dart';

class C {
  @literal
  const C();
}

C f() => C();

常见修复方法

#

在构造函数调用之前添加关键字 const

dart
import 'package:meta/meta.dart';

class C {
  @literal
  const C();
}

void f() => const C();

非常量生成枚举构造函数

#

生成式枚举构造函数必须是 'const'。

描述

#

当枚举声明包含未标记为 const 的生成式构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 E 中的构造函数未标记为 const

dart
enum E {
  e;

  E();
}

常见修复方法

#

在构造函数之前添加 const 关键字

dart
enum E {
  e;

  const E();
}

表示类型中非协变类型参数位置

#

扩展类型参数不能在其表示类型的非协变位置中使用。

描述

#

当扩展类型的类型参数在该扩展类型的表示类型的非协变位置中使用时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类型参数 T 在函数类型 void Function(T) 中用作参数类型,而参数不是协变的

dart
extension type A<T>(void Function(T) f) {}

常见修复方法

#

删除类型参数的使用

dart
extension type A(void Function(String) f) {}

非穷尽的 switch 表达式

#

类型 '{0}' 未被 switch case 完全匹配,因为它与 '{1}' 不匹配。

描述

#

switch 表达式缺少一个或多个可能流经它的值的 case 分支时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 switch 表达式没有针对值 E.three 的 case 分支

dart
enum E { one, two, three }

String f(E e) => switch (e) {
    E.one => 'one',
    E.two => 'two',
  };

常见修复方法

#

如果缺失的值对于 switch 表达式具有明显的意义,则为每个缺少匹配的值添加一个 case 分支

dart
enum E { one, two, three }

String f(E e) => switch (e) {
    E.one => 'one',
    E.two => 'two',
    E.three => 'three',
  };

如果不需要匹配缺失的值,则添加一个返回简单默认值的通配符模式

dart
enum E { one, two, three }

String f(E e) => switch (e) {
    E.one => 'one',
    E.two => 'two',
    _ => 'unknown',
  };

请注意,通配符模式将处理将来添加到类型的任何值。如果 switch 需要更新以考虑新添加的类型,您将失去让编译器警告您的能力。

非穷尽的 switch 语句

#

类型 '{0}' 未被 switch case 完全匹配,因为它与 '{1}' 不匹配。

描述

#

当针对穷举类型的 switch 语句缺少一个或多个可能流经它的值的 case 分支时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 switch 语句没有针对值 E.three 的 case 分支,并且 E 是穷举类型

dart
enum E { one, two, three }

void f(E e) {
  switch (e) {
    case E.one:
    case E.two:
  }
}

常见修复方法

#

为每个当前未匹配的常量添加一个 case 分支

dart
enum E { one, two, three }

void f(E e) {
  switch (e) {
    case E.one:
    case E.two:
      break;
    case E.three:
  }
}

如果不需要匹配缺失的值,则添加 default 子句或通配符模式

dart
enum E { one, two, three }

void f(E e) {
  switch (e) {
    case E.one:
    case E.two:
      break;
    default:
  }
}

但请注意,添加 default 子句或通配符模式将导致穷举类型的任何未来值也被处理,因此您将失去让编译器警告您 switch 是否需要更新的能力。

枚举中非 final 字段

#

枚举只能声明 final 字段。

描述

#

当枚举中的实例字段未标记为 final 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字段 f 不是 final 字段

dart
enum E {
  c;

  int f = 0;
}

常见修复方法

#

如果字段必须为枚举定义,则将该字段标记为 final

dart
enum E {
  c;

  final int f = 0;
}

如果可以删除该字段,则将其删除

dart
enum E {
  c
}

非生成构造函数

#

应为生成式构造函数 '{0}',但找到了工厂构造函数。

描述

#

当构造函数的初始化列表调用了超类中的构造函数,而被调用的构造函数是工厂构造函数时,分析器会生成此诊断信息。在初始化列表中只能调用生成式构造函数。

示例

#

以下代码会生成此诊断信息,因为构造函数 super.one() 的调用正在调用工厂构造函数

dart
class A {
  factory A.one() = B;
  A.two();
}

class B extends A {
  B() : super.one();
}

常见修复方法

#

更改 super 调用以调用生成式构造函数

dart
class A {
  factory A.one() = B;
  A.two();
}

class B extends A {
  B() : super.two();
}

如果生成式构造函数是未命名的构造函数,并且如果没有参数传递给它,则可以删除 super 调用。

非生成隐式构造函数

#

超类 '{0}' 的未命名构造函数(由 '{1}' 的默认构造函数调用)必须是生成式构造函数,但找到了工厂构造函数。

描述

#

当一个类具有隐式生成式构造函数,而超类具有显式未命名的工厂构造函数时,分析器会生成此诊断信息。子类中的隐式构造函数隐式调用超类中的未命名构造函数,但生成式构造函数只能调用另一个生成式构造函数,而不能调用工厂构造函数。

示例

#

以下代码会生成此诊断信息,因为 B 中的隐式构造函数调用了 A 中的未命名构造函数,但 A 中的构造函数是工厂构造函数,而此处需要生成式构造函数

dart
class A {
  factory A() => throw 0;
  A.named();
}

class B extends A {}

常见修复方法

#

如果超类中的未命名构造函数可以是生成式构造函数,则将其更改为生成式构造函数

dart
class A {
  A();
  A.named();
}

class B extends A { }

如果未命名构造函数不能是生成式构造函数,并且超类中还有其他生成式构造函数,则显式调用其中一个

dart
class A {
  factory A() => throw 0;
  A.named();
}

class B extends A {
  B() : super.named();
}

如果没有可用的生成式构造函数,并且无法添加,则实现超类而不是扩展它

dart
class A {
  factory A() => throw 0;
  A.named();
}

class B implements A {}

指向指针的非 native 函数类型参数

#

无法调用 'asFunction',因为指针的函数签名 '{0}' 不是有效的 C 函数签名。

描述

#

当对原生函数的指针调用方法 asFunction,但原生函数的签名不是有效的 C 函数签名时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为与指针 p 关联的函数签名 (FNative) 不是有效的 C 函数签名

dart
import 'dart:ffi';

typedef FNative = int Function(int);
typedef F = int Function(int);

class C {
  void f(Pointer<NativeFunction<FNative>> p) {
    p.asFunction<F>();
  }
}

常见修复方法

#

使 NativeFunction 签名成为有效的 C 签名

dart
import 'dart:ffi';

typedef FNative = Int8 Function(Int8);
typedef F = int Function(int);

class C {
  void f(Pointer<NativeFunction<FNative>> p) {
    p.asFunction<F>();
  }
}

非正数组维度

#

数组维度必须是正数。

描述

#

Array 注解中给出的维度小于或等于零 (0) 时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为提供了 -8 的数组维度

dart
import 'dart:ffi';

final class MyStruct extends Struct {
  @Array(-8)
  external Array<Uint8> a0;
}

常见修复方法

#

将维度更改为正整数

dart
import 'dart:ffi';

final class MyStruct extends Struct {
  @Array(8)
  external Array<Uint8> a0;
}

如果这是一个可变长度的内联数组,请将注解更改为 Array.variable()

dart
import 'dart:ffi';

final class MyStruct extends Struct {
  @Array.variable()
  external Array<Uint8> a0;
}

非 sized 类型参数

#

类型 '{1}' 不是 '{0}' 的有效类型实参。类型实参必须是原生整数、'Float'、'Double'、'Pointer' 或 'Struct'、'Union' 或 'AbiSpecificInteger' 的子类型。

描述

#

当类 Array 的类型实参不是有效类型之一时,分析器会生成此诊断信息:原生整数、FloatDoublePointerStructUnionAbiSpecificInteger 的子类型。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码产生此诊断信息,因为 Array 的类型参数是 Void,而 Void 不是有效的类型之一

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8)
  external Array<Void> a0;
}

常见修复方法

#

将类型参数更改为有效的类型之一

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8)
  external Array<Uint8> a0;
}

非同步工厂

#

工厂构造函数体不能使用 'async'、'async*' 或 'sync*'。

描述

#

当工厂构造函数的函数体标记为 asyncasync*sync* 时,分析器会生成此诊断信息。所有构造函数,包括工厂构造函数,都必须返回声明它们的类的实例,而不是 FutureStreamIterator

示例

#

以下代码产生此诊断信息,因为工厂构造函数的函数体标记为 async

dart
class C {
  factory C() async {
    return C._();
  }
  C._();
}

常见修复方法

#

如果成员必须声明为工厂构造函数,则删除出现在函数体之前的关键字

dart
class C {
  factory C() {
    return C._();
  }
  C._();
}

如果成员必须返回除封闭类实例之外的其他内容,则将该成员设为静态方法

dart
class C {
  static Future<C> m() async {
    return C._();
  }
  C._();
}

非类型作为类型参数

#

名称“{0}”不是类型,因此不能用作类型参数。

描述

#

当不是类型的标识符用作类型参数时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断,因为 x 是一个变量,而不是类型

dart
var x = 0;
List<x> xList = [];

常见修复方法

#

将类型参数更改为类型

dart
var x = 0;
List<int> xList = [];

catch 子句中的非类型

#

名称“{0}”不是类型,不能在 on-catch 子句中使用。

描述

#

catch 子句中 on 后面的标识符被定义为类型以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 f 是一个函数,而不是类型

dart
void f() {
  try {
    // ...
  } on f {
    // ...
  }
}

常见修复方法

#

将名称更改为应捕获的对象的类型

dart
void f() {
  try {
    // ...
  } on FormatException {
    // ...
  }
}

运算符的非 void 返回

#

运算符 []= 的返回类型必须为“void”。

描述

#

当运算符 []= 的声明具有除 void 以外的返回类型时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为运算符 []= 的声明的返回类型为 int

dart
class C {
  int operator []=(int index, int value) => 0;
}

常见修复方法

#

将返回类型更改为 void

dart
class C {
  void operator []=(int index, int value) => 0;
}

setter 的非 void 返回

#

setter 的返回类型必须为“void”或省略。

描述

#

当定义的 setter 具有除 void 以外的返回类型时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 setter p 的返回类型为 int

dart
class C {
  int set p(int i) => 0;
}

常见修复方法

#

将返回类型更改为 void 或省略返回类型

dart
class C {
  set p(int i) => 0;
}

未赋值的可能非空的局部变量

#

不可为空的局部变量“{0}”必须在使用前赋值。

描述

#

当引用局部变量并具有以下所有特征时,分析器会生成此诊断信息

  • 具有潜在的不可为空的类型。
  • 没有初始化器。
  • 未标记为 late
  • 分析器无法根据明确赋值的规范来证明局部变量将在引用之前被赋值。

示例

#

以下代码产生此诊断信息,因为 x 不能具有 null 值,但在赋值之前被引用

dart
String f() {
  int x;
  return x.toString();
}

以下代码产生此诊断信息,因为对 x 的赋值可能不会执行,因此它可能具有 null

dart
int g(bool b) {
  int x;
  if (b) {
    x = 1;
  }
  return x * 2;
}

以下代码产生此诊断信息,因为分析器无法基于明确赋值分析来证明 x 不会在没有赋值的情况下被引用

dart
int h(bool b) {
  int x;
  if (b) {
    x = 1;
  }
  if (b) {
    return x * 2;
  }
  return 0;
}

常见修复方法

#

如果 null 是有效值,则使变量可为空

dart
String f() {
  int? x;
  return x!.toString();
}

如果 null 不是有效值,并且存在合理的默认值,则添加初始化器

dart
int g(bool b) {
  int x = 2;
  if (b) {
    x = 1;
  }
  return x * 2;
}

否则,请确保在访问值之前,在每个可能的代码路径上都已赋值

dart
int g(bool b) {
  int x;
  if (b) {
    x = 1;
  } else {
    x = 2;
  }
  return x * 2;
}

您也可以将变量标记为 late,这将消除诊断信息,但如果变量在访问之前未赋值,则会在运行时抛出异常。仅当您确定变量始终会被赋值时,才应使用此方法,即使分析器无法基于明确赋值分析来证明这一点。

dart
int h(bool b) {
  late int x;
  if (b) {
    x = 1;
  }
  if (b) {
    return x * 2;
  }
  return 0;
}

不是类型

#

{0} 不是类型。

描述

#

当名称用作类型但声明为类型以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 f 是一个函数

dart
f() {}
g(f v) {}

常见修复方法

#

将名称替换为类型的名称。

不是二元运算符

#

“{0}”不是二元运算符。

描述

#

当只能用作一元运算符的运算符用作二元运算符时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为运算符 ~ 只能用作一元运算符

dart
var a = 5 ~ 3;

常见修复方法

#

将运算符替换为正确的二元运算符

dart
var a = 5 - 3;

位置参数不足

#

“{0}”需要 1 个位置参数,但找到了 0 个。

需要 1 个位置参数,但找到了 0 个。

“{2}”需要 {0} 个位置参数,但找到了 {1} 个。

需要 {0} 个位置参数,但找到了 {1} 个。

描述

#

当方法或函数调用具有的位置参数少于所需的位置形参的数量时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 f 声明了两个必需的形参,但仅提供了一个参数

dart
void f(int a, int b) {}
void g() {
  f(0);
}

常见修复方法

#

添加与剩余形参对应的参数

dart
void f(int a, int b) {}
void g() {
  f(0, 1);
}

未初始化的非空实例字段

#

不可为空的实例字段“{0}”必须初始化。

描述

#

当声明字段并具有以下所有特征时,分析器会生成此诊断信息

示例

#

以下代码产生此诊断信息,因为当不允许为 null 时,x 隐式初始化为 null

dart
class C {
  int x;
}

同样,以下代码产生此诊断信息,因为当不允许为 null 时,即使 x 由其他构造函数初始化,它也会由其中一个构造函数隐式初始化为 null

dart
class C {
  int x;

  C(this.x);

  C.n();
}

常见修复方法

#

如果字段存在所有实例通用的合理默认值,则添加初始化表达式

dart
class C {
  int x = 0;
}

如果应在创建实例时提供字段的值,则添加一个设置字段值的构造函数或更新现有构造函数

dart
class C {
  int x;

  C(this.x);
}

您也可以将字段标记为 late,这将消除诊断信息,但如果字段在访问之前未赋值,则会在运行时抛出异常。仅当您确定字段始终会在被引用之前赋值时,才应使用此方法。

dart
class C {
  late int x;
}

未初始化的非空变量

#

不可为空的变量“{0}”必须初始化。

描述

#

当静态字段或顶层变量的类型不可为空且没有初始化器时,分析器会生成此诊断信息。没有初始化器的字段和变量通常初始化为 null,但字段或变量的类型不允许将其设置为 null,因此必须提供显式初始化器。

示例

#

以下代码产生此诊断信息,因为字段 f 不能初始化为 null

dart
class C {
  static int f;
}

同样,以下代码产生此诊断信息,因为顶层变量 v 不能初始化为 null

dart
int v;

常见修复方法

#

如果字段或变量不能初始化为 null,则添加一个将其设置为非空值的初始化器

dart
class C {
  static int f = 0;
}

如果字段或变量应初始化为 null,则将类型更改为可为空

dart
int? v;

如果字段或变量无法在声明中初始化,但始终会在引用之前初始化,则将其标记为 late

dart
class C {
  static late int f;
}

不可迭代的展开

#

列表或集合字面量中的展开元素必须实现“Iterable”。

描述

#

当列表字面量或集合字面量中出现的展开元素的表达式的静态类型未实现 Iterable 类型时,分析器会生成此诊断信息。

示例

#

以下代码生成此诊断消息:

dart
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m};

常见修复方法

#

最常见的修复方法是将表达式替换为生成可迭代对象的表达式

dart
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m.keys};

不可 Map 的展开

#

映射字面量中的展开元素必须实现“Map”。

描述

#

当映射字面量中出现的展开元素的表达式的静态类型未实现 Map 类型时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 l 不是 Map

dart
var l =  <String>['a', 'b'];
var m = <int, String>{...l};

常见修复方法

#

最常见的修复方法是将表达式替换为生成映射的表达式

dart
var l =  <String>['a', 'b'];
var m = <int, String>{...l.asMap()};

没有注解构造函数参数

#

注解创建必须具有参数。

描述

#

当注解由单个标识符组成,但该标识符是类的名称而不是变量的名称时,分析器会生成此诊断信息。要创建类的实例,标识符后必须跟参数列表。

示例

#

以下代码产生此诊断信息,因为 C 是一个类,并且一个类不能用作注解,除非从该类调用 const 构造函数

dart
class C {
  const C();
}

@C
var x;

常见修复方法

#

添加缺少的参数列表

dart
class C {
  const C();
}

@C()
var x;

没有组合的 super 签名

#

无法从重写的方法:{1} 中推断“{0}”中缺少的类型。

描述

#

当存在一个或多个类型需要推断的方法声明,并且这些类型无法推断,因为根据重写推断的规定,没有一个重写的方法具有函数类型,该函数类型是所有其他重写的方法的超类型时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为在类 C 中声明的方法 m 缺少返回类型和参数 a 的类型,并且对于它,这两个缺失的类型都无法推断

dart
abstract class A {
  A m(String a);
}

abstract class B {
  B m(int a);
}

abstract class C implements A, B {
  m(a);
}

在此示例中,无法执行重写推断,因为重写的方法在以下方面不兼容

  • 参数类型(Stringint)都不是另一个的超类型。
  • 返回类型都不是另一个的子类型。

常见修复方法

#

如果可能,请将类型添加到子类中的方法,使其与所有重写方法中的类型一致

dart
abstract class A {
  A m(String a);
}

abstract class B {
  B m(int a);
}

abstract class C implements A, B {
  C m(Object a);
}

超类中没有生成构造函数

#

类“{0}”不能扩展“{1}”,因为“{1}”只有工厂构造函数(没有生成构造函数),而“{0}”至少有一个生成构造函数。

描述

#

当具有至少一个生成构造函数(显式或隐式)的类具有没有任何生成构造函数的超类时,分析器会生成此诊断信息。每个生成构造函数,除了在 Object 中定义的构造函数之外,都会显式或隐式地调用其超类中的生成构造函数之一。

示例

#

以下代码产生此诊断信息,因为类 B 具有隐式生成构造函数,该构造函数无法从 A 调用生成构造函数,因为 A 没有任何生成构造函数

dart
class A {
  factory A.none() => throw '';
}

class B extends A {}

常见修复方法

#

如果超类应具有生成构造函数,则添加一个

dart
class A {
  A();
  factory A.none() => throw '';
}

class B extends A {}

如果子类不应具有生成构造函数,则通过添加工厂构造函数来移除它

dart
class A {
  factory A.none() => throw '';
}

class B extends A {
  factory B.none() => throw '';
}

如果子类必须具有生成构造函数,但超类不能有,则改为实现超类

dart
class A {
  factory A.none() => throw '';
}

class B implements A {}

catch 子句中的可空类型

#

潜在的可空类型不能在“on”子句中使用,因为抛出可空表达式是无效的。

描述

#

catch 子句中 on 后面的类型为可空类型时,分析器会生成此诊断信息。指定可空类型是无效的,因为无法捕获 null(因为抛出 null 是运行时错误)。

示例

#

以下代码产生此诊断信息,因为异常类型被指定为允许 null,而 null 无法被抛出

dart
void f() {
  try {
    // ...
  } on FormatException? {
  }
}

常见修复方法

#

从类型中删除问号

dart
void f() {
  try {
    // ...
  } on FormatException {
  }
}

extends 子句中的可空类型

#

类不能扩展可空类型。

描述

#

当类声明使用 extends 子句来指定超类,并且超类后跟 ? 时,分析器会生成此诊断信息。

指定可空超类是无效的,因为这样做没有任何意义;它不会更改包含 extends 子句的类继承的接口或实现。

但请注意,将可空类型用作超类的类型参数是有效的,例如 class A extends B<C?> {}

示例

#

以下代码产生此诊断信息,因为 A? 是可空类型,而可空类型不能在 extends 子句中使用

dart
class A {}
class B extends A? {}

常见修复方法

#

从类型中删除问号

dart
class A {}
class B extends A {}

implements 子句中的可空类型

#

类、mixin 或扩展类型不能实现可空类型。

描述

#

当类、mixin 或扩展类型声明具有 implements 子句,并且接口后跟 ? 时,分析器会生成此诊断信息。

指定可空接口是无效的,因为这样做没有任何意义;它不会更改包含 implements 子句的类继承的接口。

但请注意,将可空类型用作接口的类型参数是有效的,例如 class A implements B<C?> {}

示例

#

以下代码产生此诊断信息,因为 A? 是可空类型,而可空类型不能在 implements 子句中使用

dart
class A {}
class B implements A? {}

常见修复方法

#

从类型中删除问号

dart
class A {}
class B implements A {}

on 子句中的可空类型

#

mixin 不能将可空类型作为超类约束。

描述

#

当 mixin 声明使用 on 子句来指定超类约束,并且指定的类后跟 ? 时,分析器会生成此诊断信息。

指定可空超类约束是无效的,因为这样做没有任何意义;它不会更改包含 on 子句的 mixin 所依赖的接口。

但请注意,将可空类型用作超类约束的类型参数是有效的,例如 mixin A on B<C?> {}

示例

#

以下代码产生此诊断信息,因为 A? 是可空类型,而可空类型不能在 on 子句中使用

dart
class C {}
mixin M on C? {}

常见修复方法

#

从类型中删除问号

dart
class C {}
mixin M on C {}

with 子句中的可空类型

#

类或 mixin 不能混入可空类型。

描述

#

当类或 mixin 声明具有 with 子句,并且 mixin 后跟 ? 时,分析器会生成此诊断信息。

指定可空 mixin 是无效的,因为这样做没有任何意义;它不会更改包含 with 子句的类继承的接口或实现。

但请注意,将可空类型用作 mixin 的类型参数是有效的,例如 class A with B<C?> {}

示例

#

以下代码产生此诊断信息,因为 A? 是可空类型,而可空类型不能在 with 子句中使用

dart
mixin M {}
class C with M? {}

常见修复方法

#

从类型中删除问号

dart
mixin M {}
class C with M {}

null 参数传递给非 null 类型

#

对于不可为空的类型参数“{1}”,“{0}”不应使用“null”参数调用。

描述

#

当使用不可为空的类型参数创建实例时,将 null 传递给构造函数 Future.value 或方法 Completer.complete 时,分析器会生成此诊断信息。即使类型系统无法表达此限制,传入 null 也会导致运行时异常。

示例

#

以下代码产生此诊断信息,因为即使类型参数是不可为空的类型 Stringnull 也被传递给构造函数 Future.value

dart
Future<String> f() {
  return Future.value(null);
}

常见修复方法

#

传入非空值

dart
Future<String> f() {
  return Future.value('');
}

空检查总是失败

#

此空值检查将始终抛出异常,因为表达式将始终求值为“null”。

描述

#

当空值检查运算符 (!) 用于其值只能为 null 的表达式时,分析器会生成此诊断信息。在这种情况下,运算符始终抛出异常,这可能不是预期的行为。

示例

#

以下代码产生此诊断信息,因为函数 g 将始终返回 null,这意味着 f 中的空值检查将始终抛出异常

dart
void f() {
  g()!;
}

Null g() => null;

常见修复方法

#

如果您打算始终抛出异常,则将空值检查替换为显式 throw 表达式,以使意图更清晰

dart
void f() {
  g();
  throw TypeError();
}

Null g() => null;

过时的冒号用于默认值

#

不再支持使用冒号作为默认值之前的分隔符。

描述

#

当冒号 (:) 用作可选命名参数的默认值之前的分隔符时,分析器会生成此诊断信息。虽然过去允许使用此语法,但它已被删除,取而代之的是使用等号 (=)。

示例

#

以下代码会生成此诊断,因为在可选参数 i 的默认值之前使用了冒号

dart
void f({int i : 0}) {}

常见修复方法

#

将冒号替换为等号

dart
void f({int i = 0}) {}

on 子句重复

#

类型“{0}”只能在超类约束中包含一次。

描述

#

当 mixin 的超类约束中多次列出相同的类型时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 AM 的超类约束中包含了两次

dart
mixin M on A, A {
}

class A {}
class B {}

常见修复方法

#

如果应在超类约束中包含不同的类型,则将其中一个出现项替换为另一个类型

dart
mixin M on A, B {
}

class A {}
class B {}

如果不需要其他类型,则删除重复的类型名称

dart
mixin M on A {
}

class A {}
class B {}

运算符中的可选参数

#

定义运算符时不允许使用可选参数。

描述

#

当运算符声明中的一个或多个参数是可选的时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为参数 other 是可选参数

dart
class C {
  C operator +([C? other]) => this;
}

常见修复方法

#

使所有参数成为必需参数

dart
class C {
  C operator +(C other) => this;
}

覆盖非覆盖成员

#

该字段未重写继承的 getter 或 setter。

getter 未重写继承的 getter。

该方法未重写继承的方法。

setter 未重写继承的 setter。

描述

#

当类成员使用 @override 注解进行注解,但该成员未在类的任何超类型中声明时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 m 未在 C 的任何超类型中声明

dart
class C {
  @override
  String m() => '';
}

常见修复方法

#

如果成员旨在重写具有不同名称的成员,则更新成员以具有相同的名称

dart
class C {
  @override
  String toString() => '';
}

如果成员旨在重写已从超类中移除的成员,则考虑从子类中移除该成员。

如果无法移除该成员,则移除注解。

packed 注解

#

Structs 必须最多有一个“Packed”注解。

描述

#

Struct 的子类具有多个 Packed 注解时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码产生此诊断信息,因为类 CStruct 的子类)具有两个 Packed 注解

dart
import 'dart:ffi';

@Packed(1)
@Packed(1)
final class C extends Struct {
  external Pointer<Uint8> notEmpty;
}

常见修复方法

#

删除除一个之外的所有注解

dart
import 'dart:ffi';

@Packed(1)
final class C extends Struct {
  external Pointer<Uint8> notEmpty;
}

packed 注解对齐

#

仅支持打包到 1、2、4、8 和 16 字节。

描述

#

Packed 注解的参数不是允许的值之一:1、2、4、8 或 16 时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码产生此诊断信息,因为 Packed 注解的参数 (3) 不是允许的值之一

dart
import 'dart:ffi';

@Packed(3)
final class C extends Struct {
  external Pointer<Uint8> notEmpty;
}

常见修复方法

#

将对齐方式更改为允许的值之一

dart
import 'dart:ffi';

@Packed(4)
final class C extends Struct {
  external Pointer<Uint8> notEmpty;
}

属于不同库的 part 指令

#

预期此库是“{0}”的一部分,而不是“{1}”。

描述

#

当一个库尝试将一个文件作为自身的一部分包含进来,而另一个文件是不同库的一部分时,分析器会生成此诊断信息。

示例

#

给定一个包含以下内容的文件 part.dart

dart
part of 'library.dart';

以下代码,在 library.dart 以外的任何文件中,都会产生此诊断信息,因为它尝试将 part.dart 作为自身的一部分包含进来,而 part.dart 是不同库的一部分

dart
part 'package:a/part.dart';

常见修复方法

#

如果库应使用不同的文件作为一部分,则将 part 指令中的 URI 更改为另一个文件的 URI。

如果part 文件应是此库的一部分,则更新 part-of 指令中的 URI(或库名)以使其成为正确库的 URI(或名称)。

part of 非 part

#

包含的 part“{0}”必须具有 part-of 指令。

描述

#

当找到 part 指令并且引用的文件没有 part-of 指令时,分析器会生成此诊断信息。

示例

#

给定一个包含以下内容的文件 a.dart

dart
class A {}

以下代码产生此诊断信息,因为 a.dart 不包含 part-of 指令

dart
part 'a.dart';

常见修复方法

#

如果引用的文件旨在成为另一个库的一部分,则向该文件添加 part-of 指令

dart
part of 'test.dart';

class A {}

如果引用的文件旨在成为一个库,则将 part 指令替换为 import 指令

dart
import 'a.dart';

part of 未命名库

#

库是未命名的。在 part-of 指令中,预期的是 URI,而不是库名“{0}”。

描述

#

当一个没有 library 指令(因此没有名称)的库包含 part 指令,并且part 文件中的 part of 指令使用名称来指定它所属的库时,分析器会生成此诊断信息。

示例

#

给定一个名为 part_file.dartpart 文件,其中包含以下代码

dart
part of lib;

以下代码产生此诊断信息,因为包含part 文件的库没有名称,即使part 文件使用名称来指定它所属的库

dart
part 'part_file.dart';

常见修复方法

#

更改part 文件中的 part of 指令,以通过 URI 指定其库

dart
part of 'test.dart';

路径不存在

#

路径“{0}”不存在。

描述

#

当依赖项具有 path 键,引用了不存在的目录时,分析器会生成此诊断信息。

示例

#

假设目录 doesNotExist 不存在,以下代码会产生此诊断信息,因为它被列为包的路径

yaml
name: example
dependencies:
  local_package:
    path: doesNotExist

常见修复方法

#

如果路径正确,则在该路径下创建一个目录。

如果路径不正确,则更改路径以匹配包根目录的路径。

路径不是 POSIX 路径

#

路径“{0}”不是 POSIX 风格的路径。

描述

#

当依赖项具有 path 键,其值是字符串,但不是 POSIX 风格的路径时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 path 键后面的路径是 Windows 路径

yaml
name: example
dependencies:
  local_package:
    path: E:\local_package

常见修复方法

#

将路径转换为 POSIX 路径。

路径 pubspec 文件不存在

#

目录“{0}”不包含 pubspec。

描述

#

当依赖项具有 path 键,引用了不包含 pubspec.yaml 文件的目录时,分析器会生成此诊断信息。

示例

#

假设目录 local_package 不包含文件 pubspec.yaml,以下代码会产生此诊断信息,因为它被列为包的路径

yaml
name: example
dependencies:
  local_package:
    path: local_package

常见修复方法

#

如果路径旨在成为包的根目录,则在该目录中添加一个 pubspec.yaml 文件

yaml
name: local_package

如果路径错误,则将其替换为正确的路径。

模式赋值不是局部变量

#

模式赋值中只能赋值给局部变量。

描述

#

当模式赋值将值赋给局部变量以外的任何内容时,分析器会生成此诊断信息。模式无法赋值给字段或顶层变量。

示例

#

如果使用模式进行解构时代码更简洁,则重写代码以在模式声明中将值赋给局部变量,并分别赋值给非局部变量

dart
class C {
  var x = 0;

  void f((int, int) r) {
    (x, _) = r;
  }
}

常见修复方法

#

如果使用模式赋值时代码更简洁,则重写代码以将值赋给局部变量,并分别赋值给非局部变量

dart
class C {
  var x = 0;

  void f((int, int) r) {
    var (a, _) = r;
    x = a;
  }
}

如果不用模式赋值时代码更简洁,则重写代码以不使用模式赋值

dart
class C {
  var x = 0;

  void f((int, int) r) {
    x = r.$1;
  }
}

来自延迟库的模式常量

#

延迟加载库中的常量值不能在模式中使用。

描述

#

当模式包含在不同库中声明的值,并且该库是使用延迟导入导入的时,分析器会生成此诊断信息。常量在编译时求值,但延迟加载库中的值在编译时不可用。

有关更多信息,请查看 延迟加载库

示例

#

给定一个文件 a.dart,其中定义了常量 zero

dart
const zero = 0;

以下代码产生此诊断信息,因为常量模式 a.zero 是使用延迟导入导入的

dart
import 'a.dart' deferred as a;

void f(int x) {
  switch (x) {
    case a.zero:
      // ...
      break;
  }
}

常见修复方法

#

如果您需要引用导入库中的常量,则删除 deferred 关键字

dart
import 'a.dart' as a;

void f(int x) {
  switch (x) {
    case a.zero:
      // ...
      break;
  }
}

如果您需要引用导入库中的常量,并且还需要延迟加载导入库,则将 switch 语句重写为 if 语句序列

dart
import 'a.dart' deferred as a;

void f(int x) {
  if (x == a.zero) {
    // ...
  }
}

如果您不需要引用该常量,则替换 case 表达式

dart
void f(int x) {
  switch (x) {
    case 0:
      // ...
      break;
  }
}

不可反驳上下文中模式类型不匹配

#

类型为“{0}”的匹配值无法赋值给必需类型“{1}”。

描述

#

当模式赋值或模式声明右侧的值的类型与用于匹配它的模式所需的类型不匹配时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 x 可能不是 String,因此可能与对象模式不匹配

dart
void f(Object x) {
  var String(length: a) = x;
  print(a);
}

常见修复方法

#

更改代码,使右侧表达式的类型与模式所需的类型匹配

dart
void f(String x) {
  var String(length: a) = x;
  print(a);
}

guard 内部的模式变量赋值

#

模式变量不能在封闭的守卫模式的守卫中赋值。

描述

#

当模式变量在守卫 (when) 子句中赋值时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为变量 a 在守卫子句中赋值

dart
void f(int x) {
  if (x case var a when (a = 1) > 0) {
    print(a);
  }
}

常见修复方法

#

如果存在您需要捕获的值,则将其赋值给不同的变量

dart
void f(int x) {
  var b;
  if (x case var a when (b = 1) > 0) {
    print(a + b);
  }
}

如果不存在您需要捕获的值,则删除赋值

dart
void f(int x) {
  if (x case var a when 1 > 0) {
    print(a);
  }
}

不允许的平台值

#

platforms 字段中的键不能有值。

描述

#

platforms 映射中的键具有值时,分析器会生成此诊断信息。要了解有关指定包支持的平台的更多信息,请查看平台声明文档

示例

#

以下 pubspec.yaml 产生此诊断信息,因为键 web 具有值。

yaml
name: example
platforms:
  web: "chrome"

常见修复方法

#

省略该值,并将键保留为无值

yaml
name: example
platforms:
  web:

platforms 字段中键的值目前保留供未来行为使用。

对象模式中的位置字段

#

对象模式只能使用命名字段。

描述

#

当对象模式包含一个字段,但没有指定 getter 名称时,分析器会生成此诊断信息。对象模式字段与对象的 getter 返回的值匹配。在没有指定 getter 名称的情况下,模式字段无法访问值以尝试匹配。

示例

#

以下代码产生此诊断信息,因为对象模式 String(1) 未指定要访问 String 的哪个 getter 并与值 1 进行比较

dart
void f(Object o) {
  if (o case String(1)) {}
}

常见修复方法

#

添加 getter 名称以访问该值,然后在要匹配的模式之前加上冒号

dart
void f(Object o) {
  if (o case String(length: 1)) {}
}

带有位置参数的位置 super 形式参数

#

当超类构造函数调用具有位置参数时,不能使用位置超参数。

描述

#

当提供给超类构造函数的某些(但不是全部)位置参数正在使用超参数时,分析器会生成此诊断信息。

位置超参数通过索引与超类构造函数中的位置参数关联。也就是说,第一个超参数与超类构造函数中的第一个位置参数关联,第二个超参数与第二个位置参数关联,依此类推。位置参数也是如此。同时具有位置超参数和位置参数意味着有两个值与超类的构造函数中的同一个参数关联,因此是不允许的。

示例

#

以下代码产生此诊断信息,因为构造函数 B.new 正在使用超参数将一个必需的位置参数传递给 A 中的超类构造函数,但正在超类构造函数调用中显式传递另一个

dart
class A {
  A(int x, int y);
}

class B extends A {
  B(int x, super.y) : super(x);
}

常见修复方法

#

如果所有位置参数都可以是超参数,则将普通位置参数转换为超参数

dart
class A {
  A(int x, int y);
}

class B extends A {
  B(super.x, super.y);
}

如果某些位置参数不能是超参数,则将超参数转换为普通参数

dart
class A {
  A(int x, int y);
}

class B extends A {
  B(int x, int y) : super(x, y);
}

前缀与顶层成员冲突

#

名称“{0}”已被用作导入前缀,不能用于命名顶层元素。

描述

#

当名称同时用作导入前缀和同一库中顶层声明的名称时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 f 同时用作导入前缀和函数的名称

dart
import 'dart:math' as f;

int f() => f.min(0, 1);

常见修复方法

#

如果要将该名称用于导入前缀,则重命名顶层声明

dart
import 'dart:math' as f;

int g() => f.min(0, 1);

如果要将该名称用于顶层声明,则重命名导入前缀

dart
import 'dart:math' as math;

int f() => math.min(0, 1);

前缀标识符后未跟点号

#

名称“{0}”引用导入前缀,因此后面必须跟“.”。

描述

#

当导入前缀本身被使用,而没有访问与前缀关联的库中声明的任何名称时,分析器会生成此诊断信息。前缀不是变量,因此不能用作值。

示例

#

以下代码产生此诊断信息,因为前缀 math 被当作变量使用

dart
import 'dart:math' as math;

void f() {
  print(math);
}

常见修复方法

#

如果代码不完整,则引用与前缀关联的库中的某些内容

dart
import 'dart:math' as math;

void f() {
  print(math.pi);
}

如果名称错误,则更正名称。

前缀被局部声明遮蔽

#

前缀“{0}”不能在此处使用,因为它被局部声明遮蔽。

描述

#

当导入前缀在上下文中不可见时使用,因为它被局部声明遮蔽时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为前缀 a 用于访问类 Future,但由于被参数 a 遮蔽而不可见

dart
import 'dart:async' as a;

a.Future? f(int a) {
  a.Future? x;
  return x;
}

常见修复方法

#

重命名前缀

dart
import 'dart:async' as p;

p.Future? f(int a) {
  p.Future? x;
  return x;
}

或重命名局部变量

dart
import 'dart:async' as a;

a.Future? f(int p) {
  a.Future? x;
  return x;
}

mixin 应用中的私有成员冲突

#

由“{1}”定义的私有名称“{0}”与由“{2}”定义的相同名称冲突。

描述

#

当在定义 mixin 的库以外的库中的单个类中一起使用两个定义了相同私有成员的 mixin 时,分析器会生成此诊断信息。

示例

#

给定一个包含以下代码的文件 a.dart

dart
mixin A {
  void _foo() {}
}

mixin B {
  void _foo() {}
}

以下代码产生此诊断信息,因为 mixin AB 都定义了方法 _foo

dart
import 'a.dart';

class C extends Object with A, B {}

常见修复方法

#

如果您不需要这两个 mixin,则从 with 子句中移除其中一个

dart
import 'a.dart';

class C extends Object with A, B {}

如果您需要这两个 mixin,则重命名两个 mixin 之一中的冲突成员。

私有可选参数

#

命名参数不能以下划线开头。

描述

#

当命名参数的名称以下划线开头时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为命名参数 _x 以下划线开头

dart
class C {
  void m({int _x = 0}) {}
}

常见修复方法

#

重命名参数,使其不以下划线开头

dart
class C {
  void m({int x = 0}) {}
}

私有 setter

#

setter“{0}”是私有的,不能在声明它的库外部访问。

描述

#

当在 setter 不可见的库中使用私有 setter 时,分析器会生成此诊断信息。

示例

#

给定一个包含以下内容的文件 a.dart

dart
class A {
  static int _f = 0;
}

以下代码产生此诊断信息,因为它引用了私有 setter _f,即使该 setter 不可见

dart
import 'a.dart';

void f() {
  A._f = 0;
}

常见修复方法

#

如果您能够使 setter 公开,请这样做

dart
class A {
  static int f = 0;
}

如果您无法使 setter 公开,请找到实现代码的其他方法。

读取可能未赋值的 final 变量

#

最终变量“{0}”无法读取,因为它在此处可能尚未赋值。

描述

#

当在声明位置未初始化的最终局部变量在编译器无法证明该变量在使用前总是被初始化的情况下被读取时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为最终局部变量 x 在可能尚未初始化的情况下被读取(在第 3 行)。

dart
int f() {
  final int x;
  return x;
}

常见修复方法

#

确保变量在使用前已被初始化。

dart
int f(bool b) {
  final int x;
  if (b) {
    x = 0;
  } else {
    x = 1;
  }
  return x;
}

只有一个位置参数且没有尾随逗号的记录字面量

#

只有一个位置字段的记录字面量需要尾随逗号。

描述

#

当只有一个位置字段的记录字面量在该字段后没有尾随逗号时,分析器会生成此诊断信息。

在某些情况下,只有一个位置字段的记录字面量也可能是一个带括号的表达式。需要尾随逗号来消除这两种有效解释的歧义。

示例

#

以下代码会生成此诊断信息,因为记录字面量只有一个位置字段,但没有尾随逗号。

dart
var r = const (1);

常见修复方法

#

添加尾随逗号。

dart
var r = const (1,);

只有一个位置参数且没有尾随逗号的记录类型

#

只有一个位置字段的记录类型需要尾随逗号。

描述

#

当只有一个位置字段的记录类型注解在该字段后没有尾随逗号时,分析器会生成此诊断信息。

在某些情况下,只有一个位置字段的记录类型也可能是一个带括号的表达式。需要尾随逗号来消除这两种有效解释的歧义。

示例

#

以下代码会生成此诊断信息,因为记录类型只有一个位置字段,但没有尾随逗号。

dart
void f((int) r) {}

常见修复方法

#

添加尾随逗号。

dart
void f((int,) r) {}

递归编译时常量

#

编译时常量表达式依赖于自身。

描述

#

当编译时常量的值根据自身直接或间接地定义时,分析器会生成此诊断信息,从而创建无限循环。

示例

#

以下代码会生成两次此诊断信息,因为两个常量都是根据另一个定义的。

dart
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = secondsPerHour / 60;

常见修复方法

#

通过找到至少一种定义常量的方法来打破循环。

dart
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = 60;

递归构造函数重定向

#

构造函数不能直接或间接地重定向到自身。

描述

#

当构造函数直接或间接地重定向到自身时,分析器会生成此诊断信息,从而创建无限循环。

示例

#

以下代码会生成此诊断信息,因为生成构造函数 C.aC.b 都互相重定向。

dart
class C {
  C.a() : this.b();
  C.b() : this.a();
}

以下代码会生成此诊断信息,因为工厂构造函数 AB 都互相重定向。

dart
abstract class A {
  factory A() = B;
}
class B implements A {
  factory B() = A;
  B.named();
}

常见修复方法

#

对于生成构造函数,通过定义至少一个构造函数不重定向到另一个构造函数来打破循环。

dart
class C {
  C.a() : this.b();
  C.b();
}

对于工厂构造函数,通过定义至少一个工厂构造函数来执行以下操作之一来打破循环:

  • 重定向到生成构造函数。
dart
abstract class A {
  factory A() = B;
}
class B implements A {
  factory B() = B.named;
  B.named();
}
  • 不重定向到另一个构造函数。
dart
abstract class A {
  factory A() = B;
}
class B implements A {
  factory B() {
    return B.named();
  }

  B.named();
}
  • 不作为工厂构造函数。
dart
abstract class A {
  factory A() = B;
}
class B implements A {
  B();
  B.named();
}

递归接口继承

#

“{0}”不能是自身的超接口:{1}。

“{0}”不能扩展自身。

“{0}”不能实现自身。

“{0}”不能将自身用作混入。

“{0}”不能将自身用作超类约束。

描述

#

当类型层次结构中存在循环时,分析器会生成此诊断信息。当一个类型直接或间接地声明为自身的子类型时,就会发生这种情况。

示例

#

以下代码会生成此诊断信息,因为类 A 被声明为 B 的子类型,而 BA 的子类型。

dart
class A extends B {}
class B implements A {}

常见修复方法

#

更改类型层次结构,使其没有循环。

在非重声明成员上重声明

#

{0} 没有重新声明超接口中声明的 {0}。

描述

#

当扩展类型的成员用 @redeclare 注解时,但没有已实现的接口具有相同名称的成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展类型 E 声明的成员 n@redeclare 注解,但 C 没有名为 n 的成员。

dart
import 'package:meta/meta.dart';

class C {
  void m() {}
}

extension type E(C c) implements C {
  @redeclare
  void n() {}
}

常见修复方法

#

如果注解的成员具有正确的名称,则删除注解。

dart
class C {
  void m() {}
}

extension type E(C c) implements C {
  void n() {}
}

如果注解的成员应该替换已实现接口中的成员,则更改注解的成员的名称以匹配要替换的成员。

dart
import 'package:meta/meta.dart';

class C {
  void m() {}
}

extension type E(C c) implements C {
  @redeclare
  void m() {}
}

重定向生成构造函数到缺失的构造函数

#

在“{1}”中找不到构造函数“{0}”。

描述

#

当生成构造函数重定向到未定义的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为构造函数 C.a 重定向到构造函数 C.b,但 C.b 未定义。

dart
class C {
  C.a() : this.b();
}

常见修复方法

#

如果必须调用缺少的构造函数,则定义它。

dart
class C {
  C.a() : this.b();
  C.b();
}

如果不需要调用缺少的构造函数,则删除重定向。

dart
class C {
  C.a();
}

重定向生成构造函数到非生成构造函数

#

生成构造函数不能重定向到工厂构造函数。

描述

#

当生成构造函数重定向到工厂构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为生成构造函数 C.a 重定向到工厂构造函数 C.b

dart
class C {
  C.a() : this.b();
  factory C.b() => C.a();
}

常见修复方法

#

如果生成构造函数不需要重定向到另一个构造函数,则删除重定向。

dart
class C {
  C.a();
  factory C.b() => C.a();
}

如果生成构造函数必须重定向到另一个构造函数,则使另一个构造函数成为生成(非工厂)构造函数。

dart
class C {
  C.a() : this.b();
  C.b();
}

重定向到抽象类构造函数

#

重定向构造函数“{0}”不能重定向到抽象类“{1}”的构造函数。

描述

#

当构造函数重定向到抽象类中的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 A 中的工厂构造函数重定向到 B 中的构造函数,但 B 是一个抽象类。

dart
class A {
  factory A() = B;
}

abstract class B implements A {}

常见修复方法

#

如果代码重定向到正确的构造函数,则更改类使其不是抽象类。

dart
class A {
  factory A() = B;
}

class B implements A {}

否则,更改工厂构造函数,使其重定向到具体类中的构造函数,或具有具体实现。

重定向到无效的函数类型

#

重定向的构造函数“{0}”与“{1}”的参数不兼容。

描述

#

当工厂构造函数尝试重定向到另一个构造函数,但两者具有不兼容的参数时,分析器会生成此诊断信息。如果重定向构造函数的所有参数都可以传递给另一个构造函数,并且另一个构造函数不需要重定向构造函数未声明的任何参数,则参数是兼容的。

示例

#

以下代码会生成此诊断信息,因为 A 的构造函数没有声明 B 的构造函数需要的参数。

dart
abstract class A {
  factory A() = B;
}

class B implements A {
  B(int x);
  B.zero();
}

以下代码会生成此诊断信息,因为 A 的构造函数声明了一个命名参数 (y),而 B 的构造函数不允许。

dart
abstract class A {
  factory A(int x, {int y}) = B;
}

class B implements A {
  B(int x);
}

常见修复方法

#

如果存在与重定向构造函数兼容的不同构造函数,则重定向到该构造函数。

dart
abstract class A {
  factory A() = B.zero;
}

class B implements A {
  B(int x);
  B.zero();
}

否则,更新重定向构造函数以使其兼容。

dart
abstract class A {
  factory A(int x) = B;
}

class B implements A {
  B(int x);
}

重定向到无效的返回类型

#

重定向构造函数的返回类型“{0}”不是“{1}”的子类型。

描述

#

当工厂构造函数重定向到返回类型不是工厂构造函数声明要生成的类型的子类型的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 A 不是 C 的子类,这意味着构造函数 A() 返回的值无法从构造函数 C() 返回。

dart
class A {}

class B implements C {}

class C {
  factory C() = A;
}

常见修复方法

#

如果工厂构造函数重定向到错误类中的构造函数,则更新工厂构造函数以重定向到正确的构造函数。

dart
class A {}

class B implements C {}

class C {
  factory C() = B;
}

如果定义要重定向到的构造函数的类是应该返回的类,则使其成为工厂返回类型的子类型。

dart
class A implements C {}

class B implements C {}

class C {
  factory C() = A;
}

重定向到缺失的构造函数

#

在“{1}”中找不到构造函数“{0}”。

描述

#

当构造函数重定向到不存在的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 A 中的工厂构造函数重定向到 B 中不存在的构造函数。

dart
class A {
  factory A() = B.name;
}

class B implements A {
  B();
}

常见修复方法

#

如果要重定向到的构造函数是正确的,则定义该构造函数。

dart
class A {
  factory A() = B.name;
}

class B implements A {
  B();
  B.name();
}

如果应该调用不同的构造函数,则更新重定向。

dart
class A {
  factory A() = B;
}

class B implements A {
  B();
}

重定向到非类

#

名称“{0}”不是类型,不能在重定向构造函数中使用。

描述

#

实现工厂构造函数的一种方法是通过引用构造函数的名称来重定向到另一个构造函数。当重定向到构造函数以外的其他内容时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断信息,因为 f 是一个函数

dart
C f() => throw 0;

class C {
  factory C() = f;
}

常见修复方法

#

如果构造函数未定义,则定义它或将其替换为已定义的构造函数。

如果构造函数已定义,但定义它的类不可见,那么您可能需要添加导入。

如果您尝试返回函数返回的值,请重写构造函数以从构造函数的主体返回该值。

dart
C f() => throw 0;

class C {
  factory C() => f();
}

重定向到非常量构造函数

#

常量重定向构造函数不能重定向到非常量构造函数。

描述

#

当标记为 const 的构造函数重定向到未标记为 const 的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为构造函数 C.a 被标记为 const,但重定向到未标记为 const 的构造函数 C.b

dart
class C {
  const C.a() : this.b();
  C.b();
}

常见修复方法

#

如果可以将非常量构造函数标记为 const,则将其标记为 const

dart
class C {
  const C.a() : this.b();
  const C.b();
}

如果无法将非常量构造函数标记为 const,则删除重定向或从重定向构造函数中删除 const

dart
class C {
  C.a() : this.b();
  C.b();
}

重定向到扩展为类型参数的类型别名

#

重定向构造函数不能重定向到扩展为类型参数的类型别名。

描述

#

当重定向工厂构造函数重定向到类型别名,并且类型别名扩展为类型别名的类型参数之一时,分析器会生成此诊断信息。这是不允许的,因为类型参数的值是类型而不是类。

示例

#

以下代码会生成此诊断信息,因为重定向到 B<A> 是到类型别名,其值是 T,即使看起来该值应该是 A

dart
class A implements C {}

typedef B<T> = T;

abstract class C {
  factory C() = B<A>;
}

常见修复方法

#

使用类名或定义为类的类型别名,而不是定义为类型参数的类型别名。

dart
class A implements C {}

abstract class C {
  factory C() = A;
}

在声明之前被引用

#

局部变量“{0}”在其声明之前无法被引用。

描述

#

当变量在其声明之前被引用时,分析器会生成此诊断信息。在 Dart 中,变量在其声明的块中的任何位置都可见,但只能在声明后才能被引用。

分析器还会生成上下文消息,指示声明的位置。

示例

#

以下代码会生成此诊断信息,因为 i 在其声明之前被使用。

dart
void f() {
  print(i);
  int i = 5;
}

常见修复方法

#

如果您打算引用局部变量,请将声明移动到第一次引用之前。

dart
void f() {
  int i = 5;
  print(i);
}

如果您打算引用来自外部作用域的名称,例如参数、实例字段或顶层变量,则重命名局部声明,使其不会隐藏外部变量。

dart
void f(int i) {
  print(i);
  int x = 5;
  print(x);
}

不可反驳上下文中可反驳模式

#

可反驳模式不能在不可反驳的上下文中使用。

描述

#

当在只允许不可反驳模式的上下文中使用可反驳模式时,分析器会生成此诊断信息。

不允许的可反驳模式是:

  • 逻辑或
  • 关系
  • 空值检查
  • 常量

检查的上下文是:

  • 基于模式的变量声明
  • 基于模式的 for 循环
  • 左侧带有模式的赋值

示例

#

以下代码会生成此诊断信息,因为空值检查模式(可反驳模式)位于基于模式的变量声明中,而基于模式的变量声明不允许可反驳模式。

dart
void f(int? x) {
  var (_?) = x;
}

常见修复方法

#

重写代码以不在不可反驳的上下文中使用可反驳模式。

关系模式操作数类型不可赋值

#

常量表达式类型“{0}”不可赋值给“{2}”运算符的参数类型“{1}”。

描述

#

当关系模式的操作数的类型不可赋值给将要调用的运算符的参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为关系模式中的操作数 (0) 是 int,但 C 中定义的 > 运算符期望类型为 C 的对象。

dart
class C {
  const C();

  bool operator >(C other) => true;
}

void f(C c) {
  switch (c) {
    case > 0:
      print('positive');
  }
}

常见修复方法

#

如果 switch 正在使用正确的值,则更改 case 以将该值与正确类型的对象进行比较。

dart
class C {
  const C();

  bool operator >(C other) => true;
}

void f(C c) {
  switch (c) {
    case > const C():
      print('positive');
  }
}

如果 switch 正在使用错误的值,则更改用于计算要匹配的值的表达式。

dart
class C {
  const C();

  bool operator >(C other) => true;

  int get toInt => 0;
}

void f(C c) {
  switch (c.toInt) {
    case > 0:
      print('positive');
  }
}

关系模式运算符返回类型不可赋值给 bool

#

关系模式中使用的运算符的返回类型必须可赋值给“bool”。

描述

#

当关系模式引用不生成 bool 类型值的运算符时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为关系模式 > c2 中使用的运算符 > 返回 int 类型的值,而不是 bool

dart
class C {
  const C();

  int operator >(C c) => 3;

  bool operator <(C c) => false;
}

const C c2 = C();

void f(C c1) {
  if (c1 case > c2) {}
}

常见修复方法

#

如果应该使用不同的运算符,则更改运算符。

dart
class C {
  const C();

  int operator >(C c) => 3;

  bool operator <(C c) => false;
}

const C c2 = C();

void f(C c1) {
  if (c1 case < c2) {}
}

如果运算符应返回 bool,则更新运算符的声明。

dart
class C {
  const C();

  bool operator >(C c) => true;

  bool operator <(C c) => false;
}

const C c2 = C();

void f(C c1) {
  if (c1 case > c2) {}
}

Map 模式中的 rest 元素

#

映射模式不能包含 rest 模式。

描述

#

当映射模式包含 rest 模式时,分析器会生成此诊断信息。映射模式匹配具有比模式中显式给出的键更多的键的映射(只要给定的键匹配),因此 rest 模式是不必要的。

示例

#

以下代码会生成此诊断信息,因为映射模式包含 rest 模式。

dart
void f(Map<int, String> x) {
  if (x case {0: _, ...}) {}
}

常见修复方法

#

删除 rest 模式。

dart
void f(Map<int, String> x) {
  if (x case {0: _}) {}
}

在 catch 代码块外部 rethrow

#

Rethrow 必须在 catch 子句内。

描述

#

rethrow 语句位于 catch 子句之外时,分析器会生成此诊断信息。 rethrow 语句用于再次抛出捕获的异常,但在 catch 子句之外没有捕获的异常。

示例

#

以下代码会生成此诊断信息,因为 rethrow 语句位于 catch 子句之外。

dart
void f() {
  rethrow;
}

常见修复方法

#

如果您尝试重新抛出异常,则将 rethrow 语句包装在 catch 子句中。

dart
void f() {
  try {
    // ...
  } catch (exception) {
    rethrow;
  }
}

如果您尝试抛出新异常,则将 rethrow 语句替换为 throw 表达式。

dart
void f() {
  throw UnsupportedError('Not yet implemented');
}

生成构造函数中的 return 语句

#

构造函数不能返回值。

描述

#

当生成构造函数包含指定要返回值的 return 语句时,分析器会生成此诊断信息。生成构造函数始终返回已创建的对象,因此无法返回不同的对象。

示例

#

以下代码会生成此诊断信息,因为 return 语句具有表达式。

dart
class C {
  C() {
    return this;
  }
}

常见修复方法

#

如果构造函数应创建新实例,则删除 return 语句或表达式。

dart
class C {
  C();
}

如果构造函数不应创建新实例,则将其转换为工厂构造函数。

dart
class C {
  factory C() {
    return _instance;
  }

  static C _instance = C._();

  C._();
}

生成器中的 return 语句

#

无法从使用“async*”或“sync*”修饰符的生成器函数返回值。

描述

#

当生成器函数(主体标记为 async*sync* 的函数)使用 return 语句返回值或由于使用 => 而隐式返回值时,分析器会生成此诊断信息。在任何这些情况下,它们都应该使用 yield 而不是 return

示例

#

以下代码会生成此诊断信息,因为方法 f 是生成器,并且正在使用 return 返回值。

dart
Iterable<int> f() sync* {
  return 3;
}

以下代码会生成此诊断信息,因为函数 f 是生成器,并且正在隐式返回值。

dart
Stream<int> f() async* => 3;

常见修复方法

#

如果函数使用 => 作为函数的主体,则将其转换为块函数主体,并使用 yield 返回值。

dart
Stream<int> f() async* {
  yield 3;
}

如果该方法旨在成为生成器,则使用 yield 返回值。

dart
Iterable<int> f() sync* {
  yield 3;
}

如果该方法不旨在成为生成器,则从主体中删除修饰符(如果您返回 future,则使用 async)。

dart
int f() {
  return 3;
}

返回 doNotStore 类型的值

#

“{0}”使用“doNotStore”注解,除非“{1}”也注解,否则不应返回。

描述

#

当使用 doNotStore 注解的值从没有相同注解的方法、getter 或函数返回时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为调用 f 的结果不应存储,但函数 g 未被注解以保留该语义。

dart
import 'package:meta/meta.dart';

@doNotStore
int f() => 0;

int g() => f();

常见修复方法

#

如果应该不存储的值是要返回的正确值,则使用 doNotStore 注解标记该函数。

dart
import 'package:meta/meta.dart';

@doNotStore
int f() => 0;

@doNotStore
int g() => f();

否则,从函数返回不同的值。

dart
import 'package:meta/meta.dart';

@doNotStore
int f() => 0;

int g() => 0;

返回类型无效

#

类型为“{0}”的值无法从构造函数“{2}”返回,因为它具有“{1}”的返回类型。

类型为“{0}”的值无法从函数“{2}”返回,因为它具有“{1}”的返回类型。

类型为“{0}”的值无法从方法“{2}”返回,因为它具有“{1}”的返回类型。

描述

#

当方法或函数返回其类型不可赋值给声明的返回类型的值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 的返回类型为 String,但正在返回 int

dart
String f() => 3;

常见修复方法

#

如果返回类型是正确的,则将要返回的值替换为正确类型的值,可能通过转换现有值来实现。

dart
String f() => 3.toString();

如果值是正确的,则更改返回类型以匹配。

dart
int f() => 3;

从闭包返回类型无效

#

返回的类型“{0}”不能从“{1}”函数返回,这是闭包上下文所要求的。

描述

#

当返回表达式的静态类型不可赋值给闭包所需的返回类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 f 被定义为返回 String 的函数,但分配给它的闭包返回 int

dart
String Function(String) f = (s) => 3;

常见修复方法

#

如果返回类型是正确的,则将返回的值替换为正确类型的值,可能通过转换现有值来实现。

dart
String Function(String) f = (s) => 3.toString();

没有值的 return 语句

#

“return”后缺少返回值。

描述

#

当在声明了返回类型的函数中找到没有表达式的 return 语句时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数 f 应该返回 int,但没有返回值。

dart
int f() {
  return;
}

常见修复方法

#

添加计算要返回的值的表达式。

dart
int f() {
  return 0;
}

从 core 导出的 sdk_version_async

#

类“{0}”直到 2.1 版本才从“dart:core”导出,但此代码需要在早期版本上运行。

描述

#

当在未导入 dart:async 的库中引用类 FutureStream,且代码的 SDK 约束的下限小于 2.1.0 时,分析器会生成此诊断信息。在早期版本中,这些类未在 dart:core 中定义,因此导入是必要的。

示例

#

以下是定义 SDK 约束且下限小于 2.1.0 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.0.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
void f(Future f) {}

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许引用这些类。

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

如果您需要支持旧版本的 SDK,则导入 dart:async 库。

dart
import 'dart:async';

void f(Future f) {}

const 上下文中的 sdk_version_as_expression

#

直到 2.3.2 版本才支持在常量表达式中使用 as 表达式,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.3.2 的代码中找到 常量上下文 内的 as 表达式时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用 as 表达式,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.3.2 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
const num n = 3;
const int i = n as int;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该表达式。

yaml
environment:
  sdk: '>=2.3.2 <2.4.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用 as 表达式,或更改代码以使 as 表达式不在 常量上下文 中。

dart
num x = 3;
int y = x as int;

const 上下文中的 sdk_version_bool_operator

#

直到 2.3.2 版本才支持在常量上下文中使用运算符“{0}”用于“bool”操作数,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.3.2 的代码中找到 常量上下文 内对类 bool 使用 &|^ 运算符时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用这些运算符,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.3.2 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
const bool a = true;
const bool b = false;
const bool c = a & b;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用这些运算符。

yaml
environment:
 sdk: '>=2.3.2 <2.4.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用这些运算符,或更改代码以使表达式不在 常量上下文 中。

dart
const bool a = true;
const bool b = false;
bool c = a & b;

sdk_version_constructor_tearoffs

#

分离构造函数需要“constructor-tearoffs”语言特性。

描述

#

当在 SDK 约束的下限小于 2.15 的代码中找到构造函数分离时,分析器会生成此诊断信息。早期版本不支持构造函数分离,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.15 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.9.0 <2.15.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
var setConstructor = Set.identity;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。

yaml
environment:
  sdk: '>=2.15.0 <2.16.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用构造函数分离。

dart
var setConstructor = () => Set.identity();

const 上下文中的 sdk_version_eq_eq_operator

#

直到 2.3.2 版本才支持对非原始类型使用运算符“==”,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.3.2 的代码中找到 常量上下文 内对非原始类型使用运算符 == 时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用此运算符,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.3.2 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
class C {}
const C a = null;
const C b = null;
const bool same = a == b;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。

yaml
environment:
  sdk: '>=2.3.2 <2.4.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用 == 运算符,或更改代码以使表达式不在 常量上下文 中。

dart
class C {}
const C a = null;
const C b = null;
bool same = a == b;

sdk_version_extension_methods

#

直到 2.6.0 版本才支持扩展方法,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.6.0 的代码中找到扩展声明或扩展覆盖时,分析器会生成此诊断信息。早期版本不支持使用扩展,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.6.0 的 pubspec 示例:

yaml
environment:
 sdk: '>=2.4.0 <2.7.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
extension E on String {
  void sayHello() {
    print('Hello $this');
  }
}

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用此语法。

yaml
environment:
  sdk: '>=2.6.0 <2.7.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用扩展。最常见的方法是将扩展的成员重写为顶层函数(或方法),这些函数(或方法)将绑定到 this 的值作为参数。

dart
void sayHello(String s) {
  print('Hello $s');
}

sdk_version_gt_gt_gt_operator

#

直到 2.14.0 版本才支持运算符“>>>”,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.14.0 的代码中使用运算符 >>> 时,分析器会生成此诊断信息。早期版本不支持此运算符,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.14.0 的 pubspec 示例:

yaml
environment:
 sdk: '>=2.0.0 <2.15.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
int x = 3 >>> 4;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。

yaml
environment:
  sdk: '>=2.14.0 <2.15.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用 >>> 运算符。

dart
int x = logicalShiftRight(3, 4);

int logicalShiftRight(int leftOperand, int rightOperand) {
  int divisor = 1 << rightOperand;
  if (divisor == 0) {
    return 0;
  }
  return leftOperand ~/ divisor;
}

const 上下文中的 sdk_version_is_expression

#

直到 2.3.2 版本才支持在常量上下文中使用 is 表达式,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.3.2 的代码中找到 常量上下文 内的 is 表达式时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用 is 表达式,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.3.2 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
const Object x = 4;
const y = x is int ? 0 : 1;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该表达式。

yaml
environment:
  sdk: '>=2.3.2 <2.4.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用 is 运算符,或者,如果不可能,则更改代码以使 is 表达式不在 常量上下文 中。

dart
const Object x = 4;
var y = x is int ? 0 : 1;

sdk_version_never

#

直到 2.12.0 版本才支持类型“Never”,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.12.0 的代码中找到对类 Never 的引用时,分析器会生成此诊断信息。早期版本未定义此类,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.12.0 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.5.0 <2.6.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
Never n;

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用此类型。

yaml
environment:
  sdk: '>=2.12.0 <2.13.0'

如果您需要支持旧版本的 SDK,则重写代码以不引用此类。

dart
dynamic x;

sdk_version_set_literal

#

直到 2.2 版本才支持 Set 字面量,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.2.0 的代码中找到 set 字面量时,分析器会生成此诊断信息。早期版本不支持 Set 字面量,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.2.0 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.1.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
var s = <int>{};

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用此语法。

yaml
environment:
  sdk: '>=2.2.0 <2.4.0'

如果您确实需要支持旧版本的 SDK,则将 set 字面量替换为不使用字面量创建 set 的代码。

dart
var s = new Set<int>();

sdk_version_ui_as_code

#

直到 2.3.0 版本才支持 for、if 和 spread 元素,但此代码需要在早期版本上运行。

描述

#

当在 SDK 约束的下限小于 2.3.0 的代码中找到 for、if 或 spread 元素时,分析器会生成此诊断信息。早期版本不支持使用 for、if 或 spread 元素,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是定义 SDK 约束且下限小于 2.3.0 的 pubspec 示例:

yaml
environment:
  sdk: '>=2.2.0 <2.4.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
var digits = [for (int i = 0; i < 10; i++) i];

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用此语法。

yaml
environment:
  sdk: '>=2.3.0 <2.4.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用这些元素。

dart
var digits = _initializeDigits();

List<int> _initializeDigits() {
  var digits = <int>[];
  for (int i = 0; i < 10; i++) {
    digits.add(i);
  }
  return digits;
}

const 上下文中的 sdk_version_ui_as_code

#

在 2.5.0 版本之前,常量表达式中不支持 if 和 spread 元素,但此代码需要在更早版本上运行。

描述

#

当在 SDK 约束的下限版本低于 2.5.0 的代码中发现 常量上下文 内的 if 或 spread 元素时,分析器会生成此诊断信息。在早期版本中,常量上下文 内不支持使用 if 或 spread 元素,因此此代码将无法在早期版本的 SDK 上运行。

示例

#

以下是一个 pubspec 示例,其中定义了 SDK 约束,其下限版本低于 2.5.0

yaml
environment:
  sdk: '>=2.4.0 <2.6.0'

在具有该 pubspec 的包中,如下代码会生成此诊断信息:

dart
const a = [1, 2];
const b = [...a];

常见修复方法

#

如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用此语法。

yaml
environment:
  sdk: '>=2.5.0 <2.6.0'

如果您需要支持旧版本的 SDK,则重写代码以不使用这些元素。

dart
const a = [1, 2];
const b = [1, 2];

如果不可能,请更改代码,使元素不在 常量上下文

dart
const a = [1, 2];
var b = [...a];

Set 元素类型不可赋值

#

元素类型“{0}”不能赋值给集合类型“{1}”。

描述

#

当集合字面量中的元素类型不能赋值给集合的元素类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字符串字面量 '0' 的类型为 String,它不能赋值给集合的元素类型 int

dart
var s = <int>{'0'};

常见修复方法

#

如果集合字面量的元素类型错误,请更改集合的元素类型

dart
var s = <String>{'0'};

如果元素的类型错误,请更改元素

dart
var s = <int>{'0'.length};

共享的延迟前缀

#

延迟导入的前缀不能用于其他导入指令。

描述

#

当延迟导入中的前缀也用作其他导入(无论是延迟导入还是非延迟导入)的前缀时,分析器会生成此诊断信息。延迟导入中的前缀不能与其他导入共享,因为该前缀用于加载导入的库。

示例

#

以下代码会生成此诊断信息,因为前缀 x 既用作延迟导入的前缀,也用于另一个导入。

dart
import 'dart:math' deferred as x;
import 'dart:convert' as x;

var y = x.json.encode(x.min(0, 1));

常见修复方法

#

如果可以为延迟导入使用不同的名称,请这样做

dart
import 'dart:math' deferred as math;
import 'dart:convert' as x;

var y = x.json.encode(math.min(0, 1));

如果可以为其他导入使用不同的名称,请这样做

dart
import 'dart:math' deferred as x;
import 'dart:convert' as convert;

var y = convert.json.encode(x.min(0, 1));

size 注解维度

#

“Array”必须具有与其维度匹配的“Array”注解。

描述

#

Array 注解中指定的维度数量与字段类型指定的嵌套数组数量不匹配时,分析器会生成此诊断信息。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 a0 的类型具有三个嵌套数组,但在 Array 注解中仅给出了两个维度。

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8, 8)
  external Array<Array<Array<Uint8>>> a0;
}

常见修复方法

#

如果字段的类型正确,则修复注解以使其具有所需的维度数量

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8, 8, 4)
  external Array<Array<Array<Uint8>>> a0;
}

如果字段的类型错误,则修复字段的类型

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(8, 8)
  external Array<Array<Uint8>> a0;
}

静态访问实例成员

#

不能使用静态访问来访问实例成员“{0}”。

描述

#

当使用类名来访问实例字段时,分析器会生成此诊断信息。实例字段不存在于类上;它们仅存在于类的实例上。

示例

#

以下代码会生成此诊断信息,因为 x 是一个实例字段

dart
class C {
  static int a = 0;

  int b = 0;
}

int f() => C.b;

常见修复方法

#

如果您打算访问静态字段,请将字段名称更改为现有的静态字段

dart
class C {
  static int a = 0;

  int b = 0;
}

int f() => C.a;

如果您打算访问实例字段,请使用类的实例来访问该字段

dart
class C {
  static int a = 0;

  int b = 0;
}

int f(C c) => c.b;

base 或 final 类型的子类型不是 base、final 或 sealed 类型

#

mixin“{0}”必须是“base”,因为超类型“{1}”是“base”。

mixin“{0}”必须是“base”,因为超类型“{1}”是“final”。

类型“{0}”必须是“base”、“final”或“sealed”,因为超类型“{1}”是“base”。

类型“{0}”必须是“base”、“final”或“sealed”,因为超类型“{1}”是“final”。

描述

#

当类或 mixin 具有直接或间接超类型为 basefinal,但该类或 mixin 本身未标记为 basefinalsealed 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类 BA 的子类型,而 A 是一个 base 类,但 B 既不是 basefinal 也不是 sealed

dart
base class A {}
class B extends A {}

常见修复方法

#

向类或 mixin 声明添加 basefinalsealed

dart
base class A {}
final class B extends A {}

延迟类的子类型

#

类和 mixin 不能实现延迟类。

类不能扩展延迟类。

类不能混入延迟类。

描述

#

当类型(类或 mixin)是使用延迟导入导入的库中的类的子类型时,分析器会生成此诊断信息。类型的超类型必须与该类型同时编译,而延迟库中的类要到库加载后才会编译。

有关更多信息,请查看 延迟加载库

示例

#

给定一个文件 a.dart,其中定义了类 A

dart
class A {}

以下代码会生成此诊断信息,因为 B 的超类是在延迟库中声明的。

dart
import 'a.dart' deferred as a;

class B extends a.A {}

常见修复方法

#

如果需要创建延迟库中类型的子类型,请删除 deferred 关键字

dart
import 'a.dart' as a;

class B extends a.A {}

不允许的类型的子类型

#

“{0}”不能用作超类约束。

类和 mixin 不能实现“{0}”。

类不能扩展“{0}”。

类不能混入“{0}”。

描述

#

当受限类之一用于 extendsimplementswithon 子句中时,分析器会生成此诊断信息。类 booldoubleFutureOrintNullnumString 都以这种方式受到限制,以便实现更高效的实现。

示例

#

以下代码会生成此诊断信息,因为 String 用于 extends 子句中。

dart
class A extends String {}

以下代码会生成此诊断信息,因为 String 用于 implements 子句中。

dart
class B implements String {}

以下代码会生成此诊断信息,因为 String 用于 with 子句中。

dart
class C with String {}

以下代码会生成此诊断信息,因为 String 用于 on 子句中。

dart
mixin M on String {}

常见修复方法

#

如果应指定不同的类型,请替换该类型

dart
class A extends Object {}

如果没有合适的其他类型,则删除该类型,并可能删除整个子句

dart
class B {}

ffi 类的子类型

#

类“{0}”不能扩展“{1}”。

类“{0}”不能实现“{1}”。

类“{0}”不能混入“{1}”。

描述

#

当类扩展了 StructUnion 以外的任何 FFI 类,或者实现了或混入了任何 FFI 类时,分析器会生成此诊断信息。StructUnion 是唯一可以被子类化的 FFI 类,并且只能通过扩展它们来进行子类化。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类 C 扩展了 Double

dart
import 'dart:ffi';

final class C extends Double {}

常见修复方法

#

如果类应扩展 StructUnion,请更改类的声明

dart
import 'dart:ffi';

final class C extends Struct {
  @Int32()
  external int i;
}

如果类不应扩展 StructUnion,请删除对 FFI 类的任何引用

dart
final class C {}

sealed 类的子类型

#

不应扩展、混入或实现类“{0}”,因为它已被密封。

描述

#

当密封类(具有 sealed 注解或继承或混入密封类的类)在类或 mixin 声明的 extendsimplementswith 子句中被引用,并且该声明与密封类不在同一个包中时,分析器会生成此诊断信息。

示例

#

给定一个库,它在与正在分析的包不同的包中,包含以下内容

dart
import 'package:meta/meta.dart';

class A {}

@sealed
class B {}

以下代码会生成此诊断信息,因为 C(与 B 不在同一个包中)正在扩展密封类 B

dart
import 'package:a/a.dart';

class C extends B {}

常见修复方法

#

如果类不需要成为密封类的子类型,请更改声明,使其不是子类型

dart
import 'package:a/a.dart';

class B extends A {}

如果类需要成为密封类的子类型,则更改密封类,使其不再密封,或者将子类移动到与密封类相同的包中。

struct 类的子类型

#

类“{0}”不能扩展“{1}”,因为“{1}”是“Struct”、“Union”或“AbiSpecificInteger”的子类型。

类“{0}”不能实现“{1}”,因为“{1}”是“Struct”、“Union”或“AbiSpecificInteger”的子类型。

类“{0}”不能混入“{1}”,因为“{1}”是“Struct”、“Union”或“AbiSpecificInteger”的子类型。

描述

#

当一个类扩展、实现或混入一个扩展了 StructUnion 的类时,分析器会生成此诊断信息。类只能直接扩展 StructUnion

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为类 C 扩展了 S,而 S 扩展了 Struct

dart
import 'dart:ffi';

final class S extends Struct {
  external Pointer f;
}

final class C extends S {
  external Pointer g;
}

常见修复方法

#

如果您尝试定义一个结构体或联合体,它与另一个结构体或联合体声明的一些字段共享,请直接扩展 StructUnion 并复制共享字段

dart
import 'dart:ffi';

final class S extends Struct {
  external Pointer f;
}

final class C extends Struct {
  external Pointer f;

  external Pointer g;
}

超类型扩展为类型参数

#

扩展为类型参数的类型别名不能被实现。

扩展为类型参数的类型别名不能被混入。

扩展为类型参数的类型别名不能用作超类约束。

扩展为类型参数的类型别名不能用作超类。

描述

#

当扩展为类型参数的类型别名用于 extendsimplementswithon 子句中时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展为类型参数 S 的类型别名 T 用于类 Cextends 子句中。

dart
typedef T<S> = S;

class C extends T<Object> {}

常见修复方法

#

直接使用类型实参的值

dart
typedef T<S> = S;

class C extends Object {}

super 形式参数类型不是关联类型的子类型

#

此形参的类型“{0}”不是关联的超类构造函数形参的类型“{1}”的子类型。

描述

#

当超类形参的类型不是来自超类构造函数的相应形参的子类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 B 的构造函数中超类形参 x 的类型不是 A 的构造函数中形参 x 的子类型。

dart
class A {
  A(num x);
}

class B extends A {
  B(String super.x);
}

常见修复方法

#

如果超类形参的类型可以与来自超类构造函数的形参相同,则从超类形参中删除类型注解(如果类型是隐式的,则从超类构造函数中的类型推断出来)

dart
class A {
  A(num x);
}

class B extends A {
  B(super.x);
}

如果超类形参的类型可以是相应形参类型的子类型,则更改超类形参的类型

dart
class A {
  A(num x);
}

class B extends A {
  B(int super.x);
}

如果无法更改超类形参的类型,则使用普通形参而不是超类形参

dart
class A {
  A(num x);
}

class B extends A {
  B(String x) : super(x.length);
}

没有关联命名参数的 super 形式参数

#

没有关联的命名超类构造函数形参。

描述

#

当构造函数中存在命名超类形参,并且隐式或显式调用的超类构造函数没有同名的命名形参时,分析器会生成此诊断信息。

命名超类形参按名称与超类构造函数中的命名形参关联。

示例

#

以下代码会生成此诊断信息,因为 A 中的构造函数没有名为 y 的形参。

dart
class A {
  A({int? x});
}

class B extends A {
  B({super.y});
}

常见修复方法

#

如果超类形参应与来自超类构造函数的现有形参关联,则更改名称以匹配相应形参的名称

dart
class A {
  A({int? x});
}

class B extends A {
  B({super.x});
}

如果超类形参应与尚未添加到超类构造函数的形参关联,则添加它

dart
class A {
  A({int? x, int? y});
}

class B extends A {
  B({super.y});
}

如果超类形参与来自超类构造函数的命名形参不对应,则将其更改为普通形参

dart
class A {
  A({int? x});
}

class B extends A {
  B({int? y});
}

没有关联位置参数的 super 形式参数

#

没有关联的位置超类构造函数形参。

描述

#

当构造函数中存在位置超类形参,并且隐式或显式调用的超类构造函数在相应索引处没有位置形参时,分析器会生成此诊断信息。

位置超类形参按索引与超类构造函数中的位置形参关联。也就是说,第一个超类形参与超类构造函数中的第一个位置形参关联,第二个与第二个关联,依此类推。

示例

#

以下代码会生成此诊断信息,因为 B 中的构造函数具有位置超类形参,但 A 中的超类构造函数中没有位置形参。

dart
class A {
  A({int? x});
}

class B extends A {
  B(super.x);
}

以下代码会生成此诊断信息,因为 B 中的构造函数有两个位置超类形参,但 A 中的超类构造函数中只有一个位置形参,这意味着 y 没有对应的形参。

dart
class A {
  A(int x);
}

class B extends A {
  B(super.x, super.y);
}

常见修复方法

#

如果超类构造函数应具有与超类形参对应的位置形参,请相应地更新超类构造函数

dart
class A {
  A(int x, int y);
}

class B extends A {
  B(super.x, super.y);
}

如果超类构造函数是正确的,或者无法更改,则将超类形参转换为普通形参

dart
class A {
  A(int x);
}

class B extends A {
  B(super.x, int y);
}

super 调用不是最后一个

#

(以前称为 invalid_super_invocation

超类构造函数调用必须是初始化列表中的最后一个项:“{0}”。

描述

#

当构造函数的初始化列表包含对超类中构造函数的调用,但该调用不是初始化列表中的最后一个项时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为对超类构造函数的调用不是初始化列表中的最后一个项。

dart
class A {
  A(int x);
}

class B extends A {
  B(int x) : super(x), assert(x >= 0);
}

常见修复方法

#

将对超类构造函数的调用移动到初始化列表的末尾

dart
class A {
  A(int x);
}

class B extends A {
  B(int x) : assert(x >= 0), super(x);
}

枚举构造函数中的 super 调用

#

枚举构造函数不能具有“super”初始化器。

描述

#

当枚举中构造函数的初始化列表包含对超类构造函数的调用时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为枚举 E 中的构造函数在初始化列表中具有超类构造函数调用。

dart
enum E {
  e;

  const E() : super();
}

常见修复方法

#

删除超类构造函数调用

dart
enum E {
  e;

  const E();
}

扩展中的 super 调用

#

“super”关键字不能在扩展中使用,因为扩展没有超类。

描述

#

当在扩展内部声明的成员使用 super 关键字时,分析器会生成此诊断信息。扩展不是类,也没有超类,因此 super 关键字没有任何作用。

示例

#

以下代码会生成此诊断信息,因为 super 不能在扩展中使用。

dart
extension E on Object {
  String get displayString => super.toString();
}

常见修复方法

#

删除 super 关键字

dart
extension E on Object {
  String get displayString => toString();
}

扩展类型中的 super 调用

#

“super”关键字不能在扩展类型中使用,因为扩展类型没有超类。

描述

#

当在扩展类型的实例成员中使用 super 时,分析器会生成此诊断信息。扩展类型没有超类,因此没有可以调用的继承成员。

示例

#

以下代码会生成此诊断信息,因为

dart
extension type E(String s) {
  void m() {
    super.m();
  }
}

常见修复方法

#

替换或删除 super 调用

dart
extension type E(String s) {
  void m() {
    s.toLowerCase();
  }
}

无效上下文中的 super 调用

#

“super”调用的上下文无效。

描述

#

当在实例方法之外使用关键字 super 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 super 在顶层函数中使用。

dart
void f() {
  super.f();
}

常见修复方法

#

重写代码以不使用 super

重定向构造函数中的 super 调用

#

重定向构造函数不能具有“super”初始化器。

描述

#

当重定向到另一个构造函数的构造函数也尝试调用超类中的构造函数时,分析器会生成此诊断信息。当调用重定向构造函数重定向到的构造函数时,将调用超类构造函数。

示例

#

以下代码会生成此诊断信息,因为构造函数 C.a 既重定向到 C.b 又调用了超类中的构造函数。

dart
class C {
  C.a() : this.b(), super();
  C.b();
}

常见修复方法

#

删除 super 构造函数的调用

dart
class C {
  C.a() : this.b();
  C.b();
}

switch case 正常完成

#

“case”不应正常完成。

描述

#

switch 语句中 case 标签后面的语句可能会落入下一个 casedefault 标签时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为值为零 (0) 的 case 标签会落入 default 语句。

dart
void f(int a) {
  switch (a) {
    case 0:
      print(0);
    default:
      return;
  }
}

常见修复方法

#

更改控制流,使 case 不会落入下一个标签。有几种方法可以做到这一点,包括在当前语句列表的末尾添加以下内容之一

  • return 语句,
  • throw 表达式,
  • break 语句,
  • continue,或
  • 返回类型为 Never 的函数或方法的调用。

switch 表达式不可赋值

#

switch 表达式的类型“{0}”不能赋值给 case 表达式的类型“{1}”。

描述

#

switch 语句中表达式的类型不能赋值给 case 子句中表达式的类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 s 的类型 (String) 不能赋值给 0 的类型 (int)。

dart
void f(String s) {
  switch (s) {
    case 0:
      break;
  }
}

常见修复方法

#

如果 case 表达式的类型正确,请更改 switch 语句中的表达式以使其具有正确的类型

dart
void f(String s) {
  switch (int.parse(s)) {
    case 0:
      break;
  }
}

如果 switch 表达式的类型正确,请更改 case 表达式以使其具有正确的类型

dart
void f(String s) {
  switch (s) {
    case '0':
      break;
  }
}

抽象类的生成构造函数的 tear-off

#

抽象类的生成构造函数不能被拆分 (torn off)。

描述

#

当抽象类的生成构造函数被拆分 (torn off) 时,分析器会生成此诊断信息。这是不允许的,因为创建抽象类的实例是无效的,这意味着拆分 (torn off) 的构造函数没有任何有效的用途。

示例

#

以下代码会生成此诊断信息,因为构造函数 C.new 正在被拆分 (torn off),而类 C 是一个抽象类。

dart
abstract class C {
  C();
}

void f() {
  C.new;
}

常见修复方法

#

拆分 (torn off) 具体类的构造函数。

注释中的文本方向代码点

#

Unicode 代码点“U+{0}”会更改文本的外观,使其与编译器解释的方式不同。

描述

#

当分析器遇到包含文本方向 Unicode 代码点的源代码时,会生成此诊断信息。这些代码点会导致字符串字面量或注释中的源代码以不同于编辑器中显示的方式进行解释和编译,从而导致可能的安全漏洞。

示例

#

以下代码会生成两次此诊断信息,因为标签字符串的开头和结尾都有隐藏字符。

dart
var label = 'Interactive text';

常见修复方法

#

如果代码点旨在包含在字符串字面量中,请对其进行转义

dart
var label = '\u202AInteractive text\u202C';

如果代码点不旨在包含在字符串字面量中,请删除它们

dart
var label = 'Interactive text';

字面量中的文本方向代码点

#

Unicode 代码点“U+{0}”会更改文本的外观,使其与编译器解释的方式不同。

描述

#

当分析器遇到包含文本方向 Unicode 代码点的源代码时,会生成此诊断信息。这些代码点会导致字符串字面量或注释中的源代码以不同于编辑器中显示的方式进行解释和编译,从而导致可能的安全漏洞。

示例

#

以下代码会生成两次此诊断信息,因为标签字符串的开头和结尾都有隐藏字符。

dart
var label = 'Interactive text';

常见修复方法

#

如果代码点旨在包含在字符串字面量中,请对其进行转义

dart
var label = '\u202AInteractive text\u202C';

如果代码点不旨在包含在字符串字面量中,请删除它们

dart
var label = 'Interactive text';

抛出类型无效

#

抛出表达式的类型“{0}”必须可赋值给“Object”。

描述

#

当 throw 表达式中表达式的类型不能赋值给 Object 时,分析器会生成此诊断信息。抛出 null 是无效的,因此使用可能计算结果为 null 的表达式也是无效的。

示例

#

以下代码会生成此诊断信息,因为 s 可能是 null

dart
void f(String? s) {
  throw s;
}

常见修复方法

#

向表达式添加显式 null 检查

dart
void f(String? s) {
  throw s!;
}

顶层循环依赖

#

无法推断“{0}”的类型,因为它通过循环依赖于自身:{1}。

描述

#

当顶层变量没有类型注解,并且变量的初始化器直接或间接地引用该变量时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为变量 xy 是根据彼此定义的,并且两者都没有显式类型,因此无法推断另一个变量的类型。

dart
var x = y;
var y = x;

常见修复方法

#

如果两个变量不需要相互引用,则打破循环

dart
var x = 0;
var y = x;

如果两个变量需要相互引用,则至少为其中一个变量提供显式类型

dart
int x = y;
var y = x;

但是请注意,虽然此代码不会生成任何诊断信息,但除非在引用循环中的任何变量之前,至少将其中一个变量赋值为不依赖于其他变量的值,否则它将在运行时产生堆栈溢出。

类型别名不能引用自身

#

类型定义不能直接或通过另一个类型定义递归地引用自身。

描述

#

当类型定义引用自身时(无论是直接还是间接引用),分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 F 通过 G 间接依赖于自身。

dart
typedef F = void Function(G);
typedef G = void Function(F);

常见修复方法

#

更改循环中的一个或多个类型定义,使它们都不引用自身

dart
typedef F = void Function(G);
typedef G = void Function(int);

延迟类的类型注解

#

延迟类型“{0}”不能用于声明、强制转换或类型测试。

描述

#

当类型注解在变量声明中,或者强制转换 (as) 或类型测试 (is) 中使用的类型是从使用延迟导入导入的库中声明的类型时,分析器会生成此诊断信息。这些类型需要在编译时可用,但实际上并非如此。

有关更多信息,请查看 延迟加载库

示例

#

以下代码会生成此诊断信息,因为形参 f 的类型是从延迟库导入的。

dart
import 'dart:io' deferred as io;

void f(io.File f) {}

常见修复方法

#

如果需要引用导入的类型,请删除 deferred 关键字

dart
import 'dart:io' as io;

void f(io.File f) {}

如果导入需要延迟,并且存在另一个合适的类型,请使用该类型代替延迟库中的类型。

类型参数不匹配边界约束

#

“{0}”不符合类型形参“{1}”的边界“{2}”。

描述

#

当类型实参与相应类型形参的边界不相同或不是其子类时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 String 不是 num 的子类。

dart
class A<E extends num> {}

var a = A<String>();

常见修复方法

#

将类型实参更改为边界的子类

dart
class A<E extends num> {}

var a = A<int>();

使用 null 进行类型检查

#

非空测试应使用“!= null”。

空值测试应使用“== null”。

描述

#

当存在类型检查(使用 as 运算符),且类型为 Null 时,分析器会生成此诊断信息。只有一种类型为 Null 的值,因此当显式测试 null 时,代码既更易读又性能更高。

示例

#

以下代码会生成此诊断信息,因为该代码正在通过使用类型检查来查看 s 的值是否为 null

dart
void f(String? s) {
  if (s is Null) {
    return;
  }
  print(s);
}

以下代码会生成此诊断信息,因为该代码正在通过使用类型检查来查看 s 的值是否为 null 以外的其他值。

dart
void f(String? s) {
  if (s is! Null) {
    print(s);
  }
}

常见修复方法

#

将类型检查替换为与 null 的等效比较

dart
void f(String? s) {
  if (s == null) {
    return;
  }
  print(s);
}

静态成员引用的类型参数

#

静态成员不能引用类的类型形参。

描述

#

当静态成员引用为类声明的类型形参时,分析器会生成此诊断信息。类型形参仅对类的实例有意义。

示例

#

以下代码会生成此诊断信息,因为静态方法 hasType 引用了类型形参 T

dart
class C<T> {
  static bool hasType(Object o) => o is T;
}

常见修复方法

#

如果成员可以是实例成员,则删除关键字 static

dart
class C<T> {
  bool hasType(Object o) => o is T;
}

如果成员必须是静态成员,则使成员成为泛型

dart
class C<T> {
  static bool hasType<S>(Object o) => o is S;
}

但是请注意,TS 之间没有关系,因此第二个选项会更改语义,使其与可能预期的语义不同。

类型参数是其边界的超类型

#

“{0}”不能是其上限的超类型。

描述

#

当类型形参的边界(extends 关键字后面的类型)直接或间接地是类型形参本身时,分析器会生成此诊断信息。声明类型形参必须与其自身相同或为其自身的子类型或为其自身的子类型的子类型没有帮助,因为它始终与其自身相同。

示例

#

以下代码会生成此诊断信息,因为 T 的边界为 T

dart
class C<T extends T> {}

以下代码会生成此诊断信息,因为 T1 的边界为 T2,而 T2 的边界为 T1,实际上使 T1 的边界为 T1

dart
class C<T1 extends T2, T2 extends T1> {}

常见修复方法

#

如果类型形参需要是某个类型的子类,则将边界替换为所需的类型

dart
class C<T extends num> {}

如果类型形参可以是任何类型,则删除 extends 子句

dart
class C<T> {}

使用非类型进行类型测试

#

名称“{0}”不是类型,不能在“is”表达式中使用。

描述

#

isis! 测试的右侧不是类型时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为右侧是形参,而不是类型。

dart
typedef B = int Function(int);

void f(Object a, B b) {
  if (a is b) {
    return;
  }
}

常见修复方法

#

如果您打算使用类型测试,请将右侧替换为类型

dart
typedef B = int Function(int);

void f(Object a, B b) {
  if (a is B) {
    return;
  }
}

如果您打算使用不同类型的测试,请更改测试

dart
typedef B = int Function(int);

void f(Object a, B b) {
  if (a == b) {
    return;
  }
}

使用未定义的名称进行类型测试

#

名称“{0}”未定义,因此不能在“is”表达式中使用。

描述

#

当类型测试表达式中 is 后面的名称未定义时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为名称 Srting 未定义。

dart
void f(Object o) {
  if (o is Srting) {
    // ...
  }
}

常见修复方法

#

将名称替换为类型的名称

dart
void f(Object o) {
  if (o is String) {
    // ...
  }
}

未检查地使用可空值

#

可为空的表达式不能用作条件。

可为空的表达式不能用作 for-in 循环中的迭代器。

可为空的表达式不能用于 spread。

可为空的表达式不能用于 yield-each 语句。

函数不能被无条件调用,因为它可能为“null”。

方法“{0}”不能被无条件调用,因为接收者可能为“null”。

运算符“{0}”不能被无条件调用,因为接收者可能为“null”。

属性“{0}”不能被无条件访问,因为接收者可能为“null”。

描述

#

当类型为 可能非空 的表达式在未先验证该值是否为 null 的情况下被解引用时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 s 在被引用时可能为 null

dart
void f(String? s) {
  if (s.length > 3) {
    // ...
  }
}

常见修复方法

#

如果值确实可能为 null,则添加一个测试以确保仅在值不为 null 时才访问成员

dart
void f(String? s) {
  if (s != null && s.length > 3) {
    // ...
  }
}

如果表达式是一个变量,并且该值永远不应为 null,则将变量的类型更改为不可为空

dart
void f(String s) {
  if (s.length > 3) {
    // ...
  }
}

如果您认为表达式的值永远不应为 null,但您无法更改变量的类型,并且您愿意承担在您出错时运行时抛出异常的风险,则可以断言该值不为 null

dart
void f(String? s) {
  if (s!.length > 3) {
    // ...
  }
}

未定义的注解

#

未定义的名称“{0}”用作注解。

描述

#

当未定义的名称用作注解时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为名称 undefined 未定义。

dart
@undefined
void f() {}

常见修复方法

#

如果名称正确,但尚未声明,则将该名称声明为常量值

dart
const undefined = 'undefined';

@undefined
void f() {}

如果名称错误,请将名称替换为有效常量的名称

dart
@deprecated
void f() {}

否则,删除注解。

未定义的类

#

未定义的类“{0}”。

描述

#

当分析器遇到一个标识符,该标识符似乎是一个类的名称,但未定义或在其被引用的作用域中不可见时,会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 Piont 未定义。

dart
class Point {}

void f(Piont p) {}

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的类的名称。可以通过修复类的拼写来更正上面的示例

dart
class Point {}

void f(Point p) {}

如果类已定义但不可见,则您可能需要添加导入。

初始化器中未定义的构造函数

#

类“{0}”没有名为“{1}”的构造函数。

类 '{0}' 没有未命名的构造函数。

描述

#

当在构造函数的初始化列表中调用超类构造函数,但超类未定义正在调用的构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 A 没有未命名的构造函数。

dart
class A {
  A.n();
}
class B extends A {
  B() : super();
}

以下代码会生成此诊断信息,因为 A 没有名为 m 的构造函数。

dart
class A {
  A.n();
}
class B extends A {
  B() : super.m();
}

常见修复方法

#

如果超类定义了应调用的构造函数,请更改正在调用的构造函数

dart
class A {
  A.n();
}
class B extends A {
  B() : super.n();
}

如果超类未定义合适的构造函数,请定义正在调用的构造函数

dart
class A {
  A.m();
  A.n();
}
class B extends A {
  B() : super.m();
}

未定义的枚举常量

#

“{1}”中没有名为“{0}”的常量。

描述

#

当分析器遇到一个标识符,该标识符似乎是枚举值的名称,并且该名称未定义或在其被引用的作用域中不可见时,会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 E 未定义名为 c 的常量。

dart
enum E {a, b}

var e = E.c;

常见修复方法

#

如果应定义常量,请将其添加到枚举的声明中

dart
enum E {a, b, c}

var e = E.c;

如果常量不应定义,请将名称更改为现有常量的名称

dart
enum E {a, b}

var e = E.b;

未定义的枚举构造函数

#

枚举没有名为“{0}”的构造函数。

枚举没有未命名的构造函数。

描述

#

当用于初始化枚举值的构造函数不存在时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为枚举值 c 正在由未命名的构造函数初始化,但 E 中未定义未命名的构造函数。

dart
enum E {
  c();

  const E.x();
}

以下代码会生成此诊断信息,因为枚举值 c 正在由名为 x 的构造函数初始化,但 E 中未定义名为 x 的构造函数。

dart
enum E {
  c.x();

  const E.y();
}

常见修复方法

#

如果枚举值正在由未命名的构造函数初始化,并且应使用命名构造函数之一,请添加构造函数的名称

dart
enum E {
  c.x();

  const E.x();
}

如果枚举值正在由未命名的构造函数初始化,并且没有合适的命名构造函数,请定义未命名的构造函数

dart
enum E {
  c();

  const E();
}

如果枚举值正在由命名构造函数初始化,并且应使用现有构造函数之一,请更改正在调用的构造函数的名称(或者如果应使用未命名的构造函数,则删除名称)

dart
enum E {
  c.y();

  const E();
  const E.y();
}

如果枚举值正在由命名构造函数初始化,并且没有合适的现有构造函数,请定义一个具有所用名称的构造函数

dart
enum E {
  c.x();

  const E.x();
}

未定义的扩展 getter

#

扩展“{1}”未定义 getter“{0}”。

描述

#

当使用扩展覆盖来调用 getter,但指定的扩展未定义该 getter 时,分析器会生成此诊断信息。当引用静态 getter 但指定的扩展未定义该静态 getter 时,分析器也会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展 E 未声明名为 b 的实例 getter。

dart
extension E on String {
  String get a => 'a';
}

extension F on String {
  String get b => 'b';
}

void f() {
  E('c').b;
}

以下代码会生成此诊断信息,因为扩展 E 未声明名为 a 的静态 getter。

dart
extension E on String {}

var x = E.a;

常见修复方法

#

如果 getter 的名称不正确,请将其更改为现有 getter 的名称

dart
extension E on String {
  String get a => 'a';
}

extension F on String {
  String get b => 'b';
}

void f() {
  E('c').a;
}

如果 getter 的名称正确,但扩展的名称错误,请将扩展的名称更改为正确的名称

dart
extension E on String {
  String get a => 'a';
}

extension F on String {
  String get b => 'b';
}

void f() {
  F('c').b;
}

如果 getter 和扩展的名称都正确,但未定义 getter,请定义 getter

dart
extension E on String {
  String get a => 'a';
  String get b => 'z';
}

extension F on String {
  String get b => 'b';
}

void f() {
  E('c').b;
}

未定义的扩展方法

#

扩展“{1}”未定义方法“{0}”。

描述

#

当使用扩展覆盖来调用方法,但指定的扩展未定义该方法时,分析器会生成此诊断信息。当引用静态方法但指定的扩展未定义该静态方法时,分析器也会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为扩展 E 未声明名为 b 的实例方法。

dart
extension E on String {
  String a() => 'a';
}

extension F on String {
  String b() => 'b';
}

void f() {
  E('c').b();
}

以下代码会生成此诊断信息,因为扩展 E 未声明名为 a 的静态方法。

dart
extension E on String {}

var x = E.a();

常见修复方法

#

如果方法的名称不正确,请将其更改为现有方法的名称

dart
extension E on String {
  String a() => 'a';
}

extension F on String {
  String b() => 'b';
}

void f() {
  E('c').a();
}

如果方法的名称正确,但扩展的名称错误,请将扩展的名称更改为正确的名称

dart
extension E on String {
  String a() => 'a';
}

extension F on String {
  String b() => 'b';
}

void f() {
  F('c').b();
}

如果方法和扩展的名称都正确,但未定义方法,请定义方法

dart
extension E on String {
  String a() => 'a';
  String b() => 'z';
}

extension F on String {
  String b() => 'b';
}

void f() {
  E('c').b();
}

未定义的扩展运算符

#

扩展“{1}”未定义运算符“{0}”。

描述

#

当在特定扩展上调用运算符,但该扩展未实现该运算符时,分析器会生成此诊断信息。

示例

#

以下代码产生此诊断,因为扩展 E 未定义运算符 *

dart
var x = E('') * 4;

extension E on String {}

常见修复方法

#

如果扩展应实现运算符,则向扩展添加运算符的实现

dart
var x = E('') * 4;

extension E on String {
  int operator *(int multiplier) => length * multiplier;
}

如果运算符由不同的扩展定义,则将扩展的名称更改为定义运算符的扩展的名称。

如果运算符在扩展覆盖的参数上定义,则删除扩展覆盖

dart
var x = '' * 4;

extension E on String {}

未定义的扩展 setter

#

扩展 '{1}' 未定义 setter '{0}'。

描述

#

当使用扩展覆盖来调用 setter,但指定的扩展未定义 setter 时,分析器会产生此诊断。当引用静态 setter 但指定的扩展未定义该 setter 时,分析器也会产生此诊断。

示例

#

以下代码产生此诊断,因为扩展 E 未声明名为 b 的实例 setter

dart
extension E on String {
  set a(String v) {}
}

extension F on String {
  set b(String v) {}
}

void f() {
  E('c').b = 'd';
}

以下代码产生此诊断,因为扩展 E 未声明名为 a 的静态 setter

dart
extension E on String {}

void f() {
  E.a = 3;
}

常见修复方法

#

如果 setter 的名称不正确,则将其更改为现有 setter 的名称

dart
extension E on String {
  set a(String v) {}
}

extension F on String {
  set b(String v) {}
}

void f() {
  E('c').a = 'd';
}

如果 setter 的名称正确,但扩展的名称错误,则将扩展的名称更改为正确的名称

dart
extension E on String {
  set a(String v) {}
}

extension F on String {
  set b(String v) {}
}

void f() {
  F('c').b = 'd';
}

如果 setter 和扩展的名称都正确,但未定义 setter,则定义 setter

dart
extension E on String {
  set a(String v) {}
  set b(String v) {}
}

extension F on String {
  set b(String v) {}
}

void f() {
  E('c').b = 'd';
}

未定义的函数

#

未定义函数 '{0}'。

描述

#

当分析器遇到似乎是函数名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会产生此诊断。

示例

#

以下代码产生此诊断,因为未定义名称 emty

dart
List<int> empty() => [];

void main() {
  print(emty());
}

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的函数的名称。可以通过更正函数拼写来纠正上面的示例

dart
List<int> empty() => [];

void main() {
  print(empty());
}

如果函数已定义但不可见,那么您可能需要添加导入或重新排列代码以使函数可见。

未定义的 getter

#

类型为 '{1}' 的函数类型未定义 getter '{0}'。

类型 '{1}' 未定义 getter '{0}'。

描述

#

当分析器遇到似乎是 getter 名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会产生此诊断。

示例

#

以下代码产生此诊断,因为 String 没有名为 len 的成员

dart
int f(String s) => s.len;

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的 getter 的名称。可以通过更正 getter 拼写来纠正上面的示例

dart
int f(String s) => s.length;

未定义的隐藏名称

#

库 '{0}' 未导出具有隐藏名称 '{1}' 的成员。

描述

#

当隐藏组合器包含库导入时未定义的名称时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 dart:math 未定义名称 String

dart
import 'dart:math' hide String, max;

var x = min(0, 1);

常见修复方法

#

如果应隐藏不同的名称,则更正名称。否则,从列表中删除名称

dart
import 'dart:math' hide max;

var x = min(0, 1);

未定义的标识符

#

未定义的名称 '{0}'。

描述

#

当分析器遇到未定义或在被引用的作用域中不可见的标识符时,会产生此诊断。

示例

#

以下代码产生此诊断,因为未定义名称 rihgt

dart
int min(int left, int right) => left <= rihgt ? left : right;

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的标识符。可以通过更正变量拼写来纠正上面的示例

dart
int min(int left, int right) => left <= right ? left : right;

如果标识符已定义但不可见,那么您可能需要添加导入或重新排列代码以使标识符可见。

未定义的标识符 await

#

在未使用 'async' 标记的函数体中,未定义名称 'await'。

描述

#

当在未使用 async 关键字标记的方法或函数体中使用名称 await 且未声明该名称时,分析器会产生此诊断。名称 await 仅在异步函数中引入 await 表达式。

示例

#

以下代码产生此诊断,因为名称 awaitf 的主体中使用,即使 f 的主体未使用 async 关键字标记

dart
void f(p) { await p; }

常见修复方法

#

向函数体添加关键字 async

dart
void f(p) async { await p; }

未定义的方法

#

类型为 '{1}' 的函数类型未定义方法 '{0}'。

类型 '{1}' 未定义方法 '{0}'。

描述

#

当分析器遇到似乎是方法名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会产生此诊断。

示例

#

以下代码产生此诊断,因为未定义标识符 removeMiddle

dart
int f(List<int> l) => l.removeMiddle();

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的方法的名称。可以通过更正方法拼写来纠正上面的示例

dart
int f(List<int> l) => l.removeLast();

未定义的命名参数

#

未定义命名参数 '{0}'。

描述

#

当方法或函数调用具有命名参数,但被调用的方法或函数未定义具有相同名称的参数时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 m 未声明名为 a 的命名参数

dart
class C {
  m({int? b}) {}
}

void f(C c) {
  c.m(a: 1);
}

常见修复方法

#

如果参数名称拼写错误,则将其替换为正确的名称。可以通过将 a 更改为 b 来修复上面的示例

dart
class C {
  m({int? b}) {}
}

void f(C c) {
  c.m(b: 1);
}

如果子类添加了具有疑问名称的参数,则将接收器强制转换为子类

dart
class C {
  m({int? b}) {}
}

class D extends C {
  m({int? a, int? b}) {}
}

void f(C c) {
  (c as D).m(a: 1);
}

如果应将参数添加到函数,则添加它

dart
class C {
  m({int? a, int? b}) {}
}

void f(C c) {
  c.m(a: 1);
}

未定义的运算符

#

类型 '{1}' 未定义运算符 '{0}'。

描述

#

当在未定义运算符的对象上调用用户可定义的运算符时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为类 C 未定义运算符 +

dart
class C {}

C f(C c) => c + 2;

常见修复方法

#

如果应该为类定义运算符,则定义它

dart
class C {
  C operator +(int i) => this;
}

C f(C c) => c + 2;

未定义的前缀名称

#

名称 '{0}' 正通过前缀 '{1}' 引用,但它未在使用该前缀导入的任何库中定义。

描述

#

当找到前缀标识符,其中前缀有效,但标识符未在使用该前缀导入的任何库中声明时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 dart:core 未定义任何名为 a 的内容

dart
import 'dart:core' as p;

void f() {
  p.a;
}

常见修复方法

#

如果声明名称的库尚未导入,请为该库添加导入。

如果名称错误,则将其更改为已导入库中声明的名称之一。

未引用的参数

#

参数 '{0}' 未由 '{1}' 定义。

描述

#

UseResult.unless(parameterDefined: parameterName) 形式的注解指定了注解函数未定义的参数名称时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为函数 f 没有名为 b 的参数

dart
import 'package:meta/meta.dart';

@UseResult.unless(parameterDefined: 'b')
int f([int? a]) => a ?? 0;

常见修复方法

#

更改名为 parameterDefined 的参数以匹配函数参数之一的名称

dart
import 'package:meta/meta.dart';

@UseResult.unless(parameterDefined: 'a')
int f([int? a]) => a ?? 0;

未定义的 setter

#

类型为 '{1}' 的函数类型未定义 setter '{0}'。

类型 '{1}' 未定义 setter '{0}'。

描述

#

当分析器遇到似乎是 setter 名称的标识符,但该标识符未定义或在标识符被引用的作用域中不可见时,会产生此诊断。

示例

#

以下代码产生此诊断,因为没有名为 z 的 setter

dart
class C {
  int x = 0;
  void m(int y) {
    this.z = y;
  }
}

常见修复方法

#

如果标识符未定义,则定义它或将其替换为已定义的 setter 的名称。可以通过更正 setter 拼写来纠正上面的示例

dart
class C {
  int x = 0;
  void m(int y) {
    this.x = y;
  }
}

未定义的显示名称

#

库 '{0}' 未导出具有显示名称 '{1}' 的成员。

描述

#

当显示组合器包含库导入时未定义的名称时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 dart:math 未定义名称 String

dart
import 'dart:math' show min, String;

var x = min(0, 1);

常见修复方法

#

如果应显示不同的名称,则更正名称。否则,从列表中删除名称

dart
import 'dart:math' show min;

var x = min(0, 1);

未定义的 super 成员

#

(以前称为 undefined_super_method

在 '{1}' 的超类中未定义 getter '{0}'。

在 '{1}' 的超类中未定义方法 '{0}'。

在 '{1}' 的超类中未定义运算符 '{0}'。

在 '{1}' 的超类中未定义 setter '{0}'。

描述

#

当使用 super 引用继承的成员(方法、getter、setter 或运算符),但在超类链中没有具有该名称的成员时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 Object 未定义名为 n 的方法

dart
class C {
  void m() {
    super.n();
  }
}

以下代码产生此诊断,因为 Object 未定义名为 g 的 getter

dart
class C {
  void m() {
    super.g;
  }
}

常见修复方法

#

如果您打算调用的继承成员具有不同的名称,则使调用的成员的名称与继承成员的名称匹配。

如果您打算调用的成员在同一类中定义,则删除 super.

如果未定义成员,则将成员添加到超类之一或删除调用。

未知的平台

#

平台 '{0}' 不是可识别的平台。

描述

#

当在 platforms 映射中使用未知平台名称作为键时,分析器会产生此诊断。要了解有关指定包支持平台的更多信息,请查看有关平台声明的文档

示例

#

以下 pubspec.yaml 产生此诊断,因为平台 browser 未知。

yaml
name: example
platforms:
  browser:

常见修复方法

#

如果您可以依赖自动平台检测,则省略顶层 platforms 键。

yaml
name: example

如果您需要手动指定支持的平台列表,则将 platforms 字段编写为以已知平台名称为键的映射。

yaml
name: example
platforms:
  # These are the known platforms
  android:
  ios:
  linux:
  macos:
  web:
  windows:

不必要的类型转换

#

不必要的类型转换。

描述

#

当要转换的值已知已经是它要转换成的类型时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为由于 is 测试,n 已知是 int

dart
void f(num n) {
  if (n is int) {
    (n as int).isEven;
  }
}

常见修复方法

#

删除不必要的类型转换

dart
void f(num n) {
  if (n is int) {
    n.isEven;
  }
}

不必要的开发依赖

#

对 {0} 的开发依赖项是不必要的,因为还有一个对该包的正常依赖项。

描述

#

dev_dependencies 下有一个条目,该条目也列在 dependencies 下时,分析器会产生此诊断。dependencies 下的包可用于包中的所有代码,因此无需在 dev_dependencies 下也列出它们。

示例

#

以下代码产生此诊断,因为包 meta 同时列在 dependenciesdev_dependencies

yaml
name: example
dependencies:
  meta: ^1.0.2
dev_dependencies:
  meta: ^1.0.2

常见修复方法

#

删除 dev_dependencies 下的条目(如果那是唯一列出的包,则删除 dev_dependencies 键)

yaml
name: example
dependencies:
  meta: ^1.0.2

不必要的 final 关键字

#

关键字 'final' 是不必要的,因为参数是隐式 'final'。

描述

#

当构造函数中的字段初始化参数或超参数具有关键字 final 时,分析器会产生此诊断。在这两种情况下,关键字都是不必要的,因为参数是隐式 final

示例

#

以下代码产生此诊断,因为字段初始化参数具有关键字 final

dart
class A {
  int value;

  A(final this.value);
}

以下代码产生此诊断,因为 B 中的超参数具有关键字 final

dart
class A {
  A(int value);
}

class B extends A {
  B(final super.value);
}

常见修复方法

#

删除不必要的 final 关键字

dart
class A {
  A(int value);
}

class B extends A {
  B(super.value);
}

不必要的导入

#

'{0}' 的导入是不必要的,因为所有使用的元素也由 '{1}' 的导入提供。

描述

#

当导入是不必要的,因为在导入库中导入和引用的所有名称也通过另一个导入可见时,分析器会产生此诊断。

示例

#

给定一个包含以下内容的文件 a.dart

dart
class A {}

并且,给定一个包含以下内容的 b.dart 文件

dart
export 'a.dart';

class B {}

以下代码产生此诊断,因为从 a.dart 导入的类 A 也从 b.dart 导入。删除 a.dart 的导入,语义保持不变

dart
import 'a.dart';
import 'b.dart';

void f(A a, B b) {}

常见修复方法

#

如果不需要导入,则删除它。

如果此导入导入的某些名称旨在使用但尚未被使用,并且如果这些名称未被其他导入导入,则添加对这些名称的缺失引用。

不必要的 NaN 比较

#

double 不能等于 'double.nan',因此条件始终为 'false'。

double 不能等于 'double.nan',因此条件始终为 'true'。

描述

#

当使用 ==!= 将值与 double.nan 进行比较时,分析器会产生此诊断。

Dart 遵循 IEEE 754 浮点运算语义标准,该标准规定,对于任何浮点值 x(包括 NaN、正无穷大和负无穷大),

  • NaN == x 始终为 false
  • NaN != x 始终为 true

因此,将任何值与 NaN 进行比较是毫无意义的,因为结果是已知的(基于正在使用的比较运算符)。

示例

#

以下代码产生此诊断,因为 d 正在与 double.nan 进行比较

dart
bool isNaN(double d) => d == double.nan;

常见修复方法

#

改用 getter double.isNaN

dart
bool isNaN(double d) => d.isNaN;

不必要的非空断言

#

'!' 将不起作用,因为接收器不能为 null。

描述

#

! 运算符的操作数不能为 null 时,分析器会产生此诊断。

示例

#

以下代码会生成此诊断,因为 x 不能为 null

dart
int f(int x) {
  return x!;
}

常见修复方法

#

删除空值检查运算符 (!)

dart
int f(int x) {
  return x;
}

不必要的 noSuchMethod 方法

#

不必要的 'noSuchMethod' 声明。

描述

#

当存在 noSuchMethod 的声明,声明唯一做的就是调用重写的声明,并且重写的声明不是 Object 中的声明时,分析器会产生此诊断。

重写 ObjectnoSuchMethod 的实现(无论实现做什么)都会向分析器发出信号,表明它不应标记任何未在该类中实现的继承抽象方法。即使重写实现是从超类继承的,这也有效,因此再次在子类中声明它没有价值。

示例

#

以下代码产生此诊断,因为 A 中的 noSuchMethod 的声明使得 B 中的 noSuchMethod 的声明不必要

dart
class A {
  @override
  dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {
  @override
  dynamic noSuchMethod(y) {
    return super.noSuchMethod(y);
  }
}

常见修复方法

#

删除不必要的声明

dart
class A {
  @override
  dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {}

不必要的 null 断言模式

#

空断言模式将不起作用,因为匹配的类型不可为空。

描述

#

当使用空断言模式来匹配不可为空的值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为变量 x 不可为空

dart
void f(int x) {
  if (x case var a! when a > 0) {}
}

常见修复方法

#

删除空断言模式

dart
void f(int x) {
  if (x case var a when a > 0) {}
}

不必要的 null 检查模式

#

空检查模式将不起作用,因为匹配的类型不可为空。

描述

#

当使用空检查模式来匹配不可为空的值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为值 x 不可为空

dart
void f(int x) {
  if (x case var a? when a > 0) {}
}

常见修复方法

#

删除空检查模式

dart
void f(int x) {
  if (x case var a when a > 0) {}
}

不必要的 null 比较

#

操作数不能为 'null',因此条件始终为 'false'。

操作数不能为 'null',因此条件始终为 'true'。

操作数必须为 'null',因此条件始终为 'false'。

操作数必须为 'null',因此条件始终为 'true'。

描述

#

当分析器发现与 null 的相等比较(==!= 之一),并且另一个操作数不能为 null 时,会产生此诊断。此类比较始终为 truefalse,因此它们没有意义。

示例

#

以下代码产生此诊断,因为 x 永远不能为 null,因此比较始终评估为 true

dart
void f(int x) {
  if (x != null) {
    print(x);
  }
}

以下代码产生此诊断,因为 x 永远不能为 null,因此比较始终评估为 false

dart
void f(int x) {
  if (x == null) {
    throw ArgumentError("x can't be null");
  }
}

常见修复方法

#

如果另一个操作数应该能够为 null,则更改操作数的类型

dart
void f(int? x) {
  if (x != null) {
    print(x);
  }
}

如果另一个操作数确实不能为 null,则删除条件

dart
void f(int x) {
  print(x);
}

不必要的问号

#

'?' 是不必要的,因为 '{0}' 在没有它的情况下是可为空的。

描述

#

当类型 dynamic 或类型 Null 后跟问号时,分析器会产生此诊断。这两种类型本质上都是可为空的,因此问号不会改变语义。

示例

#

以下代码产生此诊断,因为 dynamic 后面的问号是不必要的

dart
dynamic? x;

常见修复方法

#

删除不需要的问号

dart
dynamic x;

不必要的 Set 字面量

#

花括号不必要地将此表达式包装在 set 字面量中。

描述

#

当返回类型为 voidFuture<void>FutureOr<void> 的函数使用表达式函数体 (=>) 并且返回的值是包含单个元素的字面量 set 时,分析器会产生此诊断。

虽然语言允许这样做,但从 void 函数返回值是没有用的,因为它不能在调用站点使用。在这种特定情况下,返回通常是由于对语法的误解。花括号是不必要的,可以删除。

示例

#

以下代码产生此诊断,因为传递给 g 的闭包的返回类型为 void,但正在返回一个 set

dart
void f() {
  g(() => {1});
}

void g(void Function() p) {}

常见修复方法

#

从值周围删除花括号

dart
void f() {
  g(() => 1);
}

void g(void Function() p) {}

不必要的类型检查

#

不必要的类型检查;结果始终为 'false'。

不必要的类型检查;结果始终为 'true'。

描述

#

当类型检查的值(使用 isis! 之一)在编译时已知时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为测试 a is Object? 始终为 true

dart
bool f<T>(T a) => a is Object?;

常见修复方法

#

如果类型检查未检查您打算检查的内容,则更改测试

dart
bool f<T>(T a) => a is Object;

如果类型检查确实检查了您打算检查的内容,则将类型检查替换为其已知值或完全删除它

dart
bool f<T>(T a) => true;

对非本地静态成员的不限定引用

#

来自超类型的静态成员必须由定义类型的名称限定。

描述

#

当一个类中的代码引用超类中的静态成员,而没有使用超类的名称作为成员名称的前缀时,分析器会产生此诊断。静态成员只能在声明它们的类中不带前缀引用。

示例

#

以下代码产生此诊断,因为静态字段 x 在 getter g 中被引用,而没有使用定义类的名称作为前缀

dart
class A {
  static int x = 3;
}

class B extends A {
  int get g => x;
}

常见修复方法

#

使用声明类的名称作为静态成员名称的前缀

dart
class A {
  static int x = 3;
}

class B extends A {
  int get g => A.x;
}

对扩展类型的静态成员的不限定引用

#

来自扩展类型或其超类之一的静态成员必须由定义类型的名称限定。

描述

#

当找到未定义的名称,并且该名称与扩展类型或其超类之一的静态成员相同时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 m 是扩展类型 C 的静态成员

dart
class C {
  static void m() {}
}

extension E on C {
  void f() {
    m();
  }
}

常见修复方法

#

如果您尝试引用在扩展之外声明的静态成员,则在对成员的引用之前添加类或扩展的名称

dart
class C {
  static void m() {}
}

extension E on C {
  void f() {
    C.m();
  }
}

如果您正在引用尚未声明的成员,请添加声明

dart
class C {
  static void m() {}
}

extension E on C {
  void f() {
    m();
  }

  void m() {}
}

无法访问的 switch case

#

这种情况包含在以前的情况中。

描述

#

switch 语句中的 case 子句不匹配任何内容时,分析器会产生此诊断,因为所有可匹配的值都已由较早的 case 子句匹配。

示例

#

以下代码产生此诊断,因为值 1 在前面的 case 中匹配

dart
void f(int x) {
  switch (x) {
    case 1:
      print('one');
    case 1:
      print('two');
  }
}

常见修复方法

#

更改冲突的 case 以匹配不同的值

dart
void f(int x) {
  switch (x) {
    case 1:
      print('one');
    case 2:
      print('two');
  }
}

无法访问的 switch default

#

此 default 子句包含在以前的情况中。

描述

#

switch 语句中的 default 子句不匹配任何内容时,分析器会产生此诊断,因为所有可匹配的值都已由较早的 case 子句匹配。

示例

#

以下代码产生此诊断,因为值 E.e1E.e2 在前面的 case 中匹配

dart
enum E { e1, e2 }

void f(E x) {
  switch (x) {
    case E.e1:
      print('one');
    case E.e2:
      print('two');
    default:
      print('other');
  }
}

常见修复方法

#

删除不必要的 default 子句

dart
enum E { e1, e2 }
void f(E x) {
  switch (x) {
    case E.e1:
      print('one');
    case E.e2:
      print('two');
  }
}

未使用的 catch 子句

#

未使用的异常变量 '{0}',因此可以删除 'catch' 子句。

描述

#

当找到 catch 子句,并且异常参数和可选的堆栈跟踪参数都未在 catch 块中使用时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为未引用 e

dart
void f() {
  try {
    int.parse(';');
  } on FormatException catch (e) {
    // ignored
  }
}

常见修复方法

#

删除未使用的 catch 子句

dart
void f() {
  try {
    int.parse(';');
  } on FormatException {
    // ignored
  }
}

未使用的 catch 堆栈

#

未使用的堆栈跟踪变量 '{0}',可以删除。

描述

#

catch 子句中的堆栈跟踪参数未在 catch 块的主体中引用时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为未引用 stackTrace

dart
void f() {
  try {
    // ...
  } catch (exception, stackTrace) {
    // ...
  }
}

常见修复方法

#

如果您需要引用堆栈跟踪参数,则添加对其的引用。否则,删除它

dart
void f() {
  try {
    // ...
  } catch (exception) {
    // ...
  }
}

未使用的元素

#

未引用声明 '{0}'。

描述

#

当私有声明未在包含该声明的库中引用时,分析器会产生此诊断。分析以下类型的声明

  • 私有顶层声明及其所有成员
  • 公共声明的私有成员

并非所有对元素的引用都会将其标记为“已使用”

  • 为顶层变量赋值(使用标准 = 赋值或空感知 ??= 赋值)不计为使用它。
  • 在文档注释引用中引用元素不计为使用它。
  • is 表达式的右侧引用类、mixin 或枚举不计为使用它。

示例

#

假设库中没有代码引用 _C,以下代码会产生此诊断

dart
class _C {}

常见修复方法

#

如果不需要声明,则删除它。

如果声明旨在被使用,则添加代码以使用它。

未使用的元素参数

#

从未为可选参数 '{0}' 提供值。

描述

#

当从未为私有声明中声明的可选参数传递值时,分析器会产生此诊断。

示例

#

假设库中没有代码在任何 _m 的调用中为 y 传递值,以下代码会产生此诊断

dart
class C {
  void _m(int x, [int? y]) {}

  void n() => _m(0);
}

常见修复方法

#

如果不需要声明,则删除它

dart
class C {
  void _m(int x) {}

  void n() => _m(0);
}

如果声明旨在被使用,则添加代码以使用它。

未使用的字段

#

未使用字段 '{0}' 的值。

描述

#

当声明了私有字段但从未读取,即使在一个或多个位置写入时,分析器也会产生此诊断。

示例

#

以下代码产生此诊断,因为字段 _originalValue 在库中的任何位置都未读取

dart
class C {
  final String _originalValue;
  final String _currentValue;

  C(this._originalValue) : _currentValue = _originalValue;

  String get value => _currentValue;
}

可能看起来字段 _originalValue 正在初始化程序 (_currentValue = _originalValue) 中读取,但这实际上是对同名参数的引用,而不是对字段的引用。

常见修复方法

#

如果不需要字段,则删除它。

如果字段旨在被使用,则添加缺失的代码。

未使用的导入

#

未使用的导入:'{0}'。

描述

#

当导入是不必要的,因为导入库中引用的名称都没有在导入库中引用时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 dart:async 中定义的任何内容都没有在库中引用

dart
import 'dart:async';

void main() {}

常见修复方法

#

如果不需要导入,则删除它。

如果某些导入的名称旨在被使用,则添加缺失的代码。

未使用的标签

#

未使用的标签 '{0}'。

描述

#

当找到未使用的标签时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为标签 loop 在方法中的任何位置都未引用

dart
void f(int limit) {
  loop: for (int i = 0; i < limit; i++) {
    print(i);
  }
}

常见修复方法

#

如果不需要标签,则删除它

dart
void f(int limit) {
  for (int i = 0; i < limit; i++) {
    print(i);
  }
}

如果需要标签,则使用它

dart
void f(int limit) {
  loop: for (int i = 0; i < limit; i++) {
    print(i);
    if (i != 0) {
      break loop;
    }
  }
}

未使用的局部变量

#

未使用局部变量 '{0}' 的值。

描述

#

当声明了局部变量但从未读取,即使在一个或多个位置写入时,分析器也会产生此诊断。

示例

#

以下代码产生此诊断,因为从未读取 count 的值

dart
void main() {
  int count = 0;
}

常见修复方法

#

如果不需要变量,则删除它。

如果变量旨在被使用,则添加缺失的代码。

未使用的结果

#

' {0} ' 应该被使用。 {1}。

应该使用 '{0}' 的值。

描述

#

当调用使用 useResult 注解的函数,并且未使用该函数返回的值时,分析器会产生此诊断。如果调用了值的成员、将值传递给另一个函数或将值分配给变量或字段,则该值被视为已使用。

示例

#

以下代码产生此诊断,因为未使用 c.a() 的调用,即使方法 a 使用 useResult 注解

dart
import 'package:meta/meta.dart';

class C {
  @useResult
  int a() => 0;

  int b() => 0;
}

void f(C c) {
  c.a();
}

常见修复方法

#

如果您打算调用注解的函数,则使用返回的值

dart
import 'package:meta/meta.dart';

class C {
  @useResult
  int a() => 0;

  int b() => 0;
}

void f(C c) {
  print(c.a());
}

如果您打算调用不同的函数,则更正被调用函数的名称

dart
import 'package:meta/meta.dart';

class C {
  @useResult
  int a() => 0;

  int b() => 0;
}

void f(C c) {
  c.b();
}

未使用的显示名称

#

名称 {0} 已显示,但未使用。

描述

#

当显示组合器包含库中未使用的名称时,分析器会产生此诊断。因为它未被引用,所以可以删除该名称。

示例

#

以下代码产生此诊断,因为未使用函数 max

dart
import 'dart:math' show min, max;

var x = min(0, 1);

常见修复方法

#

使用该名称或删除它

dart
import 'dart:math' show min;

var x = min(0, 1);

URI 不存在

#

URI 的目标不存在:'{0}'。

描述

#

当找到 import、export 或 part 指令,其中 URI 引用不存在的文件时,分析器会产生此诊断。

示例

#

如果文件 lib.dart 不存在,以下代码会产生此诊断

dart
import 'lib.dart';

常见修复方法

#

如果 URI 拼写错误或无效,则更正 URI。

如果 URI 正确,则创建文件。

文档导入中的 URI 不存在

#

URI 的目标不存在:'{0}'。

描述

#

当找到 doc-import,其中 URI 引用不存在的文件时,分析器会产生此诊断。

示例

#

如果文件 lib.dart 不存在,以下代码会产生此诊断

dart
/// @docImport 'lib.dart';
library;

常见修复方法

#

如果 URI 拼写错误或无效,则更正 URI。

如果 URI 正确,则创建文件。

URI 尚未生成

#

URI 的目标尚未生成:'{0}'。

描述

#

当找到 import、export 或 part 指令,其中 URI 引用不存在的文件,并且文件名称以代码生成器通常生成的模式结尾时,分析器会产生此诊断,例如以下之一

  • .g.dart
  • .pb.dart
  • .pbenum.dart
  • .pbserver.dart
  • .pbjson.dart
  • .template.dart

示例

#

如果文件 lib.g.dart 不存在,以下代码会产生此诊断

dart
import 'lib.g.dart';

常见修复方法

#

如果文件是生成的文件,则运行生成该文件的生成器。

如果文件不是生成的文件,则检查 URI 的拼写或创建文件。

带有插值的 URI

#

URI 不能使用字符串插值。

描述

#

importexportpart 指令中的字符串字面量包含插值时,分析器会产生此诊断。指令中 URI 的解析必须在编译声明之前发生,因此在确定 URI 的值时无法评估表达式。

示例

#

以下代码产生此诊断,因为 import 指令中的字符串包含插值

dart
import 'dart:$m';

const m = 'math';

常见修复方法

#

从 URI 中删除插值

dart
import 'dart:math';

var zero = min(0, 0);

使用 native 扩展

#

Dart native extensions 已弃用,并且在 Dart 2.15 中不可用。

描述

#

当使用 dart-ext 方案导入库时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为本机库 x 正在使用 dart-ext 方案导入

dart
import 'dart-ext:x';

常见修复方法

#

重写代码以使用 dart:ffi 作为调用本机库内容的方式。

使用 void 结果

#

此表达式的类型为 'void',因此其值不能被使用。

描述

#

当分析器找到类型为 void 的表达式,并且该表达式用在期望值的地方,例如在成员访问之前或在赋值的右侧时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 f 未生成可以调用 toString 的对象

dart
void f() {}

void g() {
  f().toString();
}

常见修复方法

#

重写代码以使表达式具有值,或重写代码以使其不依赖于该值。

枚举中的 values 声明

#

名为 'values' 的成员不能在枚举中声明。

描述

#

当枚举声明定义名为 values 的成员时,分析器会产生此诊断,无论该成员是枚举值、实例成员还是静态成员。

任何此类成员都与返回包含所有枚举常量的列表的名为 values 的隐式静态 getter 冲突。

示例

#

以下代码产生此诊断,因为枚举 E 定义了名为 values 的实例成员

dart
enum E {
  v;
  void values() {}
}

常见修复方法

#

更改冲突成员的名称

dart
enum E {
  v;
  void getValues() {}
}

可变长度数组不是最后一个字段

#

可变长度 'Array' 只能作为 Structs 的最后一个字段出现。

描述

#

当可变长度内联 Array 不是 Struct 的最后一个成员时,分析器会产生此诊断。

有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作

示例

#

以下代码会生成此诊断信息,因为字段 a0 的类型具有三个嵌套数组,但在 Array 注解中仅给出了两个维度。

dart
import 'dart:ffi';

final class C extends Struct {
  @Array.variable()
  external Array<Uint8> a0;

  @Uint8()
  external int a1;
}

常见修复方法

#

将可变长度内联 Array 移动到 struct 中的最后一个字段。

dart
import 'dart:ffi';

final class C extends Struct {
  @Uint8()
  external int a1;

  @Array.variable()
  external Array<Uint8> a0;
}

如果内联数组具有固定大小,请使用大小进行注解

dart
import 'dart:ffi';

final class C extends Struct {
  @Array(10)
  external Array<Uint8> a0;

  @Uint8()
  external int a1;
}

声明上下文中变量模式关键字

#

声明上下文中的可变模式不能指定 'var' 或 'final' 关键字。

描述

#

当在声明上下文中使用可变模式时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为记录模式中的可变模式位于声明上下文中

dart
void f((int, int) r) {
  var (var x, y) = r;
  print(x + y);
}

常见修复方法

#

删除可变模式中的 varfinal 关键字

dart
void f((int, int) r) {
  var (x, y) = r;
  print(x + y);
}

变量类型不匹配

#

类型为 '{0}' 的值不能分配给类型为 '{1}' 的 const 变量。

描述

#

当常量表达式的评估会导致 CastException 时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 x 的值是 int,无法将其分配给 y,因为 int 不是 String

dart
const dynamic x = 0;
const String y = x;

常见修复方法

#

如果常量的声明是正确的,则更改要分配的值以使其为正确的类型

dart
const dynamic x = 0;
const String y = '$x';

如果分配的值是正确的,则更改声明以使其具有正确的类型

dart
const int x = 0;
const int y = x;

workspace 字段不是 List

#

'workspace' 字段的值必须是相对文件路径列表。

描述

#

workspace 键的值不是列表时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 workspace 键的值是字符串,而预期是列表

yaml
name: example
workspace: notPaths

常见修复方法

#

更改 workspace 字段的值,使其成为列表

yaml
name: example
workspace:
    - pkg/package_1
    - pkg/package_2

workspace 值不是字符串

#

Workspace 条目必须是目录路径(字符串)。

描述

#

workspace 列表包含不是字符串的值时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 workspace 列表包含一个映射

yaml
name: example
workspace:
    - image.gif: true

常见修复方法

#

更改 workspace 列表,使其仅包含有效的 POSIX 风格的目录路径

yaml
name: example
workspace:
    - pkg/package_1
    - pkg/package_2

workspace 值不是子目录

#

Workspace 值必须是 '{0}' 的子目录的相对路径。

描述

#

workspace 列表包含的值不是包含 `pubspec.yaml` 文件的目录的子目录的相对路径时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为 workspace 列表中的值不是包含 'pubspec.yaml' 文件的目录的子目录的相对路径

yaml
name: example
workspace:
    - /home/my_package

常见修复方法

#

更改 workspace 列表,使其仅包含子目录路径。

yaml
name: example
workspace:
    - pkg/package_1
    - pkg/package_2

运算符的参数数量错误

#

运算符 '-' 应声明 0 或 1 个参数,但找到 {0} 个。

运算符 '{0}' 应精确声明 {1} 个参数,但找到 {2} 个。

描述

#

当运算符的声明具有错误的参数数量时,分析器会产生此诊断。

示例

#

以下代码产生此诊断,因为运算符 + 必须具有与右操作数对应的单个参数

dart
class C {
  int operator +(a, b) => 0;
}

常见修复方法

#

添加或删除参数以匹配所需的数量

dart
class C {
  int operator +(a) => 0;
}

setter 的参数数量错误

#

Setter 必须精确声明一个必需的位置参数。

描述

#

当找到未精确声明一个必需的位置参数的 setter 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 setter s 声明了两个必需参数

dart
class C {
  set s(int x, int y) {}
}

以下代码会产生此诊断,因为 setter s 声明了一个可选参数

dart
class C {
  set s([int? x]) {}
}

常见修复方法

#

更改声明,使其正好有一个必需的位置参数

dart
class C {
  set s(int x) {}
}

类型参数数量错误

#

类型“{0}”声明了 {1} 个类型参数,但给出了 {2} 个类型实参。

描述

#

当使用具有类型参数的类型并提供类型实参时,但类型实参的数量与类型参数的数量不相同时,分析器会产生此诊断。

当调用构造函数且类型实参的数量与为类声明的类型参数的数量不匹配时,分析器也会产生此诊断。

示例

#

以下代码会产生此诊断,因为 C 有一个类型参数,但在用作类型注解时提供了两个类型实参

dart
class C<E> {}

void f(C<int, int> x) {}

以下代码会产生此诊断,因为 C 声明了一个类型参数,但在创建实例时提供了两个类型实参

dart
class C<E> {}

var c = C<int, int>();

常见修复方法

#

根据需要添加或删除类型实参,以匹配为类型定义的类型参数的数量

dart
class C<E> {}

void f(C<int> x) {}

构造函数的类型参数数量错误

#

构造函数“{0}.{1}”没有类型参数。

描述

#

当在命名构造函数的名称后提供类型实参时,分析器会产生此诊断。构造函数无法声明类型参数,因此调用只能提供与类关联的类型实参,并且这些类型实参必须跟在类名而不是构造函数名称之后。

示例

#

以下代码会产生此诊断,因为类型参数(<String>)跟在构造函数的名称而不是类的名称之后

dart
class C<T> {
  C.named();
}
C f() => C.named<String>();

常见修复方法

#

如果类型实参用于类的类型参数,则将类型实参移动到类名之后

dart
class C<T> {
  C.named();
}
C f() => C<String>.named();

如果类型实参不用于类的类型参数,则删除它们

dart
class C<T> {
  C.named();
}
C f() => C.named();

枚举的类型参数数量错误

#

枚举声明了 {0} 个类型参数,但给出了 {1} 个类型实参。

描述

#

当实例化具有类型参数的枚举中的枚举值并提供类型实参时,但类型实参的数量与类型参数的数量不相同时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为枚举值 c 提供了一个类型实参,即使枚举 E 被声明为具有两个类型参数

dart
enum E<T, U> {
  c<int>()
}

常见修复方法

#

如果类型参数的数量正确,则更改类型实参的数量以匹配类型参数的数量

dart
enum E<T, U> {
  c<int, String>()
}

如果类型实参的数量正确,则更改类型参数的数量以匹配类型实参的数量

dart
enum E<T> {
  c<int>()
}

扩展的类型参数数量错误

#

扩展“{0}”声明了 {1} 个类型参数,但给出了 {2} 个类型实参。

描述

#

当使用具有类型参数的扩展并提供类型实参时,但类型实参的数量与类型参数的数量不相同时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为扩展 E 被声明为具有单个类型参数 (T),但扩展覆盖具有两个类型实参

dart
extension E<T> on List<T> {
  int get len => length;
}

void f(List<int> p) {
  E<int, String>(p).len;
}

常见修复方法

#

更改类型实参,使其数量与类型参数的数量相同

dart
extension E<T> on List<T> {
  int get len => length;
}

void f(List<int> p) {
  E<int>(p).len;
}

方法的类型参数数量错误

#

方法“{0}”声明了 {1} 个类型参数,但给出了 {2} 个类型实参。

描述

#

当使用的方法或函数的类型实参数量与声明中指定的类型参数数量不同时,分析器会产生此诊断。必须没有类型实参,或者实参的数量必须与参数的数量匹配。

示例

#

以下代码会产生此诊断,因为方法 m 的调用有两个类型实参,但 m 的声明只有一个类型参数

dart
class C {
  int m<A>(A a) => 0;
}

int f(C c) => c.m<int, int>(2);

常见修复方法

#

如果类型实参是必要的,则通过添加或删除类型实参来使它们与类型参数的数量匹配

dart
class C {
  int m<A>(A a) => 0;
}

int f(C c) => c.m<int>(2);

如果类型实参不是必要的,则删除它们

dart
class C {
  int m<A>(A a) => 0;
}

int f(C c) => c.m(2);

在非生成器中使用 yield

#

Yield 语句必须在生成器函数中(用 'async*' 或 'sync*' 标记的函数)。

Yield-each 语句必须在生成器函数中(用 'async*' 或 'sync*' 标记的函数)。

描述

#

yieldyield* 语句出现在函数体未使用 async*sync* 修饰符之一标记的函数中时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 yield 正在函数体没有修饰符的函数中使用

dart
Iterable<int> get digits {
  yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}

以下代码会产生此诊断,因为 yield* 正在函数体具有 async 修饰符而不是 async* 修饰符的函数中使用

dart
Stream<int> get digits async {
  yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}

常见修复方法

#

添加修饰符,或将现有修饰符更改为 async*sync*

dart
Iterable<int> get digits sync* {
  yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}

yield 类型无效

#

类型为“{0}”的 yielded 值必须可赋值给“{1}”。

“yield*”表达式隐含的类型“{0}”必须可赋值给“{1}”。

描述

#

yieldyield* 表达式产生的对象类型与要从生成器(用 sync*async* 标记的函数或方法)返回的 IterableStream 类型返回的对象类型不匹配时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 getter zero 被声明为返回一个返回整数的 Iterable,但 yield 正在从 iterable 返回一个字符串

dart
Iterable<int> get zero sync* {
  yield '0';
}

常见修复方法

#

如果函数的返回类型是正确的,则修复关键字 yield 后面的表达式以返回正确的类型

dart
Iterable<int> get zero sync* {
  yield 0;
}

如果关键字 yield 后面的表达式是正确的,则更改函数的返回类型以允许它

dart
Iterable<String> get zero sync* {
  yield '0';
}

始终声明返回类型

#

函数“{0}”应该有返回类型,但没有。

方法“{0}”应该有返回类型,但没有。

描述

#

当方法或函数没有显式返回类型时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为函数 f 没有返回类型

dart
f() {}

常见修复方法

#

添加显式返回类型

dart
void f() {}

始终将控制体放在新行

#

语句应位于单独的行上。

描述

#

当受控制流语句(ifforwhiledo)控制的代码与控制流语句在同一行时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 return 语句与控制 return 是否会执行的 if 在同一行

dart
void f(bool b) {
  if (b) return;
}

常见修复方法

#

将受控语句放到单独的、缩进的行上

dart
void f(bool b) {
  if (b)
    return;
}

始终将必需的命名参数放在最前面

#

必需的命名参数应在可选的命名参数之前。

描述

#

当必需的命名参数出现在可选的命名参数之后时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为必需的参数 x 在可选的参数 y 之后

dart
void f({int? y, required int x}) {}

常见修复方法

#

重新排序参数,使所有必需的命名参数都在任何可选的命名参数之前

dart
void f({required int x, int? y}) {}

始终使用 package 导入

#

对于“lib”目录中的文件,使用“package:”导入。

描述

#

当“lib”目录内的库中的 import 使用相对路径导入同一包的“lib”目录内的另一个库时,分析器会产生此诊断。

示例

#

假设名为 a.dart 的文件和以下代码都在同一包的“lib”目录内,则以下代码会产生此诊断,因为使用了相对 URI 来导入 a.dart

dart
import 'a.dart';

常见修复方法

#

使用包导入

dart
import 'package:p/a.dart';

注解 overrides

#

成员“{0}”覆盖了继承的成员,但没有用“@override”注解。

描述

#

当成员覆盖了继承的成员,但没有用 @override 注解时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为类 B 中的方法 m 覆盖了类 A 中同名的方法,但没有标记为有意覆盖

dart
class A {
  void m() {}
}

class B extends A {
  void m() {}
}

常见修复方法

#

如果子类中的成员旨在覆盖超类中的成员,则添加 @override 注解

dart
class A {
  void m() {}
}

class B extends A {
  @override
  void m() {}
}

如果子类中的成员不旨在覆盖超类中的成员,则重命名其中一个成员

dart
class A {
  void m() {}
}

class B extends A {
  void m2() {}
}

避免空的 else 代码块

#

“else”子句中不允许空语句。

描述

#

else 之后的语句是空语句(分号)时,分析器会产生此诊断。

有关更多信息,请参阅 avoid_empty_else 的文档。

示例

#

以下代码会产生此诊断,因为 else 后面的语句是空语句

dart
void f(int x, int y) {
  if (x > y)
    print("1");
  else ;
    print("2");
}

常见修复方法

#

如果空语句之后的语句旨在仅在条件为 false 时执行,则删除空语句

dart
void f(int x, int y) {
  if (x > y)
    print("1");
  else
    print("2");
}

如果没有旨在仅在条件为 false 时执行的代码,则删除整个 else 子句

dart
void f(int x, int y) {
  if (x > y)
    print("1");
  print("2");
}

避免在 forEach 调用中使用函数字面量

#

不应将函数字面量传递给“forEach”。

描述

#

Iterable.forEach 的参数是闭包时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 forEach 调用的参数是闭包

dart
void f(Iterable<String> s) {
  s.forEach((e) => print(e));
}

常见修复方法

#

如果闭包可以被 tear-off 替换,则替换闭包

dart
void f(Iterable<String> s) {
  s.forEach(print);
}

如果闭包不能被 tear-off 替换,则使用 for 循环来迭代元素

dart
void f(Iterable<String> s) {
  for (var e in s) {
    print(e);
  }
}

避免使用 FutureOr<void>

#

不要使用类型 'FutureOr<void>'。'.

描述

#

当类型 FutureOr<void> 用作结果的类型时(准确地说:它用于非逆变的位置),分析器会产生此诊断。类型 FutureOr<void> 是有问题的,因为它可能看起来编码了结果是 Future<void>,或者结果应该被丢弃(当它是 void 时)。但是,没有安全的方法来检测我们是哪种情况,因为 void 类型的表达式可以评估为任何对象,包括任何类型的 future。

拥有一个类型,其含义类似于“忽略此对象;还要注意,因为它可能是一个 future”,在概念上也是不健全的。

类型 FutureOr<void> 的逆变出现(例如,对于形式参数的类型)是一个例外,并且不会为这些出现发出警告。此例外的原因是该类型不描述结果,而是描述对其他人提供的值的约束。类似地,类型别名声明也是一个例外,因为它们很可能用于逆变位置(例如,作为形式参数的类型)。因此,在类型别名声明中,仅检查类型参数边界。

示例

#
dart
import 'dart:async';

FutureOr<void> m() => null;

常见修复方法

#

类型 FutureOr<void> 的一个常用替代方案是 Future<void>?。此类型编码结果是 Future<void> 或 null,并且在运行时没有歧义,因为没有对象可以同时具有这两种类型。

可能并不总是可以使用类型 Future<void>? 作为类型 FutureOr<void> 的替代方案,因为后者是所有类型的超类型,而前者不是。在这种情况下,将 FutureOr<void> 替换为类型 void 可能是有效的补救措施。

避免初始化为 null

#

对“null”进行多余的初始化。

描述

#

当可为空的变量显式初始化为 null 时,分析器会产生此诊断。变量可以是局部变量、字段或顶级变量。

未显式初始化的变量或字段会自动初始化为 null。在 Dart 中没有“未初始化的内存”的概念。

示例

#

以下代码会产生此诊断,因为变量 f 显式初始化为 null

dart
class C {
  int? f = null;

  void m() {
    if (f != null) {
      print(f);
    }
  }
}

常见修复方法

#

删除不必要的初始化

dart
class C {
  int? f;

  void m() {
    if (f != null) {
      print(f);
    }
  }
}

避免使用 print

#

不要在生产代码中调用“print”。

描述

#

当在生产代码中调用函数 print 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为不能在生产环境中调用函数 print

dart
void f(int x) {
  print('x = $x');
}

常见修复方法

#

如果您正在编写使用 Flutter 的代码,则使用函数 debugPrint,并使用 kDebugMode 进行测试保护

dart
import 'package:flutter/foundation.dart';

void f(int x) {
  if (kDebugMode) {
    debugPrint('x = $x');
  }
}

如果您正在编写不使用 Flutter 的代码,则使用日志服务,例如 package:logging,来写入信息。

避免相对 lib 导入

#

不能使用相对路径导入“lib”中的库。

描述

#

import 指令中的 URI 路径中包含 lib 时,分析器会产生此诊断。

示例

#

假设“lib”目录中有一个名为 a.dart 的文件

dart
class A {}

以下代码会产生此诊断,因为 import 包含一个包含 lib 的路径

dart
import '../lib/a.dart';

常见修复方法

#

重写 import 以不在 URI 中包含 lib

dart
import 'a.dart';

避免重命名方法参数

#

参数名“{0}”与被覆盖方法中的名称“{1}”不匹配。

描述

#

当覆盖超类方法的某个方法更改了参数的名称时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 B 中的方法 m 的参数名为 b,这与 A 中被覆盖的方法的参数名称不同

dart
class A {
  void m(int a) {}
}

class B extends A {
  @override
  void m(int b) {}
}

常见修复方法

#

重命名其中一个参数,使它们相同

dart
class A {
  void m(int a) {}
}

class B extends A {
  @override
  void m(int a) {}
}

避免在 setter 上使用返回类型

#

Setter 上不必要的返回类型。

描述

#

当 setter 具有显式返回类型时,分析器会产生此诊断。

Setter 永远不会返回值,因此声明 setter 的返回类型是多余的。

示例

#

以下代码会产生此诊断,因为 setter s 具有显式返回类型(void

dart
void set s(int p) {}

常见修复方法

#

删除返回类型

dart
set s(int p) {}

避免为 void 返回 null

#

不要从返回类型为“void”的函数中返回“null”。

不要从返回类型为“void”的方法中返回“null”。

描述

#

当返回类型为 void 的函数显式返回 null 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为在 void 函数中显式返回了 null

dart
void f() {
  return null;
}

常见修复方法

#

删除不必要的显式 null

dart
void f() {
  return;
}

避免遮蔽类型参数

#

类型参数“{0}”遮蔽了封闭 {1} 中的类型参数。

描述

#

当类型参数遮蔽了封闭声明中的类型参数时,分析器会产生此诊断。

用不同的类型参数遮蔽类型参数可能会导致难以调试的细微错误。

示例

#

以下代码会产生此诊断,因为方法 m 定义的类型参数 T 遮蔽了类 C 定义的类型参数 T

dart
class C<T> {
  void m<T>() {}
}

常见修复方法

#

重命名其中一个类型参数

dart
class C<T> {
  void m<S>() {}
}

避免在表达式语句中使用单个级联

#

不必要的级联表达式。

描述

#

当使用单个级联运算符且表达式的值未用于任何用途(例如赋值给变量或作为参数传递)时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为级联表达式 s..length 的值未使用

dart
void f(String s) {
  s..length;
}

常见修复方法

#

将级联运算符替换为简单的访问运算符

dart
void f(String s) {
  s.length;
}

避免慢速异步 IO 操作

#

使用异步 'dart:io' 方法。

描述

#

当使用具有同步等效项的异步文件 I/O 方法时,分析器会产生此诊断。

以下是特定的标记异步方法

  • Directory.exists
  • Directory.stat
  • File.lastModified
  • File.exists
  • File.stat
  • FileSystemEntity.isDirectory
  • FileSystemEntity.isFile
  • FileSystemEntity.isLink
  • FileSystemEntity.type

示例

#

以下代码会产生此诊断,因为调用了异步方法 exists

dart
import 'dart:io';

Future<void> g(File f) async {
  await f.exists();
}

常见修复方法

#

使用该方法的同步版本

dart
import 'dart:io';

void g(File f) {
  f.existsSync();
}

避免使用 type.toString

#

在生产代码中使用 'Type' 上的 'toString' 是不安全的。

描述

#

当在静态类型为 Type 的值上调用方法 toString 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为在 runtimeType 返回的 Type 上调用了方法 toString

dart
bool isC(Object o) => o.runtimeType.toString() == 'C';

class C {}

常见修复方法

#

如果类型必须完全相同,则使用显式比较

dart
bool isC(Object o) => o.runtimeType == C;

class C {}

如果类型子类型的实例返回 true 也可以,则使用类型检查

dart
bool isC(Object o) => o is C;

class C {}

避免将类型用作参数名称

#

参数名“{0}”与可见的类型名称匹配。

描述

#

当参数列表中的参数名称与可见类型(名称在作用域内的类型)相同时,分析器会产生此诊断。

这通常表明参数的预期名称缺失,导致类型的名称用作参数的名称而不是参数的类型。即使情况并非如此(参数的名称是有意的),参数的名称也会遮蔽现有类型,这可能会导致难以诊断的错误。

示例

#

以下代码会产生此诊断,因为函数 f 有一个名为 int 的参数,它遮蔽了来自 dart:core 的类型 int

dart
void f(int) {}

常见修复方法

#

如果参数名缺失,则为参数添加名称

dart
void f(int x) {}

如果参数旨在具有 dynamic 的隐式类型,则重命名参数,使其不遮蔽任何可见类型的名称

dart
void f(int_) {}

避免不必要的容器

#

“Container”的不必要实例。

描述

#

当 widget 树包含 Container 的实例,并且构造函数的唯一参数是 child: 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 Container 构造函数的调用仅具有 child: 参数

dart
import 'package:flutter/material.dart';

Widget buildRow() {
  return Container(
    child: Row(
      children: [
        Text('a'),
        Text('b'),
      ],
    )
  );
}

常见修复方法

#

如果您打算为构造函数提供其他参数,请添加它们

dart
import 'package:flutter/material.dart';

Widget buildRow() {
  return Container(
    color: Colors.red.shade100,
    child: Row(
      children: [
        Text('a'),
        Text('b'),
      ],
    )
  );
}

如果不需要其他参数,则解包子 widget

dart
import 'package:flutter/material.dart';

Widget buildRow() {
  return Row(
    children: [
      Text('a'),
      Text('b'),
    ],
  );
}

避免在 Flutter 中使用 Web 库

#

不要在 Flutter web 插件之外使用仅限 web 的库。

描述

#

当非 web 插件的包中的库包含对仅限 web 的库的导入时,分析器会产生此诊断

  • dart:html
  • dart:js
  • dart:js_util
  • dart:js_interop
  • dart:js_interop_unsafe
  • package:js
  • package:web

示例

#

当在非 web 插件的包中找到时,以下代码会产生此诊断,因为它导入了 dart:html

dart
import 'dart:html';

import 'package:flutter/material.dart';

class C {}

常见修复方法

#

如果该包不打算成为 web 插件,则删除导入

dart
import 'package:flutter/material.dart';

class C {}

如果该包打算成为 web 插件,则将以下行添加到该包的 pubspec.yaml 文件中

yaml
flutter:
  plugin:
    platforms:
      web:
        pluginClass: HelloPlugin
        fileName: hello_web.dart

有关更多信息,请参阅 开发包 & 插件

仅等待 Future

#

在“{0}”的实例上使用“await”,它不是“Future”的子类型。

描述

#

await 之后的表达式具有除 Future<T>FutureOr<T>Future<T>?FutureOr<T>?dynamic 之外的任何类型时,分析器会产生此诊断。

await null 表达式是一个例外,因为它是一种引入微任务延迟的常用方法。

除非表达式可以产生 Future,否则 await 是不必要的,并且可能导致读者假设不存在的异步级别。

示例

#

以下代码会产生此诊断,因为 await 之后的表达式的类型为 int

dart
void f() async {
  await 23;
}

常见修复方法

#

删除 await

dart
void f() async {
  23;
}

驼峰命名扩展

#

扩展名“{0}”不是 UpperCamelCase 标识符。

描述

#

当扩展的名称未使用“UpperCamelCase”命名约定时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为扩展的名称不是以大写字母开头的

dart
extension stringExtension on String {}

常见修复方法

#

如果扩展需要有一个名称(需要在本库之外可见),则重命名扩展,使其具有有效名称

dart
extension StringExtension on String {}

如果扩展不需要有名称,则删除扩展的名称

dart
extension on String {}

驼峰命名类型

#

类型名称“{0}”不是 UpperCamelCase 标识符。

描述

#

当类型(类、mixin、枚举或 typedef)的名称未使用“UpperCamelCase”命名约定时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为类的名称不是以大写字母开头的

dart
class c {}

常见修复方法

#

重命名类型,使其具有有效名称

dart
class C {}

取消订阅

#

“StreamSubscription”的未取消实例。

描述

#

当创建了 StreamSubscription 的实例但未调用方法 cancel 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 subscription 未被取消

dart
import 'dart:async';

void f(Stream stream) {
  // ignore: unused_local_variable
  var subscription = stream.listen((_) {});
}

常见修复方法

#

取消订阅

dart
import 'dart:async';

void f(Stream stream) {
  var subscription = stream.listen((_) {});
  subscription.cancel();
}

关闭 sinks

#

“Sink”的未关闭实例。

描述

#

当创建了 Sink 的实例但未调用方法 close 时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 sink 未被关闭

dart
import 'dart:io';

void g(File f) {
  var sink = f.openWrite();
  sink.write('x');
}

常见修复方法

#

关闭 sink

dart
import 'dart:io';

void g(File f) {
  var sink = f.openWrite();
  sink.write('x');
  sink.close();
}

集合方法不相关的类型

#

参数类型“{0}”与“{1}”不相关。

描述

#

当核心库中的任何一种方法以不适当类型的参数调用时,分析器会产生此诊断。这些方法是那些没有为参数提供足够具体类型的,以允许正常的类型检查来捕获错误的方法。

检查的参数是

  • Iterable<E>.contains 的参数应与 E 相关
  • List<E>.remove 的参数应与 E 相关
  • Map<K, V>.containsKey 的参数应与 K 相关
  • Map<K, V>.containsValue 的参数应与 V 相关
  • Map<K, V>.remove 的参数应与 K 相关
  • Map<K, V>.[] 的参数应与 K 相关
  • Queue<E>.remove 的参数应与 E 相关
  • Set<E>.lookup 的参数应与 E 相关
  • Set<E>.remove 的参数应与 E 相关

示例

#

以下代码会产生此诊断,因为 contains 的参数是一个 String,它不可赋值给 int,列表 l 的元素类型

dart
bool f(List<int> l)  => l.contains('1');

常见修复方法

#

如果元素类型是正确的,则更改参数以具有相同的类型

dart
bool f(List<int> l)  => l.contains(1);

如果参数类型是正确的,则更改元素类型

dart
bool f(List<String> l)  => l.contains('1');

常量标识符名称

#

常量名“{0}”不是 lowerCamelCase 标识符。

描述

#

当常量的名称不遵循 lowerCamelCase 命名约定时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为顶级变量的名称不是 lowerCamelCase 标识符

dart
const EMPTY_STRING = '';

常见修复方法

#

重写名称以遵循 lowerCamelCase 命名约定

dart
const emptyString = '';

finally 代码块中的控制流

#

在“finally”子句中使用“{0}”。

描述

#

finally 子句包含 returnbreakcontinue 语句时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为在 finally 块内部有一个 return 语句

dart
int f() {
  try {
    return 1;
  } catch (e) {
    print(e);
  } finally {
    return 0;
  }
}

常见修复方法

#

如果不需要该语句,则删除该语句,如果该块为空,则删除 finally 子句

dart
int f() {
  try {
    return 1;
  } catch (e) {
    print(e);
  }
}

如果需要该语句,则将该语句移动到 finally 块外部

dart
int f() {
  try {
    return 1;
  } catch (e) {
    print(e);
  }
  return 0;
}

流控制结构中的花括号

#

{0} 中的语句应包含在块中。

描述

#

当控制结构(ifforwhiledo 语句)具有除块之外的语句时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 then 语句未包含在块中

dart
int f(bool b) {
  if (b)
    return 1;
  return 0;
}

常见修复方法

#

在应为块的语句周围添加大括号

dart
int f(bool b) {
  if (b) {
    return 1;
  }
  return 0;
}

悬挂的库文档注释

#

悬空的库文档注释。

描述

#

当看起来是库文档的文档注释之后没有跟 library 指令时,分析器会产生此诊断。更具体地说,当文档注释出现在库中的第一个指令之前时(假设它不是 library 指令),或者在第一个顶级声明之前,并与声明之间隔着一个或多个空行时,会产生此诊断。

示例

#

以下代码会产生此诊断,因为在第一个 import 指令之前有一个文档注释

dart
/// This is a great library.
import 'dart:core';

以下代码会产生此诊断,因为在第一个类声明之前有一个文档注释,但注释和声明之间有一个空行。

dart
/// This is a great library.

class C {}

常见修复方法

#

如果注释是库文档,则添加一个没有名称的 library 指令

dart
/// This is a great library.
library;

import 'dart:core';

如果注释是以下声明的文档,则删除空行

dart
/// This is a great library.
class C {}

依赖于引用的包

#

导入的包“{0}”不是导入包的依赖项。

描述

#

当包导入引用未在 pubspec.yaml 文件中指定的包时,分析器会产生此诊断。

显式依赖于您引用的包可确保它们始终存在,并允许您对它们施加依赖约束,以防止破坏性更改。

示例

#

给定一个包含以下内容的 pubspec.yaml 文件

yaml
dependencies:
  meta: ^3.0.0

以下代码会产生此诊断,因为没有对包 a 的依赖

dart
import 'package:a/a.dart';

常见修复方法

#

依赖项应该是常规依赖项还是 dev 依赖项取决于包是从公共库(libbin 下的库)引用,还是仅从私有库(例如 test 下的库)引用。

如果包至少从一个公共库引用,则在 pubspec.yaml 文件中的 dependencies 字段下添加对该包的常规依赖项

yaml
dependencies:
  a: ^1.0.0
  meta: ^3.0.0

如果包仅从私有库引用,则在 pubspec.yaml 文件中的 dev_dependencies 字段下添加对该包的 dev 依赖项

yaml
dependencies:
  meta: ^3.0.0
dev_dependencies:
  a: ^1.0.0

空的 catch 代码块

#

空的 catch 块。

描述

#

catch 子句中的块为空时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 catch 块为空

dart
void f() {
  try {
    print('Hello');
  } catch (exception) {}
}

常见修复方法

#

如果异常不应被忽略,则添加代码来处理异常

dart
void f() {
  try {
    print('We can print.');
  } catch (exception) {
    print("We can't print.");
  }
}

如果异常旨在被忽略,则添加注释解释原因

dart
void f() {
  try {
    print('We can print.');
  } catch (exception) {
    // Nothing to do.
  }
}

如果异常旨在被忽略并且没有任何好的理由解释原因,则重命名异常参数

dart
void f() {
  try {
    print('We can print.');
  } catch (_) {}
}

空的构造函数体

#

空的构造函数体应使用“;”而不是“{}”编写。

描述

#

当构造函数具有空的块体时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 C 的构造函数具有一个空的块体

dart
class C {
  C() {}
}

常见修复方法

#

用分号替换块

dart
class C {
  C();
}

空语句

#

不必要的空语句。

描述

#

当找到空语句时,分析器会产生此诊断。

示例

#

以下代码会产生此诊断,因为 while 循环控制的语句是一个空语句

dart
void f(bool condition) {
  while (condition);
    g();
}

void g() {}

常见修复方法

#

如果没有需要控制的语句,则删除空语句和它所属的控制结构(注意删除的任何其他代码是否具有需要保留的副作用)

dart
void f(bool condition) {
  g();
}

void g() {}

如果没有需要控制的语句,但由于其他原因仍然需要控制结构,则用块替换空语句,使代码的结构更清晰

dart
void f(bool condition) {
  while (condition) {}
  g();
}

void g() {}

如果有需要控制的语句,则删除空语句并调整代码,使适当的语句受到控制,可能需要添加块

dart
void f(bool condition) {
  while (condition) {
    g();
  }
}

void g() {}

文件名

#

文件名“{0}”不是 lower_case_with_underscores 标识符。

描述

#

.dart 文件的名称未使用 lower_case_with_underscores 时,分析器会产生此诊断。

示例

#

名为 SliderMenu.dart 的文件会产生此诊断,因为文件名使用了 UpperCamelCase 约定。

常见修复方法

#

重命名文件以使用 lower_case_with_underscores 约定,例如 slider_menu.dart

hash 和 equals 方法

#

缺少“{0}”的相应覆盖。

描述

#

当类或 mixin 覆盖了 == 的定义但没有覆盖 hashCode 的定义,或者相反地覆盖了 hashCode 的定义但没有覆盖 == 的定义时,分析器会产生此诊断。

对于常见的哈希映射实现要正常运行,对象的 == 运算符和 hashCode 属性都必须一致。因此,当覆盖任一方法时,都应覆盖两者。

示例

#

以下代码会产生此诊断,因为类 C 覆盖了 == 运算符,但没有覆盖 getter hashCode

dart
class C {
  final int value;

  C(this.value);

  @override
  bool operator ==(Object other) =>
      other is C &&
      other.runtimeType == runtimeType &&
      other.value == value;
}

常见修复方法

#

如果需要覆盖其中一个成员,则添加另一个成员的覆盖

dart
class C {
  final int value;

  C(this.value);

  @override
  bool operator ==(Object other) =>
      other is C &&
      other.runtimeType == runtimeType &&
      other.value == value;

  @override
  int get hashCode => value.hashCode;
}

如果不需要覆盖任何一个成员,则删除不必要的覆盖

dart
class C {
  final int value;

  C(this.value);
}

实现导入

#

导入另一个包的“lib/src”目录中的库。

描述

#

当 import 引用了位于不同包的 lib/src 目录内的库时,分析器会产生此诊断,这违反了 pub 包的约定

示例

#

以下代码(假设它不是 ffi 包的一部分)会产生此诊断,因为正在导入的库位于顶层 src 目录内

dart
import 'package:ffi/src/allocation.dart';

常见修复方法

#

如果正在导入的库包含公共 API 的一部分的代码,则导入导出公共 API 的公共库

dart
import 'package:ffi/ffi.dart';

如果正在导入的库不是包的公共 API 的一部分,则要么找到一种不同的方法来实现您的目标(假设这是可能的),要么提出一个 issue,要求包作者使其成为公共 API 的一部分。

隐式调用 tear-off

#

“call”方法的隐式 tear-off。

描述

#

当具有 call 方法的对象被分配给函数类型变量时,分析器会产生此诊断,隐式 tear-off 了 call 方法。

示例

#

以下代码会产生此诊断,因为 Callable 的实例被传递给期望 Function 的函数

dart
class Callable {
  void call() {}
}

void callIt(void Function() f) {
  f();
}

void f() {
  callIt(Callable());
}

常见修复方法

#

显式 tear-off call 方法

dart
class Callable {
  void call() {}
}

void callIt(void Function() f) {
  f();
}

void f() {
  callIt(Callable().call);
}

使用 JS 互操作类型的无效运行时检查

#

从“{0}”到“{1}”的类型转换将 Dart 值转换为 JS 互操作类型,这可能不是平台一致的。

从“{0}”到“{1}”的类型转换将 JS 互操作值转换为 Dart 类型,这可能不是平台一致的。

从“{0}”到“{1}”的类型转换将 JS 互操作值转换为不兼容的 JS 互操作类型,这可能不是平台一致的。

“{0}”和“{1}”之间的运行时检查检查 Dart 值是否为 JS 互操作类型,这可能不是平台一致的。

“{0}”和“{1}”之间的运行时检查检查 JS 互操作值是否为 Dart 类型,这可能不是平台一致的。

“{0}”和“{1}”之间的运行时检查涉及两个 JS 互操作类型之间可能不是平台一致的非平凡运行时检查。

'{0}' 和 '{1}' 之间的运行时检查涉及到 JS 互操作值和不相关的 JS 互操作类型之间的运行时检查,这将始终为真,并且不会检查底层类型。

描述

#

is 测试具有以下任一情况时,分析器会产生此诊断信息:

  • 右侧是 JS 互操作类型,无论是直接使用还是作为另一个类型的类型参数,或
  • 左侧是 JS 互操作值。

示例

#

以下代码会产生此诊断信息,因为 JS 互操作类型 JSBoolean 位于 is 测试的右侧

dart
import 'dart:js_interop';

bool f(Object b) => b is JSBoolean;

以下代码会产生此诊断信息,因为 JS 互操作类型 JSString 被用作 is 测试右侧的类型参数

dart
import 'dart:js_interop';

bool f(List<Object> l) => l is List<JSString>;

以下代码会产生此诊断信息,因为 JS 互操作值 a 位于 is 测试的左侧

dart
import 'dart:js_interop';

bool f(JSAny a) => a is String;

常见修复方法

#

使用 JS 互操作助手(例如 isA)来检查 JS 互操作值的底层类型

dart
import 'dart:js_interop';

void f(Object b) => b.jsify()?.isA<JSBoolean>();

无效地使用 doNotSubmit 成员

#

不应将 '{0}' 的用法提交到源代码控制。

描述

#

当使用 @doNotSubmit 注释的成员在同样使用 @doNotSubmit 注释的成员声明之外被引用时,分析器会产生此诊断信息。

示例

#

给定一个文件 a.dart,其中包含以下声明

dart
import 'package:meta/meta.dart';

@doNotSubmit
void emulateCrash() { /* ... */ }

以下代码会产生此诊断信息,因为声明在同样使用 @doNotSubmit 注释的成员之外被引用

dart
import 'a.dart';

void f() {
  emulateCrash();
}

常见修复方法

#

最常见的情况是,当本地测试完成后,应删除对该成员的引用。

如果在该成员之上构建其他功能,也请使用 @doNotSubmit 注释新添加的成员

dart
import 'package:meta/meta.dart';

import 'a.dart';

@doNotSubmit
void emulateCrashWithOtherFunctionality() {
  emulateCrash();
  // do other things.
}

库注解

#

此注解应附加到库指令。

描述

#

当应用于整个库的注解未与 library 指令关联时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为应用于整个库的 TestOn 注解与 import 指令而不是 library 指令关联

dart
@TestOn('browser')

import 'package:test/test.dart';

void main() {}

常见修复方法

#

将注解与 library 指令关联,必要时添加一个

dart
@TestOn('browser')
library;

import 'package:test/test.dart';

void main() {}

库名称

#

库名称 '{0}' 不是 lower_case_with_underscores 标识符。

描述

#

当库的名称未使用 lower_case_with_underscores 命名约定时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为库名称 libraryName 不是 lower_case_with_underscores 标识符

dart
library libraryName;

常见修复方法

#

如果不需要库名称,则删除库名称

dart
library;

如果需要库名称,则将其转换为使用 lower_case_with_underscores 命名约定

dart
library library_name;

库前缀

#

前缀 '{0}' 不是 lower_case_with_underscores 标识符。

描述

#

当导入前缀未使用 lower_case_with_underscores 命名约定时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为前缀 ffiSupport 不是 lower_case_with_underscores 标识符

dart
import 'package:ffi/ffi.dart' as ffiSupport;

常见修复方法

#

将前缀转换为使用 lower_case_with_underscores 命名约定

dart
import 'package:ffi/ffi.dart' as ffi_support;

公共 API 中的库私有类型

#

在公共 API 中无效地使用了私有类型。

描述

#

当库的公共 API 中引用了不属于该库公共 API 的类型时,分析器会产生此诊断信息。

在公共 API 中使用私有类型可能会使 API 在定义库之外无法使用。

示例

#

以下代码会产生此诊断信息,因为公共函数 f 的参数 c 具有库私有类型 (_C)

dart
void f(_C c) {}

class _C {}

常见修复方法

#

如果 API 不需要定义库之外使用,则将其设为私有

dart
void _f(_C c) {}

class _C {}

如果 API 需要成为库的公共 API 的一部分,则使用不同的公共类型,或者将引用的类型设为公共类型

dart
void f(C c) {}

class C {}

仅字面量的布尔表达式

#

布尔表达式具有常量值。

描述

#

if 或循环语句中条件的值已知始终为 true 或始终为 false 时,分析器会产生此诊断信息。对于条件为布尔字面量 truewhile 循环,则会进行例外处理。

示例

#

以下代码会产生此诊断信息,因为条件将始终求值为 true

dart
void f() {
  if (true) {
    print('true');
  }
}

该 lint 将评估由常量组成的表达式子集,因此以下代码也会产生此诊断信息,因为条件将始终求值为 false

dart
void g(int i) {
  if (1 == 0 || 3 > 4) {
    print('false');
  }
}

常见修复方法

#

如果条件错误,则更正条件,使其值在编译时无法得知

dart
void g(int i) {
  if (i == 0 || i > 4) {
    print('false');
  }
}

如果条件正确,则简化代码以不评估条件

dart
void f() {
  print('true');
}

List 中没有相邻的字符串

#

不要在列表字面量中使用相邻的字符串。

描述

#

当列表字面量中有两个相邻的字符串字面量时,分析器会产生此诊断信息。Dart 中相邻的字符串会连接在一起形成一个字符串,但意图可能是每个字符串都是列表中的单独元素。

示例

#

以下代码会产生此诊断信息,因为字符串 'a''b' 相邻

dart
List<String> list = ['a' 'b', 'c'];

常见修复方法

#

如果这两个字符串旨在成为列表的单独元素,则在它们之间添加逗号

dart
List<String> list = ['a', 'b', 'c'];

如果这两个字符串旨在成为单个连接的字符串,则手动合并字符串

dart
List<String> list = ['ab', 'c'];

或者使用 + 运算符连接字符串

dart
List<String> list = ['a' + 'b', 'c'];

没有重复的 case 值

#

case 子句 ('{0}') 的值等于较早的 case 子句 ('{1}') 的值。

描述

#

当同一个 switch 语句中的两个或多个 case 子句具有相同的值时,分析器会产生此诊断信息。

第一个之后的任何 case 子句都无法执行,因此具有重复的 case 子句会产生误导。

此诊断信息通常是由于拼写错误或常量值更改导致的。

示例

#

以下代码会产生此诊断信息,因为两个 case 子句具有相同的值 (1)

dart
// @dart = 2.14
void f(int v) {
  switch (v) {
    case 1:
      break;
    case 1:
      break;
  }
}

常见修复方法

#

如果其中一个子句应具有不同的值,则更改子句的值

dart
void f(int v) {
  switch (v) {
    case 1:
      break;
    case 2:
      break;
  }
}

如果值正确,则将语句合并为单个子句

dart
void f(int v) {
  switch (v) {
    case 1:
      break;
  }
}

库前缀没有前导下划线

#

库前缀 '{0}' 以下划线开头。

描述

#

当导入上声明的前缀名称以下划线开头时,分析器会产生此诊断信息。

库前缀本质上在声明库之外不可见,因此指示私有的前导下划线没有增加任何价值。

示例

#

以下代码会产生此诊断信息,因为前缀 _core 以下划线开头

dart
import 'dart:core' as _core;

常见修复方法

#

删除下划线

dart
import 'dart:core' as core;

局部标识符没有前导下划线

#

局部变量 '{0}' 以下划线开头。

描述

#

当局部变量的名称以下划线开头时,分析器会产生此诊断信息。

局部变量本质上在声明库之外不可见,因此指示私有的前导下划线没有增加任何价值。

示例

#

以下代码会产生此诊断信息,因为参数 _s 以下划线开头

dart
int f(String _s) => _s.length;

常见修复方法

#

删除下划线

dart
int f(String s) => s.length;

createState 中没有逻辑

#

不要在 'createState' 中放置任何逻辑。

描述

#

StatefulWidget 子类中的 createState 实现包含除返回调用零参数构造函数的结果之外的任何逻辑时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为构造函数调用带有参数

dart
import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  @override
  MyState createState() => MyState(0);
}

class MyState extends State {
  int x;

  MyState(this.x);
}

常见修复方法

#

重写代码,使 createState 不包含任何逻辑

dart
import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  @override
  MyState createState() => MyState();
}

class MyState extends State {
  int x = 0;

  MyState();
}

没有通配符变量使用

#

引用的标识符是通配符。

描述

#

当引用名称仅由下划线组成的参数或局部变量时,分析器会产生此诊断信息。此类名称将在未来版本的 Dart 语言中变为非绑定,从而使引用非法。

示例

#

以下代码会产生此诊断信息,因为参数名称由两个下划线组成

dart
// @dart = 3.6
void f(int __) {
  print(__);
}

以下代码会产生此诊断信息,因为局部变量的名称由单个下划线组成

dart
// @dart = 3.6
void f() {
  int _ = 0;
  print(_);
}

常见修复方法

#

如果要引用变量或参数,则为其命名,使其至少包含一个非下划线字符

dart
void f(int p) {
  print(p);
}

如果不想引用变量或参数,则将引用替换为不同的表达式

dart
void f() {
  print(0);
}

非常量标识符名称

#

变量名 '{0}' 不是 lowerCamelCase 标识符。

描述

#

当未声明为 const 的类成员、顶层声明、变量、参数、命名参数或命名构造函数的名称未使用 lowerCamelCase 约定 时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为顶层变量 Count 未以小写字母开头

dart
var Count = 0;

常见修复方法

#

更改声明中的名称以遵循 lowerCamelCase 约定

dart
var count = 0;

可空类型参数上的 null 检查

#

不应在类型可能是可空类型参数的变量上使用空值检查运算符。

描述

#

当在类型为 T? 的变量上使用空值检查运算符时,分析器会产生此诊断信息,其中 T 是允许类型参数为空的类型参数(要么没有边界,要么具有可为空的边界)。

给定一个具有可空边界的泛型类型参数 T,当处理类型为 T? 的变量时,很容易引入错误的空值检查。具体来说,拥有 T? x; 并想断言 x 已设置为类型 T 的有效值的情况并不少见。一个常见的错误是使用 x! 这样做。这几乎总是错误的,因为如果 T 是可空类型,则 x 可能有效地将 null 作为类型 T 的值。

示例

#

以下代码会产生此诊断信息,因为 t 的类型为 T?,并且 T 允许类型参数为空(因为它没有 extends 子句)

dart
T f<T>(T? t) => t!;

常见修复方法

#

使用类型参数转换变量

dart
T f<T>(T? t) => t as T;

重写的字段

#

字段覆盖从 '{0}' 继承的字段。

描述

#

当一个类定义一个覆盖超类字段的字段时,分析器会产生此诊断信息。

用另一个字段覆盖一个字段会导致对象具有两个不同的字段,但由于字段具有相同的名称,因此在给定的作用域中只能引用其中一个字段。这可能会导致混淆,即对其中一个字段的引用可能会被误认为是另一个字段的引用。

示例

#

以下代码会产生此诊断信息,因为 B 中的字段 f 遮蔽了 A 中的字段 f

dart
class A {
  int f = 1;
}

class B extends A {
  @override
  int f = 2;
}

常见修复方法

#

如果这两个字段表示相同的属性,则从子类中删除该字段

dart
class A {
  int f = 1;
}

class B extends A {}

如果这两个字段应有所不同,则重命名其中一个字段

dart
class A {
  int f = 1;
}

class B extends A {
  int g = 2;
}

如果这两个字段在某种程度上相关,但不能相同,则找到实现所需语义的不同方法。

包名称

#

包名 '{0}' 不是 lower_case_with_underscores 标识符。

描述

#

当包的名称未使用 lower_case_with_underscores 命名约定时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为包的名称使用了 lowerCamelCase 命名约定

yaml
name: somePackage

常见修复方法

#

使用 lower_case_with_underscores 命名约定重写包的名称

yaml
name: some_package

带有包前缀的库名称

#

库名称不是以包名称为前缀的点分隔路径。

描述

#

当库的名称不遵循这些准则时,分析器会产生此诊断信息

  • 所有库名称都以包名称为前缀。
  • 使入口库与包的名称相同。
  • 对于包中的所有其他库,在包名称后添加库的 Dart 文件的点分隔路径。
  • 对于 lib 下的库,省略顶层目录名称。

例如,给定一个名为 my_package 的包,以下是包中各种文件的库名称

示例

#

假设包含以下代码的文件不在名为 special.dart 的文件中,该文件位于名为 something 的包的 lib 目录中(这将是该规则的例外),则分析器会产生此诊断信息,因为库的名称不符合上述准则

dart
library something.special;

常见修复方法

#

更改库的名称以符合准则。

优先使用相邻字符串连接

#

字符串字面量不应通过 '+' 运算符连接。

描述

#

当使用 + 运算符连接两个字符串字面量时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为两个字符串字面量正在使用 + 运算符连接

dart
var s = 'a' + 'b';

常见修复方法

#

删除运算符

dart
var s = 'a' 'b';

优先使用集合字面量

#

不必要的构造函数调用。

描述

#

当使用构造函数创建列表、映射或集合,但字面量会产生相同结果时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 Map 的构造函数正用于创建可以使用字面量创建的映射

dart
var m = Map<String, String>();

常见修复方法

#

使用字面量表示

dart
var m = <String, String>{};

优先使用条件赋值

#

'if' 语句可以替换为可空感知赋值。

描述

#

当对变量的赋值以变量是否具有值 null 为条件,并且可以使用 ??= 运算符代替时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为将参数 snull 进行比较,以确定是否分配不同的值

dart
int f(String? s) {
  if (s == null) {
    s = '';
  }
  return s.length;
}

常见修复方法

#

使用 ??= 运算符而不是显式的 if 语句

dart
int f(String? s) {
  s ??= '';
  return s.length;
}

优先使用 const 构造函数

#

使用 'const' 和构造函数以提高性能。

描述

#

当 const 构造函数的调用前面既没有 const 也没有在 常量上下文 中时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 const 构造函数的调用既没有以 const 为前缀,也没有在 常量上下文

dart
class C {
  const C();
}

C c = C();

常见修复方法

#

如果可以将上下文设为 常量上下文,则这样做

dart
class C {
  const C();
}

const C c = C();

如果无法将上下文设为 常量上下文,则在构造函数调用之前添加 const

dart
class C {
  const C();
}

C c = const C();

优先在不可变类中使用 const 构造函数

#

'@immutable' 类中的构造函数应声明为 'const'。

描述

#

当在具有 @immutable 注解的类中找到非 const 构造函数时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 C 中的构造函数未声明为 const,即使 C 具有 @immutable 注解

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  C(this.f);
}

常见修复方法

#

如果该类确实旨在是不可变的,则将 const 修饰符添加到构造函数

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  const C(this.f);
}

如果该类是可变的,则删除 @immutable 注解

dart
class C {
  final f;

  C(this.f);
}

优先使用 const 声明

#

对于初始化为常量值的 final 变量,请使用 'const'。

描述

#

当顶层变量、静态字段或局部变量标记为 final 并且初始化为常量值时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为顶层变量 v 既是 final 又初始化为常量值

dart
final v = const <int>[];

以下代码会产生此诊断信息,因为静态字段 f 既是 final 又初始化为常量值

dart
class C {
  static final f = const <int>[];
}

以下代码会产生此诊断信息,因为局部变量 v 既是 final 又初始化为常量值

dart
void f() {
  final v = const <int>[];
  print(v);
}

常见修复方法

#

将关键字 final 替换为 const,并从初始化程序中删除 const

dart
class C {
  static const f = <int>[];
}

优先使用 const 字面量创建不可变对象

#

将 'const' 字面量用作 '@immutable' 类的构造函数的参数。

描述

#

当将非 const 列表、映射或集合字面量作为参数传递给在用 @immutable 注解的类中声明的构造函数时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为列表字面量 ([1]) 正在传递给不可变类中的构造函数,但不是常量列表

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  const C(this.f);
}

C c = C([1]);

常见修复方法

#

如果可以将上下文设为 常量上下文,则这样做

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  const C(this.f);
}

const C c = C([1]);

如果上下文不能设为 常量上下文,但可以使用 const 调用构造函数,则在构造函数调用之前添加 const

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  const C(this.f);
}

C c = const C([1]);

如果上下文不能设为 常量上下文,并且无法使用 const 调用构造函数,则在集合字面量之前添加关键字 const

dart
import 'package:meta/meta.dart';

@immutable
class C {
  final f;

  const C(this.f);
}

C c = C(const [1]);

优先使用 contains 方法

#

始终为 'false',因为 'indexOf' 始终大于或等于 -1。

始终为 'true',因为 'indexOf' 始终大于或等于 -1。

不必要地使用 'indexOf' 来测试是否包含。

描述

#

当使用方法 indexOf 并且结果仅与 -10 进行比较,且语义等同于使用 contains 时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 if 语句中的条件正在检查列表是否包含该字符串

dart
void f(List<String> l, String s) {
  if (l.indexOf(s) < 0) {
    // ...
  }
}

常见修复方法

#

改用 contains,必要时对条件取反

dart
void f(List<String> l, String s) {
  if (l.contains(s)) {
    // ...
  }
}

优先使用双引号

#

不必要地使用单引号。

描述

#

当字符串字面量使用单引号 (') 时,如果可以使用双引号 (") 而无需额外的转义并且不损害可读性,则分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为字符串字面量使用了单引号,但没有必要

dart
void f(String name) {
  print('Hello $name');
}

常见修复方法

#

使用双引号代替单引号

dart
void f(String name) {
  print("Hello $name");
}

优先使用 final 字段

#

私有字段 {0} 可以是 'final'。

描述

#

当私有字段仅赋值一次时,分析器会产生此诊断信息。该字段可以在多个构造函数中初始化,但仍然会被标记,因为这些构造函数中只能运行一个。

示例

#

以下代码会产生此诊断信息,因为字段 _f 仅赋值一次,在字段的初始化程序中

dart
class C {
  int _f = 1;

  int get f => _f;
}

常见修复方法

#

将字段标记为 final

dart
class C {
  final int _f = 1;

  int get f => _f;
}

优先使用 for 元素而不是 mapFromIterable

#

从可迭代对象构建映射时,使用 'for' 元素。

描述

#

当使用 Map.fromIterable 构建可以使用 for 元素构建的映射时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 fromIterable 正在用于构建可以使用 for 元素构建的映射

dart
void f(Iterable<String> data) {
  Map<String, int>.fromIterable(
    data,
    key: (element) => element,
    value: (element) => element.length,
  );
}

常见修复方法

#

使用 for 元素构建映射

dart
void f(Iterable<String> data) {
  <String, int>{
    for (var element in data)
      element: element.length
  };
}

优先使用函数声明而不是变量

#

使用函数声明而不是变量赋值将函数绑定到名称。

描述

#

当闭包被赋值给局部变量,并且该局部变量在任何地方都没有被重新赋值时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为局部变量 f 被初始化为闭包,并且没有被赋予任何其他值

dart
void g() {
  var f = (int i) => i * 2;
  f(1);
}

常见修复方法

#

将局部变量替换为局部函数

dart
void g() {
  int f(int i) => i * 2;
  f(1);
}

优先使用泛型函数类型别名

#

在 'typedef' 中使用泛型函数类型语法。

描述

#

当 typedef 使用较旧的函数类型别名语法编写时,其中声明的名称嵌入在函数类型中,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为它使用了较旧的语法

dart
typedef void F<T>();

常见修复方法

#

重写 typedef 以使用较新的语法

dart
typedef F<T> = void Function();

优先使用 if-null 运算符

#

在测试 'null' 时,使用 '??' 运算符而不是 '?:'。

描述

#

当条件表达式(使用 ?: 运算符)用于在局部变量为 null 时选择不同的值时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为变量 s 正与 null 进行比较,以便在 snull 时可以返回不同的值

dart
String f(String? s) => s == null ? '' : s;

常见修复方法

#

改用 if-null 运算符

dart
String f(String? s) => s ?? '';

优先使用初始化形式参数

#

使用初始化形式参数将参数赋值给字段。

描述

#

当构造函数参数用于初始化字段而没有修改时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为参数 c 仅用于设置字段 c

dart
class C {
  int c;

  C(int c) : this.c = c;
}

常见修复方法

#

使用初始化形式参数来初始化字段

dart
class C {
  int c;

  C(this.c);
}

优先使用内联 adds 方法

#

列表项的添加可以内联。

多个列表项的添加可以内联。

描述

#

当在列表字面量上调用方法 addaddAll 时,如果要添加的元素可以包含在列表字面量中,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 add 方法正在用于添加 b,而它可以直接包含在列表字面量中

dart
List<String> f(String a, String b) {
  return [a]..add(b);
}

以下代码会产生此诊断信息,因为 addAll 方法正在用于添加 b 的元素,而它可以直接包含在列表字面量中

dart
List<String> f(String a, List<String> b) {
  return [a]..addAll(b);
}

常见修复方法

#

如果正在使用 add 方法,则将参数作为列表的元素,并删除调用

dart
List<String> f(String a, String b) {
  return [a, b];
}

如果正在使用 addAll 方法,则在参数上使用展开运算符以将其元素添加到列表,并删除调用

dart
List<String> f(String a, List<String> b) {
  return [a, ...b];
}

优先使用插值而不是组合字符串

#

使用插值来组合字符串和值。

描述

#

当字符串字面量和计算字符串正在使用 + 运算符连接时,但字符串插值可以达到相同的结果,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为字符串 s 使用 + 运算符与其他字符串连接

dart
String f(String s) {
  return '(' + s + ')';
}

常见修复方法

#

使用字符串插值

dart
String f(List<String> l) {
  return '(${l[0]}, ${l[1]})';
}

优先使用 isEmpty 属性

#

比较始终为 'false',因为长度始终大于或等于 0。

比较始终为 'true',因为长度始终大于或等于 0。

使用 'isEmpty' 而不是 'length' 来测试集合是否为空。

使用 'isNotEmpty' 而不是 'length' 来测试集合是否为空。

描述

#

当调用 Iterable.lengthMap.length 的结果与零 (0) 进行相等性比较时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为正在检查调用 length 的结果是否等于零

dart
int f(Iterable<int> p) => p.length == 0 ? 0 : p.first;

常见修复方法

#

length 的使用替换为使用 isEmptyisNotEmpty

dart
void f(Iterable<int> p) => p.isEmpty ? 0 : p.first;

优先使用 isNotEmpty 属性

#

使用 'isNotEmpty' 而不是对 'isEmpty' 的结果取反。

描述

#

当调用 Iterable.isEmptyMap.isEmpty 的结果被取反时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为调用 Iterable.isEmpty 的结果被取反

dart
void f(Iterable<int> p) => !p.isEmpty ? p.first : 0;

常见修复方法

#

重写代码以使用 isNotEmpty

dart
void f(Iterable<int> p) => p.isNotEmpty ? p.first : 0;

优先使用 is! 运算符

#

使用 'is!' 运算符而不是对 'is' 运算符的值取反。

描述

#

当使用前缀 ! 运算符对 is 测试的结果取反时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为使用前缀 ! 运算符对测试 o 是否为 String 的结果取反

dart
String f(Object o) {
  if (!(o is String)) {
    return o.toString();
  }
  return o;
}

常见修复方法

#

改用 is! 运算符

dart
String f(Object o) {
  if (o is! String) {
    return o.toString();
  }
  return o;
}

优先使用 Iterable.whereType 方法

#

使用 'whereType' 选择给定类型的元素。

描述

#

当方法 Iterable.where 正在用于根据元素的类型进行过滤时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为方法 where 正在用于仅访问可迭代对象中的字符串

dart
Iterable<Object> f(Iterable<Object> p) => p.where((e) => e is String);

常见修复方法

#

重写代码以使用 whereType

dart
Iterable<String> f(Iterable<Object> p) => p.whereType<String>();

这也可能允许您收紧代码中的类型或删除其他类型检查。

优先使用空感知运算符

#

使用可空感知运算符 '?.' 而不是显式的 'null' 比较。

描述

#

当与 null 的比较用于保护成员引用,并且当受保护的目标为 null 时使用 null 作为结果时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 length 的调用受 null 比较保护,即使默认值为 null

dart
int? f(List<int>? p) {
  return p == null ? null : p.length;
}

常见修复方法

#

改用可空感知访问运算符

dart
int? f(List<int>? p) {
  return p?.length;
}

优先使用相对导入

#

对于 'lib' 目录中的文件,使用相对导入。

描述

#

lib 目录内的库中的 import 使用 package: URI 引用同一包中的另一个库时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为它在可以使用相对 URI 时使用了 package: URI

dart
import 'package:my_package/bar.dart';

常见修复方法

#

使用相对 URI 导入库

dart
import 'bar.dart';

优先使用单引号

#

不必要地使用双引号。

描述

#

当字符串字面量使用双引号 (") 时,如果可以使用单引号 (') 而无需额外的转义并且不损害可读性,则分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为字符串字面量使用了双引号,但没有必要

dart
void f(String name) {
  print("Hello $name");
}

常见修复方法

#

使用单引号代替双引号

dart
void f(String name) {
  print('Hello $name');
}

优先为未初始化的变量声明类型

#

未初始化的字段应具有显式类型注解。

未初始化的变量应具有显式类型注解。

描述

#

当没有初始化程序的变量没有显式类型注解时,分析器会产生此诊断信息。

如果没有类型注解或初始化程序,变量的类型为 dynamic,这允许将任何值分配给变量,通常会导致难以识别的错误。

示例

#

以下代码会产生此诊断信息,因为变量 r 既没有类型注解也没有初始化程序

dart
Object f() {
  var r;
  r = '';
  return r;
}

常见修复方法

#

如果可以初始化变量,则添加初始化程序

dart
Object f() {
  var r = '';
  return r;
}

如果无法初始化变量,则添加显式类型注解

dart
Object f() {
  String r;
  r = '';
  return r;
}

优先使用 void 而不是 null

#

不必要地使用类型 'Null'。

描述

#

当在 void 将是有效选择的位置使用 Null 时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为函数 f 声明为返回 null(在未来的某个时间)

dart
Future<Null> f() async {}

常见修复方法

#

Null 的使用替换为使用 void

dart
Future<void> f() async {}

提供弃用消息

#

缺少弃用消息。

描述

#

当使用 deprecated 注解而不是 Deprecated 注解时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为函数 f 使用 deprecated 注解

dart
@deprecated
void f() {}

常见修复方法

#

将代码转换为使用较长的形式

dart
@Deprecated('Use g instead. Will be removed in 4.0.0.')
void f() {}

递归 getter

#

getter '{0}' 递归地返回自身。

描述

#

当 getter 调用自身时,分析器会产生此诊断信息,从而导致无限循环。

示例

#

以下代码会产生此诊断信息,因为 getter count 调用自身

dart
class C {
  int _count = 0;

  int get count => count;
}

常见修复方法

#

更改 getter 以不调用自身

dart
class C {
  int _count = 0;

  int get count => _count;
}

安全的 pubspec URL

#

不应使用 '{0}' 协议,因为它不安全。

描述

#

pubspec.yaml 文件中的 URL 使用不安全的方案(例如 http)时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 pubspec.yaml 文件包含 http URL

yaml
dependencies:
  example: any
    repository: http://github.com/dart-lang/example

常见修复方法

#

更改 URL 的方案以使用安全方案,例如 https

yaml
dependencies:
  example: any
    repository: https://github.com/dart-lang/example

使用 SizedBox 用于空白

#

使用 'SizedBox' 将空白添加到布局中。

描述

#

当仅使用 height 和/或 width 参数创建 Container 时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 Container 仅具有 width 参数

dart
import 'package:flutter/material.dart';

Widget buildRow() {
  return Row(
    children: <Widget>[
      const Text('...'),
      Container(
        width: 4,
        child: Text('...'),
      ),
      const Expanded(
        child: Text('...'),
      ),
    ],
  );
}

常见修复方法

#

Container 替换为相同尺寸的 SizedBox

dart
import 'package:flutter/material.dart';

Widget buildRow() {
  return Row(
    children: <Widget>[
      Text('...'),
      SizedBox(
        width: 4,
        child: Text('...'),
      ),
      Expanded(
        child: Text('...'),
      ),
    ],
  );
}

SizedBox 收缩/扩展

#

使用 'SizedBox.{0}' 以避免需要指定 'height' 和 'width'。

描述

#

SizedBox 构造函数调用将 heightwidth 的值都指定为 0.0double.infinity 时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 heightwidth 均为 0.0

dart
import 'package:flutter/material.dart';

Widget build() {
  return SizedBox(
    height: 0.0,
    width: 0.0,
    child: const Text(''),
  );
}

以下代码会产生此诊断信息,因为 heightwidth 均为 double.infinity

dart
import 'package:flutter/material.dart';

Widget build() {
  return SizedBox(
    height: double.infinity,
    width: double.infinity,
    child: const Text(''),
  );
}

常见修复方法

#

如果两者均为 0.0,则使用 SizedBox.shrink

dart
import 'package:flutter/material.dart';

Widget build() {
  return SizedBox.shrink(
    child: const Text(''),
  );
}

如果两者均为 double.infinity,则使用 SizedBox.expand

dart
import 'package:flutter/material.dart';

Widget build() {
  return SizedBox.expand(
    child: const Text(''),
  );
}

斜线用于文档注释

#

对文档注释使用行尾形式 ('///')。

描述

#

当文档注释使用块注释样式(由 /***/ 分隔)时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 f 的文档注释使用了块注释样式

dart
/**
 * Example.
 */
void f() {}

常见修复方法

#

使用行尾注释样式

dart
/// Example.
void f() {}

最后排序子属性

#

'{0}' 参数应是 widget 构造函数调用中的最后一个参数。

描述

#

childchildren 参数不是 widget 类构造函数调用中的最后一个参数时,分析器会产生此诊断信息。如果 childchildren 参数之后的所有参数都是函数表达式,则会进行例外处理。

示例

#

以下代码会产生此诊断信息,因为 child 参数不是 Center 构造函数调用中的最后一个参数

dart
import 'package:flutter/material.dart';

Widget createWidget() {
  return Center(
    child: Text('...'),
    widthFactor: 0.5,
  );
}

常见修复方法

#

childchildren 参数移动到最后

dart
import 'package:flutter/material.dart';

Widget createWidget() {
  return Center(
    widthFactor: 0.5,
    child: Text('...'),
  );
}

首先排序构造函数

#

构造函数声明应在非构造函数声明之前。

描述

#

当构造函数声明前面有一个或多个非构造函数声明时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为 C 的构造函数出现在方法 m 之后

dart
class C {
  void m() {}

  C();
}

常见修复方法

#

将所有构造函数声明移动到任何其他声明之前

dart
class C {
  C();

  void m() {}
}

排序 pub 依赖

#

依赖项未按字母顺序排序。

描述

#

pubspec.yaml 文件中依赖项映射中的键未按字母顺序排序时,分析器会产生此诊断信息。检查的依赖项映射是 dependenciesdev_dependenciesdependency_overrides 映射。

示例

#

以下代码会产生此诊断信息,因为 dependencies 映射中的条目未排序

yaml
dependencies:
  path: any
  collection: any

常见修复方法

#

对条目进行排序

yaml
dependencies:
  collection: any
  path: any

首先排序未命名的构造函数

#

未命名构造函数的位置无效。

描述

#

当未命名构造函数出现在命名构造函数之后时,分析器会产生此诊断信息。

示例

#

以下代码会产生此诊断信息,因为未命名构造函数位于命名构造函数之后

dart
class C {
  C.named();

  C();
}

常见修复方法

#

将未命名构造函数移动到任何其他构造函数之前

dart
class C {
  C();

  C.named();
}

在 equals 方法中测试类型

#

在 '==' 中缺少 '{0}' 的类型测试。

描述

#

== 运算符的重写没有包含对参数值的类型测试时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 other 未进行类型测试

dart
class C {
  final int f;

  C(this.f);

  @override
  bool operator ==(Object other) {
    return (other as C).f == f;
  }
}

常见修复方法

#

执行 is 测试作为计算返回值的一部分

dart
class C {
  final int f;

  C(this.f);

  @override
  bool operator ==(Object other) {
    return other is C && other.f == f;
  }
}

在 finally 代码块中抛出异常

#

在 'finally' 代码块中使用 '{0}'。

描述

#

当在 finally 代码块内找到 throw 语句时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 finally 代码块内存在 throw 语句

dart
void f() {
  try {
    // ...
  } catch (e) {
    // ...
  } finally {
    throw 'error';
  }
}

常见修复方法

#

重写代码,使 throw 语句不在 finally 代码块内

dart
void f() {
  try {
    // ...
  } catch (e) {
    // ...
  }
  throw 'error';
}

类型初始化形式参数

#

不要不必要地为初始化形参添加类型注解。

描述

#

当初始化形参(this.x)或超类形参(super.x)的显式类型注解与其字段或重写形参相同时,分析器会生成此诊断信息。

如果构造函数形参使用 this.x 初始化字段,则该形参的类型隐式地与字段类型相同。如果构造函数形参使用 super.x 转发到超类构造函数,则该形参的类型隐式地与超类构造函数形参类型相同。

示例

#

以下代码会生成此诊断信息,因为形参 this.c 的显式类型与字段 c 相同

dart
class C {
  int c;

  C(int this.c);
}

以下代码会生成此诊断信息,因为形参 super.a 的显式类型与超类中的形参 a 相同

dart
class A {
  A(int a);
}

class B extends A {
  B(int super.a);
}

常见修复方法

#

从形参中移除类型注解

dart
class C {
  int c;

  C(this.c);
}

常量模式中的类型字面量

#

使用 'TypeName _' 而不是类型字面量。

描述

#

当类型字面量作为模式出现时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类型字面量被用作常量模式

dart
void f(Object? x) {
  if (x case num) {
    // ...
  }
}

常见修复方法

#

如果类型字面量旨在匹配给定类型的对象,则使用变量模式

dart
void f(Object? x) {
  if (x case num _) {
    // ...
  }
}

或对象模式

dart
void f(Object? x) {
  if (x case num()) {
    // ...
  }
}

如果类型字面量旨在匹配类型字面量本身,则将其写为常量模式

dart
void f(Object? x) {
  if (x case const (num)) {
    // ...
  }
}

未等待的 Future

#

此表达式计算的 'Future' 缺少 'await'。

描述

#

当从 async(或 async*)方法或函数内的调用返回 Future 实例,且该 future 既未被 await 也未传递给 unawaited 函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数 g 返回一个 future,但该 future 未被 await

dart
Future<void> f() async {
  g();
}

Future<int> g() => Future.value(0);

常见修复方法

#

如果 future 需要在后续代码执行之前完成,则在调用前添加 await

dart
Future<void> f() async {
  await g();
}

Future<int> g() => Future.value(0);

如果 future 不需要在后续代码执行之前完成,则将返回 Future 的调用包装在 unawaited 函数的调用中

dart
import 'dart:async';

Future<void> f() async {
  unawaited(g());
}

Future<int> g() => Future.value(0);

文档注释中意外的 HTML

#

尖括号将被解释为 HTML。

描述

#

当文档注释包含尖括号文本 (<...>) 但不是允许的例外情况之一时,分析器会生成此诊断信息。

此类文本会被 markdown 解释为 HTML 标签,这通常不是本意。

请参阅 lint 规则描述 以获取允许的例外情况列表。

示例

#

以下代码会生成此诊断信息,因为文档注释包含文本 <int>,但它不是允许的例外情况之一

dart
/// Converts a List<int> to a comma-separated String.
String f(List<int> l) => '';

常见修复方法

#

如果文本旨在成为代码跨度的一部分,则在代码周围添加反引号

dart
/// Converts a `List<int>` to a comma-separated String.
String f(List<int> l) => '';

如果文本旨在成为链接的一部分,则在代码周围添加方括号

dart
/// Converts a [List<int>] to a comma-separated String.
String f(List<int> l) => '';

如果文本旨在按原样打印,包括尖括号,则在尖括号前添加反斜杠转义符

dart
/// Converts a List\<int\> to a comma-separated String.
String f(List<int> l) => '';

字符串插值中不必要的大括号

#

字符串插值中不必要的花括号。

描述

#

当带有花括号的字符串插值用于插值简单标识符,且后面没有字母数字文本时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为插值元素 ${s} 使用了不必要的花括号

dart
String f(String s) {
  return '"${s}"';
}

常见修复方法

#

移除不必要的花括号

dart
String f(String s) {
  return '"$s"';
}

不必要的 const 关键字

#

不必要的 'const' 关键字。

描述

#

当在 常量上下文 中使用关键字 const 时,分析器会生成此诊断信息。该关键字不是必需的,因为它是隐含的。

示例

#

以下代码会生成此诊断信息,因为列表字面量中的关键字 const 是不需要的

dart
const l = const <int>[];

由于变量声明中的关键字 const,该列表隐式地是 const

常见修复方法

#

移除不必要的关键字

dart
const l = <int>[];

不必要的构造函数名称

#

不必要的 '.new' 构造函数名称。

描述

#

当对未命名构造函数的引用使用 .new 时,分析器会生成此诊断信息。唯一需要 .new 的地方是在构造函数拆分中。

示例

#

以下代码会生成此诊断信息,因为 .new 被用于引用不需要它的未命名构造函数

dart
var o = Object.new();

常见修复方法

#

移除不必要的 .new

dart
var o = Object();

不必要的 final 关键字

#

局部变量不应标记为 'final'。

描述

#

当局部变量被标记为 final 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为局部变量 c 被标记为 final

dart
void f(int a, int b) {
  final c = a + b;
  print(c);
}

常见修复方法

#

如果变量没有类型注解,则将 final 替换为 var

dart
void f(int a, int b) {
  var c = a + b;
  print(c);
}

如果变量有类型注解,则移除 final 修饰符

dart
void f(int a, int b) {
  int c = a + b;
  print(c);
}

不必要的 getter 和 setter

#

不必要地使用 getter 和 setter 包装字段。

描述

#

当 getter 和 setter 对返回和设置字段的值而没有任何额外处理时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为名为 c 的 getter/setter 对仅公开名为 _c 的字段

dart
class C {
  int? _c;

  int? get c => _c;

  set c(int? v) => _c = v;
}

常见修复方法

#

使字段公开并移除 getter 和 setter

dart
class C {
  int? c;
}

不必要的 ignore 注释

#

诊断信息 '{0}' 没有在此位置生成,因此不需要忽略它。

诊断信息 '{0}' 没有在此文件中生成,因此不需要忽略它。

描述

#

当指定忽略一个未生成的诊断信息时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 unused_local_variable 诊断信息未在被忽略的位置报告

dart
// ignore: unused_local_variable
void f() {}

常见修复方法

#

移除忽略注释

dart
void f() {}

不必要的 lambda 表达式

#

闭包应为 tear-off。

描述

#

当闭包(lambda)可以被 tear-off 替换时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为传递给 forEach 的闭包仅包含对函数 print 的调用,并使用闭包的参数

dart
void f(List<String> strings) {
  strings.forEach((string) {
    print(string);
  });
}

常见修复方法

#

将闭包替换为正在使用闭包调用的函数或方法的 tear-off

dart
void f(List<String> strings) {
  strings.forEach(print);
}

不必要的 late 关键字

#

不必要的 'late' 修饰符。

描述

#

当带有初始化器的顶层变量或静态字段被标记为 late 时,分析器会生成此诊断信息。顶层变量和静态字段隐式地是 late 的,因此不需要显式标记。

示例

#

以下代码会生成此诊断信息,因为静态字段 c 具有修饰符 late,即使它有一个初始化器

dart
class C {
  static late String c = '';
}

常见修复方法

#

移除关键字 late

dart
class C {
  static String c = '';
}

不必要的库名称

#

库名称不是必需的。

描述

#

library 指令指定名称时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 library 指令包含名称

dart
library some.name;

class C {}

常见修复方法

#

library 指令中移除名称

dart
library;

class C {}

如果库有任何部分,则任何使用库名称的 part of 声明都应更新为使用库的 URI。

不必要的 new 关键字

#

不必要的 'new' 关键字。

描述

#

当使用关键字 new 调用构造函数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为关键字 new 被用于调用 Object 的未命名构造函数

dart
var o = new Object();

常见修复方法

#

移除关键字 new

dart
var o = Object();

不必要的空感知赋值

#

不必要地赋值 'null'。

描述

#

当空感知赋值的右侧是 null 字面量时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为当 s 已经为 null 时,空感知运算符被用于将 null 赋值给 s

dart
void f(String? s) {
  s ??= null;
}

常见修复方法

#

如果应将非空值赋值给左侧操作数,则更改右侧

dart
void f(String? s) {
  s ??= '';
}

如果没有非空值要赋值给左侧操作数,则移除赋值

dart
void f(String? s) {
}

if-null 运算符中不必要的 null

#

不必要地使用 '??' 和 'null'。

描述

#

?? 运算符的右操作数是字面量 null 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 ?? 运算符的右侧操作数是 null

dart
String? f(String? s) => s ?? null;

常见修复方法

#

如果应将非空值用作右侧操作数,则更改右侧

dart
String f(String? s) => s ?? '';

如果没有非空值用作右侧操作数,则移除运算符和右侧操作数

dart
String? f(String? s) => s;

final 变量声明中不必要的可空类型

#

类型可以是非可空的。

描述

#

当 final 字段或变量具有可空类型,但被初始化为非空值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 final 变量 i 具有可空类型 (int?),但永远不会为 null

dart
final int? i = 1;

常见修复方法

#

使类型变为非可空的

dart
final int i = 1;

不必要的 overrides 注解

#

不必要的重写。

描述

#

当实例成员重写了继承的成员,但仅使用完全相同的参数调用了被重写的成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为方法 D.m 除了调用被重写的方法之外,没有做任何其他事情

dart
class C {
  int m(int x) => x;
}

class D extends C {
  @override
  int m(int x) => super.m(x);
}

常见修复方法

#

如果该方法应该做比被重写的方法更多的事情,则实现缺失的功能

dart
class C {
  int m(int x) => x;
}

class D extends C {
  @override
  int m(int x) => super.m(x) + 1;
}

如果应该通过更改返回类型或一个或多个参数类型、使其中一个参数为 covariant、添加文档注释或添加其他注解来修改被重写的方法,则更新代码

dart
import 'package:meta/meta.dart';

class C {
  int m(int x) => x;
}

class D extends C {
  @mustCallSuper
  @override
  int m(int x) => super.m(x);
}

如果重写方法没有更改或增强代码的语义,则移除它

dart
class C {
  int m(int x) => x;
}

class D extends C {}

不必要的括号

#

不必要地使用括号。

描述

#

当使用括号但它们不影响代码的语义时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为二元表达式周围的括号是不必要的

dart
int f(int a, int b) => (a + b);

常见修复方法

#

移除不必要的括号

dart
int f(int a, int b) => a + b;

不必要的原始字符串

#

不必要地使用原始字符串。

描述

#

当字符串字面量被标记为原始字符串(以 r 为前缀),但使字符串成为原始字符串不会更改字符串的值时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为无论是否使用 r,字符串字面量都将具有相同的值

dart
var s = r'abc';

常见修复方法

#

移除字符串字面量前面的 r

dart
var s = 'abc';

不必要的语句

#

不必要的语句。

描述

#

当表达式语句没有明显的副作用时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为两个调用的返回值相加没有明显的副作用

dart
void f(int Function() first, int Function() second) {
  first() + second();
}

常见修复方法

#

如果不需要计算表达式,则移除它

dart
void f(int Function() first, int Function() second) {
}

如果需要表达式的值,则使用它,可以先将其赋值给局部变量

dart
void f(int Function() first, int Function() second) {
  print(first() + second());
}

如果表达式的某些部分需要执行,则移除不必要的部分

dart
void f(int Function() first, int Function() second) {
  first();
  second();
}

不必要的字符串转义

#

字符串字面量中不必要的转义符。

描述

#

当字符串中的字符在转义是不必要时被转义时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为单引号不需要在双引号分隔的字符串内转义

dart
var s = "Don\'t use a backslash here.";

常见修复方法

#

移除不必要的反斜杠

dart
var s = "Don't use a backslash here.";

不必要的字符串插值

#

不必要地使用字符串插值。

描述

#

当字符串字面量包含单个 String 值变量的插值且没有其他字符时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字符串字面量包含单个插值,并且插值之外没有任何字符

dart
String f(String s) => '$s';

常见修复方法

#

将字符串字面量替换为插值的内容

dart
String f(String s) => s;

不必要的 this 关键字

#

不必要的 'this.' 限定符。

描述

#

当关键字 this 用于访问未被遮蔽的成员时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为使用 this 访问字段 _f 是不必要的

dart
class C {
  int _f = 2;

  int get f => this._f;
}

常见修复方法

#

移除 this.

dart
class C {
  int _f = 2;

  int get f => _f;
}

展开操作中不必要的 toList 调用

#

在 spread 中不必要地使用 'toList'。

描述

#

当在 spread 运算符应用于列表之前,使用 toListIterable 转换为 List 时,分析器会生成此诊断信息。 spread 运算符可以应用于任何 Iterable,因此转换是不必要的。

示例

#

以下代码会生成此诊断信息,因为 toListmap 的结果上调用,而 map 的结果是一个 Iterable,spread 运算符可以直接应用于它

dart
List<String> toLowercase(List<String> strings) {
  return [
    ...strings.map((String s) => s.toLowerCase()).toList(),
  ];
}

常见修复方法

#

移除 toList 的调用

dart
List<String> toLowercase(List<String> strings) {
  return [
    ...strings.map((String s) => s.toLowerCase()),
  ];
}

不必要的下划线

#

不必要地使用多个下划线。

描述

#

当未使用的变量以多个下划线命名时(例如 __),分析器会生成此诊断信息。可以使用单个 _ 通配符变量代替。

示例

#

以下代码会生成此诊断信息,因为 __ 参数未使用

dart
void function(int __) { }

常见修复方法

#

将名称替换为单个下划线

dart
void function(int _) { }

不相关的类型相等性检查

#

操作数的类型 ('{0}') 不是正在匹配的值 ('{1}') 的子类型或超类型。

右操作数的类型 ('{0}') 不是左操作数 ('{1}') 的子类型或超类型。

描述

#

当比较两个对象,且两个对象的静态类型都不是另一个对象的子类型时,分析器会生成此诊断信息。

这样的比较通常会返回 false,并且可能无法反映程序员的意图。

可能存在误报。例如,名为 Point 的类可能具有名为 CartesianPointPolarPoint 的子类,它们都不是彼此的子类型,但测试实例的相等性可能仍然是合适的。

作为一个具体的例子,package:fixnum 中的类 Int64Int32 允许将实例与 int 进行比较,前提是 int 在右侧。这种情况被诊断信息专门允许,但其他此类情况则不允许。

示例

#

以下代码会生成此诊断信息,因为字符串 s 正在与整数 1 进行比较

dart
bool f(String s) {
  return s == 1;
}

常见修复方法

#

将其中一个操作数替换为与另一个操作数兼容的内容

dart
bool f(String s) {
  return s.length == 1;
}

不安全的可变性

#

此类型是不安全的:类型参数出现在非协变位置。

描述

#

当实例成员的结果类型在其封闭声明的类型参数中是 逆变或不变 时,分析器会生成此诊断信息。变量的结果类型是其类型,getter 或方法的结果类型是其返回类型。此 lint 警告此类成员,因为它们很可能在运行时导致类型检查失败,而在调用站点没有静态警告或错误。

示例

#

以下代码会生成此诊断信息,因为 Xf 的类型中作为参数类型出现,这是此类型参数的逆变出现

dart
class C<X> {
  bool Function(X) f;
  C(this.f);
}

这是不安全的:如果 c 的静态类型为 C<num>,运行时类型为 C<int>,则 c.f 将抛出异常。因此,每个调用 c.f(a) 也将抛出异常,即使在 a 作为 c.f 的参数具有正确类型的情况下也是如此。

常见修复方法

#

如果 linted 成员是或可以是私有的,那么您可能可以强制确保它永远不会在除了 this 之外的任何其他接收器上访问。这足以确保不会发生运行时类型错误。例如

dart
class C<X> {
  // NB: Ensure manually that `_f` is only accessed on `this`.
  // ignore: unsafe_variance
  bool Function(X) _f;

  C(this._f);

  // We can write a forwarding method to allow clients to call `_f`.
  bool f(X x) => _f(x);
}

您可以通过为 linted 成员使用更通用的类型来消除不安全的 variance。在这种情况下,您可能需要在调用站点检查运行时类型并执行向下转型。

dart
class C<X> {
  bool Function(Never) f;
  C(this.f);
}

如果 c 的静态类型为 C<num>,则您可以测试类型。例如,c.f is bool Function(num)。如果它具有该类型,您可以安全地使用 num 类型的参数调用它。

您还可以通过使用更通用的类型(如 Function)来消除不安全的 variance,Function 本质上是函数的 dynamic 类型。

dart
class C<X> {
  Function f;
  C(this.f);
}

这将使 c.f(a) 在动态上是安全的:它将抛出异常当且仅当参数 a 没有函数所需的类型时。这比原始版本更好,因为它不会因为静态类型不匹配而抛出异常。它仅在出于健全性原因必须抛出时才抛出。

同步使用 BuildContext

#

不要跨异步间隙使用 'BuildContext',并使用不相关的 'mounted' 检查来保护。

不要跨异步间隙使用 'BuildContext'。

描述

#

BuildContext 在异步间隙之后被 StatefulWidget 引用,而没有首先检查 mounted 属性时,分析器会生成此诊断信息。

存储 BuildContext 以供稍后使用可能会导致难以诊断的崩溃。异步间隙隐式地存储 BuildContext,使得它们很容易被忽略而难以诊断。

示例

#

以下代码会生成此诊断信息,因为 contextawait 之后传递给构造函数

dart
import 'package:flutter/material.dart';

class MyWidget extends Widget {
  void onButtonTapped(BuildContext context) async {
    await Future.delayed(const Duration(seconds: 1));
    Navigator.of(context).pop();
  }
}

常见修复方法

#

如果可以移除异步间隙,请移除

dart
import 'package:flutter/material.dart';

class MyWidget extends Widget {
  void onButtonTapped(BuildContext context) {
    Navigator.of(context).pop();
  }
}

如果无法移除异步间隙,则使用 mounted 来保护 context 的使用

dart
import 'package:flutter/material.dart';

class MyWidget extends Widget {
  void onButtonTapped(BuildContext context) async {
    await Future.delayed(const Duration(seconds: 1));
    if (context.mounted) {
      Navigator.of(context).pop();
    }
  }
}

使用 ColoredBox

#

使用 'ColoredBox' 而不是仅具有 'Color' 的 'Container'。

描述

#

当创建仅设置颜色的 Container 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为设置的容器的唯一属性是 color

dart
import 'package:flutter/material.dart';

Widget build() {
  return Container(
    color: Colors.red,
    child: const Text('hello'),
  );
}

常见修复方法

#

Container 替换为 ColoredBox

dart
import 'package:flutter/material.dart';

Widget build() {
  return ColoredBox(
    color: Colors.red,
    child: const Text('hello'),
  );
}

使用 DecoratedBox

#

使用 'DecoratedBox' 而不是仅具有 'Decoration' 的 'Container'。

描述

#

当创建仅设置 decoration 的 Container 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为设置的容器的唯一属性是 decoration

dart
import 'package:flutter/material.dart';

Widget buildArea() {
  return Container(
    decoration: const BoxDecoration(
      color: Colors.red,
      borderRadius: BorderRadius.all(
        Radius.circular(5),
      ),
    ),
    child: const Text('...'),
  );
}

常见修复方法

#

Container 替换为 DecoratedBox

dart
import 'package:flutter/material.dart';

Widget buildArea() {
  return DecoratedBox(
    decoration: const BoxDecoration(
      color: Colors.red,
      borderRadius: BorderRadius.all(
        Radius.circular(5),
      ),
    ),
    child: const Text('...'),
  );
}

Flutter 颜色使用完整的十六进制值

#

'Color' 的实例应使用 8 位十六进制整数创建(例如 '0xFFFFFFFF')。

描述

#

Color 类的构造函数的参数是一个未表示为 8 位十六进制整数的字面量整数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为参数 (1) 未表示为 8 位十六进制整数

dart
import 'package:flutter/material.dart';

Color c = Color(1);

常见修复方法

#

将表示形式转换为 8 位十六进制整数

dart
import 'package:flutter/material.dart';

Color c = Color(0x00000001);

参数使用函数类型语法

#

使用泛型函数类型语法来声明参数 '{0}'。

描述

#

当使用旧式函数值参数语法时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为函数值参数 f 是使用旧式语法声明的

dart
void g(bool f(String s)) {}

常见修复方法

#

使用泛型函数类型语法来声明参数

dart
void g(bool Function(String) f) {}

使用 if-null 将 null 转换为 bool

#

使用 if-null 运算符将 'null' 转换为 'bool'。

描述

#

当可空 bool 值表达式与布尔字面量进行比较(使用 ==!=)时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为可空布尔变量 btrue 进行比较

dart
void f(bool? b) {
  if (b == true) {
    // Treats `null` as `false`.
  }
}

常见修复方法

#

重写条件以使用 ?? 代替

dart
void f(bool? b) {
  if (b ?? false) {
    // Treats `null` as `false`.
  }
}

在 Widget 构造函数中使用 key 参数

#

公共 widget 的构造函数应具有名为 'key' 的命名参数。

描述

#

当不是库私有的 Widget 子类中的构造函数没有名为 key 的参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为类 MyWidget 的构造函数没有名为 key 的参数

dart
import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {
  MyWidget({required int height});
}

以下代码会生成此诊断信息,因为类 MyWidget 的默认构造函数没有名为 key 的参数

dart
import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {}

常见修复方法

#

向构造函数添加名为 key 的参数,并在必要时显式声明构造函数

dart
import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {
  MyWidget({super.key, required int height});
}

为私有字段和变量使用 late 关键字

#

对具有非可空类型的私有成员使用 'late'。

描述

#

当私有字段或变量被标记为可空,但每个引用都假定该变量永远不会为 null 时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为私有顶层变量 _i 是可空的,但每个引用都假定它不会为 null

dart
void f() {
  _i!.abs();
}

int? _i;

常见修复方法

#

将变量或字段标记为既非可空又为 late,以表明它将始终被赋值为非空值

dart
void f() {
  _i.abs();
}

late int _i;

使用命名常量

#

使用常量 '{0}' 而不是返回相同对象的构造函数。

描述

#

当使用与已知 const 变量相同的值创建常量时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为存在一个已知的 const 字段 (Duration.zero),其值与构造函数调用将求得的值相同

dart
Duration d = const Duration(seconds: 0);

常见修复方法

#

将构造函数调用替换为对已知 const 变量的引用

dart
Duration d = Duration.zero;

使用空感知元素

#

使用空感知标记 '?' 而不是通过 'if' 进行空检查。

描述

#

当在集合字面量内部使用空检查而不是空感知标记时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为使用空检查来决定是否应将 x 插入到列表中,而空感知标记 '?' 将更简洁且更不脆弱。

dart
f(int? x) => [if (x != null) x];

常见修复方法

#

将空检查替换为空感知标记 '?'

dart
f(int? x) => [?x];

使用原始字符串

#

使用原始字符串以避免使用转义符。

描述

#

当包含转义符且没有插值的字符串字面量可以标记为原始字符串以避免需要转义符时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字符串包含转义字符,如果将字符串设为原始字符串,则不需要转义

dart
var s = 'A string with only \\ and \$';

常见修复方法

#

将字符串标记为原始字符串并移除不必要的反斜杠

dart
var s = r'A string with only \ and $';

尽可能使用 rethrow

#

使用 'rethrow' 重新抛出捕获的异常。

描述

#

当捕获的异常使用 throw 表达式而不是 rethrow 语句抛出时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为捕获的异常 e 是使用 throw 表达式抛出的

dart
void f() {
  try {
    // ...
  } catch (e) {
    throw e;
  }
}

常见修复方法

#

使用 rethrow 而不是 throw

dart
void f() {
  try {
    // ...
  } catch (e) {
    rethrow;
  }
}

使用 setter 更改属性

#

该方法用于更改属性。

描述

#

当方法用于设置字段的值,或函数用于设置顶层变量的值,而没有其他操作时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为方法 setF 用于设置字段 _f 的值,并且没有做其他工作

dart
class C {
  int _f = 0;

  void setF(int value) => _f = value;
}

常见修复方法

#

将方法转换为 setter

dart
class C {
  int _f = 0;

  set f(int value) => _f = value;
}

使用 StringBuffer

#

使用字符串缓冲区而不是 '+' 来组合字符串。

描述

#

当在循环内将值连接到字符串,而没有使用 StringBuffer 进行连接时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为字符串 result 是通过在 for 循环中重复连接来计算的

dart
String f() {
  var result = '';
  for (int i = 0; i < 10; i++) {
    result += 'a';
  }
  return result;
}

常见修复方法

#

使用 StringBuffer 计算结果

dart
String f() {
  var buffer = StringBuffer();
  for (int i = 0; i < 10; i++) {
    buffer.write('a');
  }
  return buffer.toString();
}

在 part of 指令中使用字符串

#

part-of 指令使用库名称。

描述

#

part of 指令使用库名称来引用该 part 所属的库时,分析器会生成此诊断信息。

示例

#

给定一个名为 lib.dart 的文件,其中包含以下内容

dart
library lib;

part 'test.dart';

以下代码会生成此诊断信息,因为 part of 指令使用库的名称而不是其所属库的 URI

dart
part of lib;

常见修复方法

#

使用 URI 引用库

dart
part of 'lib.dart';

使用 super 参数

#

参数 '{0}' 可以是 super 参数。

参数 '{0}' 可以是 super 参数。

描述

#

当构造函数的参数被传递给超类构造函数,而没有被引用或修改,并且没有使用 super 参数时,分析器会生成此诊断信息。

示例

#

以下代码会生成此诊断信息,因为 B 的构造函数的参数仅用作超类构造函数的参数

dart
class A {
  A({int? x, int? y});
}
class B extends A {
  B({int? x, int? y}) : super(x: x, y: y);
}

常见修复方法

#

使用 super 参数传递参数

dart
class A {
  A({int? x, int? y});
}
class B extends A {
  B({super.x, super.y});
}

使用截断除法

#

使用截断除法。

描述

#

当两个数字相除的结果使用 toInt 转换为整数时,分析器会生成此诊断信息。

Dart 有一个内置的整数除法运算符,它既更高效又更简洁。

示例

#

以下代码会生成此诊断,因为使用 toIntxy 相除的结果转换为整数

dart
int divide(int x, int y) => (x / y).toInt();

常见修复方法

#

使用整数除法运算符 (~/)

dart
int divide(int x, int y) => x ~/ y;

有效的正则表达式

#

正则表达式语法无效。

描述

#

当传递给 RegExp 类的默认构造函数的字符串不包含有效的正则表达式时,分析器会生成此诊断信息。

使用无效语法创建的正则表达式将在运行时抛出 FormatException

示例

#

以下代码会生成此诊断信息,因为正则表达式无效

dart
var r = RegExp(r'(');

常见修复方法

#

修复正则表达式

dart
var r = RegExp(r'\(');

void 检查

#

赋值给 'void' 类型的变量。

描述

#

当将值赋值给 void 类型的变量时,分析器会生成此诊断信息。

无法访问此类变量的值,因此赋值没有意义。

示例

#

以下代码会生成此诊断信息,因为字段 value 的类型为 void,但正在为其赋值

dart
class A<T> {
  T? value;
}

void f(A<void> a) {
  a.value = 1;
}

以下代码会生成此诊断信息,因为方法 m 中参数 p 的类型为 void,但在调用中正在为其赋值

dart
class A<T> {
  void m(T p) { }
}

void f(A<void> a) {
  a.m(1);
}

常见修复方法

#

如果变量的类型不正确,则更改变量的类型

dart
class A<T> {
  T? value;
}

void f(A<int> a) {
  a.value = 1;
}

如果变量的类型正确,则移除赋值

dart
class A<T> {
  T? value;
}

void f(A<void> a) {}