- 诊断
- abi_specific_integer_invalid
- abi_specific_integer_mapping_extra
- abi_specific_integer_mapping_missing
- abi_specific_integer_mapping_unsupported
- 抽象字段初始化器
- 抽象密封类
- 抽象超类成员引用
- 不明确的导出
- 不明确的扩展成员访问
- 不明确的导入
- 集合或映射字面量同时存在
- 集合或映射字面量任一存在
- 指针字段上的注解
- 参数必须是常量
- 参数类型不可赋值
- 参数类型不可赋值给错误处理程序
- 重定向构造函数中的断言
- 资产目录不存在
- 资产不存在
- 资产字段不是列表
- 资产缺少路径
- 资产不是字符串
- 资产不是字符串或映射
- 资产路径不是字符串
- 对“不存储”的赋值
- 对常量的赋值
- 对 final 的赋值
- 对 final 局部变量的赋值
- 对 final 的赋值,没有 setter
- 对函数的赋值
- 对方法的赋值
- 对类型的赋值
- 异步 for in 错误的上下文中
- 延迟局部变量初始化器中的 await
- 不兼容类型的 await
- 主体可能正常完成
- 主体可能正常完成,捕获错误
- 主体可能正常完成,可为空
- switch 成员上的 break 标签
- 内置标识符作为类型
- 声明中的内置标识符
- 回调不能使用 TypedData
- 调用不能返回 TypedData
- case 块未终止
- case 表达式类型实现 equals
- case 表达式类型不是 switch 表达式子类型
- 从可为空的强制转换总是失败
- 从 null 的强制转换总是失败
- 强制转换为非类型
- 类用作 mixin
- 集合元素来自延迟库
- 复合实现 finalizable
- 具体类具有枚举超接口
- 具有抽象成员的具体类
- 构造函数和静态成员冲突
- 冲突的泛型接口
- 冲突的类型变量和容器
- 冲突的类型变量和成员
- 常量模式永远不会匹配值类型
- 常量模式使用非常量表达式
- 常量构造函数参数类型不匹配
- 常量构造函数使用非常量初始化字段
- 常量构造函数使用非常量超类
- 常量构造函数使用非 final 字段
- 常量延迟类
- 常量使用非常量值初始化
- 常量使用来自延迟库的非常量值初始化
- 常量实例字段
- 常量映射键不是原始相等性
- 常量未初始化
- 常量集合元素不是原始相等性
- 常量展开预期列表或集合
- 常量展开预期映射
- 常量使用非常量
- 常量使用非常量参数
- 常量使用类型参数
- continue 标签无效
- 创建结构体或联合体
- 使用非类型创建
- 无用代码
- 无用代码,捕获后跟捕获
- 无用代码,在子类型捕获上
- 无用空感知表达式
- 默认列表构造函数
- 函数类型中的默认值
- 重定向工厂构造函数中的默认值
- 必需参数上的默认值
- 扩展的延迟导入
- 未赋值的延迟局部变量
- 依赖项字段不是映射
- 默认值使用冒号已弃用
- 已弃用的导出使用
- 已弃用的字段
- 已弃用的成员使用
- 来自同一包的已弃用的成员使用
- 注释引用中已弃用的 new
- 函数的已弃用子类型
- 不允许的类型实例化表达式
- 除法优化
- 重复构造函数
- 重复定义
- 重复导出
- 重复的字段形式参数
- 重复的字段名称
- 重复的隐藏名称
- 重复忽略
- 重复导入
- 重复的命名参数
- 重复的部分
- 重复的模式赋值变量
- 重复的模式字段
- 模式中重复的剩余元素
- 重复的显示名称
- 重复的变量模式
- 空映射模式
- 带逗号的空记录字面量
- 带逗号的空记录类型命名字段列表
- 带逗号的空记录类型
- 空结构体
- 枚举常量与封闭枚举同名
- 枚举常量使用非常量构造函数
- 枚举混合使用实例变量
- 枚举包含抽象成员
- 枚举带名称值
- 常量集中存在相等元素
- 集中存在相等元素
- 常量映射中存在相等键
- 映射中存在相等键
- 映射模式中存在相等键
- 预期一个列表模式类型参数
- 预期一个列表类型参数
- 预期一个集合类型参数
- 预期两个映射模式类型参数
- 预期两个映射类型参数
- 导出内部库
- 导出旧版符号
- 导出非库
- 映射中的表达式
- 扩展非类
- 扩展作为表达式
- 扩展中静态和实例冲突
- 扩展声明抽象成员
- 扩展声明构造函数
- 扩展声明实例字段
- 扩展声明对象成员
- 扩展覆盖对静态成员的访问
- 扩展覆盖参数不可赋值
- 扩展覆盖没有访问权限
- 扩展覆盖使用级联
- 扩展类型构造函数带 super 形式参数
- 扩展类型构造函数带 super 调用
- 扩展类型声明实例字段
- 扩展类型声明对象成员
- 扩展类型实现不允许的类型
- 扩展类型实现自身
- 扩展类型实现非超类型
- 扩展类型实现表示非超类型
- 扩展类型继承成员冲突
- 扩展类型表示依赖于自身
- 扩展类型表示类型为底层
- 扩展类型包含抽象成员
- 外部带初始化程序
- 结构体字段上的额外注释
- 额外的位置参数
- 额外的位置参数可以是命名参数
- extra_size_annotation_carray
- 字段由多个初始化器初始化
- 字段在初始化器和声明中初始化
- 字段在参数和初始化器中初始化
- 字段初始化器工厂构造函数
- 结构体中的字段初始化器
- 字段初始化器不可赋值
- 字段初始化器位于构造函数之外
- 字段初始化器重定向构造函数
- 初始化形式参数不可赋值
- 带有初始化器的结构体中的字段
- 字段必须在结构体中为外部
- final 在声明和构造函数中初始化
- final 未初始化
- final 在构造函数中未初始化
- Flutter 字段不是映射
- for-in-of 循环中元素类型无效
- for-in-of 循环中类型无效
- for-in 循环使用常量变量
- 泛型方法类型实例化在动态类型上
- 泛型结构体子类
- getter 类型不是 setter 类型子类型
- 异步生成器返回类型非法
- 异步返回类型非法
- 具体枚举成员非法
- 枚举值非法
- 同步生成器返回类型非法
- 实现非类
- 重复实现
- 实现超类
- 隐式超类初始化器缺少参数
- 初始化器中存在隐式 this 引用
- 使用 load 函数导入延迟库
- 导入内部库
- 将传统库导入到空安全库中
- 导入非库
- 继承不一致
- 语言版本覆盖不一致
- 模式变量逻辑或不一致
- 不存在字段的初始化器
- 静态字段的初始化器
- 不存在字段的初始化形式参数
- 实例访问静态成员
- 从工厂访问实例成员
- 从静态访问实例成员
- 实例化抽象类
- 实例化枚举
- 实例化类型别名扩展到类型参数
- 整数字面量作为 double 不精确
- 整数字面量超出范围
- 注释无效
- 来自延迟库的注释常量值无效
- 来自延迟库的注释无效
- 注释目标无效
- 赋值无效
- 依赖关系无效
- 异常值无效
- 导出内部元素无效
- 间接导出内部元素无效
- 扩展参数计数无效
- 工厂方法声明无效
- 工厂方法实现无效
- 工厂名称无效,不是类
- 字段名称无效
- 结构体中的字段类型无效
- 实现覆盖无效
- 内联函数类型无效
- 内部注释无效
- 语言版本覆盖无效
- 字面量注释无效
- 构造函数上的修饰符无效
- setter 上的修饰符无效
- 非虚拟注释无效
- 空感知运算符无效
- 覆盖无效
- 覆盖非虚拟成员无效
- 共享 case 范围内的模式变量无效
- 平台字段无效
- 对生成枚举构造函数的引用无效
- 对 this 的引用无效
- catch 错误的返回类型无效
- 密封注释无效
- 超类形式参数位置无效
- 常量字面量中的类型参数无效
- URI 无效
- 在扩展中使用 covariant 无效
- 使用 do_not_submit 成员无效
- 使用内部成员无效
- 使用空值无效
- 在库外部使用类型无效
- 重写成员可见性使用无效
- 测试成员可见性使用无效
- 可见性注解无效
- 重写注解可见性无效
- 模板外部可见性注解无效
- 调用扩展方法时未带调用
- 调用非函数
- 调用非函数表达式
- 标签在外部作用域中
- 标签未定义
- 带有常量构造函数的延迟 final 字段
- 延迟 final 局部变量已赋值
- 叶调用不能返回句柄
- 叶调用不能接受句柄
- 列表元素类型不可赋值
- main 函数第一个位置参数类型
- main 函数具有必需的命名参数
- main 函数具有过多必需的位置参数
- main 函数不是函数
- 映射条目不在映射中
- 映射键类型不可赋值
- 映射值类型不可赋值
- 结构体字段上的注解不匹配
- 结构体字段上缺少注解
- 缺少 Dart 库
- 参数缺少默认值
- 缺少依赖项
- switch 语句中缺少枚举常量
- 缺少异常值
- 结构体中缺少字段类型
- 缺少名称
- 缺少命名模式字段名称
- 缺少必须重写的重写
- 缺少必需参数
- 缺少必需参数
- 缺少返回值
- C 数组缺少大小注解
- 缺少变量模式
- 混合应用中具体超类调用的成员类型
- 混合应用未实现接口
- 混合应用中没有具体超类调用的成员
- 混合类声明扩展非 Object 类
- 混合类声明构造函数
- 混合类继承自非 Object 类
- 混合类实例化
- 混合非类
- 混合密封类
- 混合超类约束延迟类
- 混合超类约束非接口
- 多个重定向构造函数调用
- 多个超类初始化器
- 必须是原生函数类型
- 必须是子类型
- 必须是不可变的
- 必须调用 super
- 必须返回 void
- 名称不是字符串
- 原生字段类型无效
- 原生字段缺少类型
- 原生字段不是静态的
- 带有未定义构造函数默认值的 new
- 非抽象类继承抽象成员
- 非布尔条件
- 非布尔表达式
- 非布尔否定表达式
- 非布尔操作数
- 非常量注解构造函数
- 非常量 case 表达式
- 来自延迟库的非常量 case 表达式
- 非常量默认值
- 来自延迟库的非常量默认值
- 非常量列表元素
- 非常量映射元素
- 非常量映射键
- 非常量映射模式键
- 非常量映射值
- 非常量关系模式表达式
- 非常量集合元素
- 非常量类型参数
- 常量参数的非常量参数
- 对字面量构造函数的非常量调用
- 非常量生成枚举构造函数
- 表示类型中非协变类型参数位置
- 非详尽的 switch 表达式
- 非详尽的 switch 语句
- 枚举中的非 final 字段
- 非生成构造函数
- 非生成隐式构造函数
- 非叶子调用不能接受类型化数据
- 指向指针的非原生函数类型参数
- 非正数组维度
- 非大小类型参数
- 非同步工厂
- 非类型作为类型参数
- catch 子句中的非类型
- 运算符的非 void 返回值
- 设置器的非 void 返回值
- 未赋值的潜在非空局部变量
- 不是类型
- 不是二元运算符
- 位置参数不足
- 未初始化的非空实例字段
- 未初始化的非空变量
- 不可迭代的展开
- 不是 map 展开
- 没有注释构造函数参数
- 没有组合的超类签名
- 超类中没有生成构造函数
- catch 子句中的可空类型
- extends 子句中的可空类型
- implements 子句中的可空类型
- on 子句中的可空类型
- with 子句中的可空类型
- 对非空类型的空参数
- 空检查总是失败
- 默认值的过时冒号
- 重复 on
- 运算符中的可选参数
- 在非重写成员上重写
- 打包注释
- 打包注释对齐
- 属于不同的库
- 属于非部分
- 属于未命名的库
- 路径不存在
- 路径不是 POSIX
- 路径 pubspec 不存在
- 模式赋值不是局部变量
- 来自延迟库的模式常量
- 不可反驳上下文中模式类型不匹配
- 模式变量赋值在保护内
- 不允许平台值
- 对象模式中的位置字段
- 带位置参数的位置超类形式参数
- 前缀与顶层成员冲突
- 前缀标识符后没有点
- 前缀被局部声明遮蔽
- 混合应用中的私有冲突
- 私有可选参数
- 私有设置器
- 读取潜在未赋值的 final
- 记录字面量一个位置没有尾部逗号
- 记录类型一个位置没有尾部逗号
- 递归编译时常量
- 递归构造函数重定向
- 递归接口继承
- 在非重新声明成员上重新声明
- 将生成重定向到缺失的构造函数
- 将生成重定向到非生成构造函数
- 重定向到抽象类构造函数
- 重定向到无效函数类型
- 重定向到无效返回值类型
- 重定向到缺失的构造函数
- 重定向到非类
- 重定向到非常量构造函数
- 重定向到类型别名扩展到类型参数
- 在声明之前引用
- 不可反驳上下文中不可反驳的模式
- 关系模式操作数类型不可分配
- 关系模式运算符返回类型不可分配为布尔值
- 映射模式中的剩余元素
- 在 catch 外部重新抛出
- 在生成式构造函数中返回
- 在生成器中返回
- 返回非存储值
- 返回无效类型
- 从闭包返回无效类型
- 无值返回
- SDK 版本异步从核心导出
- SDK 版本作为常量上下文中的表达式
- SDK 版本布尔运算符在常量上下文中的使用
- SDK 版本构造函数撕裂
- SDK 版本 == 运算符在常量上下文中的使用
- SDK 版本扩展方法
- SDK 版本 >>> 运算符
- SDK 版本 is 表达式在常量上下文中的使用
- SDK 版本永不
- SDK 版本集合字面量
- SDK 版本 UI 作为代码
- SDK 版本 UI 作为代码在常量上下文中的使用
- 集合元素类型不可分配
- 共享延迟前缀
- 大小注释维度
- 对实例成员的静态访问
- 基类或最终类的子类型不是基类、最终类或密封类
- 延迟类的子类型
- 不允许类型的子类型
- FFI 类的子类型
- 密封类的子类型
- 结构类的子类型
- 超类型扩展到类型参数
- 超形式参数类型不是关联类型的子类型
- 没有关联命名参数的超形式参数
- 没有关联位置参数的超形式参数
- 超调用不是最后一个
- 枚举构造函数中的超
- 扩展中的超
- 扩展类型中的超
- 无效上下文中的超
- 重定向构造函数中的超
- switch case 正常完成
- switch 表达式不可分配
- 抽象类的生成式构造函数的撕裂
- 注释中的文本方向代码点
- 字面量中的文本方向代码点
- 抛出无效类型
- 顶层循环
- 类型别名不能引用自身
- 类型注释延迟类
- 类型参数不匹配边界
- 使用 null 进行类型检查
- 类型参数被静态引用
- 类型参数是其边界的超类型
- 使用非类型进行类型测试
- 使用未定义名称进行类型测试
- 对可空值的未经检查的使用
- 未定义注释
- 未定义类
- 初始化程序中未定义的构造函数
- 未定义的枚举常量
- 未定义的枚举构造函数
- 未定义的扩展获取器
- 未定义的扩展方法
- 未定义的扩展运算符
- 未定义的扩展设置器
- 未定义函数
- 未定义获取器
- 未定义的隐藏名称
- 未定义标识符
- 未定义标识符 await
- 未定义方法
- 未定义的命名参数
- 未定义运算符
- 未定义的前缀名称
- 未定义的引用参数
- 未定义设置器
- 未定义的显示名称
- 未定义的超成员
- 未知平台
- 不必要的强制转换
- 不必要的开发依赖项
- 不必要的 final
- 不必要的导入
- 不必要的 NaN 比较
- 不必要的非空断言
- 不必要的 NoSuchMethod 错误
- 不必要的空断言模式
- 不必要的空检查模式
- 不必要的空比较
- 不必要的问号
- 不必要的集合字面量
- 不必要的类型检查
- 对非本地静态成员的非限定引用
- 对扩展类型静态成员的非限定引用
- 无法到达的 switch case
- 未使用的 catch 子句
- 未使用的 catch 栈
- 未使用的元素
- 未使用的字段
- 未使用的导入
- 未使用的标签
- 未使用的局部变量
- 未使用的结果
- 未使用的显示名称
- URI 不存在
- URI 未生成
- 带有插值的 URI
- 使用原生扩展
- 使用 void 结果
- 枚举中的值声明
- 声明上下文中使用变量模式关键字
- 变量类型不匹配
- 操作符参数数量错误
- setter 参数数量错误
- 类型参数数量错误
- 构造函数类型参数数量错误
- 枚举类型参数数量错误
- 扩展类型参数数量错误
- 方法类型参数数量错误
- 非生成器中的 yield
- 无效类型的 yield
此页面列出了 Dart 分析器生成的诊断消息,并详细说明了这些消息的含义以及如何修复您的代码。有关分析器的更多信息,请参阅 自定义静态分析。
诊断
#分析器针对不符合语言规范或可能以意外方式工作的代码生成以下诊断。
abi_specific_integer_invalid
#扩展 'AbiSpecificInteger' 的类必须恰好有一个 const 构造函数,没有其他成员,也没有类型参数。
描述
#当扩展 AbiSpecificInteger
的类不满足以下所有要求时,分析器会生成此诊断
- 必须恰好有一个构造函数
- 构造函数必须标记为
const
- 除了一个构造函数之外,不能有任何其他成员
- 不能有任何类型参数
示例
#以下代码会生成此诊断,因为类 C
没有定义 const 构造函数
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
}
以下代码会生成此诊断,因为构造函数不是 const
构造函数
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
C();
}
以下代码会生成此诊断,因为类 C
定义了多个构造函数
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C.zero();
const C.one();
}
以下代码会生成此诊断,因为类 C
定义了一个字段
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
final int i;
const C(this.i);
}
以下代码会产生此诊断信息,因为类C
具有类型参数。
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C<T> extends AbiSpecificInteger { // type parameters
const C();
}
常见修复方法
#更改类,使其满足没有类型参数且只有一个成员为const
构造函数的要求。
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
注释。
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
@AbiSpecificIntegerMapping({Abi.linuxX64 : Uint16()})
final class C extends AbiSpecificInteger {
const C();
}
常见修复方法
#删除除一个之外的所有注释,并根据需要合并参数。
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
注释。
import 'dart:ffi';
final class C extends AbiSpecificInteger {
const C();
}
常见修复方法
#在类上添加AbiSpecificIntegerMapping
注释。
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
注释的映射参数中的值不是以下整数类型之一时,分析器会产生此诊断信息。
Int8
Int16
Int32
Int64
Uint8
Uint16
UInt32
Uint64
示例
#以下代码会产生此诊断信息,因为映射项的值为Array<Uint8>
,这不是有效的整数类型。
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Array<Uint8>(4)})
final class C extends AbiSpecificInteger {
const C();
}
常见修复方法
#在映射中使用其中一个有效类型作为值。
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C();
}
抽象字段初始化器
#抽象字段不能有初始化器。
描述
#当具有abstract
修饰符的字段也具有初始化器时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为f
被标记为abstract
并且具有初始化器。
abstract class C {
abstract int f = 0;
}
以下代码会产生此诊断信息,因为f
被标记为abstract
,并且在构造函数中有一个初始化器。
abstract class C {
abstract int f;
C() : f = 0;
}
常见修复方法
#如果字段必须是抽象的,则删除初始化器。
abstract class C {
abstract int f;
}
如果字段不需要是抽象的,则删除关键字。
abstract class C {
int f = 0;
}
抽象密封类
#'sealed' 类不能标记为 'abstract',因为它已经是隐式抽象的。
描述
#当使用修饰符abstract
和sealed
同时声明一个类时,分析器会生成此诊断信息。密封类隐式地是抽象的,因此不允许显式使用这两个修饰符。
示例
#以下代码会生成此诊断信息,因为类C
使用abstract
和sealed
同时声明。
abstract sealed class C {}
常见修复方法
#如果类应该是抽象的而不是密封的,则删除sealed
修饰符。
abstract class C {}
如果类应该是抽象的和密封的,则删除abstract
修饰符。
sealed class C {}
抽象超类成员引用
#{0} '{1}' 在超类型中始终是抽象的。
描述
#当使用super
引用继承的成员时,但超类链中没有该成员的具体实现,分析器会生成此诊断信息。抽象成员不能被调用。
示例
#以下代码会生成此诊断信息,因为B
没有继承a
的具体实现。
abstract class A {
int get a;
}
class B extends A {
int get a => super.a;
}
常见修复方法
#删除对抽象成员的调用,可能将其替换为对具体成员的调用。
不明确的导出
#名称 '{0}' 在库 '{1}' 和 '{2}' 中定义。
描述
#当两个或多个导出指令导致从多个库导出相同的名称时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的文件a.dart
class C {}
以及一个包含以下内容的文件b.dart
class C {}
以下代码会生成此诊断信息,因为名称C
正在从a.dart
和b.dart
导出。
export 'a.dart';
export 'b.dart';
常见修复方法
#如果其中一个库中的任何名称都不需要导出,则删除不必要的导出指令。
export 'a.dart';
如果所有导出指令都是必需的,则在除一个指令之外的所有指令中隐藏名称。
export 'a.dart';
export 'b.dart' hide C;
不明确的扩展成员访问
#在 {1} 中定义了一个名为 '{0}' 的成员,并且没有更具体的成员。
描述
#当代码引用对象的成员(例如,o.m()
或 o.m
或 o[i]
)时,其中o
的静态类型没有声明该成员(例如,m
或 []
),则分析器会尝试在扩展中查找该成员。例如,如果成员是m
,则分析器会查找声明名为m
的成员并具有可以将o
的静态类型分配给的扩展类型的扩展。当作用域中存在多个此类扩展时,将选择扩展类型最具体的扩展。
当没有一个扩展的扩展类型比所有其他扩展的扩展类型更具体时,分析器会生成此诊断信息,这使得对成员的引用变得模棱两可。
示例
#以下代码会生成此诊断信息,因为无法在E1
中的成员和E2
中的成员之间进行选择。
extension E1 on String {
int get charCount => 1;
}
extension E2 on String {
int get charCount => 2;
}
void f(String s) {
print(s.charCount);
}
常见修复方法
#如果你不需要两个扩展,那么你可以删除或隐藏其中一个。
如果你需要两个扩展,那么使用扩展覆盖显式选择要使用的扩展。
extension E1 on String {
int get charCount => length;
}
extension E2 on String {
int get charCount => length;
}
void f(String s) {
print(E2(s).charCount);
}
不明确的导入
#名称“{0}”在库 {1} 中定义。
描述
#当引用在两个或多个导入库中声明的名称时,分析器会生成此诊断信息。
示例
#给定一个定义类(本例中为C
)的库(a.dart
)
class A {}
class C {}
以及一个定义具有相同名称的不同类的库(b.dart
)
class B {}
class C {}
以下代码会生成此诊断信息
import 'a.dart';
import 'b.dart';
void f(C c1, C c2) {}
常见修复方法
#如果不需要任何库,则删除它们的导入指令。
import 'a.dart';
void f(C c1, C c2) {}
如果名称仍然由多个库定义,则在除一个库之外的所有库的导入指令中添加hide
子句。
import 'a.dart' hide C;
import 'b.dart';
void f(C c1, C c2) {}
如果你必须能够引用多个这些类型,则为每个导入指令添加一个前缀,并使用适当的前缀限定引用。
import 'a.dart' as a;
import 'b.dart' as b;
void f(a.C c1, b.C c2) {}
集合或映射字面量同时存在
#该字面量不能是映射或集合,因为它至少包含一个字面量映射条目或一个扩展运算符扩展“Map”,以及至少一个既不是映射条目也不是集合的元素。
描述
#由于映射和集合字面量使用相同的定界符({
和 }
),分析器会查看类型参数和元素以确定你指的是哪种字面量。当没有类型参数时,分析器会使用元素的类型。如果所有元素都是字面量映射条目,并且所有扩展运算符都扩展了Map
,那么它就是一个Map
。如果没有任何元素是字面量映射条目,并且所有扩展运算符都扩展了Iterable
,那么它就是一个Set
。如果两者都不符合,那么它就是模棱两可的。
当至少一个元素是字面量映射条目或一个扩展运算符扩展Map
,并且至少一个元素既不是映射条目也不是集合时,分析器会生成此诊断信息,这使得分析器无法确定你是在编写映射字面量还是集合字面量。
示例
#以下代码会生成此诊断信息
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, ...b, ...c};
列表b
只能扩展到集合中,映射a
和c
只能扩展到映射中,而字面量不能同时是两者。
常见修复方法
#解决此问题的两种常见方法。第一种方法是删除所有一种或另一种类型的扩展元素,以便元素保持一致。在这种情况下,这可能意味着删除列表并决定如何处理现在未使用的参数。
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, ...c};
第二种方法是将一种类型的元素更改为与其他元素一致的元素。例如,你可以将列表的元素添加为映射到自身的键。
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, for (String s in b) s: s, ...c};
集合或映射字面量任一存在
#该字面量必须是映射或集合,但元素没有足够的信息来进行类型推断。
描述
#由于映射和集合字面量使用相同的定界符({
和 }
),分析器会查看类型参数和元素来确定您指的是哪种字面量。当没有类型参数并且所有元素都是展开元素(这两种字面量中都允许)时,分析器会使用正在展开的表达式的类型。如果所有表达式都具有类型 Iterable
,则它是一个集合字面量;如果它们都具有类型 Map
,则它是一个映射字面量。
当没有一个正在展开的表达式具有允许分析器确定您是在编写映射字面量还是集合字面量的类型时,就会产生此诊断信息。
示例
#以下代码会生成此诊断信息
union(a, b) => {...a, ...b};
问题出现是因为没有类型参数,并且没有关于 a
或 b
类型的信息。
常见修复方法
#有三种常见的解决此问题的方法。第一种是在字面量中添加类型参数。例如,如果字面量意图是一个映射字面量,您可以编写类似以下内容
union(a, b) => <String, String>{...a, ...b};
第二个解决方法是添加类型信息,以便表达式具有类型 Iterable
或类型 Map
。您可以添加显式类型转换,或者在本例中,为两个参数的声明添加类型
union(List<int> a, List<int> b) => {...a, ...b};
第三个解决方法是添加上下文信息。在本例中,这意味着为函数添加一个返回类型
Set<String> union(a, b) => {...a, ...b};
在其他情况下,您可能需要在其他地方添加类型。例如,假设原始代码如下所示
union(a, b) {
var x = {...a, ...b};
return x;
}
您可以在 x
上添加一个类型注释,如下所示
union(a, b) {
Map<String, String> x = {...a, ...b};
return x;
}
指针字段上的注解
#结构类中类型为 'Pointer' 的字段不应该有任何注释。
描述
#当在 Struct
的子类中声明的类型为 Pointer
的字段也具有与其关联的注释时,分析器会产生此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为字段 p
具有类型 Pointer
并且在 Struct
的子类中声明,具有注释 @Double()
import 'dart:ffi';
final class C extends Struct {
@Double()
external Pointer<Int8> p;
}
常见修复方法
#从字段中删除注释
import 'dart:ffi';
final class C extends Struct {
external Pointer<Int8> p;
}
参数必须是常量
#参数 '{0}' 必须是常量。
描述
#当 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的调用具有 isLeaf
参数,其值不是常量表达式时,分析器会产生此诊断信息。
当 Pointer.fromFunction
或 NativeCallable.isolateLocal
的调用具有 exceptionalReturn
参数,其值不是常量表达式时,分析器也会产生此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为 isLeaf
参数的值是一个参数,因此不是常量
import 'dart:ffi';
int Function(int) fromPointer(
Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
return p.asFunction(isLeaf: isLeaf);
}
常见修复方法
#如果存在可用的合适常量,则用常量替换参数
import 'dart:ffi';
const isLeaf = false;
int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
return p.asFunction(isLeaf: isLeaf);
}
如果不存在合适的常量,则用布尔文字替换参数
import 'dart:ffi';
int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
return p.asFunction(isLeaf: true);
}
参数类型不可赋值
#参数类型“{0}”无法分配给参数类型“{1}”。{2}
描述
#当参数的静态类型无法分配给相应参数的静态类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为num
无法分配给String
String f(String x) => x;
String g(num y) => f(y);
常见修复方法
#如果可能,请重写代码,以便静态类型可分配。在上面的示例中,您可能可以更改参数y
的类型
String f(String x) => x;
String g(String y) => f(y);
如果无法进行此修复,则添加代码以处理参数值不是所需类型的情况。一种方法是将其他类型强制转换为所需类型
String f(String x) => x;
String g(num y) => f(y.toString());
另一种方法是添加显式类型测试和回退代码
String f(String x) => x;
String g(Object y) => f(y is String ? y : '');
如果您认为参数的运行时类型将始终与参数的静态类型相同,并且您愿意冒在运行时抛出异常的风险(如果您错了),则添加显式强制转换
String f(String x) => x;
String g(num y) => f(y as String);
参数类型不可赋值给错误处理程序
#参数类型“{0}”无法分配给参数类型“{1} Function(Object)”或“{1} Function(Object, StackTrace)”。
描述
#当Future.catchError
的调用具有一个参数,该参数是一个函数,其参数与调用该函数时传递给该函数的参数不兼容时,分析器会生成此诊断信息。catchError
的第一个参数的静态类型只是Function
,即使传递的函数预计将具有一个类型为Object
的参数或两个类型为Object
和StackTrace
的参数。
示例
#以下代码会生成此诊断信息,因为传递给catchError
的闭包不接受任何参数,但该函数需要至少接受一个参数
void f(Future<int> f) {
f.catchError(() => 0);
}
以下代码会生成此诊断信息,因为传递给catchError
的闭包接受三个参数,但它不能超过两个必需参数
void f(Future<int> f) {
f.catchError((one, two, three) => 0);
}
以下代码会生成此诊断信息,因为即使传递给catchError
的闭包接受一个参数,该闭包的类型也不与Object
兼容
void f(Future<int> f) {
f.catchError((String error) => 0);
}
常见修复方法
#更改传递给catchError
的函数,使其具有一个或两个必需参数,并且参数具有所需的类型
void f(Future<int> f) {
f.catchError((Object error) => 0);
}
重定向构造函数中的断言
#重定向构造函数不能包含“assert”初始化器。
描述
#当重定向构造函数(将构造函数重定向到同一类中的另一个构造函数的构造函数)在初始化列表中包含断言时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为未命名的构造函数是重定向构造函数,并且在初始化列表中也包含断言
class C {
C(int x) : assert(x > 0), this.name();
C.name() {}
}
常见修复方法
#如果不需要断言,则将其删除
class C {
C(int x) : this.name();
C.name() {}
}
如果需要断言,则将构造函数转换为工厂构造函数
class C {
factory C(int x) {
assert(x > 0);
return C.name();
}
C.name() {}
}
资产目录不存在
#资产目录“{0}”不存在。
描述
#当资产列表包含引用不存在的目录的值时,分析器会生成此诊断信息。
示例
#假设目录assets
不存在,以下代码会生成此诊断信息,因为它被列为包含资产的目录
name: example
flutter:
assets:
- assets/
常见修复方法
#如果路径正确,则在该路径上创建一个目录。
如果路径不正确,则将路径更改为与包含资产的目录的路径匹配。
资产不存在
#资产文件“{0}”不存在。
描述
#当资产列表包含引用不存在的文件的值时,分析器会生成此诊断信息。
示例
#假设文件doesNotExist.gif
不存在,以下代码会生成此诊断信息,因为它被列为资产
name: example
flutter:
assets:
- doesNotExist.gif
常见修复方法
#如果路径正确,则在该路径上创建一个文件。
如果路径不正确,则将路径更改为与包含资产的文件的路径匹配。
资产字段不是列表
#预期“assets”字段的值为相对文件路径列表。
描述
#当assets
键的值不是列表时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为assets
键的值是字符串,而预期的是列表
name: example
flutter:
assets: assets/
常见修复方法
#更改资产列表的值,使其成为列表
name: example
flutter:
assets:
- assets/
资产缺少路径
#资产映射条目必须包含“path”字段。
描述
#当资产映射缺少path
值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为资产映射缺少path
值
name: example
flutter:
assets:
- flavors:
- premium
常见修复方法
#更改资产映射,使其包含一个path
字段,该字段具有字符串值(有效的 POSIX 风格文件路径)
name: example
flutter:
assets:
- path: assets/image.gif
flavors:
- premium
资产不是字符串
#资产必须是文件路径(字符串)。
描述
#当assets
列表包含不是字符串的值时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为assets
列表包含一个映射。
name: example
flutter:
assets:
- image.gif: true
常见修复方法
#更改assets
列表,使其仅包含有效的 POSIX 风格文件路径。
name: example
flutter:
assets:
- assets/image.gif
资产不是字符串或映射
#资产值需要是文件路径(字符串)或映射。
描述
#当资产值不是字符串或映射时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为资产值是一个列表。
name: example
flutter:
assets:
- [one, two, three]
常见修复方法
#如果您需要指定除资产路径之外的其他内容,请用包含path
键(有效的 POSIX 风格文件路径)的映射替换该值。
name: example
flutter:
assets:
- path: assets/image.gif
flavors:
- premium
如果您只需要指定路径,请用资产的路径(有效的 POSIX 风格文件路径)替换该值。
name: example
flutter:
assets:
- assets/image.gif
资产路径不是字符串
#资产路径需要是文件路径(字符串)。
描述
#当资产映射包含一个不是字符串的path
值时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为资产映射包含一个值为列表的path
值。
name: example
flutter:
assets:
- path: [one, two, three]
flavors:
- premium
常见修复方法
#更改asset
映射,使其包含一个值为字符串(有效的 POSIX 风格文件路径)的path
值。
name: example
flutter:
assets:
- path: image.gif
flavors:
- premium
对“不存储”的赋值
#'{0}' 被标记为 'doNotStore',不应该被分配给字段或顶级变量。
描述
#当显式或隐式地用 doNotStore
注解标记的函数(包括方法和 getter)的值存储在字段或顶级变量中时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为函数f
的值被存储在顶级变量x
中。
import 'package:meta/meta.dart';
@doNotStore
int f() => 1;
var x = f();
常见修复方法
#用调用生成值的函数来替换对字段或变量的引用。
对常量的赋值
#常量变量不能被分配值。
描述
#当分析器发现对具有const
修饰符的顶级变量、静态字段或局部变量的赋值时,会产生此诊断信息。编译时常量的值在运行时不能更改。
示例
#以下代码产生此诊断信息,因为c
被分配了一个值,即使它具有const
修饰符。
const c = 0;
void f() {
c = 1;
print(c);
}
常见修复方法
#如果变量必须是可赋值的,则删除const
修饰符。
var c = 0;
void f() {
c = 1;
print(c);
}
如果常量不应该被更改,则要么删除赋值,要么使用局部变量来代替对常量的引用。
const c = 0;
void f() {
var v = 1;
print(v);
}
对 final 的赋值
#'{0}' 不能用作 setter,因为它已 final。
描述
#当分析器发现对 setter 的调用,但没有 setter,因为具有相同名称的字段被声明为final
或const
时,会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为v
是 final。
class C {
final v = 0;
}
f(C c) {
c.v = 1;
}
常见修复方法
#如果需要设置字段的值,则从字段中删除修饰符final
class C {
int v = 0;
}
f(C c) {
c.v = 1;
}
对 final 局部变量的赋值
#final 变量 '{0}' 只能设置一次。
描述
#当声明为 final 的局部变量在初始化后被赋值时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为x
是 final 的,所以它在初始化后不能被赋值。
void f() {
final x = 0;
x = 3;
print(x);
}
常见修复方法
#删除关键字final
,如果没有任何类型注释,则用var
替换它。
void f() {
var x = 0;
x = 3;
print(x);
}
对 final 的赋值,没有 setter
#类 '{1}' 中没有名为 '{0}' 的 setter。
描述
#当找到 setter 的引用时,分析器会产生此诊断;该类型没有定义 setter;但有一个同名的 getter 定义。
示例
#以下代码会产生此诊断,因为C
中没有名为x
的 setter,但有一个名为x
的 getter。
class C {
int get x => 0;
set y(int p) {}
}
void f(C c) {
c.x = 1;
}
常见修复方法
#如果要调用现有的 setter,请更正名称。
class C {
int get x => 0;
set y(int p) {}
}
void f(C c) {
c.y = 1;
}
如果要调用 setter 但它还不存在,请声明它。
class C {
int get x => 0;
set x(int p) {}
set y(int p) {}
}
void f(C c) {
c.x = 1;
}
对函数的赋值
#函数不能被赋值。
描述
#当函数的名称出现在赋值表达式的左侧时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为对函数f
的赋值无效。
void f() {}
void g() {
f = () {};
}
常见修复方法
#如果右侧应该被赋值给其他东西,例如局部变量,则更改左侧。
void f() {}
void g() {
var x = () {};
print(x);
}
如果意图是更改函数的实现,则定义一个函数值变量而不是函数。
void Function() f = () {};
void g() {
f = () {};
}
对方法的赋值
#方法不能被赋值。
描述
#当赋值的目标是方法时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为f
不能被赋值,因为它是一个方法。
class C {
void f() {}
void g() {
f = null;
}
}
常见修复方法
#重写代码,使其不包含对方法的赋值。
对类型的赋值
#类型不能被赋值。
描述
#当类型名称出现在赋值表达式的左侧时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为对类C
的赋值无效。
class C {}
void f() {
C = null;
}
常见修复方法
#如果右侧应该被赋值给其他东西,例如局部变量,则更改左侧。
void f() {}
void g() {
var c = null;
print(c);
}
异步 for in 错误的上下文中
#async for-in 循环只能在 async 函数中使用。
描述
#当在函数或方法中找到 async for-in 循环时,分析器会产生此诊断,其主体未标记为async
或async*
。
示例
#以下代码产生此诊断是因为f
的函数体没有标记为async
或async*
,但f
包含一个异步for-in循环。
void f(list) {
await for (var e in list) {
print(e);
}
}
常见修复方法
#如果函数应该返回一个Future
,则用async
标记函数体。
Future<void> f(list) async {
await for (var e in list) {
print(e);
}
}
如果函数应该返回一个Stream
的值,则用async*
标记函数体。
Stream<void> f(list) async* {
await for (var e in list) {
print(e);
}
}
如果函数应该是同步的,则删除循环前的await
。
void f(list) {
for (var e in list) {
print(e);
}
}
延迟局部变量初始化器中的 await
#在“late”局部变量的初始化器中不能使用“await”表达式。
描述
#当使用late
修饰符的局部变量在其初始化器中使用await
表达式时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为在v
的初始化器中使用了await
表达式,而v
是一个标记为late
的局部变量。
Future<int> f() async {
late var v = await 42;
return v;
}
常见修复方法
#如果初始化器可以重写为不使用await
,则重写它。
Future<int> f() async {
late var v = 42;
return v;
}
如果初始化器不能重写,则删除late
修饰符。
Future<int> f() async {
var v = await 42;
return v;
}
不兼容类型的 await
#对于扩展类型不是“Future”子类型的表达式,不能使用“await”表达式。
描述
#当await
表达式中表达式的类型为扩展类型,且扩展类型不是Future
的子类时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为扩展类型E
不是Future
的子类。
extension type E(int i) {}
void f(E e) async {
await e;
}
常见修复方法
#如果扩展类型定义正确,则删除await
。
extension type E(int i) {}
void f(E e) {
e;
}
如果扩展类型旨在可等待,则在implements
子句中添加Future
(或Future
的子类型)(如果不存在则添加implements
子句),并使表示类型匹配。
extension type E(Future<int> i) implements Future<int> {}
void f(E e) async {
await e;
}
主体可能正常完成
#函数体可能正常完成,导致返回“null”,但返回类型“{0}”是一个可能非空类型。
描述
#当方法或函数的返回类型是可能非空类型,但如果控制流到达函数末尾会隐式返回null
时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为方法m
在方法末尾插入了null
的隐式返回,但方法声明为不返回null
。
class C {
int m(int t) {
print(t);
}
}
以下代码产生此诊断是因为方法m
在方法末尾插入了null
的隐式返回,但由于类C
可以用非空类型参数实例化,因此方法实际上声明为不返回null
。
class C<T> {
T m(T t) {
print(t);
}
}
常见修复方法
#如果存在可以返回的合理值,则在方法末尾添加一个return
语句。
class C<T> {
T m(T t) {
print(t);
return t;
}
}
如果方法不会到达隐式返回,则在方法末尾添加一个throw
。
class C<T> {
T m(T t) {
print(t);
throw '';
}
}
如果方法在末尾有意返回null
,则在方法末尾添加一个显式返回null
,并更改返回类型,使其可以返回null
。
class C<T> {
T? m(T t) {
print(t);
return null;
}
}
主体可能正常完成,捕获错误
#此“onError”处理程序必须返回一个可分配给“{0}”的值,但结束时没有返回值。
描述
#当传递给Future.catchError
方法的onError
参数的闭包需要返回非null
值(由于Future
的类型参数)但可以隐式返回null
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为传递给catchError
方法的闭包需要返回一个int
,但没有以显式的return
结束,导致它隐式返回null
void g(Future<int> f) {
f.catchError((e, st) {});
}
常见修复方法
#如果闭包有时应该返回非null
值,则在闭包中添加显式返回
void g(Future<int> f) {
f.catchError((e, st) {
return -1;
});
}
如果闭包应该始终返回null
,则将Future
的类型参数更改为void
或Null
void g(Future<void> f) {
f.catchError((e, st) {});
}
主体可能正常完成,可为空
#此函数的可空返回类型为“{0}”,但结束时没有返回值。
描述
#当方法或函数可以通过从末尾掉落隐式返回null
时,分析器会生成此诊断信息。虽然这是有效的 Dart 代码,但最好让null
的返回显式。
示例
#以下代码会生成此诊断信息,因为函数f
隐式返回null
String? f() {}
常见修复方法
#如果null
的返回是故意的,则将其显式化
String? f() {
return null;
}
如果函数应该沿着该路径返回非空值,则添加缺少的 return 语句
String? f() {
return '';
}
switch 成员上的 break 标签
#break 标签解析为“case”或“default”语句。
描述
#当 switch 语句中的 case 子句中的 break 具有与另一个 case 子句关联的标签时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为标签l
与0
的 case 子句相关联
void f(int i) {
switch (i) {
l: case 0:
break;
case 1:
break l;
}
}
常见修复方法
#如果意图是将控制权转移到 switch 后的语句,则从 break 语句中删除标签
void f(int i) {
switch (i) {
case 0:
break;
case 1:
break;
}
}
如果意图是将控制权转移到不同的 case 块,则使用continue
而不是break
void f(int i) {
switch (i) {
l: case 0:
break;
case 1:
continue l;
}
}
内置标识符作为类型
#内置标识符“{0}”不能用作类型。
描述
#当在需要类型名称的地方使用内置标识符时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为import
不能用作类型,因为它是一个内置标识符
import<int> x;
常见修复方法
#用有效类型的名称替换内置标识符
List<int> x;
声明中的内置标识符
#内置标识符“{0}”不能用作前缀名称。
内置标识符“{0}”不能用作类型名称。
内置标识符“{0}”不能用作类型参数名称。
内置标识符“{0}”不能用作 typedef 名称。
内置标识符“{0}”不能用作扩展名。
内置标识符“{0}”不能用作扩展类型名。
描述
#当在类、扩展、mixin、typedef、类型参数或导入前缀的声明中使用的名称是内置标识符时,分析器会生成此诊断信息。内置标识符不能用于命名任何这些类型的声明。
示例
#以下代码会生成此诊断信息,因为mixin
是一个内置标识符
extension mixin on int {}
常见修复方法
#为声明选择一个不同的名称。
回调不能使用 TypedData
#FFI 回调不能接受类型化数据参数或返回值。
描述
#当Pointer.fromFunction
的调用,NativeCallable
的构造函数之一具有类型化数据参数或返回值时,分析器会生成此诊断信息。
类型化数据解包仅在叶 FFI 调用的参数上受支持。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为g
的参数类型是类型化数据。
import 'dart:ffi';
import 'dart:typed_data';
void f(Uint8List i) {}
void g() {
Pointer.fromFunction<Void Function(Pointer<Uint8>)>(f);
}
常见修复方法
#使用Pointer
类型代替。
import 'dart:ffi';
void f(Pointer<Uint8> i) {}
void g() {
Pointer.fromFunction<Void Function(Pointer<Uint8>)>(f);
}
调用不能返回 TypedData
#FFI 调用不能返回类型化数据。
描述
#当Pointer.asFunction
、DynamicLibrary.lookupFunction
或@Native
的返回类型是类型化数据时,分析器会生成此诊断信息。
类型化数据解包仅在叶 FFI 调用的参数上受支持。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为 dart 函数签名包含类型化数据,但isLeaf
参数为false
import 'dart:ffi';
import 'dart:typed_data';
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
p.asFunction<Uint8List Function()>();
}
常见修复方法
#使用Pointer
类型代替。
import 'dart:ffi';
void f(Pointer<NativeFunction<Pointer<Uint8> Function()>> p) {
p.asFunction<Pointer<Uint8> Function()>();
}
case 块未终止
#'case' 的最后一条语句应该是 'break'、'continue'、'rethrow'、'return' 或 'throw'。
描述
#当case
块中的最后一条语句不是必需的终止符之一时,分析器会生成此诊断信息:break
、continue
、rethrow
、return
或throw
。
示例
#以下代码会生成此诊断信息,因为case
块以赋值结束
void f(int x) {
switch (x) {
case 0:
x += 2;
default:
x += 1;
}
}
常见修复方法
#添加必需的终止符之一。
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
覆盖了==
运算符
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 结构。
class C {
final int value;
const C(this.value);
bool operator ==(Object other) {
return false;
}
}
void f(C c) {
if (c == C(0)) {
// ...
}
}
如果无法重写 switch 语句,并且==
的实现不是必需的,请将其删除。
class C {
final int value;
const C(this.value);
}
void f(C c) {
switch (c) {
case C(0):
break;
}
}
如果您无法重写 switch 语句,也无法删除 ==
的定义,那么请查找其他可用于控制 switch 的值。
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
后面表达式静态类型的子类型的静态类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 1
是一个 int
,它不是 String
(s
的类型)的子类型。
void f(String s) {
switch (s) {
case 1:
break;
}
}
常见修复方法
#如果 case
表达式的值错误,请更改 case
表达式,使其具有所需的类型。
void f(String s) {
switch (s) {
case '1':
break;
}
}
如果 case
表达式的值正确,请更改 switch
表达式,使其具有所需的类型。
void f(int s) {
switch (s) {
case 1:
break;
}
}
从可为空的强制转换总是失败
#此强制转换将始终抛出异常,因为可空局部变量“{0}”未赋值。
描述
#当具有可空类型的局部变量未赋值且强制转换为非可空类型时,分析器会生成此诊断。由于变量未赋值,因此它具有 null
的默认值,导致强制转换抛出异常。
示例
#以下代码会生成此诊断,因为变量 x
在已知具有 null
值的情况下强制转换为非可空类型(int
)。
void f() {
num? x;
x as int;
print(x);
}
常见修复方法
#如果预期变量在强制转换之前具有值,请添加初始化程序或赋值。
void f() {
num? x = 3;
x as int;
print(x);
}
如果预期变量不会被赋值,请删除强制转换。
void f() {
num? x;
print(x);
}
从 null 的强制转换总是失败
#此强制转换始终抛出异常,因为表达式始终计算为“null”。
描述
#当类型为 Null
的表达式强制转换为非可空类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为已知 n
始终为 null
,但它被强制转换为非可空类型。
void f(Null n) {
n as int;
}
常见修复方法
#删除不必要的强制转换。
void f(Null n) {
n;
}
强制转换为非类型
#名称“{0}”不是类型,因此不能在“as”表达式中使用。
描述
#当强制转换表达式中 as
后面的名称被定义为除类型以外的其他内容时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 x
是一个变量,而不是一个类型。
num x = 0;
int y = x as x;
常见修复方法
#将名称替换为类型的名称
num x = 0;
int y = x as int;
类用作 mixin
#类 '{0}' 不能用作 mixin,因为它既不是 mixin 类也不是 mixin。
描述
#当在 with
子句中使用既不是 mixin class
也不是 mixin
的类时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 M
用作 mixin,但它没有定义为 mixin class
class M {}
class C with M {}
常见修复方法
#如果该类可以是纯 mixin,则将 class
更改为 mixin
mixin M {}
class C with M {}
如果该类既需要是类又需要是 mixin,则添加 mixin
mixin class M {}
class C with M {}
集合元素来自延迟库
#来自延迟库的常量值不能用作 'const' 映射文字中的键。
来自延迟库的常量值不能用作 'const' 构造函数中的值。
来自延迟库的常量值不能用作 'const' 列表文字中的值。
来自延迟库的常量值不能用作 'const' 映射文字中的值。
来自延迟库的常量值不能用作 'const' 集合文字中的值。
描述
#当显式(因为它以 const
关键字为前缀)或隐式(因为它出现在 常量上下文 中)为常量的集合文字包含在使用延迟导入导入的库中声明的值时,分析器会生成此诊断信息。常量在编译时进行评估,而来自延迟库的值在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义常量 zero
的文件 a.dart
const zero = 0;
以下代码会生成此诊断信息,因为常量列表文字包含 a.zero
,它使用 deferred
导入进行导入
import 'a.dart' deferred as a;
var l = const [a.zero];
常见修复方法
#如果集合文字不需要是常量,则删除 const
关键字
import 'a.dart' deferred as a;
var l = [a.zero];
如果集合需要是常量并且必须引用导入的常量,则从导入中删除关键字 deferred
import 'a.dart' as a;
var l = const [a.zero];
如果您不需要引用常量,则用合适的值替换它
var l = const [0];
复合实现 finalizable
#类 '{0}' 不能实现 Finalizable。
描述
#当 Struct
或 Union
的子类实现 Finalizable
时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为类 S
实现 Finalizable
import 'dart:ffi';
final class S extends Struct implements Finalizable {
external Pointer notEmpty;
}
常见修复方法
#尝试从类中移除 implements 子句。
import 'dart:ffi';
final class S extends Struct {
external Pointer notEmpty;
}
具体类具有枚举超接口
#具体类不能以 'Enum' 作为超接口。
描述
#当具体类间接以类 Enum
作为超接口时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为具体类 B
通过实现 A
以 Enum
作为超接口。
abstract class A implements Enum {}
class B implements A {}
常见修复方法
#如果实现的类不是你想要实现的类,请更改它。
abstract class A implements Enum {}
class B implements C {}
class C {}
如果实现的类可以更改为不实现 Enum
,请这样做。
abstract class A {}
class B implements A {}
如果实现的类无法更改为不实现 Enum
,请将其从 implements
子句中移除。
abstract class A implements Enum {}
class B {}
具有抽象成员的具体类
#'{0}' 必须有方法体,因为 '{1}' 不是抽象的。
描述
#当分析器发现具体类中的成员没有具体实现时,会产生此诊断信息。具体类不允许包含抽象成员。
示例
#以下代码会产生此诊断信息,因为 m
是一个抽象方法,但 C
不是一个抽象类。
class C {
void m();
}
常见修复方法
#如果可以创建类的实例,请为该成员提供实现。
class C {
void m() {}
}
如果不能创建类的实例,请将该类标记为抽象类。
abstract class C {
void m();
}
构造函数和静态成员冲突
#'{0}' 不能同时用于命名构造函数和静态字段。
'{0}' 不能同时用于命名构造函数和静态 getter。
'{0}' 不能同时用于命名构造函数和静态方法。
'{0}' 不能同时用于命名构造函数和静态 setter。
描述
#当命名构造函数和静态方法或静态字段具有相同的名称时,分析器会产生此诊断信息。两者都使用类的名称进行访问,因此具有相同的名称会导致引用不明确。
示例
#以下代码会产生此诊断信息,因为静态字段 foo
和命名构造函数 foo
具有相同的名称。
class C {
C.foo();
static int foo = 0;
}
以下代码会产生此诊断信息,因为静态方法 foo
和命名构造函数 foo
具有相同的名称。
class C {
C.foo();
static void foo() {}
}
常见修复方法
#重命名成员或构造函数。
冲突的泛型接口
#{0} '{1}' 不能同时实现 '{2}' 和 '{3}',因为类型参数不同。
描述
#当类尝试多次实现泛型接口,并且类型参数的值不同时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 C
被定义为同时实现 I<int>
(因为它扩展了 A
)和 I<String>
(因为它实现了 B
),但 int
和 String
不是相同的类型。
class I<T> {}
class A implements I<int> {}
class B implements I<String> {}
class C extends A implements B {}
常见修复方法
#重新设计类型层次结构以避免这种情况。例如,你可以使一个或两个继承类型成为泛型,以便 C
可以为两个类型参数指定相同的类型。
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
的名称相同
class C<C> {}
常见修复方法
#重命名类型参数或类、mixin 或扩展
class C<T> {}
冲突的类型变量和成员
#'{0}' 不能同时用作类型变量和此类中的成员的名称。
'{0}' 不能同时用作类型变量和此枚举中的成员的名称。
'{0}' 不能同时用作类型变量和此扩展类型中的成员的名称。
'{0}' 不能同时用作类型变量和此扩展中的成员的名称。
'{0}' 不能同时用作类型变量和此 mixin 中的成员的名称。
描述
#当类、mixin 或扩展声明使用与声明它的类、mixin 或扩展的成员之一相同的名称声明类型参数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为类型参数 T
与字段 T
的名称相同
class C<T> {
int T = 0;
}
常见修复方法
#重命名类型参数或与之冲突的成员
class C<T> {
int total = 0;
}
常量模式永远不会匹配值类型
#匹配的值类型 '{0}' 永远不可能等于此类型为 '{1}' 的常量。
描述
#当常量模式永远无法匹配它正在测试的值,因为常量的类型已知永远不会匹配值的类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为常量模式 (true)
的类型为 bool
,而正在匹配的值 (x
) 的类型为 int
,布尔值永远无法匹配整数
void f(int x) {
if (x case true) {}
}
常见修复方法
#如果值的类型正确,请重写模式以使其兼容
void f(int x) {
if (x case 3) {}
}
如果常量的类型正确,则重写该值以使其兼容。
void f(bool x) {
if (x case true) {}
}
常量模式使用非常量表达式
#常量模式的表达式必须是有效的常量。
描述
#当常量模式的表达式不是有效的常量时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为常量模式 i
不是常量。
void f(int e, int i) {
switch (e) {
case i:
break;
}
}
常见修复方法
#如果要匹配的值已知,则将表达式替换为常量。
void f(int e, int i) {
switch (e) {
case 0:
break;
}
}
如果要匹配的值未知,则重写代码以不使用模式。
void f(int e, int i) {
if (e == i) {}
}
常量构造函数参数类型不匹配
#类型为 '{0}' 的值不能分配给常量构造函数中类型为 '{1}' 的参数。
描述
#当常量值的运行时类型不能分配给常量构造函数参数的静态类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 i
的运行时类型为 int
,它不能分配给 s
的静态类型。
class C {
final String s;
const C(this.s);
}
const dynamic i = 0;
void f() {
const C(i);
}
常见修复方法
#将正确类型的传递给构造函数。
class C {
final String s;
const C(this.s);
}
const dynamic i = 0;
void f() {
const C('$i');
}
常量构造函数使用非常量初始化字段
#无法定义 'const' 构造函数,因为字段 '{0}' 使用非常量值初始化。
描述
#当构造函数具有关键字 const
,但类中的字段初始化为非常量值时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为字段 s
初始化为非常量值。
String x = '3';
class C {
final String s = x;
const C();
}
常见修复方法
#如果字段可以初始化为常量值,则将初始化程序更改为常量表达式。
class C {
final String s = '3';
const C();
}
如果字段不能初始化为常量值,则从构造函数中删除关键字 const
。
String x = '3';
class C {
final String s = x;
C();
}
常量构造函数使用非常量超类
#常量构造函数不能调用 '{0}' 的非常量超级构造函数。
描述
#当标记为 const
的构造函数调用其超类中未标记为 const
的构造函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 B
中的 const
构造函数调用了类 A
中的构造函数 nonConst
,而超类构造函数不是 const
构造函数。
class A {
const A();
A.nonConst();
}
class B extends A {
const B() : super.nonConst();
}
常见修复方法
#如果调用当前正在调用的超类构造函数不是必需的,则调用超类中的常量构造函数。
class A {
const A();
A.nonConst();
}
class B extends A {
const B() : super();
}
如果必须调用当前构造函数,并且可以修改它,则在超类中的构造函数中添加 const
。
class A {
const A();
const A.nonConst();
}
class B extends A {
const B() : super.nonConst();
}
如果必须调用当前构造函数并且无法修改它,则从子类中的构造函数中删除const
。
class A {
const A();
A.nonConst();
}
class B extends A {
B() : super.nonConst();
}
常量构造函数使用非 final 字段
#无法为具有非final字段的类定义const构造函数。
描述
#当构造函数被标记为const构造函数,但构造函数是在至少包含一个非final实例字段(直接或通过继承)的类中定义时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字段x
不是final。
class C {
int x;
const C(this.x);
}
常见修复方法
#如果可以将所有字段标记为final,则这样做。
class C {
final int x;
const C(this.x);
}
如果无法将所有字段标记为final,则从构造函数中删除关键字const
。
class C {
int x;
C(this.x);
}
常量延迟类
#延迟类不能使用'const'创建。
描述
#当使用延迟导入导入的库中的类用于创建const
对象时,分析器会产生此诊断。常量在编译时进行评估,而延迟库中的类在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#以下代码会产生此诊断,因为它尝试从延迟库中创建const
类的实例。
import 'dart:convert' deferred as convert;
const json2 = convert.JsonCodec();
常见修复方法
#如果对象不需要是常量,则更改代码以创建非常量实例。
import 'dart:convert' deferred as convert;
final json2 = convert.JsonCodec();
如果对象必须是常量,则从导入指令中删除deferred
。
import 'dart:convert' as convert;
const json2 = convert.JsonCodec();
常量使用非常量值初始化
#常量变量必须用常量值初始化。
描述
#当将静态无法确定为常量的值分配给声明为const
变量的变量时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为x
没有声明为const
。
var x = 0;
const y = x;
常见修复方法
#如果要分配的值可以声明为const
,则更改声明。
const x = 0;
const y = x;
如果值不能声明为const
,则从变量中删除const
修饰符,可能使用final
代替。
var x = 0;
final y = x;
常量使用来自延迟库的非常量值初始化
#延迟库中的常量值不能用于初始化'const'变量。
描述
#当使用延迟导入导入的库中的const
变量初始化const
变量时,分析器会产生此诊断。常量在编译时进行评估,而延迟库中的值在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#以下代码会产生此诊断,因为变量pi
正在使用库dart:math
中的常量math.pi
进行初始化,而dart:math
被导入为延迟库。
import 'dart:math' deferred as math;
const pi = math.pi;
常见修复方法
#如果您需要引用从导入库中导入的常量的值,则删除关键字deferred
import 'dart:math' as math;
const pi = math.pi;
如果您不需要引用导入的常量,则删除引用
const pi = 3.14;
常量实例字段
#只有静态字段可以声明为常量。
描述
#当实例字段被标记为常量时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为f
是一个实例字段
class C {
const int f = 3;
}
常见修复方法
#如果该字段需要是一个实例字段,则删除关键字const
,或将其替换为final
class C {
final int f = 3;
}
如果该字段确实应该是一个常量字段,则将其设为静态字段
class C {
static const int f = 3;
}
常量映射键不是原始相等性
#常量映射中的键的类型不能重写'=='运算符或'hashCode',但类'{0}'却重写了。
描述
#当常量映射文字中用作键的对象的类实现==
运算符、hashCode
获取器或两者时,分析器会生成此诊断信息。常量映射的实现同时使用==
运算符和hashCode
获取器,因此除了从Object
继承的实现之外,任何其他实现都需要在编译时执行任意代码,这是不支持的。
示例
#以下代码会生成此诊断信息,因为常量映射包含一个类型为C
的键,而类C
重写了==
的实现
class C {
const C();
bool operator ==(Object other) => true;
}
const map = {C() : 0};
以下代码会生成此诊断信息,因为常量映射包含一个类型为C
的键,而类C
重写了hashCode
的实现
class C {
const C();
int get hashCode => 3;
}
const map = {C() : 0};
常见修复方法
#如果您能从类中删除==
和hashCode
的实现,请这样做
class C {
const C();
}
const map = {C() : 0};
如果您不能从类中删除==
和hashCode
的实现,请将映射设为非常量
class C {
const C();
bool operator ==(Object other) => true;
}
final map = {C() : 0};
常量未初始化
#常量'{0}'必须初始化。
描述
#当声明为常量的变量没有初始化器时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为c
没有初始化
const c;
常见修复方法
#添加一个初始化器
const c = 'c';
常量集合元素不是原始相等性
#const_set_element_type_implements_equals
)
常量集合中的元素不能重写'=='运算符或'hashCode',但类型'{0}'却重写了。
描述
#当用作常量集合文字元素的对象类实现==
运算符、hashCode
获取器或两者时,分析器会生成此诊断信息。常量集合的实现同时使用==
运算符和hashCode
获取器,因此除了从Object
继承的实现之外,任何其他实现都需要在编译时执行任意代码,这是不支持的。
示例
#以下代码会生成此诊断信息,因为常量集合包含一个类型为C
的元素,而类C
重写了==
的实现。
class C {
const C();
bool operator ==(Object other) => true;
}
const set = {C()};
以下代码会生成此诊断信息,因为常量集合包含一个类型为C
的元素,而类C
重写了hashCode
的实现。
class C {
const C();
int get hashCode => 3;
}
const map = {C()};
常见修复方法
#如果您能从类中删除==
和hashCode
的实现,请这样做
class C {
const C();
}
const set = {C()};
如果无法从类中删除==
和hashCode
的实现,则将集合设为非常量。
class C {
const C();
bool operator ==(Object other) => true;
}
final set = {C()};
常量展开预期列表或集合
#在此展开中需要一个列表或集合。
描述
#当常量列表或集合中展开运算符的表达式计算结果不是列表或集合时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为list1
的值为null
,既不是列表也不是集合。
const dynamic list1 = 42;
const List<int> list2 = [...list1];
常见修复方法
#将表达式更改为计算结果为常量列表或常量集合的表达式。
const dynamic list1 = [42];
const List<int> list2 = [...list1];
常量展开预期映射
#在此展开中需要一个映射。
描述
#当常量映射中展开运算符的表达式计算结果不是映射时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为map1
的值为null
,不是映射。
const dynamic map1 = 42;
const Map<String, int> map2 = {...map1};
常见修复方法
#将表达式更改为计算结果为常量映射的表达式。
const dynamic map1 = {'answer': 42};
const Map<String, int> map2 = {...map1};
常量使用非常量
#正在调用的构造函数不是常量构造函数。
描述
#当使用const
关键字调用未标记为const
的构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为A
中的构造函数不是常量构造函数。
class A {
A();
}
A f() => const A();
常见修复方法
#如果希望并将类设为常量类(通过将类中所有字段,包括继承的字段,设为final),则在构造函数中添加const
关键字。
class A {
const A();
}
A f() => const A();
否则,删除const
关键字。
class A {
A();
}
A f() => A();
常量使用非常量参数
#常量创建的参数必须是常量表达式。
描述
#当使用不是常量表达式的参数调用常量构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为i
不是常量。
class C {
final int i;
const C(this.i);
}
C f(int i) => const C(i);
常见修复方法
#要么将所有参数设为常量表达式,要么删除const
关键字以使用构造函数的非常量形式。
class C {
final int i;
const C(this.i);
}
C f(int i) => C(i);
常量使用类型参数
#常量构造函数撕裂不能使用类型参数作为类型参数。
常量创建不能使用类型参数作为类型参数。
常量函数撕裂不能使用类型参数作为类型参数。
描述
#当类型参数用作构造函数的 const
调用中的类型参数时,分析器会生成此诊断信息。这是不允许的,因为类型参数的值(将在运行时使用的实际类型)在编译时无法知道。
示例
#以下代码会生成此诊断信息,因为类型参数 T
在创建常量时用作类型参数
class C<T> {
const C();
}
C<T> newC<T>() => const C<T>();
常见修复方法
#如果在编译时可以知道将用于类型参数的类型,则删除类型参数的使用
class C<T> {
const C();
}
C<int> newC() => const C<int>();
如果在运行时才能知道将用于类型参数的类型,则删除关键字 const
class C<T> {
const C();
}
C<T> newC<T>() => C<T>();
continue 标签无效
#continue_label_on_switch
)
'continue' 语句中使用的标签必须在循环或 switch 成员上定义。
描述
#当 continue
语句中的标签解析为 switch
语句上的标签时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为用于标记 switch
语句的标签 l
在 continue
语句中使用
void f(int i) {
l: switch (i) {
case 0:
continue l;
}
}
常见修复方法
#找到另一种方法来实现所需的控制流;例如,通过引入一个重新执行 switch
语句的循环。
创建结构体或联合体
#'Struct' 和 'Union' 的子类由本机内存支持,不能通过生成式构造函数实例化。
描述
#当使用生成式构造函数实例化 Struct
或 Union
的子类时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为类 C
使用生成式构造函数实例化
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int a;
}
void f() {
C();
}
常见修复方法
#如果需要分配类描述的结构,则使用 ffi
包来执行此操作
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}' 不是类。
描述
#当使用 new
或 const
的实例创建指定未定义为类的名称时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 f
是函数而不是类
int f() => 0;
void g() {
new f();
}
常见修复方法
#如果要创建类,则将无效名称替换为有效类的名称
int f() => 0;
void g() {
new Object();
}
如果名称是函数的名称,并且希望调用该函数,则删除 new
或 const
关键字
int f() => 0;
void g() {
f();
}
无用代码
#无用代码。
描述
#当分析器发现代码不会被执行时,会产生此诊断信息,因为执行永远不会到达该代码。
示例
#以下代码会产生此诊断信息,因为print
的调用发生在函数返回之后
void f() {
return;
print('here');
}
常见修复方法
#如果不需要该代码,则将其删除
void f() {
return;
}
如果需要执行该代码,则将其移动到将被执行的位置
void f() {
print('here');
return;
}
或者,重写它之前的代码,以便可以到达它
void f({bool skipPrinting = true}) {
if (skipPrinting) {
return;
}
print('here');
}
无用代码,捕获后跟捕获
#无用代码:在 'catch (e)' 或 'on Object catch (e)' 之后的 catch 子句永远不会被执行。
描述
#当分析器发现一个无法执行的catch
子句时,会产生此诊断信息,因为该子句位于catch (e)
或on Object catch (e)
形式的catch
子句之后。第一个与抛出对象匹配的catch
子句将被选中,而这两种形式都将匹配任何对象,因此不会选中任何后续的catch
子句。
示例
#以下代码会生成此诊断信息
void f() {
try {
} catch (e) {
} on String {
}!]
}
常见修复方法
#如果该子句应该可选择,则将其移动到通用子句之前
void f() {
try {
} on String {
} catch (e) {
}
}
如果该子句不需要可选择,则将其删除
void f() {
try {
} catch (e) {
}
}
无用代码,在子类型捕获上
#无用代码:此 on-catch 块不会被执行,因为 '{0}' 是 '{1}' 的子类型,因此已经被捕获。
描述
#当分析器发现一个无法执行的catch
子句时,会产生此诊断信息,因为该子句位于一个捕获相同类型或其超类型的catch
子句之后。第一个与抛出对象匹配的catch
子句将被选中,而前面的子句始终匹配高亮显示子句可以匹配的任何内容,因此高亮显示子句永远不会被选中。
示例
#以下代码会生成此诊断信息
void f() {
try {
} on num {
} on int {
}!]
}
常见修复方法
#如果该子句应该可选择,则将其移动到通用子句之前
void f() {
try {
} on int {
} on num {
}
}
如果该子句不需要可选择,则将其删除
void f() {
try {
} on num {
}
}
无用空感知表达式
#左操作数不能为 null,因此右操作数永远不会被执行。
描述
#分析器在两种情况下会产生此诊断信息。
第一种情况是,??
运算符的左操作数不能为null
。只有当左操作数的值为null
时,才会计算右操作数,而由于左操作数不能为null
,因此右操作数永远不会被计算。
第二种情况是,使用??=
运算符的赋值语句的左侧不能为null
。只有当左侧的值为null
时,才会计算右侧,而由于左侧不能为null
,因此右侧永远不会被计算。
示例
#以下代码会产生此诊断信息,因为x
不能为null
int f(int x) {
return x ?? 0;
}
以下代码会产生此诊断信息,因为f
不能为null
class C {
int f = -1;
void m(int x) {
f ??= x;
}
}
常见修复方法
#如果诊断报告针对??
运算符,则删除??
运算符和右操作数
int f(int x) {
return x;
}
如果诊断报告针对赋值,并且赋值不需要,则删除赋值
class C {
int f = -1;
void m(int x) {
}
}
如果赋值需要,但应基于不同的条件,则重写代码以使用=
和不同的条件
class C {
int f = -1;
void m(int x) {
if (f < 0) {
f = x;
}
}
}
默认列表构造函数
#启用空安全时,默认的'List'构造函数不可用。
描述
#当分析器在已选择加入空安全的代码中找到对类List
的默认构造函数的使用时,它会生成此诊断。
示例
#假设以下代码已选择加入空安全,它会生成此诊断,因为它使用默认的List
构造函数
var l = List<int>();
常见修复方法
#如果没有提供初始大小,则将代码转换为使用列表文字
var l = <int>[];
如果需要提供初始大小,并且元素只有一个合理的初始值,则使用List.filled
var l = List.filled(3, 0);
如果需要提供初始大小,但每个元素都需要计算,则使用List.generate
var l = List.generate(3, (i) => i);
函数类型中的默认值
#函数类型中的参数不能具有默认值。
描述
#当与参数关联的函数类型包含具有默认值的可选参数时,分析器会生成此诊断。这是不允许的,因为参数的默认值不是函数类型的一部分,因此包含它们不会提供任何价值。
示例
#以下代码会生成此诊断,因为参数p
具有默认值,即使它是参数g
类型的部分
void f(void Function([int p = 0]) g) {
}
常见修复方法
#从函数类型参数中删除默认值
void f(void Function([int p]) g) {
}
重定向工厂构造函数中的默认值
#重定向到另一个构造函数的工厂构造函数中不允许使用默认值。
描述
#当重定向到另一个构造函数的工厂构造函数为可选参数指定默认值时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为A
中的工厂构造函数为可选参数x
指定了默认值
class A {
factory A([int x = 0]) = B;
}
class B implements A {
B([int x = 1]) {}
}
常见修复方法
#从工厂构造函数中删除默认值
class A {
factory A([int x]) = B;
}
class B implements A {
B([int x = 1]) {}
}
请注意,此修复可能会更改省略可选参数时使用的值。如果发生这种情况,并且该更改是一个问题,则考虑在工厂方法中将可选参数设为必需参数
class A {
factory A(int x) = B;
}
class B implements A {
B([int x = 1]) {}
}
必需参数上的默认值
#必需的命名参数不能具有默认值。
描述
#当命名参数同时具有required
修饰符和默认值时,分析器会生成此诊断。如果参数是必需的,则在调用站点始终提供参数的值,因此默认值永远不会被使用。
示例
#以下代码会生成此诊断
void log({required String message = 'no message'}) {}
常见修复方法
#如果参数确实是必需的,则删除默认值
void log({required String message}) {}
如果参数并非始终需要,则删除required
修饰符。
void log({String message = 'no message'}) {}
扩展的延迟导入
#延迟库的导入必须隐藏所有扩展。
描述
#当使用延迟导入导入的库声明在导入库中可见的扩展时,分析器会生成此诊断信息。扩展方法在编译时解析,而延迟库中的扩展在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义了命名扩展的a.dart
文件
class C {}
extension E on String {
int get size => length;
}
以下代码会生成此诊断信息,因为命名扩展对库可见
import 'a.dart' deferred as a;
void f() {
a.C();
}
常见修复方法
#如果库必须作为deferred
导入,则要么添加一个列出被引用的名称的show
子句,要么添加一个列出所有命名扩展的hide
子句。添加show
子句将如下所示
import 'a.dart' deferred as a show C;
void f() {
a.C();
}
添加hide
子句将如下所示
import 'a.dart' deferred as a hide E;
void f() {
a.C();
}
第一个修复的优点是,如果向导入的库添加了新的扩展,则这些扩展不会导致生成诊断信息。
如果库不需要作为deferred
导入,或者您需要使用其中声明的扩展方法,则删除关键字deferred
。
import 'a.dart' as a;
void f() {
a.C();
}
未赋值的延迟局部变量
#延迟局部变量 '{0}' 在此点处肯定未赋值。
描述
#当确定性赋值分析表明标记为late
的局部变量在赋值之前被读取时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为x
在读取之前没有被赋值
void f(bool b) {
late int x;
print(x);
}
常见修复方法
#在从变量读取之前为其赋值。
void f(bool b) {
late int x;
x = b ? 1 : 0;
print(x);
}
依赖项字段不是映射
#预期 '{0}' 字段的值为一个映射。
描述
#当dependencies
或dev_dependencies
键的值不是映射时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为顶层dependencies
键的值是一个列表
name: example
dependencies:
- meta
常见修复方法
#使用映射作为dependencies
键的值。
name: example
dependencies:
meta: ^1.0.2
默认值使用冒号已弃用
#在默认值之前使用冒号作为分隔符已过时,并且在语言版本 3.0 及更高版本中将不再支持。
描述
#当在可选命名参数的默认值之前使用冒号 (:
) 作为分隔符时,分析器会生成此诊断信息。虽然此语法允许,但它已过时,建议使用等号 (=
)。
示例
#以下代码会生成此诊断信息,因为在可选参数i
的默认值之前使用了冒号。
void f({int i : 0}) {}
常见修复方法
#将冒号替换为等号。
void f({int i = 0}) {}
已弃用的导出使用
#间接导入 '{0}' 的功能已弃用。
描述
#当一个库从第二个库导入一个名称,而第二个库从第三个库导出该名称,但已表明它将来不会导出第三个库时,分析器会生成此诊断信息。
示例
#假设有一个库 a.dart
定义了类 A
class A {}
以及一个第二个库 b.dart
,它导出 a.dart
,但已将导出标记为已弃用
import 'a.dart';
@deprecated
export 'a.dart';
以下代码会生成此诊断信息,因为类 A
在将来的某个版本中将不会从 b.dart
导出
import 'b.dart';
A? a;
常见修复方法
#如果该名称可从您可以导入的其他库获得,则将现有导入替换为该库的导入(或者如果您仍然需要旧导入,则添加定义库的导入)
import 'a.dart';
A? a;
如果该名称不可用,请查看库作者的说明或直接联系他们,了解如何更新您的代码。
已弃用的字段
#字段 '{0}' 已不再使用,可以删除。
描述
#当 pubspec.yaml
文件中使用已弃用的键时,分析器会生成此诊断信息。未使用的键会占用空间,并且可能暗示不再有效的语义。
示例
#以下代码会生成此诊断信息,因为 author
键已不再使用
name: example
author: 'Dash'
常见修复方法
#删除已弃用的键
name: example
已弃用的成员使用
#'{0}' 已弃用,不应使用。
'{0}' 已弃用,不应使用。{1}
描述
#当在不同的包中使用已弃用的库或类成员时,分析器会生成此诊断信息。
示例
#如果类 C
中的方法 m
用 @deprecated
注释,则以下代码会生成此诊断信息
void f(C c) {
c.m();
}
常见修复方法
#用 @deprecated
注释的声明的文档应指示使用什么代码来代替已弃用的代码。
来自同一包的已弃用的成员使用
#'{0}' 已弃用,不应使用。
'{0}' 已弃用,不应使用。{1}
描述
#当在声明它的同一个包中使用已弃用的库成员或类成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 x
已弃用
@deprecated
var x = 0;
var y = x;
常见修复方法
#修复方法取决于已弃用内容及其替换内容。已弃用声明的文档应指示使用什么代码来代替已弃用的代码。
注释引用中已弃用的 new
#在注释引用中使用 'new' 关键字已弃用。
描述
#当注释引用(文档注释中方括号内声明的名称)使用关键字new
引用构造函数时,分析器会生成此诊断信息。此形式已弃用。
示例
#以下代码会生成此诊断信息,因为未命名的构造函数使用new C
进行引用。
/// See [new C].
class C {
C();
}
以下代码会生成此诊断信息,因为名为c
的构造函数使用new C.c
进行引用。
/// See [new C.c].
class C {
C.c();
}
常见修复方法
#如果引用的是命名构造函数,则删除关键字new
。
/// See [C.c].
class C {
C.c();
}
如果引用的是未命名的构造函数,则删除关键字new
并在类名后追加.new
。
/// See [C.new].
class C {
C.c();
}
函数的已弃用子类型
#扩展“Function”已弃用。
实现“Function”没有效果。
混合“Function”已弃用。
描述
#当类Function
在类或混合的extends
、implements
或with
子句中使用时,分析器会生成此诊断信息。在类中使用Function
类没有语义价值,因此实际上是死代码。
示例
#以下代码会生成此诊断信息,因为Function
用作F
的超类。
class F extends Function {}
常见修复方法
#从任何子句中删除Function
类,如果Function
是子句中唯一的类型,则删除整个子句。
class F {}
不允许的类型实例化表达式
#只有泛型类型、泛型函数、泛型实例方法或泛型构造函数可以具有类型参数。
描述
#当表达式后的值不是允许的类型之一时,分析器会生成此诊断信息。允许的值类型包括:
- 泛型类型,
- 泛型构造函数,以及
- 泛型函数,包括顶级函数、静态和实例成员以及局部函数。
示例
#以下代码会生成此诊断信息,因为i
是顶级变量,它不是允许的类型之一。
int i = 1;
void f() {
print(i<int>);
}
常见修复方法
#如果引用的值正确,则删除类型参数。
int i = 1;
void f() {
print(i);
}
除法优化
#运算符 x ~/ y 比 (x / y).toInt() 更有效。
描述
#当使用toInt
将两个数字相除的结果转换为整数时,分析器会生成此诊断信息。Dart 具有内置的整数除法运算符,它既更高效又更简洁。
示例
#以下代码会生成此诊断信息,因为使用toInt
将x
和y
相除的结果转换为整数。
int divide(int x, int y) => (x / y).toInt();
常见修复方法
#使用整数除法运算符 (~/
)。
int divide(int x, int y) => x ~/ y;
重复构造函数
#名为“{0}”的构造函数已定义。
无名构造函数已定义。
描述
#当类声明多个无名构造函数或声明多个具有相同名称的构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为有两个无名构造函数的声明
class C {
C();
C();
}
以下代码会生成此诊断信息,因为有两个名为 m
的构造函数的声明
class C {
C.m();
C.m();
}
常见修复方法
#如果有多个无名构造函数,并且所有构造函数都需要,则为所有构造函数或除一个以外的所有构造函数命名
class C {
C();
C.n();
}
如果有多个无名构造函数,并且除一个以外的所有构造函数都不需要,则删除不需要的构造函数
class C {
C();
}
如果有多个命名构造函数,并且所有构造函数都需要,则重命名除一个以外的所有构造函数
class C {
C.m();
C.n();
}
如果有多个命名构造函数,并且除一个以外的所有构造函数都不需要,则删除不需要的构造函数
class C {
C.m();
}
重复定义
#名称 '{0}' 已定义。
描述
#当在同一作用域中声明一个名称,并且之前存在具有相同名称的声明时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为名称 x
被声明了两次
int x = 0;
int x = 1;
常见修复方法
#为其中一个声明选择不同的名称。
int x = 0;
int y = 1;
重复导出
#重复导出。
描述
#当找到与文件之前导出的内容相同的导出指令时,分析器会生成此诊断信息。第二个导出没有增加价值,应该删除。
示例
#以下代码会生成此诊断信息,因为同一个库被导出两次
export 'package:meta/meta.dart';
export 'package:meta/meta.dart';
常见修复方法
#删除不必要的导出
export 'package:meta/meta.dart';
重复的字段形式参数
#字段 '{0}' 不能在同一个构造函数中由多个参数初始化。
描述
#当构造函数参数列表中存在多个用于同一字段的初始化形式参数时,分析器会生成此诊断信息。对将立即被覆盖的值赋值没有用。
示例
#以下代码会生成此诊断信息,因为 this.f
在参数列表中出现两次
class C {
int f;
C(this.f, this.f) {}
}
常见修复方法
#删除其中一个初始化形式参数
class C {
int f;
C(this.f) {}
}
重复的字段名称
#字段名称 '{0}' 已在该记录中使用。
描述
#当记录字面量或记录类型注释包含一个字段,其名称与同一字面量或类型中先前声明的字段相同,分析器会生成此诊断信息。
示例
#以下代码产生此诊断,因为记录字面量有两个名为a
的字段。
var r = (a: 1, a: 2);
以下代码产生此诊断,因为记录类型注释有两个名为a
的字段,一个是位置字段,另一个是命名字段。
void f((int a, {int a}) r) {}
常见修复方法
#重命名一个或两个字段。
var r = (a: 1, b: 2);
重复的隐藏名称
#重复的隐藏名称。
描述
#当名称在hide
子句中多次出现时,分析器会产生此诊断。重复名称是不必要的。
示例
#以下代码产生此诊断,因为名称min
被隐藏多次。
import 'dart:math' hide min, min;
var x = pi;
常见修复方法
#如果名称在一个或多个地方拼写错误,则更正拼写错误的名称。
import 'dart:math' hide max, min;
var x = pi;
如果名称没有拼写错误,则从列表中删除不必要的名称。
import 'dart:math' hide min;
var x = pi;
重复忽略
#诊断“{0}”不需要在这里忽略,因为它已经被忽略了。
描述
#当诊断名称出现在ignore
注释中,但诊断已经被忽略时,分析器会产生此诊断,无论是因为它已经被包含在同一个ignore
注释中,还是因为它出现在ignore-in-file
注释中。
示例
#以下代码产生此诊断,因为名为unused_local_variable
的诊断已经被忽略了整个文件,因此不需要在特定行上忽略它。
// ignore_for_file: unused_local_variable
void f() {
// ignore: unused_local_variable
var x = 0;
}
以下代码产生此诊断,因为名为unused_local_variable
的诊断在同一行上被忽略了两次。
void f() {
// ignore: unused_local_variable, unused_local_variable
var x = 0;
}
常见修复方法
#删除忽略注释,或者如果忽略注释忽略了多个诊断,则删除不必要的诊断名称。
// ignore_for_file: unused_local_variable
void f() {
var x = 0;
}
重复导入
#重复导入。
描述
#当发现一个导入指令与文件之前的一个导入指令相同,分析器会产生此诊断。第二个导入没有增加价值,应该被删除。
示例
#以下代码会生成此诊断信息
import 'package:meta/meta.dart';
import 'package:meta/meta.dart';
@sealed class C {}
常见修复方法
#删除不必要的导入。
import 'package:meta/meta.dart';
@sealed class C {}
重复的命名参数
#命名参数“{0}”的参数已经被指定了。
描述
#当调用具有两个或多个具有相同名称的命名参数时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为有两个名为a
的参数。
void f(C c) {
c.m(a: 0, a: 1);
}
class C {
void m({int? a, int? b}) {}
}
常见修复方法
#如果其中一个参数应该有不同的名称,则更改名称。
void f(C c) {
c.m(a: 0, b: 1);
}
class C {
void m({int? a, int? b}) {}
}
如果其中一个参数是错误的,则删除它。
void f(C c) {
c.m(a: 1);
}
class C {
void m({int? a, int? b}) {}
}
重复的部分
#库已经包含一个具有 URI“{0}”的部分。
描述
#当一个文件在多个部分指令中被引用时,分析器会产生此诊断。
示例
#给定一个包含以下内容的文件part.dart
part of lib;
以下代码产生此诊断,因为文件part.dart
被包含多次。
library lib;
part 'part.dart';
part 'part.dart';
常见修复方法
#删除除第一个重复部分指令之外的所有指令。
library lib;
part 'part.dart';
重复的模式赋值变量
#变量“{0}”已经在该模式中被赋值了。
描述
#当同一个模式赋值中,单个模式变量被赋值多次时,分析器会产生此诊断。
示例
#以下代码会产生此诊断信息,因为变量a
在模式(a, a)
中被赋值两次。
int f((int, int) r) {
int a;
(a, a) = r;
return a;
}
常见修复方法
#如果您需要捕获所有值,请为每个匹配的子模式使用唯一的变量。
int f((int, int) r) {
int a, b;
(a, b) = r;
return a + b;
}
如果某些值不需要捕获,请使用通配符模式_
来避免将值绑定到变量。
int f((int, int) r) {
int a;
(_, a) = r;
return a;
}
重复的模式字段
#字段 '{0}' 已在此模式中匹配。
描述
#当记录模式多次匹配同一字段,或对象模式多次匹配同一 getter 时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为记录字段a
在同一个记录模式中被匹配两次。
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, a: 2):
return;
}
}
以下代码会产生此诊断信息,因为 getter f
在同一个对象模式中被匹配两次。
void f(Object o) {
switch (o) {
case C(f: 1, f: 2):
return;
}
}
class C {
int? f;
}
常见修复方法
#如果模式应该匹配重复字段的多个值,请使用逻辑或模式。
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, b: _) || (a: 2, b: _):
break;
}
}
如果模式应该匹配多个字段,请更改其中一个字段的名称。
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, b: 2):
return;
}
}
模式中重复的剩余元素
#列表或映射模式中最多允许一个剩余元素。
描述
#当列表或映射模式中存在多个剩余模式时,分析器会产生此诊断信息。剩余模式将捕获所有未被其他子模式匹配的值,因此后续的剩余模式将变得不必要,因为没有剩余的值可以捕获。
示例
#以下代码会产生此诊断信息,因为列表模式中有两个剩余模式。
void f(List<int> x) {
if (x case [0, ..., ...]) {}
}
常见修复方法
#删除除一个之外的所有剩余模式。
void f(List<int> x) {
if (x case [0, ...]) {}
}
重复的显示名称
#重复显示的名称。
描述
#当show
子句中出现多个相同的名称时,分析器会产生此诊断信息。重复名称是不必要的。
示例
#以下代码会产生此诊断信息,因为名称min
被显示多次。
import 'dart:math' show min, min;
var x = min(2, min(0, 1));
常见修复方法
#如果名称在一个或多个地方拼写错误,则更正拼写错误的名称。
import 'dart:math' show max, min;
var x = max(2, min(0, 1));
如果名称没有拼写错误,则从列表中删除不必要的名称。
import 'dart:math' show min;
var x = min(2, min(0, 1));
重复的变量模式
#变量 '{0}' 已在此模式中定义。
描述
#当逻辑与模式的分支声明一个在同一模式的早期分支中已声明的变量时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为变量a
在逻辑与模式的两个分支中都被声明。
void f((int, int) r) {
if (r case (var a, 0) && (0, var a)) {
print(a);
}
}
常见修复方法
#如果您需要在多个分支中捕获匹配的值,请更改变量的名称,使其唯一。
void f((int, int) r) {
if (r case (var a, 0) && (0, var b)) {
print(a + b);
}
}
如果您只需要在一个分支中捕获匹配的值,请从除一个分支之外的所有分支中删除变量模式。
void f((int, int) r) {
if (r case (var a, 0) && (0, _)) {
print(a);
}
}
空映射模式
#映射模式必须至少包含一个条目。
描述
#当映射模式为空时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为映射模式为空。
void f(Map<int, String> x) {
if (x case {}) {}
}
常见修复方法
#如果模式应该匹配任何映射,则将其替换为对象模式。
void f(Map<int, String> x) {
if (x case Map()) {}
}
如果模式应该只匹配空映射,则在模式中检查长度。
void f(Map<int, String> x) {
if (x case Map(isEmpty: true)) {}
}
带逗号的空记录字面量
#没有字段的记录字面量不能有尾随逗号。
描述
#当没有字段的记录字面量有尾随逗号时,分析器会产生此诊断信息。空记录字面量不能包含逗号。
示例
#以下代码产生此诊断信息,因为空记录字面量有尾随逗号。
var r = (,);
常见修复方法
#如果记录意图为空,则删除逗号。
var r = ();
如果记录意图有一个或多个字段,则添加用于计算这些字段值的表达式。
var r = (3, 4);
带逗号的空记录类型命名字段列表
#记录类型中命名字段的列表不能为空。
描述
#当记录类型具有空命名字段列表时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为记录类型具有空命名字段列表。
void f((int, int, {}) r) {}
常见修复方法
#如果记录意图具有命名字段,则添加字段的类型和名称。
void f((int, int, {int z}) r) {}
如果记录不意图具有命名字段,则删除花括号。
void f((int, int) r) {}
带逗号的空记录类型
#没有字段的记录类型不能有尾随逗号。
描述
#当没有字段的记录类型有尾随逗号时,分析器会产生此诊断信息。空记录类型不能包含逗号。
示例
#以下代码产生此诊断信息,因为空记录类型有尾随逗号。
void f((,) r) {}
常见修复方法
#如果记录类型意图为空,则删除逗号。
void f(() r) {}
如果记录类型意图有一个或多个字段,则添加这些字段的类型。
void f((int, int) r) {}
空结构体
#类 '{0}' 不能为空,因为它是的子类 '{1}'。
描述
#当的子类 Struct
或 Union
没有任何字段时,分析器会产生此诊断信息。没有空 Struct
或 Union
是不支持的。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断信息,因为类 C
,它扩展了 Struct
,没有声明任何字段。
import 'dart:ffi';
final class C extends Struct {}
常见修复方法
#如果类意图是一个结构体,则声明一个或多个字段。
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
如果类意图用作类型参数 Pointer
,则将其设为的子类 Opaque
。
import 'dart:ffi';
final class C extends Opaque {}
如果类不意图是一个结构体,则删除或更改扩展子句。
class C {}
枚举常量与封闭枚举同名
#枚举值的名称不能与枚举的名称相同。
描述
#当枚举值与声明它的枚举具有相同的名称时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为枚举值 E
与封闭枚举 E
具有相同的名称。
enum E {
E
}
常见修复方法
#如果枚举的名称正确,则重命名常量。
enum E {
e
}
如果常量的名称正确,则重命名枚举。
enum F {
E
}
枚举常量使用非常量构造函数
#调用的构造函数不是 'const' 构造函数。
描述
#当枚举值使用工厂构造函数或未标记为 const
的生成构造函数创建时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为枚举值e
正在通过工厂构造函数初始化。
enum E {
e();
factory E() => e;
}
常见修复方法
#使用标记为const
的生成构造函数。
enum E {
e._();
factory E() => e;
const E._();
}
枚举混合使用实例变量
#应用于枚举的混入不能具有实例变量。
描述
#当应用于枚举的混入声明一个或多个实例变量时,分析器会产生此诊断信息。这是不允许的,因为枚举值是常量,并且枚举中的构造函数无法初始化任何混入的字段。
示例
#以下代码产生此诊断信息,因为混入M
定义了实例字段x
。
mixin M {
int x = 0;
}
enum E with M {
a
}
常见修复方法
#如果您需要应用混入,请将所有实例字段更改为 getter 和 setter 对,并在必要时在枚举中实现它们。
mixin M {
int get x => 0;
}
enum E with M {
a
}
如果您不需要应用混入,请将其删除。
enum E {
a
}
枚举包含抽象成员
#'{0}' 必须具有方法体,因为 '{1}' 是一个枚举。
描述
#当发现枚举的成员没有具体的实现时,分析器会产生此诊断信息。枚举不允许包含抽象成员。
示例
#以下代码产生此诊断信息,因为m
是一个抽象方法,而 E
是一个枚举。
enum E {
e;
void m();
}
常见修复方法
#为该成员提供实现。
enum E {
e;
void m() {}
}
枚举带名称值
#名称 'values' 不是枚举的有效名称。
描述
#当枚举被声明为具有名称 values
时,分析器会产生此诊断信息。这是不允许的,因为枚举有一个隐式静态字段名为 values
,两者会发生冲突。
示例
#以下代码产生此诊断信息,因为存在一个名为 values
的枚举声明。
enum values {
c
}
常见修复方法
#将枚举重命名为除 values
之外的其他名称。
常量集中存在相等元素
#常量集合文字中的两个元素不能相等。
描述
#当常量集合文字中的两个元素具有相同的值时,分析器会产生此诊断信息。集合只能包含每个值一次,这意味着其中一个值是不必要的。
示例
#以下代码产生此诊断信息,因为字符串 'a'
被指定了两次。
const Set<String> set = {'a', 'a'};
常见修复方法
#删除其中一个重复的值。
const Set<String> set = {'a'};
请注意,文字集合会保留其元素的顺序,因此选择要删除的元素可能会影响迭代器返回元素的顺序。
集中存在相等元素
#集合字面量中的两个元素不应该相等。
描述
#当非常量集合中的元素与同一集合中之前的元素相同时,分析器会生成此诊断信息。如果两个元素相同,则第二个值将被忽略,这使得拥有这两个元素毫无意义,并且可能表明存在错误。
示例
#以下代码会生成此诊断信息,因为元素 1
出现了两次
const a = 1;
const b = 1;
var s = <int>{a, b};
常见修复方法
#如果两个元素都应该包含在集合中,则更改其中一个元素
const a = 1;
const b = 2;
var s = <int>{a, b};
如果只需要其中一个元素,则删除不需要的那个元素
const a = 1;
var s = <int>{a};
请注意,文字集合会保留其元素的顺序,因此选择要删除的元素可能会影响迭代器返回元素的顺序。
常量映射中存在相等键
#常量映射字面量中的两个键不能相等。
描述
#当常量映射中的键与同一映射中之前的键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得拥有这两个键值对毫无意义。
示例
#以下代码会生成此诊断信息,因为键 1
被使用了两次
const map = <int, String>{1: 'a', 2: 'b', 1: 'c', 4: 'd'};
常见修复方法
#如果两个条目都应该包含在映射中,则更改其中一个键使其不同
const map = <int, String>{1: 'a', 2: 'b', 3: 'c', 4: 'd'};
如果只需要其中一个条目,则删除不需要的那个条目
const map = <int, String>{1: 'a', 2: 'b', 4: 'd'};
请注意,字面量映射会保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。
映射中存在相等键
#映射字面量中的两个键不应该相等。
描述
#当非常量映射中的键与同一映射中之前的键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得拥有这两个键值对毫无意义,并且可能表明存在错误。
示例
#以下代码会生成此诊断信息,因为键 a
和 b
的值相同
const a = 1;
const b = 1;
var m = <int, String>{a: 'a', b: 'b'};
常见修复方法
#如果两个条目都应该包含在映射中,则更改其中一个键
const a = 1;
const b = 2;
var m = <int, String>{a: 'a', b: 'b'};
如果只需要其中一个条目,则删除不需要的那个条目
const a = 1;
var m = <int, String>{a: 'a'};
请注意,字面量映射会保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。
映射模式中存在相等键
#映射模式中的两个键不能相等。
描述
#当映射模式包含多个具有相同名称的键时,分析器会生成此诊断信息。同一个键不能匹配两次。
示例
#以下代码会生成此诊断信息,因为键 'a'
出现了两次
void f(Map<String, int> x) {
if (x case {'a': 1, 'a': 2}) {}
}
常见修复方法
#如果您尝试匹配两个不同的键,请更改模式中的其中一个键
void f(Map<String, int> x) {
if (x case {'a': 1, 'b': 2}) {}
}
如果您尝试匹配同一个键,但允许多个模式中的任何一个匹配,请使用逻辑或模式
void f(Map<String, int> x) {
if (x case {'a': 1 || 2}) {}
}
预期一个列表模式类型参数
#列表模式需要一个类型参数或没有类型参数,但找到了 {0} 个。
描述
#当列表模式具有多个类型参数时,分析器会生成此诊断信息。列表模式可以具有零个类型参数或一个类型参数,但不能具有多个类型参数。
示例
#以下代码会生成此诊断信息,因为列表模式 ([0]
) 具有两个类型参数
void f(Object x) {
if (x case <int, int>[0]) {}
}
常见修复方法
#删除除一个以外的所有类型参数
void f(Object x) {
if (x case <int>[0]) {}
}
预期一个列表类型参数
#列表字面量需要一个类型参数或没有类型参数,但找到了 {0} 个。
描述
#当列表字面量具有多个类型参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为列表字面量具有两个类型参数,而它最多只能有一个类型参数
var l = <int, int>[];
常见修复方法
#删除除一个以外的所有类型参数
var l = <int>[];
预期一个集合类型参数
#集合字面量需要一个类型参数或没有类型参数,但找到了 {0} 个。
描述
#当集合字面量具有多个类型参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为集合字面量具有三个类型参数,而它最多只能有一个类型参数
var s = <int, String, int>{0, 'a', 1};
常见修复方法
#删除除一个以外的所有类型参数
var s = <int>{0, 1};
预期两个映射模式类型参数
#映射模式需要两个类型参数或没有类型参数,但找到了 {0} 个。
描述
#当映射模式具有一个类型参数或多个类型参数时,分析器会生成此诊断信息。映射模式可以具有两个类型参数或零个类型参数,但不能具有其他数量的类型参数。
示例
#以下代码会生成此诊断信息,因为映射模式 (<int>{}
) 具有一个类型参数
void f(Object x) {
if (x case <int>{0: _}) {}
}
常见修复方法
#添加或删除类型参数,直到有 2 个或没有类型参数
void f(Object x) {
if (x case <int, int>{0: _}) {}
}
预期两个映射类型参数
#映射字面量需要两个类型参数或没有类型参数,但找到了 {0} 个。
描述
#当映射字面量具有一个或多个类型参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为映射字面量具有三个类型参数,而它可以具有两个或零个类型参数
var m = <int, String, int>{};
常见修复方法
#删除除两个以外的所有类型参数
var m = <int, String>{};
导出内部库
#库 '{0}' 是内部库,无法导出。
描述
#当分析器发现一个导出的 dart:
URI 引用了内部库时,它会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 _interceptors
是一个内部库
export 'dart:_interceptors';
常见修复方法
#删除导出指令。
导出旧版符号
#符号 '{0}' 定义在遗留库中,无法从启用空安全性的库中重新导出。
描述
#当一个已启用空安全性的库导出另一个库,而被导出的库未启用空安全性时,分析器会产生此诊断信息。
示例
#假设有一个未启用空安全性的库
// @dart = 2.8
String s;
以下代码会产生此诊断信息,因为它正在从一个未启用空安全性的库导出符号
export 'optedOut.dart';
class C {}
常见修复方法
#如果可以,请迁移被导出的库,使其不再需要禁用空安全性
String? s;
如果无法迁移库,则删除导出
class C {}
如果被导出的库(未启用空安全性的库)本身导出了一个已启用空安全性的库,那么您的库可以间接导出已启用空安全性的库中的符号。您可以在库的导出指令中添加一个隐藏组合器,隐藏未启用空安全性的库中声明的所有名称。
导出非库
#导出的库 '{0}' 不能包含部分指令。
描述
#当导出指令引用的是部分而不是库时,分析器会产生此诊断信息。
示例
#给定一个包含以下内容的文件part.dart
part of lib;
以下代码会产生此诊断信息,因为文件 part.dart
是一个部分,而只有库可以被导出
library lib;
export 'part.dart';
常见修复方法
#删除导出指令,或将 URI 更改为包含部分的库的 URI。
映射中的表达式
#表达式不能在映射字面量中使用。
描述
#当分析器在看似映射字面量的代码中发现表达式而不是映射条目时,它会产生此诊断信息。
示例
#以下代码会生成此诊断信息
var map = <String, int>{'a': 0, 'b': 1, 'c'};
常见修复方法
#如果表达式旨在计算条目中的键或值,请通过用键或值替换表达式来修复问题。例如
var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
扩展非类
#类只能扩展其他类。
描述
#当 extends
子句包含一个声明为非类的名称时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 f
被声明为一个函数
void f() {}
class C extends f {}
常见修复方法
#如果您希望该类扩展除Object
以外的类,请将extends
子句中的名称替换为该类的名称。
void f() {}
class C extends B {}
class B {}
如果您希望该类扩展Object
,请删除extends
子句。
void f() {}
class C {}
扩展作为表达式
#扩展“'{0}'”不能用作表达式。
描述
#当扩展的名称在表达式中使用时,除了在扩展覆盖中或用于限定对扩展的静态成员的访问之外,分析器会生成此诊断。因为类定义了一种类型,所以类的名称可以用来引用表示该类类型的Type
的实例。另一方面,扩展不定义类型,不能用作类型文字。
示例
#以下代码会生成此诊断,因为E
是一个扩展。
extension E on int {
static String m() => '';
}
var x = E;
常见修复方法
#用可以引用的名称替换扩展的名称,例如在扩展上定义的静态成员。
extension E on int {
static String m() => '';
}
var x = E.m();
扩展中静态和实例冲突
#扩展不能定义静态成员“'{0}'”和具有相同名称的实例成员。
描述
#当扩展声明包含具有相同名称的实例成员和静态成员时,分析器会生成此诊断。实例成员和静态成员不能具有相同的名称,因为在扩展体中对名称的非限定使用不清楚引用的是哪个成员。
示例
#以下代码会生成此诊断,因为名称a
用于两个不同的成员。
extension E on Object {
int get a => 0;
static int a() => 0;
}
常见修复方法
#重命名或删除其中一个成员。
extension E on Object {
int get a => 0;
static int b() => 0;
}
扩展声明抽象成员
#扩展不能声明抽象成员。
描述
#当在扩展中声明抽象声明时,分析器会生成此诊断。扩展只能声明具体成员。
示例
#以下代码会生成此诊断,因为方法a
没有主体。
extension E on String {
int a();
}
常见修复方法
#为成员提供实现或将其删除。
扩展声明构造函数
#扩展不能声明构造函数。
描述
#当在扩展中找到构造函数声明时,分析器会生成此诊断。定义构造函数是无效的,因为扩展不是类,并且无法创建扩展的实例。
示例
#以下代码会生成此诊断,因为E
中有一个构造函数声明。
extension E on String {
E() : super();
}
常见修复方法
#删除构造函数或将其替换为静态方法。
扩展声明实例字段
#扩展不能声明实例字段。
描述
#当在扩展中找到实例字段声明时,分析器会生成此诊断。定义实例字段是无效的,因为扩展只能添加行为,不能添加状态。
示例
#以下代码会生成此诊断,因为s
是一个实例字段。
extension E on String {
String s;
}
常见修复方法
#删除字段,将其设为静态字段,或将其转换为 getter、setter 或方法。
扩展声明对象成员
#扩展不能声明与“Object”声明的成员具有相同名称的成员。
描述
#当扩展声明声明的成员与类Object
中声明的成员同名时,分析器会生成此诊断信息。由于始终会优先找到Object
中的成员,因此永远无法使用此类成员。
示例
#以下代码会生成此诊断信息,因为toString
由Object
定义
extension E on String {
String toString() => this;
}
常见修复方法
#删除该成员或将其重命名,使其名称不与Object
中的成员冲突。
extension E on String {
String displayString() => this;
}
扩展覆盖对静态成员的访问
#扩展重写不能用于从扩展中访问静态成员。
描述
#当扩展重写是静态成员调用接收器时,分析器会生成此诊断信息。与类中的静态成员类似,应使用扩展的名称而不是扩展重写来访问扩展的静态成员。
示例
#以下代码会生成此诊断信息,因为m
是静态的
extension E on String {
static void m() {}
}
void f() {
E('').m();
}
常见修复方法
#将扩展重写替换为扩展的名称。
extension E on String {
static void m() {}
}
void f() {
E.m();
}
扩展覆盖参数不可赋值
#扩展重写“{0}”的参数类型不可分配给扩展类型“{1}”。
描述
#当扩展重写参数不可分配给扩展扩展的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为3
不是String
extension E on String {
void method() {}
}
void f() {
E(3).method();
}
常见修复方法
#如果使用的是正确的扩展,请更新参数以使其具有正确的类型。
extension E on String {
void method() {}
}
void f() {
E(3.toString()).method();
}
如果存在对参数类型有效的其他扩展,请替换扩展的名称或解包参数,以便找到正确的扩展。
扩展覆盖没有访问权限
#扩展重写只能用于访问实例成员。
描述
#当找到未用于访问扩展成员之一的扩展重写时,分析器会生成此诊断信息。扩展重写语法没有运行时语义;它只控制在编译时选择哪个成员。
示例
#以下代码会生成此诊断信息,因为E(i)
不是表达式
extension E on int {
int get a => 0;
}
void f(int i) {
print(E(i));
}
常见修复方法
#如果要调用扩展的成员之一,请添加调用。
extension E on int {
int get a => 0;
}
void f(int i) {
print(E(i).a);
}
如果不想调用成员,请解包参数。
extension E on int {
int get a => 0;
}
void f(int i) {
print(i);
}
扩展覆盖使用级联
#扩展重写没有值,因此不能用作级联表达式的接收器。
描述
#当扩展重写用作级联表达式的接收者时,分析器会生成此诊断信息。级联表达式 e..m
的值是接收者 e
的值,但扩展重写不是表达式,没有值。
示例
#以下代码会生成此诊断信息,因为 E(3)
不是表达式
extension E on int {
void m() {}
}
f() {
E(3)..m();
}
常见修复方法
#使用 .
而不是 ..
extension E on int {
void m() {}
}
f() {
E(3).m();
}
如果有多个级联访问,则需要为每个访问复制扩展重写。
扩展类型构造函数带 super 形式参数
#扩展类型构造函数不能声明超类形式参数。
描述
#当扩展类型中的构造函数具有超类参数时,分析器会生成此诊断信息。超类参数无效,因为扩展类型没有超类。
示例
#以下代码会生成此诊断信息,因为命名构造函数 n
包含超类参数
extension type E(int i) {
E.n(this.i, super.foo);
}
常见修复方法
#如果需要该参数,请将超类参数替换为普通参数
extension type E(int i) {
E.n(this.i, String foo);
}
如果不需要该参数,请删除超类参数
extension type E(int i) {
E.n(this.i);
}
扩展类型构造函数带 super 调用
#扩展类型构造函数不能包含超类初始化器。
描述
#当扩展类型中的构造函数在初始化列表中包含对超类构造函数的调用时,分析器会生成此诊断信息。由于扩展类型没有超类,因此没有构造函数可以调用。
示例
#以下代码会生成此诊断信息,因为构造函数 E.n
在其初始化列表中调用了超类构造函数
extension type E(int i) {
E.n() : i = 0, super.n();
}
常见修复方法
#删除对超类构造函数的调用
extension type E(int i) {
E.n() : i = 0;
}
扩展类型声明实例字段
#扩展类型不能声明实例字段。
描述
#当扩展类型声明的正文中存在字段声明时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型 E
声明了一个名为 f
的字段
extension type E(int i) {
final int f = 0;
}
常见修复方法
#如果不需要该字段,则将其删除或将其替换为 getter 和/或 setter
extension type E(int i) {
int get f => 0;
}
如果需要该字段,则将扩展类型转换为类
class E {
final int i;
final int f = 0;
E(this.i);
}
扩展类型声明对象成员
#扩展类型不能声明与 'Object' 声明的成员同名的成员。
描述
#当扩展类型声明的正文中包含与 Object
声明的成员同名的成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 Object
已经定义了一个名为 hashCode
的成员
extension type E(int i) {
int get hashCode => 0;
}
常见修复方法
#如果需要具有实现语义的成员,请重命名该成员
extension type E(int i) {
int get myHashCode => 0;
}
如果不需要具有实现语义的成员,请删除该成员
extension type E(int i) {}
扩展类型实现不允许的类型
#扩展类型不能实现“{0}”。
描述
#当扩展类型实现它不允许实现的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型不能实现类型 dynamic
extension type A(int i) implements dynamic {}
常见修复方法
#从实现子句中删除不允许的类型
extension type A(int i) {}
扩展类型实现自身
#扩展类型不能实现自身。
描述
#当扩展类型直接或间接实现自身时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型 A
直接实现自身
extension type A(int i) implements A {}
以下代码会生成此诊断信息,因为扩展类型 A
间接实现自身(通过 B
)
extension type A(int i) implements B {}
extension type B(int i) implements A {}
常见修复方法
#通过从参与循环的至少一个类型的实现子句中删除一个类型来打破循环
extension type A(int i) implements B {}
extension type B(int i) {}
扩展类型实现非超类型
#“{0}”不是“{1}”的超类型,即表示类型。
描述
#当扩展类型实现的类型不是表示类型的超类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型 A
实现 String
,但 String
不是表示类型 int
的超类型
extension type A(int i) implements String {}
常见修复方法
#如果表示类型正确,则删除或替换实现子句中的类型
extension type A(int i) {}
如果表示类型不正确,则用正确的类型替换它
extension type A(String s) implements String {}
扩展类型实现表示非超类型
#“{0}”是“{1}”的表示类型,不是“{2}”的超类型,即“{3}”的表示类型。
描述
#当扩展类型实现另一个扩展类型,并且实现的扩展类型的表示类型不是实现扩展类型的表示类型的子类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型 B
实现 A
,但 A
的表示类型(num
)不是 B
的表示类型(String
)的子类型
extension type A(num i) {}
extension type B(String s) implements A {}
常见修复方法
#更改两个扩展类型的表示类型,使实现类型的表示类型成为实现类型的表示类型的超类型
extension type A(num i) {}
extension type B(int n) implements A {}
或从实现子句中删除实现的类型
extension type A(num i) {}
extension type B(String s) {}
扩展类型继承成员冲突
#扩展类型“{0}”从实现的类型中具有多个名为“{1}”的不同成员。
描述
#当扩展类型实现两个或多个其他类型,并且至少两个类型声明具有相同名称的成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展类型 C
同时实现 A
和 B
,并且两者都声明了一个名为 m
的成员
class A {
void m() {}
}
extension type B(A a) {
void m() {}
}
extension type C(A a) implements A, B {}
常见修复方法
#如果扩展类型不需要实现所有列出的类型,则删除除引入冲突成员的类型之外的所有类型
class A {
void m() {}
}
extension type B(A a) {
void m() {}
}
extension type C(A a) implements A {}
如果扩展类型需要实现所有列出的类型,但可以重命名这些类型中的成员,则为冲突的成员提供唯一的名称。
class A {
void m() {}
}
extension type B(A a) {
void n() {}
}
extension type C(A a) implements A, B {}
扩展类型表示依赖于自身
#扩展类型表示不能依赖于自身。
描述
#当扩展类型具有依赖于自身(直接或间接)的表示类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为扩展类型 A
的表示类型直接依赖于 A
extension type A(A a) {}
以下两个代码示例会生成此诊断,因为扩展类型 A
的表示类型通过扩展类型 B
间接依赖于 A
extension type A(B b) {}
extension type B(A a) {}
extension type A(List<B> b) {}
extension type B(List<A> a) {}
常见修复方法
#通过为循环中的至少一种类型选择不同的表示类型来消除依赖关系。
extension type A(String s) {}
扩展类型表示类型为底层
#表示类型不能是底部类型。
描述
#当扩展类型的表示类型为 底部类型 Never
时,分析器会生成此诊断。类型 Never
不能是扩展类型的表示类型,因为没有可以扩展的值。
示例
#以下代码会生成此诊断,因为扩展类型 E
的表示类型为 Never
extension type E(Never n) {}
常见修复方法
#用不同的类型替换扩展类型。
extension type E(String s) {}
扩展类型包含抽象成员
#'{0}' 必须具有方法体,因为 '{1}' 是扩展类型。
描述
#当扩展类型声明抽象成员时,分析器会生成此诊断。由于扩展类型成员引用是静态解析的,因此扩展类型中的抽象成员永远不会被执行。
示例
#以下代码会生成此诊断,因为扩展类型 E
中的方法 m
是抽象的。
extension type E(String s) {
void m();
}
常见修复方法
#如果成员旨在可执行,则提供成员的实现。
extension type E(String s) {
void m() {}
}
如果成员不打算可执行,则将其删除。
extension type E(String s) {}
外部带初始化程序
#外部字段不能有初始化器。
外部变量不能有初始化器。
描述
#当用关键字 external
标记的字段或变量具有初始化器,或者当外部字段在构造函数中初始化时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为外部字段 x
在初始化器中被赋值。
class C {
external int x;
C() : x = 0;
}
以下代码会生成此诊断,因为外部字段 x
有初始化器。
class C {
external final int x = 0;
}
以下代码会生成此诊断,因为外部顶级变量 x
有初始化器。
external final int x = 0;
常见修复方法
#删除初始化器。
class C {
external final int x;
}
结构体字段上的额外注释
#结构体类中的字段必须只有一个注解来指示其原生类型。
描述
#当 Struct
子类的字段有多个注解描述字段的原生类型时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为字段 x
有两个注解描述字段的原生类型
import 'dart:ffi';
final class C extends Struct {
@Int32()
@Int16()
external int x;
}
常见修复方法
#删除除一个以外的所有注解
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
额外的位置参数
#位置参数过多:预期 {0} 个,但找到 {1} 个。
描述
#当方法或函数调用具有比方法或函数允许的更多位置参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 f
定义了 2 个参数,但调用时使用了 3 个参数
void f(int a, int b) {}
void g() {
f(1, 2, 3);
}
常见修复方法
#删除与参数不对应的参数
void f(int a, int b) {}
void g() {
f(1, 2);
}
额外的位置参数可以是命名参数
#位置参数过多:预期 {0} 个,但找到 {1} 个。
描述
#当方法或函数调用具有比方法或函数允许的更多位置参数时,分析器会生成此诊断信息,但方法或函数定义了命名参数。
示例
#以下代码会生成此诊断信息,因为 f
定义了 2 个位置参数,但有一个命名参数可以用于第三个参数
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2, 3);
}
常见修复方法
#如果某些参数应该是命名参数的值,则在参数之前添加名称
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2, c: 3);
}
否则,删除与位置参数不对应的参数
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2);
}
extra_size_annotation_carray
#“数组”必须只有一个“数组”注解。
描述
#当 Struct
子类的字段有多个注解描述原生数组的大小,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为字段 a0
有两个注解指定原生数组的大小
import 'dart:ffi';
final class C extends Struct {
@Array(4)
@Array(8)
external Array<Uint8> a0;
}
常见修复方法
#删除除一个以外的所有注解
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
字段由多个初始化器初始化
#字段“{0}”不能在同一个构造函数中初始化两次。
描述
#当构造函数的初始化列表多次初始化字段时,分析器会生成此诊断信息。由于只保留最后一个值,因此没有值可以允许两个初始化程序,因为只保留最后一个值。
示例
#以下代码会生成此诊断信息,因为字段 f
被初始化了两次
class C {
int f;
C() : f = 0, f = 1;
}
常见修复方法
#删除其中一个初始化程序
class C {
int f;
C() : f = 0;
}
字段在初始化器和声明中初始化
#如果字段是 final 且已在声明时初始化,则不能在构造函数中初始化字段。
描述
#当 final 字段在字段声明和构造函数中的初始化程序中都被初始化时,分析器会生成此诊断信息。final 字段只能赋值一次,因此不能在两个地方初始化。
示例
#以下代码会生成此诊断信息,因为 f
是
class C {
final int f = 0;
C() : f = 1;
}
常见修复方法
#如果初始化不依赖于传递给构造函数的任何值,并且所有构造函数都需要将字段初始化为相同的值,则从构造函数中删除初始化程序
class C {
final int f = 0;
C();
}
如果初始化依赖于传递给构造函数的值,或者不同的构造函数需要以不同的方式初始化字段,则删除字段声明中的初始化程序。
class C {
final int f;
C() : f = 1;
}
字段在参数和初始化器中初始化
#字段不能在参数列表和初始化程序中同时初始化。
描述
#当字段在参数列表和构造函数的初始化程序列表中同时初始化时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为字段 f
通过初始化形式参数和初始化程序列表同时初始化
class C {
int f;
C(this.f) : f = 0;
}
常见修复方法
#如果字段应由参数初始化,则删除初始化程序列表中的初始化。
class C {
int f;
C(this.f);
}
如果字段应在初始化程序列表中初始化,并且不需要参数,则删除参数。
class C {
int f;
C() : f = 0;
}
如果字段应在初始化程序列表中初始化,并且需要参数,则将其设为普通参数。
class C {
int f;
C(int g) : f = g * 2;
}
字段初始化器工厂构造函数
#初始化形式参数不能在工厂构造函数中使用。
描述
#当工厂构造函数具有初始化形式参数时,分析器会生成此诊断信息。工厂构造函数不能为字段分配值,因为没有创建实例;因此,没有要分配的字段。
示例
#以下代码会生成此诊断信息,因为工厂构造函数使用初始化形式参数
class C {
int? f;
factory C(this.f) => throw 0;
}
常见修复方法
#用普通参数替换初始化形式参数。
class C {
int? f;
factory C(int f) => throw 0;
}
结构体中的字段初始化器
#'Struct' 和 'Union' 子类的构造函数不能具有字段初始化程序。
描述
#当 Struct
或 Union
子类的构造函数具有一个或多个字段初始化程序时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为类 C
的构造函数具有字段 f
的初始化程序
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
@Int32()
int f;
C() : f = 0;
}
常见修复方法
#删除字段初始化程序。
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
@Int32()
int f;
C();
}
字段初始化器不可赋值
#初始化程序类型 '{0}' 不能在常量构造函数中分配给字段类型 '{1}'。
初始化程序类型 '{0}' 不能分配给字段类型 '{1}'。
描述
#当构造函数的初始化程序列表将字段初始化为不可分配给该字段的值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 0
的类型为 int
,而 int
不能分配给类型为 String
的字段
class C {
String s;
C() : s = 0;
}
常见修复方法
#如果字段的类型正确,则更改分配给它的值,以便该值具有有效的类型。
class C {
String s;
C() : s = '0';
}
如果值的类型正确,则更改字段的类型以允许分配。
class C {
int s;
C() : s = 0;
}
字段初始化器位于构造函数之外
#字段形式参数只能在构造函数中使用。
初始化形式参数只能在构造函数中使用。
描述
#当在构造函数以外的任何地方使用初始化形式参数作为参数列表时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为初始化形式参数 this.x
在方法 m
中使用。
class A {
int x = 0;
m([this.x = 0]) {}
}
常见修复方法
#用普通参数替换初始化形式参数,并在方法体中为字段赋值。
class A {
int x = 0;
m([int x = 0]) {
this.x = x;
}
}
字段初始化器重定向构造函数
#重定向构造函数不能有字段初始化器。
描述
#当重定向构造函数在对象中初始化字段时,分析器会生成此诊断信息。这是不允许的,因为在应该初始化字段时,还没有创建具有该字段的实例。
示例
#以下代码会生成此诊断信息,因为构造函数 C.zero
(它重定向到构造函数 C
)有一个初始化形式参数,用于初始化字段 f
。
class C {
int f;
C(this.f);
C.zero(this.f) : this(f);
}
以下代码会生成此诊断信息,因为构造函数 C.zero
(它重定向到构造函数 C
)有一个初始化器,用于初始化字段 f
。
class C {
int f;
C(this.f);
C.zero() : f = 0, this(1);
}
常见修复方法
#如果初始化是由初始化形式参数完成的,则使用普通参数。
class C {
int f;
C(this.f);
C.zero(int f) : this(f);
}
如果初始化是在初始化器中完成的,则删除初始化器。
class C {
int f;
C(this.f);
C.zero() : this(0);
}
初始化形式参数不可赋值
#参数类型“{0}”与字段类型“{1}”不兼容。
描述
#当初始化形式参数的类型不能赋值给正在初始化的字段的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为初始化形式参数的类型为 String
,但字段的类型为 int
。参数必须具有子类型为字段类型的类型。
class C {
int f;
C(String this.f);
}
常见修复方法
#如果字段的类型不正确,则更改字段的类型以匹配参数的类型,并考虑从参数中删除类型。
class C {
String f;
C(this.f);
}
如果参数的类型不正确,则删除参数的类型。
class C {
int f;
C(this.f);
}
如果字段和参数的类型都正确,则使用初始化器而不是初始化形式参数将参数值转换为正确类型的值。
class C {
int f;
C(String s) : f = int.parse(s);
}
带有初始化器的结构体中的字段
#'Struct' 和 'Union' 子类的字段不能有初始化器。
描述
#当 Struct
子类中的字段有初始化器时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为字段 p
有一个初始化器。
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
Pointer p = nullptr;
}
常见修复方法
#删除初始化器。
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
Pointer p;
}
字段必须在结构体中为外部
#'Struct' 和 'Union' 子类的字段必须标记为外部。
描述
#当 Struct
或 Union
子类中的字段没有标记为 external
时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断信息,因为字段a
未标记为external
import 'dart:ffi';
final class C extends Struct {
@Int16()
int a;
}
常见修复方法
#添加所需的external
修饰符
import 'dart:ffi';
final class C extends Struct {
@Int16()
external int a;
}
final 在声明和构造函数中初始化
#'{0}' 是最终的,并且在声明时被赋予了一个值,因此它不能被设置为一个新值。
描述
#当一个最终字段被初始化两次时,分析器会产生此诊断信息:一次是在声明时,另一次是在构造函数的参数中。
示例
#以下代码产生此诊断信息,因为字段f
被初始化了两次
class C {
final int f = 0;
C(this.f);
}
常见修复方法
#如果该字段对所有实例都应该具有相同的值,则删除参数列表中的初始化
class C {
final int f = 0;
C();
}
如果该字段在不同的实例中可以具有不同的值,则删除声明中的初始化
class C {
final int f;
C(this.f);
}
final 未初始化
#最终变量 '{0}' 必须被初始化。
描述
#当一个最终字段或变量没有被初始化时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为x
没有初始化器
final x;
常见修复方法
#对于变量和静态字段,您可以添加一个初始化器
final x = 0;
对于实例字段,您可以像前面的示例中那样添加一个初始化器,或者您可以在每个构造函数中初始化该字段。您可以使用初始化形式参数来初始化该字段
class C {
final int x;
C(this.x);
}
您也可以使用构造函数中的初始化器来初始化该字段
class C {
final int x;
C(int y) : x = y * 2;
}
final 在构造函数中未初始化
#所有最终变量都必须被初始化,但 '{0}' 和 '{1}' 没有。
所有最终变量都必须被初始化,但 '{0}' 没有。
所有最终变量都必须被初始化,但 '{0}'、'{1}' 和其他 {2} 个没有。
描述
#当一个类定义了一个或多个没有初始化器的最终实例字段,并且至少有一个构造函数没有初始化这些字段时,分析器会产生此诊断信息。所有最终实例字段在实例创建时都必须被初始化,无论是通过字段的初始化器还是通过构造函数。
示例
#以下代码会生成此诊断信息
class C {
final String value;
C();
}
常见修复方法
#如果该值应该直接传递给构造函数,则使用初始化形式参数来初始化字段value
class C {
final String value;
C(this.value);
}
如果该值应该从调用者提供的值间接计算,则添加一个参数并包含一个初始化器
class C {
final String value;
C(Object o) : value = o.toString();
}
如果该字段的值不依赖于可以传递给构造函数的值,则在字段声明中添加该字段的初始化器
class C {
final String value = '';
C();
}
如果该字段的值不依赖于可以传递给构造函数的值,但不同的构造函数需要将其初始化为不同的值,则在初始化列表中添加该字段的初始化器
class C {
final String value;
C() : value = '';
C.named() : value = 'c';
}
但是,如果该值对所有实例都相同,则考虑使用静态字段而不是实例字段
class C {
static const String value = '';
C();
}
Flutter 字段不是映射
#'flutter' 字段的值应为一个映射。
描述
#当flutter
键的值不是一个映射时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为顶级 flutter
键的值是一个字符串。
name: example
flutter: true
常见修复方法
#如果您需要指定 Flutter 特定的选项,请将值更改为一个映射。
name: example
flutter:
uses-material-design: true
如果您不需要指定 Flutter 特定的选项,请删除 flutter
键。
name: example
for-in-of 循环中元素类型无效
#在 'for' 循环中使用的类型 '{0}' 必须实现 '{1}',其类型参数可以分配给 '{2}'。
描述
#当 for-in 循环中的 Iterable
或 Stream
的元素类型无法分配给循环变量时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 <String>[]
的元素类型为 String
,而 String
无法分配给 e
的类型 (int
)。
void f() {
for (int e in <String>[]) {
print(e);
}
}
常见修复方法
#如果循环变量的类型正确,请更新可迭代对象的类型。
void f() {
for (int e in <int>[]) {
print(e);
}
}
如果可迭代对象的类型正确,请更新循环变量的类型。
void f() {
for (String e in <String>[]) {
print(e);
}
}
for-in-of 循环中类型无效
#在 'for' 循环中使用的类型 '{0}' 必须实现 '{1}'。
描述
#当 for-in 循环中 in
后面的表达式类型不是 Iterable
的子类时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 m
是一个 Map
,而 Map
不是 Iterable
的子类。
void f(Map<String, String> m) {
for (String s in m) {
print(s);
}
}
常见修复方法
#用产生可迭代值的表达式替换该表达式。
void f(Map<String, String> m) {
for (String s in m.values) {
print(s);
}
}
for-in 循环使用常量变量
#for-in 循环变量不能是 'const'。
描述
#当 for-in 循环中声明的循环变量被声明为 const
时,分析器会产生此诊断信息。该变量不能是 const
,因为该值无法在编译时计算。
示例
#以下代码会产生此诊断信息,因为循环变量 x
被声明为 const
。
void f() {
for (const x in [0, 1, 2]) {
print(x);
}
}
常见修复方法
#如果有类型注解,请从声明中删除 const
修饰符。
如果没有类型,请用 final
、var
或类型注解替换 const
修饰符。
void f() {
for (final x in [0, 1, 2]) {
print(x);
}
}
泛型方法类型实例化在动态类型上
#对类型为 'dynamic' 的接收者的方法撕裂不能具有类型参数。
描述
#当从类型为 dynamic
的接收器中分离实例方法时,分析器会生成此诊断信息,并且分离包含类型参数。由于分析器无法知道方法有多少个类型参数,或者它是否具有任何类型参数,因此它无法验证类型参数是否正确。因此,不允许使用类型参数。
示例
#以下代码会生成此诊断信息,因为 p
的类型为 dynamic
,并且 m
的分离具有类型参数
void f(dynamic list) {
list.fold<int>;
}
常见修复方法
#如果您可以使用比 dynamic
更具体的类型,则更改接收器的类型
void f(List<Object> list) {
list.fold<int>;
}
如果无法使用更具体的类型,则删除类型参数
void f(dynamic list) {
list.cast;
}
泛型结构体子类
#类 '{0}' 无法扩展 'Struct' 或 'Union',因为 '{0}' 是泛型的。
描述
#当 Struct
或 Union
的子类具有类型参数时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为类 S
定义了类型参数 T
import 'dart:ffi';
final class S<T> extends Struct {
external Pointer notEmpty;
}
常见修复方法
#从类中删除类型参数
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
的子类型
class C {
num get x => 0;
set x(int y) {}
}
常见修复方法
#如果 getter 的类型正确,则更改 setter 的类型
class C {
num get x => 0;
set x(num y) {}
}
如果 setter 的类型正确,则更改 getter 的类型
class C {
int get x => 0;
set x(int y) {}
}
异步生成器返回类型非法
#标记为 'async*' 的函数必须具有返回类型,该类型是 'Stream
描述
#当函数主体具有 async*
修饰符,但函数的返回类型既不是 Stream
也不是 Stream
的超类型时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为函数 `f` 的主体具有 `async*` 修饰符,即使返回值类型 `int` 不是 `Stream` 的超类型。
int f() async* {}
常见修复方法
#如果函数应该是异步的,则将返回值类型更改为 `Stream` 或 `Stream` 的超类型。
Stream<int> f() async* {}
如果函数应该是同步的,则删除 `async*` 修饰符。
int f() => 0;
异步返回类型非法
#标记为 `async` 的函数必须具有返回值类型,该类型是 `Future` 的超类型。
描述
#当函数主体具有 `async` 修饰符,但函数的返回值类型不可分配给 `Future` 时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为函数 `f` 的主体具有 `async` 修饰符,即使返回值类型不可分配给 `Future`。
int f() async {
return 0;
}
常见修复方法
#如果函数应该是异步的,则将返回值类型更改为可分配给 `Future` 的类型。
Future<int> f() async {
return 0;
}
如果函数应该是同步的,则删除 `async` 修饰符。
int f() => 0;
具体枚举成员非法
#在实现 `Enum` 的类中,不能声明名为 `{0}` 的具体实例成员。
在实现 `Enum` 的类中,不能从 `{1}` 继承名为 `{0}` 的具体实例成员。
描述
#当枚举声明、实现 `Enum` 的类或具有 `Enum` 超类约束的混合类声明或继承名为 `index`、`hashCode` 或 `==` 的具体实例成员时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为枚举 `E` 声明了一个名为 `index` 的实例 getter。
enum E {
v;
int get index => 0;
}
以下代码产生此诊断信息,因为类 `C` 实现 `Enum`,并声明了一个名为 `hashCode` 的实例字段。
abstract class C implements Enum {
int hashCode = 0;
}
以下代码产生此诊断信息,因为类 `C` 通过类 `A` 间接实现 `Enum`,并声明了一个名为 `hashCode` 的实例 getter。
abstract class A implements Enum {}
abstract class C implements A {
int get hashCode => 0;
}
以下代码产生此诊断信息,因为混合类 `M` 在 `on` 子句中具有 `Enum`,并声明了一个名为 `==` 的显式运算符。
mixin M on Enum {
bool operator ==(Object other) => false;
}
常见修复方法
#重命名冲突的成员。
enum E {
v;
int get getIndex => 0;
}
枚举值非法
#在实现 `Enum` 的类中,不能声明名为 `values` 的实例成员。
在实现 `Enum` 的类中,不能从 `{0}` 继承名为 `values` 的实例成员。
描述
#当实现 `Enum` 的类或具有 `Enum` 超类约束的 mixin 具有名为 `values` 的实例成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为实现 `Enum` 的类 `C` 声明了一个名为 `values` 的实例字段。
abstract class C implements Enum {
int get values => 0;
}
以下代码会生成此诊断信息,因为实现 `Enum` 的类 `B` 从 `A` 继承了一个名为 `values` 的实例方法。
abstract class A {
int values() => 0;
}
abstract class B extends A implements Enum {}
常见修复方法
#更改冲突成员的名称。
abstract class C implements Enum {
int get value => 0;
}
同步生成器返回类型非法
#标记为 'sync*' 的函数必须具有一个返回类型,该类型是 'Iterable
描述
#当函数体具有 `sync*` 修饰符,但函数的返回类型既不是 `Iterable` 也不是 `Iterable` 的超类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为函数 `f` 的主体具有 'sync*' 修饰符,但返回类型 `int` 不是 `Iterable` 的超类型。
int f() sync* {}
常见修复方法
#如果函数应该返回一个可迭代对象,则将返回类型更改为 `Iterable` 或 `Iterable` 的超类型。
Iterable<int> f() sync* {}
如果函数应该返回单个值,则删除 `sync*` 修饰符。
int f() => 0;
实现非类
#类和 mixin 只能实现其他类和 mixin。
描述
#当类或 mixin 声明的 `implements` 子句中使用的名称被定义为除类或 mixin 之外的其他内容时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 `x` 是一个变量,而不是一个类或 mixin。
var x;
class C implements x {}
常见修复方法
#如果名称是已存在且正在导入的类或 mixin 的名称,则向导入添加前缀,以便名称的本地定义不会遮蔽导入的名称。
如果名称是已存在但未导入的类或 mixin 的名称,则添加一个导入(带有前缀),用于声明它的库。
否则,要么用现有类或 mixin 的名称替换 `implements` 子句中的名称,要么从 `implements` 子句中删除该名称。
重复实现
#'{0}' 只能实现一次。
描述
#当 `implements` 子句中多次指定单个类时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 `A` 在列表中出现了两次。
class A {}
class B implements A, A {}
常见修复方法
#删除除一个之外的所有类名。
class A {}
class B implements A {}
实现超类
#“{0}”不能同时用于“extends”和“implements”子句。
“{0}”不能同时用于“extends”和“with”子句。
描述
#当一个类在类声明的extends
子句中列出,并且也在同一个声明的implements
或with
子句中列出时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类A
同时用于类B
的extends
和implements
子句。
class A {}
class B extends A implements A {}
以下代码会生成此诊断信息,因为类A
同时用于类B
的extends
和with
子句。
mixin class A {}
class B extends A with A {}
常见修复方法
#如果您想从该类继承实现,请从implements
子句中删除该类。
class A {}
class B extends A {}
如果您不想从该类继承实现,请删除extends
子句。
class A {}
class B implements A {}
隐式超类初始化器缺少参数
#来自“{0}”的隐式调用无名构造函数具有必需参数。
描述
#当构造函数隐式调用来自超类的无名构造函数,超类的无名构造函数具有必需参数,并且没有与必需参数相对应的超参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类B
中的无名构造函数隐式调用类A
中的无名构造函数,但A
中的构造函数具有名为x
的必需位置参数。
class A {
A(int x);
}
class B extends A {
B();
}
以下代码会生成此诊断信息,因为类B
中的无名构造函数隐式调用类A
中的无名构造函数,但A
中的构造函数具有名为x
的必需命名参数。
class A {
A({required int x});
}
class B extends A {
B();
}
常见修复方法
#如果您可以在子类中的构造函数中添加参数,请添加与超类构造函数中的必需参数相对应的超参数。新参数可以是必需的
class A {
A({required int x});
}
class B extends A {
B({required super.x});
}
或者它是可选的。
class A {
A({required int x});
}
class B extends A {
B({super.x = 0});
}
如果您无法在子类中的构造函数中添加参数,请使用必需参数添加显式超构造函数调用。
class A {
A(int x);
}
class B extends A {
B() : super(0);
}
初始化器中存在隐式 this 引用
#实例成员“{0}”不能在初始化器中访问。
描述
#当分析器在构造函数的初始化列表中找到对实例成员的引用时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为defaultX
是一个实例成员
class C {
int x;
C() : x = defaultX;
int get defaultX => 0;
}
常见修复方法
#如果该成员可以设置为静态,则将其设置为静态
class C {
int x;
C() : x = defaultX;
static int get defaultX => 0;
}
如果不能,则用不使用实例成员的其他表达式替换初始化器中的引用
class C {
int x;
C() : x = 0;
int get defaultX => 0;
}
使用 load 函数导入延迟库
#导入的库定义了一个名为“loadLibrary”的顶级函数,该函数被延迟导入此库而隐藏。
描述
#当分析器发现使用延迟导入导入声明了名为loadLibrary
的函数的库时,它会生成此诊断信息。延迟导入会引入一个名为loadLibrary
的隐式函数。此函数用于加载延迟库的内容,并且隐式函数会隐藏延迟库中的显式声明。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义了名为loadLibrary
的函数的文件a.dart
void loadLibrary(Library library) {}
class Library {}
以下代码会生成此诊断信息,因为a.loadLibrary
的隐式声明隐藏了a.dart
中loadLibrary
的显式声明
import 'a.dart' deferred as a;
void f() {
a.Library();
}
常见修复方法
#如果导入的库不需要延迟,则删除关键字deferred
import 'a.dart' as a;
void f() {
a.Library();
}
如果导入的库需要延迟,并且您需要引用导入的函数,则重命名导入库中的函数
void populateLibrary(Library library) {}
class Library {}
如果导入的库需要延迟,并且您不需要引用导入的函数,则添加hide
子句
import 'a.dart' deferred as a hide loadLibrary;
void f() {
a.Library();
}
导入内部库
#库“{0}”是内部库,不能导入。
描述
#当分析器发现导入的dart:
URI 引用了内部库时,它会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 _interceptors
是一个内部库
import 'dart:_interceptors';
常见修复方法
#删除导入指令。
将传统库导入到空安全库中
#库“{0}”是旧版库,不应该导入到空安全库中。
描述
#当空安全的库导入非空安全的库时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的文件a.dart
// @dart = 2.9
class A {}
以下代码会生成此诊断信息,因为空安全的库正在导入非空安全的库
import 'a.dart';
A? f() => null;
常见修复方法
#如果您可以将导入的库迁移为空安全库,则迁移它并更新或删除迁移库的语言版本。
如果您无法迁移导入的库,则导入的库需要使用 2.12 之前的语言版本,因为在该版本中,空安全默认启用。
导入非库
#导入的库“{0}”不能包含 part-of 指令。
描述
#当将 部分文件 导入库时,分析器会生成此诊断信息。
示例
#假设有一个名为 part.dart
的 部分文件,其中包含以下内容
part of lib;
以下代码会生成此诊断信息,因为导入的文件不能包含 part-of 指令
library lib;
import 'part.dart';
常见修复方法
#继承不一致
#超接口没有为“{0}”提供有效的覆盖:{1}。
描述
#当一个类继承了两个或多个成员的冲突签名,并且没有提供满足所有继承签名的实现时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 C
继承了 A
中 m
的声明,而该实现与从 B
继承的 m
的签名不一致
class A {
void m({int? a}) {}
}
class B {
void m({int? b}) {}
}
class C extends A implements B {
}
常见修复方法
#添加一个满足所有继承签名的实现方法
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.dart
的 部分文件,其中包含以下内容
// @dart = 2.14
part of 'test.dart';
以下代码会生成此诊断信息,因为库的部分必须与定义的编译单元具有相同的语言版本
// @dart = 2.15
part 'part.dart';
常见修复方法
#从 部分文件 中删除语言版本覆盖,以便它隐式使用与定义的编译单元相同的版本
part of 'test.dart';
如果需要,请调整定义编译单元中的语言版本覆盖,使其适合该部分中的代码,或者将部分文件中的代码迁移为与新语言版本一致。
模式变量逻辑或不一致
#变量“{0}”在逻辑或模式的这个分支中具有不同的类型和/或最终性。
描述
#当在逻辑或模式的所有分支上声明的模式变量在每个分支上没有相同的类型时,分析器会产生此诊断信息。当变量在不同分支上具有不同的最终性时,也会产生此诊断信息。在逻辑或模式的多个分支上声明的模式变量要求在每个分支中具有相同的类型和最终性,以便可以在逻辑或模式保护的代码中知道变量的类型和最终性。
示例
#以下代码会产生此诊断信息,因为变量a
在一个分支上定义为int
,而在另一个分支上定义为double
void f(Object? x) {
if (x case (int a) || (double a)) {
print(a);
}
}
以下代码会产生此诊断信息,因为变量a
在第一个分支中是final
,而在第二个分支中不是final
void f(Object? x) {
if (x case (final int a) || (int a)) {
print(a);
}
}
常见修复方法
#如果变量的最终性不同,请决定它应该是final
还是非final
,并使情况一致
void f(Object? x) {
if (x case (int a) || (int a)) {
print(a);
}
}
如果变量的类型不同,并且类型对匹配的条件不重要,请确保变量在两个分支上具有相同的类型
void f(Object? x) {
if (x case (num a) || (num a)) {
print(a);
}
}
如果变量的类型不同,并且类型对匹配的条件很重要,请考虑将条件分解为多个if
语句或case
子句
void f(Object? x) {
if (x case int a) {
print(a);
} else if (x case double a) {
print(a);
}
}
不存在字段的初始化器
#“{0}”不是封闭类中的字段。
描述
#当构造函数初始化在包含构造函数的类中未声明的字段时,分析器会产生此诊断信息。构造函数不能初始化未声明的字段和从超类继承的字段。
示例
#以下代码会产生此诊断信息,因为初始化程序正在初始化x
,但x
不是类中的字段
class C {
int? y;
C() : x = 0;
}
常见修复方法
#如果应该初始化不同的字段,请将名称更改为字段的名称
class C {
int? y;
C() : y = 0;
}
如果必须声明字段,请添加声明
class C {
int? x;
int? y;
C() : x = 0;
}
静态字段的初始化器
#“{0}”是封闭类中的静态字段。在构造函数中初始化的字段不能是静态的。
描述
#当在构造函数中使用初始化形式参数或初始化列表中的赋值来初始化静态字段时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为静态字段 a
正在通过初始化形式参数 this.a
进行初始化。
class C {
static int? a;
C(this.a);
}
常见修复方法
#如果该字段应该是实例字段,则删除关键字 static
。
class C {
int? a;
C(this.a);
}
如果您打算初始化一个实例字段,但输入了错误的名称,则更正正在初始化的字段的名称。
class C {
static int? a;
int? b;
C(this.b);
}
如果您确实想初始化静态字段,则将初始化移到构造函数体中。
class C {
static int? a;
C(int? c) {
a = c;
}
}
不存在字段的初始化形式参数
#“{0}”不是封闭类中的字段。
描述
#当在未声明正在初始化的字段的类中的构造函数中找到初始化形式参数时,分析器会生成此诊断信息。构造函数无法初始化未声明的字段以及从超类继承的字段。
示例
#以下代码会生成此诊断信息,因为字段 x
未定义。
class C {
int? y;
C(this.x);
}
常见修复方法
#如果字段名称错误,则将其更改为现有字段的名称。
class C {
int? y;
C(this.y);
}
如果字段名称正确,但尚未定义,则声明该字段。
class C {
int? x;
int? y;
C(this.x);
}
如果需要该参数,但它不应该初始化字段,则将其转换为普通参数并使用它。
class C {
int y;
C(int x) : y = x * 2;
}
如果不需要该参数,则将其删除。
class C {
int? y;
C();
}
实例访问静态成员
#无法通过实例访问静态 {1} '{0}'。
描述
#当使用访问运算符通过类的实例访问静态成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 zero
是一个静态字段,但它被访问的方式好像是一个实例字段。
void f(C c) {
c.zero;
}
class C {
static int zero = 0;
}
常见修复方法
#使用类来访问静态成员。
void f(C c) {
C.zero;
}
class C {
static int zero = 0;
}
从工厂访问实例成员
#无法从工厂构造函数访问实例成员。
描述
#当工厂构造函数包含对实例成员的非限定引用时,分析器会生成此诊断信息。在生成式构造函数中,类的实例是在执行构造函数体之前创建和初始化的,因此可以将实例绑定到 this
并像在实例方法中一样访问它。但是,在工厂构造函数中,实例是在执行主体之前创建的,因此 this
无法用于引用它。
示例
#以下代码会生成此诊断信息,因为 x
在工厂构造函数中不在作用域内。
class C {
int x;
factory C() {
return C._(x);
}
C._(this.x);
}
常见修复方法
#重写代码,使其不再引用实例成员。
class C {
int x;
factory C() {
return C._(0);
}
C._(this.x);
}
从静态访问实例成员
#无法从静态方法访问实例成员。
描述
#当静态方法包含对实例成员的非限定引用时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断是因为在静态方法中引用了实例字段x
class C {
int x = 0;
static int m() {
return x;
}
}
常见修复方法
#如果方法必须引用实例成员,则它不能是静态的,因此请删除关键字
class C {
int x = 0;
int m() {
return x;
}
}
如果方法不能成为实例方法,则添加一个参数,以便可以传入类的实例
class C {
int x = 0;
static int m(C c) {
return c.x;
}
}
实例化抽象类
#抽象类不能实例化。
描述
#当分析器发现构造函数调用并且构造函数在抽象类中声明时,它会产生此诊断。即使您不能创建抽象类的实例,抽象类也可以声明构造函数,这些构造函数可以被子类调用。
示例
#以下代码产生此诊断是因为C
是一个抽象类
abstract class C {}
var c = new C();
常见修复方法
#如果存在可以使用的抽象类的具体子类,则创建具体子类的实例。
实例化枚举
#枚举不能实例化。
描述
#当枚举被实例化时,分析器会产生此诊断。通过调用构造函数创建枚举的实例是无效的;只有枚举声明中命名的实例才能存在。
示例
#以下代码产生此诊断是因为枚举E
正在被实例化
// @dart = 2.16
enum E {a}
var e = E();
常见修复方法
#如果您打算使用枚举的实例,则引用枚举中定义的常量之一
// @dart = 2.16
enum E {a}
var e = E.a;
如果您打算使用类的实例,则使用该类的名称代替枚举的名称。
实例化类型别名扩展到类型参数
#扩展为类型参数的类型别名不能实例化。
描述
#当发现构造函数调用,其中被实例化的类型是类型别名的类型参数之一的类型别名时,分析器会产生此诊断。这是不允许的,因为类型参数的值是类型而不是类。
示例
#以下代码产生此诊断,因为它创建了A
的实例,即使A
是一个定义为等效于类型参数的类型别名
typedef A<T> = T;
void f() {
const A<int>();
}
常见修复方法
#使用类名或定义为类的类型别名,而不是定义为类型参数的类型别名
typedef A<T> = C<T>;
void f() {
const A<int>();
}
class C<T> {
const C();
}
整数字面量作为 double 不精确
#整数文字被用作双精度数,但不能在不溢出或丢失精度的情况下表示为 64 位双精度数:'{0}'。
描述
#当一个整数字面量被隐式转换为双精度浮点数,但无法在不溢出或丢失精度的情况下表示为 64 位双精度浮点数时,分析器会生成此诊断信息。如果上下文需要 double
类型,则整数字面量会隐式转换为双精度浮点数。
示例
#以下代码会生成此诊断信息,因为整数 9223372036854775807
无法精确地表示为双精度浮点数。
double x = 9223372036854775807;
常见修复方法
#如果您需要使用精确值,请使用 BigInt
类来表示该值。
var x = BigInt.parse('9223372036854775807');
如果您需要使用双精度浮点数,请将值更改为可以精确表示的值。
double x = 9223372036854775808;
整数字面量超出范围
#整数字面量 {0} 无法在 64 位中表示。
描述
#当一个整数字面量的值太大(正数)或太小(负数)而无法在 64 位字中表示时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为该值无法在 64 位中表示。
var x = 9223372036854775810;
常见修复方法
#如果您需要表示当前值,请将其包装在 BigInt
类的实例中。
var x = BigInt.parse('9223372036854775810');
注释无效
#注解必须是常量变量引用或常量构造函数调用。
描述
#当发现一个注解使用的是既不是标记为 const
的变量,也不是 const
构造函数的调用时,分析器会生成此诊断信息。
获取器不能用作注解。
示例
#以下代码会生成此诊断信息,因为变量 v
不是 const
变量。
var v = 0;
@v
void f() {
}
以下代码会生成此诊断信息,因为 f
不是变量。
@f
void f() {
}
以下代码会生成此诊断信息,因为 f
不是构造函数。
@f()
void f() {
}
以下代码会生成此诊断信息,因为 g
是一个获取器。
@g
int get g => 0;
常见修复方法
#如果注解引用的是一个不是 const
构造函数的变量,请在变量声明中添加关键字 const
。
const v = 0;
@v
void f() {
}
如果注解没有引用变量,请将其删除。
int v = 0;
void f() {
}
来自延迟库的注释常量值无效
#来自延迟库的常量值不能用在注解中。
描述
#当在注解的参数列表中引用了在作为延迟库导入的库中定义的常量时,分析器会生成此诊断信息。注解是在编译时评估的,而来自延迟库的值在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#以下代码会生成此诊断信息,因为常量 pi
被引用在注解的参数列表中,即使定义它的库被作为延迟库导入。
import 'dart:math' deferred as math;
class C {
const C(double d);
}
@C(math.pi)
void f () {}
常见修复方法
#如果您需要引用导入的常量,请删除deferred
关键字。
import 'dart:math' as math;
class C {
const C(double d);
}
@C(math.pi)
void f () {}
如果导入需要延迟,并且存在另一个合适的常量,请使用该常量代替延迟库中的常量。
来自延迟库的注释无效
#延迟库中的常量值不能用作注释。
描述
#当使用延迟导入的库中的常量作为注释时,分析器会生成此诊断信息。注释在编译时进行评估,而延迟库中的常量在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#以下代码会生成此诊断信息,因为常量pi
用作注释,而库dart:math
被导入为deferred
import 'dart:math' deferred as math;
@math.pi
void f() {}
常见修复方法
#如果您需要将常量引用为注释,请从导入中删除关键字deferred
。
import 'dart:math' as math;
@math.pi
void f() {}
如果您可以使用不同的常量作为注释,请用不同的常量替换注释。
@deprecated
void f() {}
注释目标无效
#注释“{0}”只能用于{1}。
描述
#当注释应用于它不支持的声明类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为optionalTypeArgs
注释未定义为对顶层变量有效。
import 'package:meta/meta.dart';
@optionalTypeArgs
int x = 0;
常见修复方法
#从声明中删除注释。
赋值无效
#类型为“{0}”的值不能分配给类型为“{1}”的变量。
描述
#当分配给变量的表达式的静态类型不可分配给变量的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为初始化程序的类型(int
)不可分配给变量的类型(String
)。
int i = 0;
String s = i;
常见修复方法
#如果分配的值在运行时始终可分配,即使静态类型没有反映这一点,请添加显式强制转换。
否则,更改分配的值,使其具有预期的类型。在前面的示例中,这可能看起来像
int i = 0;
String s = i.toString();
如果您无法更改值,请更改变量的类型,使其与分配的值的类型兼容。
int i = 0;
int s = i;
依赖关系无效
#可发布的包不能具有“{0}”依赖项。
描述
#当可发布的包在其pubspec.yaml
文件的dependencies
列表中包含一个不是发布托管依赖项的包时,分析器会生成此诊断信息。
要了解有关不同类型的依赖项来源的更多信息,请查看 包依赖项。
示例
#以下代码会产生此诊断信息,因为对包 transmogrify
的依赖项不是 pub 托管的依赖项。
name: example
dependencies:
transmogrify:
path: ../transmogrify
常见修复方法
#如果要将包发布到 pub.dev
,请将依赖项更改为发布到 pub.dev
的托管包。
如果该包不打算发布到 pub.dev
,请在它的 pubspec.yaml
文件中添加一个 publish_to: none
条目,将其标记为不打算发布。
name: example
publish_to: none
dependencies:
transmogrify:
path: ../transmogrify
异常值无效
#当函数的返回类型为 'void'、'Handle' 或 'Pointer' 时,方法 {0} 不能具有异常返回值(第二个参数)。
描述
#当调用 Pointer.fromFunction
或 NativeCallable.isolateLocal
方法时,如果第二个参数(异常返回值)存在,并且调用返回的类型为 void
、Handle
或 Pointer
,则分析器会产生此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为在 f
的返回类型为 void
时提供了第二个参数。
import 'dart:ffi';
typedef T = Void Function(Int8);
void f(int i) {}
void g() {
Pointer.fromFunction<T>(f, 42);
}
常见修复方法
#删除异常值。
import 'dart:ffi';
typedef T = Void Function(Int8);
void f(int i) {}
void g() {
Pointer.fromFunction<T>(f);
}
导出内部元素无效
#成员 '{0}' 不能作为包的公共 API 的一部分导出。
描述
#当一个 公共库 导出一个用 internal
注解标记的声明时,分析器会产生此诊断信息。
示例
#假设在 src
目录中有一个名为 a.dart
的文件,其中包含以下内容:
import 'package:meta/meta.dart';
@internal class One {}
以下代码在 公共库 中找到时会产生此诊断信息,因为 export
指令正在导出一个仅供内部使用的名称。
export 'src/a.dart';
常见修复方法
#如果需要导出,请添加一个 hide
子句来隐藏内部名称。
export 'src/a.dart' hide One;
如果不需要导出,请将其删除。
间接导出内部元素无效
#成员 '{0}' 不能作为包的公共 API 的一部分导出,但作为 '{1}' 的签名的一部分被间接导出。
描述
#当一个 公共库 导出一个顶层函数,该函数的返回类型或至少一个参数类型用 internal
注解标记时,分析器会产生此诊断信息。
示例
#假设在 src
目录中有一个名为 a.dart
的文件,其中包含以下内容:
import 'package:meta/meta.dart';
@internal
typedef IntFunction = int Function();
int f(IntFunction g) => g();
以下代码会产生此诊断信息,因为函数 f
的参数类型为 IntFunction
,而 IntFunction
仅供内部使用。
export 'src/a.dart' show f;
常见修复方法
#如果函数必须是公共的,请将函数签名中的所有类型都改为公共类型。
如果函数不需要导出,则停止导出它,方法是将其从show
子句中删除,将其添加到hide
子句中,或者删除导出。
扩展参数计数无效
#扩展覆盖必须恰好有一个参数:扩展方法中'this'的值。
描述
#当扩展覆盖没有恰好一个参数时,分析器会生成此诊断。参数是用于计算扩展方法中this
值的表达式,因此必须有一个参数。
示例
#以下代码会生成此诊断,因为没有参数
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E().join('b');
}
并且,以下代码会生成此诊断,因为有多个参数
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E('a', 'b').join('c');
}
常见修复方法
#为扩展覆盖提供一个参数
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E('a').join('b');
}
工厂方法声明无效
#工厂方法 '{0}' 必须具有返回值类型。
描述
#当用factory
注解的方法具有void
的返回值类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为方法createC
用factory
注解,但没有返回值
import 'package:meta/meta.dart';
class Factory {
@factory
void createC() {}
}
class C {}
常见修复方法
#将返回值类型更改为除void
以外的类型
import 'package:meta/meta.dart';
class Factory {
@factory
C createC() => C();
}
class C {}
工厂方法实现无效
#工厂方法 '{0}' 没有返回新分配的对象。
描述
#当用factory
注解的方法没有返回新分配的对象时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为方法createC
返回字段的值,而不是C
的新创建实例
import 'package:meta/meta.dart';
class Factory {
C c = C();
@factory
C createC() => c;
}
class C {}
常见修复方法
#将方法更改为返回返回值类型的新创建实例
import 'package:meta/meta.dart';
class Factory {
@factory
C createC() => C();
}
class C {}
工厂名称无效,不是类
#工厂构造函数的名称必须与紧邻的类的名称相同。
描述
#当工厂构造函数的名称与周围类的名称不同时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为工厂构造函数的名称(A
)与周围类(C
)的名称不同
class A {}
class C {
factory A() => throw 0;
}
常见修复方法
#如果工厂返回周围类的实例,并且您希望它成为未命名的工厂构造函数,则重命名工厂
class A {}
class C {
factory C() => throw 0;
}
如果工厂返回周围类的实例,并且您希望它成为命名工厂构造函数,则在工厂构造函数名称前加上周围类的名称。
class A {}
class C {
factory C.a() => throw 0;
}
如果工厂返回不同类的实例,则将工厂移至该类。
class A {
factory A() => throw 0;
}
class C {}
如果工厂返回不同类的实例,但您无法修改该类或不想移动工厂,则将其转换为静态方法。
class A {}
class C {
static A a() => throw 0;
}
字段名称无效
#当整数是位置字段的索引时,记录字段名称不能是美元符号后跟整数。
记录字段名称不能是私有的。
记录字段名称不能与“Object”中的成员相同。
描述
#当记录字面量或记录类型注释的字段名称无效时,分析器会生成此诊断。如果名称为
- 私有(以
_
开头) - 与
Object
上定义的成员之一相同 - 与位置字段的名称相同(如果字段是具有指定名称的位置字段,则会例外)
示例
#以下代码会生成此诊断,因为记录字面量有一个名为toString
的字段,它是Object
上定义的方法。
var r = (a: 1, toString: 4);
以下代码会生成此诊断,因为记录类型注释有一个名为hashCode
的字段,它是Object
上定义的 getter。
void f(({int a, int hashCode}) r) {}
以下代码会生成此诊断,因为记录字面量有一个名为_a
的私有字段。
var r = (_a: 1, b: 2);
以下代码会生成此诊断,因为记录类型注释有一个名为_a
的私有字段。
void f(({int _a, int b}) r) {}
以下代码会生成此诊断,因为记录字面量有一个名为$1
的字段,它也是另一个位置参数的名称。
var r = (2, $1: 1);
以下代码会生成此诊断,因为记录类型注释有一个名为$1
的字段,它也是另一个位置参数的名称。
void f((int, String, {int $1}) r) {}
常见修复方法
#重命名字段。
var r = (a: 1, d: 4);
结构体中的字段类型无效
#结构类中的字段不能具有类型“{0}”。它们只能声明为“int”、“double”、“Array”、“Pointer”或“Struct”或“Union”的子类型。
描述
#当Struct
的子类的字段类型不是int
、double
、Array
、Pointer
或Struct
或Union
的子类型时,分析器会生成此诊断。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断,因为字段str
的类型为String
,它不是Struct
子类字段允许的类型之一。
import 'dart:ffi';
final class C extends Struct {
external String s;
@Int32()
external int i;
}
常见修复方法
#使用允许的类型之一来表示该字段。
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
。
class A {
int add(int a) => a;
}
class B extends A {
int add(num a);
}
这是一个问题,因为在像下面这样调用 B.add
时
void f(B b) {
b.add(3.4);
}
B.add
预计能够接受例如 double
,但当方法 A.add
被执行(因为它时 add
的唯一具体实现)时,会抛出运行时异常,因为 double
不能被赋值给类型为 int
的参数。
常见修复方法
#如果子类中的方法可以符合超类中的实现,那么更改子类中的声明(如果它相同,则将其删除)。
class A {
int add(int a) => a;
}
class B extends A {
int add(int a);
}
如果超类中的方法可以被泛化为子类中方法的有效实现,那么更改超类方法。
class A {
int add(num a) => a.floor();
}
class B extends A {
int add(num a);
}
如果超类中的方法和子类中的方法都不能更改,那么在子类中提供该方法的具体实现。
class A {
int add(int a) => a;
}
class B extends A {
int add(num a) => a.floor();
}
内联函数类型无效
#内联函数类型不能用作泛型函数类型中的参数。
描述
#当泛型函数类型具有使用旧的内联函数类型语法编写的函数值参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为泛型函数类型中用于定义 F
的参数 f
使用了内联函数类型语法。
typedef F = int Function(int f(String s));
常见修复方法
#对参数的类型使用泛型函数语法。
typedef F = int Function(int Function(String));
内部注释无效
#包的私有 API 中只有公共元素可以被注释为内部。
描述
#当一个声明被注释为 internal
注释,并且该声明位于 公共库 中或具有私有名称时,分析器会生成此诊断信息。
示例
#以下代码在 公共库 中会产生此诊断信息,因为 internal
注解不能应用于 公共库 中的声明。
import 'package:meta/meta.dart';
@internal
class C {}
以下代码,无论是在公共库还是内部库中,都会产生此诊断信息,因为 internal
注解不能应用于具有私有名称的声明。
import 'package:meta/meta.dart';
@internal
class _C {}
void f(_C c) {}
常见修复方法
#如果声明具有私有名称,则删除注解。
class _C {}
void f(_C c) {}
如果声明具有公共名称并且旨在对包内部可见,则将带注解的声明移到内部库(换句话说,是 src
目录中的库)。
否则,删除注解的使用。
class C {}
语言版本覆盖无效
#Dart 语言版本覆盖注释不能后跟任何非空白字符。
Dart 语言版本覆盖注释必须使用版本号(例如 '2.0')指定,位于 '=' 字符之后。
Dart 语言版本覆盖注释必须使用 '=' 字符指定。
Dart 语言版本覆盖注释必须使用两个斜杠指定。
Dart 语言版本覆盖注释必须使用全小写字母 'dart' 指定。
Dart 语言版本覆盖号不能以字母为前缀。
Dart 语言版本覆盖号必须以 '@dart' 开头。
语言版本覆盖不能指定大于最新已知语言版本的版本:{0}.{1}。
语言版本覆盖必须在任何声明或指令之前指定。
描述
#当注释似乎是试图指定语言版本覆盖,但与这种注释的要求不符时,分析器会产生此诊断信息。有关更多信息,请参阅 每个库的语言版本选择。
示例
#以下代码会产生此诊断信息,因为在这样的注释中,'dart' 一词必须是小写,并且 'dart' 一词和版本号之间没有等号。
// @Dart 2.13
常见修复方法
#如果注释旨在作为语言版本覆盖,则更改注释以遵循正确的格式。
// @dart = 2.13
字面量注释无效
#只有 const 构造函数可以具有 @literal
注解。
描述
#当 literal
注解应用于 const 构造函数以外的任何内容时,分析器会产生此诊断信息。
示例
#以下代码会生成此诊断,因为构造函数不是 const
构造函数
import 'package:meta/meta.dart';
class C {
@literal
C();
}
以下代码会产生此诊断信息,因为 x
不是构造函数。
import 'package:meta/meta.dart';
@literal
var x;
常见修复方法
#如果注解位于构造函数上,并且构造函数应该始终使用 const
调用(如果可能),则使用 const
关键字标记构造函数。
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
如果构造函数不能标记为const
,则删除该注释。
如果注释不在构造函数上,则删除该注释。
var x;
构造函数上的修饰符无效
#修饰符“{0}”不能应用于构造函数体。
描述
#当构造函数体以以下修饰符之一为前缀时,分析器会生成此诊断:async
、async*
或sync*
。构造函数体必须是同步的。
示例
#以下代码会生成此诊断,因为C
的构造函数体被标记为async
class C {
C() async {}
}
常见修复方法
#如果构造函数可以是同步的,则删除修饰符。
class C {
C();
}
如果构造函数不能是同步的,则使用静态方法来创建实例。
class C {
C();
static Future<C> c() async {
return C();
}
}
setter 上的修饰符无效
#Setter不能使用“async”、“async*”或“sync*”。
描述
#当setter体以以下修饰符之一为前缀时,分析器会生成此诊断:async
、async*
或sync*
。Setter体必须是同步的。
示例
#以下代码会生成此诊断,因为setterx
的体被标记为async
class C {
set x(int i) async {}
}
常见修复方法
#如果setter可以是同步的,则删除修饰符。
class C {
set x(int i) {}
}
如果setter不能是同步的,则使用方法来设置值。
class C {
void x(int i) async {}
}
非虚拟注释无效
#注释“@nonVirtual”只能应用于具体的实例成员。
描述
#当nonVirtual
注释出现在类、mixin或枚举的成员之外,或者成员不是具体的实例成员时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为注释在类声明上,而不是类内部的成员上。
import 'package:meta/meta.dart';
@nonVirtual
class C {}
以下代码会生成此诊断,因为方法m
是抽象方法。
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
void m();
}
以下代码会生成此诊断,因为方法m
是静态方法。
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
static void m() {}
}
常见修复方法
#如果声明不是类、mixin或枚举的成员,则删除注释。
class C {}
如果成员意图是具体的实例成员,则将其设为如此。
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
void m() {}
}
如果成员不意图是具体的实例成员,则删除注释。
abstract class C {
static void m() {}
}
空感知运算符无效
#由于短路运算,接收者不能为null,因此不能使用空感知运算符“{0}”。
接收者不能为null,因此空感知运算符“{0}”是不必要的。
描述
#当在已知为非空的可接收者上使用空感知运算符(?.
、?..
、?[
、?..[
或...?
)时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为s
不能为null
int? getLength(String s) {
return s?.length;
}
以下代码产生此诊断信息,因为a
不能为null
var a = [];
var b = [...?a];
以下代码产生此诊断信息,因为s?.length
不能返回null
void f(String? s) {
s?.length?.isEven;
}
s?.length
不能返回null
的原因是,在s
为null
的情况下,s
后面的空感知运算符会短路length
和isEven
的求值。换句话说,如果s
为null
,则length
和isEven
都不会被调用;如果s
不为null
,则length
不能返回null
值。无论哪种情况,isEven
都不能在null
值上调用,因此空感知运算符不是必需的。有关更多详细信息,请参阅了解空安全。
以下代码产生此诊断信息,因为s
不能为null
。
void f(Object? o) {
var s = o as String;
s?.length;
}
尽管o
可以为null
,但s
不能为null
的原因是,它被强制转换为String
类型,这是一个非空类型。如果o
的值曾经为null
,则强制转换将失败,并且不会调用length
。
常见修复方法
#用非空感知等效项替换空感知运算符;例如,将?.
更改为.
int getLength(String s) {
return s.length;
}
(请注意,返回值类型也已更改为非空类型,这在某些情况下可能不合适。)
覆盖无效
#'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效重写。
设置器 '{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效重写。
描述
#当发现类中的某个成员重写了超类型中的某个成员,但重写无效时,分析器会产生此诊断信息。如果以下所有条件都为真,则重写有效
- 它允许被重写成员允许的所有参数。
- 它不需要被重写成员不需要的任何参数。
- 被重写成员的每个参数的类型都可分配给重写中相应的参数。
- 重写的返回值类型可分配给被重写成员的返回值类型。
示例
#以下代码产生此诊断信息,因为参数s
的类型(String
)不可分配给参数i
的类型(int
)
class A {
void m(int i) {}
}
class B extends A {
void m(String s) {}
}
常见修复方法
#如果无效方法旨在重写超类中的方法,则将其更改为符合
class A {
void m(int i) {}
}
class B extends A {
void m(int i) {}
}
如果它不打算重写超类中的方法,则将其重命名
class A {
void m(int i) {}
}
class B extends A {
void m2(String s) {}
}
覆盖非虚拟成员无效
#成员 '{0}' 在 '{1}' 中声明为非虚拟,不能在子类中重写。
描述
#当类、mixin 或枚举中的某个成员重写了在其上具有@nonVirtual
注释的成员时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断是因为类 B
中的方法 m
覆盖了类 A
中的方法 m
,而类 A
中的方法 m
被 @nonVirtual
注解标记。
import 'package:meta/meta.dart';
class A {
@nonVirtual
void m() {}
}
class B extends A {
@override
void m() {}
}
常见修复方法
#如果超类中方法的注解是正确的(超类中的方法不打算被覆盖),则删除或重命名覆盖方法。
import 'package:meta/meta.dart';
class A {
@nonVirtual
void m() {}
}
class B extends A {}
如果超类中的方法打算被覆盖,则删除 @nonVirtual
注解。
class A {
void m() {}
}
class B extends A {
@override
void m() {}
}
共享 case 范围内的模式变量无效
#变量 '{0}' 在所有共享此代码块的用例中类型和/或 final 属性不一致。
变量 '{0}' 在一些共享此代码块的用例中可用,但在其他用例中不可用。
变量 '{0}' 不可使用,因为存在标签或 'default' 用例。
描述
#当 switch 语句中的多个 case 子句共享一个代码块,并且至少其中一个子句声明了一个在共享语句中被引用的变量,但该变量要么没有在所有 case 子句中声明,要么以不一致的方式声明时,分析器会产生此诊断。
如果变量没有在所有 case 子句中声明,那么如果其中一个没有声明该变量的子句匹配并执行了代码块,该变量将没有值。这包括其中一个 case 子句是 default
子句的情况。
如果变量以不一致的方式声明,例如在某些情况下是 final
,而在其他情况下不是 final
,或者在不同情况下具有不同的类型,那么变量的类型或 final 属性的语义将没有定义。
示例
#以下代码产生此诊断是因为变量 a
仅在一个 case 子句中声明,如果第二个子句匹配 x
,则该变量将没有值。
void f(Object? x) {
switch (x) {
case int a when a > 0:
case 0:
a;
}
}
以下代码产生此诊断是因为变量 a
没有在 default
子句中声明,如果代码块执行,因为没有其他子句匹配 x
,则该变量将没有值。
void f(Object? x) {
switch (x) {
case int a when a > 0:
default:
a;
}
}
以下代码产生此诊断是因为变量 a
将没有值,因为不同的 case 组导致控制在标签处继续执行。
void f(Object? x) {
switch (x) {
someLabel:
case int a when a > 0:
a;
case int b when b < 0:
continue someLabel;
}
}
以下代码产生此诊断是因为变量a
虽然在所有case子句中都被赋值,但在每个子句中没有关联相同的类型
void f(Object? x) {
switch (x) {
case int a when a < 0:
case num a when a > 0:
a;
}
}
以下代码产生此诊断是因为变量a
在第一个case子句中是final
,而在第二个case子句中不是final
void f(Object? x) {
switch (x) {
case final int a when a < 0:
case int a when a > 0:
a;
}
}
常见修复方法
#如果变量没有在所有case中声明,并且您需要在语句中引用它,那么在其他case中声明它
void f(Object? x) {
switch (x) {
case int a when a > 0:
case int a when a == 0:
a;
}
}
如果变量没有在所有case中声明,并且您不需要在语句中引用它,那么删除对它的引用并从其他case中删除声明
void f(int x) {
switch (x) {
case > 0:
case 0:
}
}
如果变量的类型不同,请决定变量应该具有的类型,并使case保持一致
void f(Object? x) {
switch (x) {
case num a when a < 0:
case num a when a > 0:
a;
}
}
如果变量的最终性不同,请决定它应该是final
还是非final
,并使情况一致
void f(Object? x) {
switch (x) {
case final int a when a < 0:
case final int a when a > 0:
a;
}
}
平台字段无效
#“platforms”字段必须是一个以平台为键的映射。
描述
#当指定顶级platforms
字段,但其值不是一个以键为值的映射时,分析器会产生此诊断。要了解有关指定包支持平台的更多信息,请查看平台声明文档。
示例
#以下pubspec.yaml
产生此诊断,因为platforms
应该是一个映射。
name: example
platforms:
- android
- web
- ios
常见修复方法
#如果您能依赖自动平台检测,那么省略顶级platforms
字段。
name: example
如果您需要手动指定支持平台的列表,那么将platforms
字段写成一个以平台名称为键的映射。
name: example
platforms:
android:
web:
ios:
对生成枚举构造函数的引用无效
#生成式枚举构造函数只能用作重定向的目标。
描述
#当在枚举上定义的生成式构造函数被用于创建枚举常量之一以外的任何地方,或者用作同一枚举中另一个构造函数的重定向目标时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为E
的构造函数被用于在函数f
中创建实例
enum E {
a(0);
const E(int x);
}
E f() => const E(2);
常见修复方法
#如果存在具有相同值的枚举值,或者如果您添加了这样的常量,那么直接引用该常量
enum E {
a(0), b(2);
const E(int x);
}
E f() => E.b;
如果您需要使用构造函数调用,那么使用工厂构造函数
enum E {
a(0);
const E(int x);
factory E.c(int x) => a;
}
E f() => E.c(2);
对 this 的引用无效
#对“this”表达式的无效引用。
描述
#当在实例方法或生成式构造函数之外使用this
时,分析器会产生此诊断。保留字this
仅在实例方法、生成式构造函数或延迟实例字段声明的初始化程序的上下文中定义。
示例
#以下代码产生此诊断,因为v
是一个顶级变量
C f() => this;
class C {}
常见修复方法
#使用适当类型的变量代替this
,必要时声明它
C f(C c) => c;
class C {}
catch 错误的返回类型无效
#类型为“{0}”的值不能被“onError”处理程序返回,因为它必须可分配给“{1}”。
返回类型“{0}”不可分配给“{1}”,这是“Future.catchError”的要求。
描述
#当 Future.catchError
的调用参数的返回类型与 Future
实例返回的类型不兼容时,分析器会生成此诊断信息。在运行时,catchError
方法尝试将回调中的值作为 future 的结果返回,这会导致抛出另一个异常。
示例
#以下代码会生成此诊断信息,因为 future
被声明为返回一个 int
,而 callback
被声明为返回一个 String
,而 String
不是 int
的子类型。
void f(Future<int> future, String Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
以下代码会生成此诊断信息,因为传递给 catchError
的闭包返回一个 int
,而 future
被声明为返回一个 String
。
void f(Future<String> future) {
future.catchError((error, stackTrace) => 3);
}
常见修复方法
#如果 Future
实例的声明正确,则更改回调以匹配。
void f(Future<int> future, int Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
如果 Future
实例的声明错误,则更改它以匹配回调。
void f(Future<String> future, String Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
密封注释无效
#@sealed
注解只能应用于类。
描述
#当除了类声明之外的声明带有 @sealed
注解时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 @sealed
注解位于方法声明上。
import 'package:meta/meta.dart';
class A {
@sealed
void m() {}
}
常见修复方法
#删除注解。
class A {
void m() {}
}
超类形式参数位置无效
#超级参数只能在非重定向生成式构造函数中使用。
描述
#当在非重定向生成式构造函数之外的地方使用超级参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为超级参数 x
位于重定向生成式构造函数中。
class A {
A(int x);
}
class B extends A {
B.b(super.x) : this._();
B._() : super(0);
}
以下代码会生成此诊断信息,因为超级参数 x
不在生成式构造函数中。
class A {
A(int x);
}
class C extends A {
factory C.c(super.x) => C._();
C._() : super(0);
}
以下代码会生成此诊断信息,因为超级参数 x
位于方法中。
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(super.x) {}
}
常见修复方法
#如果包含超级参数的函数可以更改为非重定向生成式构造函数,则执行此操作。
class A {
A(int x);
}
class B extends A {
B.b(super.x);
}
如果包含超级参数的函数不能更改为非重定向生成式构造函数,则删除 super
。
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(int x) {}
}
常量字面量中的类型参数无效
#常量列表字面量不能包含类型参数作为类型参数,例如 '{0}'。
常量映射字面量不能包含类型参数作为类型参数,例如 '{0}'。
常量集合字面量不能包含类型参数作为类型参数,例如 '{0}'。
描述
#当在以 const
为前缀的列表、映射或集合字面量中使用类型参数作为类型参数时,分析器会生成此诊断信息。这是不允许的,因为类型参数的值(在运行时将使用的实际类型)在编译时无法知道。
示例
#以下代码会生成此诊断信息,因为类型参数 T
在创建常量列表时用作类型参数。
List<T> newList<T>() => const <T>[];
以下代码会产生此诊断,因为类型参数T
在创建常量映射时用作类型参数。
Map<String, T> newSet<T>() => const <String, T>{};
以下代码会产生此诊断,因为类型参数T
在创建常量集合时用作类型参数。
Set<T> newSet<T>() => const <T>{};
常见修复方法
#如果在编译时可以知道将用于类型参数的类型,则删除类型参数。
List<int> newList() => const <int>[];
如果在运行时才能知道将用于类型参数的类型,则删除关键字 const
List<T> newList<T>() => <T>[];
URI 无效
#无效的 URI 语法:'{0}'。
描述
#当指令中的 URI 不符合有效 URI 的语法时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为'#'
不是有效的 URI。
import '#';
常见修复方法
#将无效的 URI 替换为有效的 URI。
在扩展中使用 covariant 无效
#扩展中不能有修饰符'{0}'。
描述
#当在扩展中声明的成员在参数声明中使用关键字covariant
时,分析器会产生此诊断。扩展不是类,也没有子类,因此该关键字没有用。
示例
#以下代码会产生此诊断,因为i
被标记为协变。
extension E on String {
void a(covariant int i) {}
}
常见修复方法
#删除covariant
关键字。
extension E on String {
void a(int i) {}
}
使用 do_not_submit 成员无效
#不应将'{0}'的使用提交到源代码控制。
描述
#当用@doNotSubmit
注释的成员在用@doNotSubmit
注释的成员声明之外被引用时,分析器会产生此诊断。
示例
#给定一个包含以下声明的文件a.dart
import 'package:meta/meta.dart';
@doNotSubmit
void emulateCrash() { /* ... */ }
以下代码会产生此诊断,因为该声明在用@doNotSubmit
注释的成员之外被引用。
import 'a.dart';
void f() {
emulateCrash();
}
常见修复方法
#最常见的情况是,在完成本地测试后,应删除对该成员的引用。
如果在该成员之上构建了额外的功能,则也用@doNotSubmit
注释新添加的成员。
import 'package:meta/meta.dart';
import 'a.dart';
@doNotSubmit
void emulateCrashWithOtherFunctionality() {
emulateCrash();
// do other things.
}
使用内部成员无效
#成员'{0}'只能在其包内使用。
描述
#当在包含声明的包之外找到对用internal
注释注释的声明的引用时,分析器会产生此诊断。
示例
#给定一个包p
,它定义了一个包含用internal
注释注释的声明的库。
import 'package:meta/meta.dart';
@internal
class C {}
以下代码会产生此诊断,因为它引用了类C
,而该类不打算在包p
之外使用。
import 'package:p/src/p.dart';
void f(C c) {}
常见修复方法
#删除对内部声明的引用。
使用空值无效
#值为始终为 'null' 的表达式不能被解引用。
描述
#当一个值为始终为 null
的表达式被解引用时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 x
始终为 null
int f(Null x) {
return x.length;
}
常见修复方法
#如果该值允许为除 null
之外的其他值,则更改表达式的类型
int f(String? x) {
return x!.length;
}
在库外部使用类型无效
#类 '{0}' 无法在其库之外扩展,因为它是一个最终类。
类 '{0}' 无法在其库之外扩展,因为它是一个接口类。
类 '{0}' 无法在其库之外扩展、实现或混合,因为它是一个密封类。
类 '{0}' 无法在其库之外实现,因为它是一个基类。
类 '{0}' 无法在其库之外实现,因为它是一个最终类。
类 '{0}' 无法在其库之外用作混合超类约束,因为它是一个最终类。
混合 '{0}' 无法在其库之外实现,因为它是一个基混合。
描述
#当 extends
、implements
、with
或 on
子句以不允许的方式使用类或混合时,分析器会产生此诊断信息,该方式取决于该类或混合的声明上的修饰符。
该消息指定了声明的使用方式以及不允许的原因。
示例
#给定一个定义基类 A
的文件 a.dart
base class A {}
以下代码会产生此诊断信息,因为类 B
实现了类 A
,但 base
修饰符阻止 A
在其定义的库之外被实现
import 'a.dart';
final class B implements A {}
常见修复方法
#此类型的使用在其声明库之外受到限制。如果存在可提供类似功能的不同、不受限制的类型,则替换该类型
class B implements C {}
class C {}
如果没有合适的不同类型,则删除该类型,并可能删除整个子句
class B {}
重写成员可见性使用无效
#成员 '{0}' 只能用于覆盖。
描述
#当用 visibleForOverriding
注释的实例成员在声明它的库之外被引用时,分析器会产生此诊断信息,原因是除了覆盖它之外的任何原因。
示例
#给定一个包含以下声明的文件a.dart
import 'package:meta/meta.dart';
class A {
@visibleForOverriding
void a() {}
}
以下代码会产生此诊断信息,因为方法 m
正在被调用,即使它公开的唯一原因是允许它被覆盖
import 'a.dart';
class B extends A {
void b() {
a();
}
}
常见修复方法
#删除对该成员的无效使用。
测试成员可见性使用无效
#成员 '{0}' 只能在 '{1}' 或测试中使用。
描述
#当用 @visibleForTesting
注释的成员在声明它的库之外或 test
目录中的库中被引用时,分析器会产生此诊断信息。
示例
#给定一个包含以下内容的文件 c.dart
import 'package:meta/meta.dart';
class C {
@visibleForTesting
void m() {}
}
以下代码,当不在 test
目录中时,会产生此诊断,因为方法 m
被标记为仅对测试可见
import 'c.dart';
void f(C c) {
c.m();
}
常见修复方法
#如果注释的成员不应该在测试之外被引用,那么请移除引用
import 'c.dart';
void f(C c) {}
如果在测试之外引用注释的成员是可以的,那么请移除注释
class C {
void m() {}
}
可见性注解无效
#成员 '{0}' 被注释为 '{1}',但此注释仅对公共成员的声明有意义。
描述
#当 visibleForTemplate
或 visibleForTesting
注释应用于非公共声明时,分析器会产生此诊断。
示例
#以下代码会生成此诊断信息
import 'package:meta/meta.dart';
@visibleForTesting
void _someFunction() {}
void f() => _someFunction();
常见修复方法
#如果声明不需要被测试代码使用,那么请移除注释
void _someFunction() {}
void f() => _someFunction();
如果需要,请将其设为公共
import 'package:meta/meta.dart';
@visibleForTesting
void someFunction() {}
void f() => someFunction();
重写注解可见性无效
#注释 'visibleForOverriding' 只能应用于可以被覆盖的公共实例成员。
描述
#当类以外的任何东西被注释为 visibleForOverriding
时,分析器会产生此诊断。因为只有公共实例成员可以在定义库之外被覆盖,所以对任何其他声明进行注释都没有意义。
示例
#以下代码会产生此诊断,因为注释位于类上,而类不能被覆盖
import 'package:meta/meta.dart';
@visibleForOverriding
class C {}
常见修复方法
#删除注解。
class C {}
模板外部可见性注解无效
#注释 'visibleOutsideTemplate' 只能应用于被注释为 'visibleForTemplate' 的类、枚举或 mixin 的成员。
描述
#当 @visibleOutsideTemplate
注释使用不正确时,分析器会产生此诊断。此注释仅用于注释具有 @visibleForTemplate
注释的类、枚举或 mixin 的成员,以使这些成员不受 @visibleForTemplate
强加的可见性限制。
示例
#以下代码会产生此诊断,因为类级别没有 @visibleForTemplate
注释
import 'package:angular_meta/angular_meta.dart';
class C {
@visibleOutsideTemplate
int m() {
return 1;
}
}
以下代码会产生此诊断,因为注释位于类声明上,而不是类、枚举或 mixin 的成员上
import 'package:angular_meta/angular_meta.dart';
@visibleOutsideTemplate
class C {}
常见修复方法
#如果类仅对模板可见,以便模板可以引用它,那么请在类上添加 @visibleForTemplate
注释
import 'package:angular_meta/angular_meta.dart';
@visibleForTemplate
class C {
@visibleOutsideTemplate
int m() {
return 1;
}
}
如果 @visibleOutsideTemplate
注释位于除具有 @visibleForTemplate
注释的类、枚举或 mixin 的成员以外的任何地方,请移除注释
class C {}
调用扩展方法时未带调用
#扩展“{0}”未定义“call”方法,因此无法在调用中使用覆盖。
描述
#当使用扩展覆盖调用函数,但扩展未声明call
方法时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为扩展E
未定义call
方法。
extension E on String {}
void f() {
E('')();
}
常见修复方法
#如果扩展旨在定义call
方法,则声明它。
extension E on String {
int call() => 0;
}
void f() {
E('')();
}
如果扩展类型定义了call
方法,则删除扩展覆盖。
如果未定义call
方法,则重写代码,使其不调用call
方法。
调用非函数
#“{0}”不是函数。
描述
#当分析器发现函数调用,但被调用函数的名称被定义为非函数时,它会生成此诊断。
示例
#以下代码会生成此诊断,因为Binary
是函数类型名称,而不是函数。
typedef Binary = int Function(int, int);
int f() {
return Binary(1, 2);
}
常见修复方法
#将名称替换为函数名称。
调用非函数表达式
#表达式未计算为函数,因此无法调用它。
描述
#当发现函数调用,但被引用的名称不是函数名称,或计算函数的表达式未计算出函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为x
不是函数。
int x = 0;
int f() => x;
var y = x();
以下代码会生成此诊断,因为f()
未返回函数。
int x = 0;
int f() => x;
var y = f()();
常见修复方法
#如果需要调用函数,则将参数列表之前的代码替换为函数名称或计算函数的表达式。
int x = 0;
int f() => x;
var y = f();
标签在外部作用域中
#无法引用在外部方法中声明的标签“{0}”。
描述
#当break
或continue
语句引用在包含break
或continue
语句的函数的外部方法或函数中声明的标签时,分析器会生成此诊断。break
和continue
语句不能用于将控制权转移到包含它们的函数之外。
示例
#以下代码会生成此诊断,因为标签loop
在局部函数g
外部声明。
void f() {
loop:
while (true) {
void g() {
break loop;
}
g();
}
}
常见修复方法
#尝试重写代码,使其无需将控制权转移到局部函数之外,可能通过内联局部函数。
void f() {
loop:
while (true) {
break loop;
}
}
如果这不可行,则尝试重写局部函数,以便可以使用函数返回的值来确定是否转移控制权。
void f() {
loop:
while (true) {
bool g() {
return true;
}
if (g()) {
break loop;
}
}
}
标签未定义
#无法引用未定义的标签“{0}”。
描述
#当分析器发现对在引用它的 break
或 continue
语句的作用域中未定义的标签的引用时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为标签 loop
在任何地方都没有定义
void f() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break loop;
}
}
}
}
常见修复方法
#如果标签应该在最内层的 do
、for
、switch
或 while
语句上,则删除标签
void f() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break;
}
}
}
}
如果标签应该在其他语句上,则添加标签
void f() {
loop: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break loop;
}
}
}
}
带有常量构造函数的延迟 final 字段
#在具有生成式 const 构造函数的类中不能有延迟的 final 字段。
描述
#当一个类至少有一个 const
构造函数,并且还包含一个标记为 late
和 final
的字段时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 A
有一个 const
构造函数,而 final
字段 f
被标记为 late
class A {
late final int f;
const A();
}
常见修复方法
#如果字段不需要标记为 late
,则从字段中删除 late
修饰符
class A {
final int f = 0;
const A();
}
如果字段必须标记为 late
,则从构造函数中删除 const
修饰符
class A {
late final int f;
A();
}
延迟 final 局部变量已赋值
#延迟的 final 局部变量已被赋值。
描述
#当分析器能够证明标记为 late
和 final
的局部变量在发生另一个赋值的地方已经赋值时,分析器会生成此诊断信息。
由于 final
变量只能赋值一次,因此后续赋值肯定会失败,因此会标记它们。
示例
#以下代码会生成此诊断信息,因为 final
变量 v
在两个地方被赋值
int f() {
late final int v;
v = 0;
v += 1;
return v;
}
常见修复方法
#如果您需要能够重新分配变量,则删除 final
关键字
int f() {
late int v;
v = 0;
v += 1;
return v;
}
如果您不需要重新分配变量,则删除除第一次赋值之外的所有赋值
int f() {
late final int v;
v = 0;
return v;
}
叶调用不能返回句柄
#FFI 叶子调用不能返回 'Handle'。
描述
#当在 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的调用中,isLeaf
参数的值为 true
,并且将要返回的函数的返回类型为 Handle
时,分析器会生成此诊断信息。
当 Native
注释中的 isLeaf
参数的值为 true
,并且注释上的类型参数是返回类型为 Handle
的函数类型时,分析器也会生成此诊断信息。
在所有这些情况下,叶子调用仅支持以下类型:bool
、int
、float
、double
以及作为返回类型的 void
。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为函数 p
返回一个 Handle
,但 isLeaf
参数为 true
import 'dart:ffi';
void f(Pointer<NativeFunction<Handle Function()>> p) {
p.asFunction<Object Function()>(isLeaf: true);
}
常见修复方法
#如果函数返回一个句柄,则删除 isLeaf
参数
import 'dart:ffi';
void f(Pointer<NativeFunction<Handle Function()>> p) {
p.asFunction<Object Function()>();
}
如果函数返回支持的类型之一,则更正类型信息。
import 'dart:ffi';
void f(Pointer<NativeFunction<Int32 Function()>> p) {
p.asFunction<int Function()>(isLeaf: true);
}
叶调用不能接受句柄
#FFI 叶子调用不能接受类型为 'Handle' 的参数。
描述
#当在 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的调用中,isLeaf
参数的值为 true
,并且返回的函数具有类型为 Handle
的参数时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为函数 p
具有类型为 Handle
的参数,但 isLeaf
参数为 true
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
p.asFunction<void Function(Object)>(isLeaf: true);
}
常见修复方法
#如果函数至少有一个类型为 Handle
的参数,则删除 isLeaf
参数。
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
p.asFunction<void Function(Object)>();
}
如果函数的任何参数都不是 Handle
,则更正类型信息。
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
p.asFunction<void Function(int)>(isLeaf: true);
}
列表元素类型不可赋值
#元素类型 '{0}' 不能分配给列表类型 '{1}'。
描述
#当列表文字中元素的类型不能分配给列表的元素类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 2.5
是一个双精度数,而列表只能容纳整数。
List<int> x = [1, 2.5, 3];
常见修复方法
#如果您打算向列表中添加不同的对象,则用计算预期对象的表达式替换元素。
List<int> x = [1, 2, 3];
如果对象不应该在列表中,则删除该元素。
List<int> x = [1, 3];
如果计算出的对象是正确的,则扩展列表的元素类型以允许它包含所有不同类型的对象。
List<num> x = [1, 2.5, 3];
main 函数第一个位置参数类型
#'main' 函数的第一个位置参数的类型必须是 'List
描述
#当名为 main
的函数的第一个位置参数不是 List<String>
的超类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 List<int>
不是 List<String>
的超类型。
void main(List<int> args) {}
常见修复方法
#如果函数是入口点,则将第一个位置参数的类型更改为 List<String>
的超类型。
void main(List<String> args) {}
如果函数不是入口点,则更改函数名称。
void f(List<int> args) {}
main 函数具有必需的命名参数
#函数“main”不能有任何必需的命名参数。
描述
#当名为main
的函数具有一个或多个必需的命名参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为名为main
的函数具有一个必需的命名参数(x
)
void main({required int x}) {}
常见修复方法
#如果函数是入口点,则删除required
关键字。
void main({int? x}) {}
如果函数不是入口点,则更改函数名称。
void f({required int x}) {}
main 函数具有过多必需的位置参数
#函数“main”不能具有超过两个必需的位置参数。
描述
#当名为main
的函数具有超过两个必需的位置参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为函数main
具有三个必需的位置参数。
void main(List<String> args, int x, int y) {}
常见修复方法
#如果函数是入口点且未使用额外的参数,则将其删除。
void main(List<String> args, int x) {}
如果函数是入口点,但使用的额外参数用于函数未用作入口点的情况,则将额外参数设为可选。
void main(List<String> args, int x, [int y = 0]) {}
如果函数不是入口点,则更改函数名称。
void f(List<String> args, int x, int y) {}
main 函数不是函数
#名为“main”的声明必须是函数。
描述
#当库包含一个名为main
的声明,但该声明不是顶级函数的声明时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为名称main
用于声明顶级变量。
var main = 3;
常见修复方法
#使用不同的名称进行声明。
var mainIndex = 3;
映射条目不在映射中
#映射条目只能在映射文字中使用。
描述
#当在集合文字中找到映射条目(键/值对)时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为文字包含映射条目,即使它是一个集合文字。
var collection = <String>{'a' : 'b'};
常见修复方法
#如果您打算将集合作为映射,则更改代码使其成为映射。在前面的示例中,您可以通过添加另一个类型参数来实现这一点。
var collection = <String, String>{'a' : 'b'};
在其他情况下,您可能需要将显式类型从Set
更改为Map
。
如果您打算将集合作为集合,则删除映射条目,可能通过用逗号替换冒号来实现,如果两个值都应包含在集合中。
var collection = <String>{'a', 'b'};
映射键类型不可赋值
#元素类型“{0}”无法分配给映射键类型“{1}”。
描述
#当映射字面量中键值对的键类型无法分配给映射的键类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为2
是int
类型,但映射的键需要是String
类型。
var m = <String, String>{2 : 'a'};
常见修复方法
#如果映射的类型正确,则更改键以具有正确的类型。
var m = <String, String>{'2' : 'a'};
如果键的类型正确,则更改映射的键类型。
var m = <int, String>{2 : 'a'};
映射值类型不可赋值
#元素类型“{0}”无法分配给映射值类型“{1}”。
描述
#当映射字面量中键值对的值类型无法分配给映射的值类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为2
是int
类型,但映射的值需要是String
类型。
var m = <String, String>{'a' : 2};
常见修复方法
#如果映射的类型正确,则更改值以具有正确的类型。
var m = <String, String>{'a' : '2'};
如果值的类型正确,则更改映射的值类型。
var m = <String, int>{'a' : 2};
结构体字段上的注解不匹配
#注释与字段的声明类型不匹配。
描述
#当Struct
或Union
子类中字段的注释与字段的Dart类型不匹配时,分析器会产生此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为注释Double
与Dart类型int
不匹配。
import 'dart:ffi';
final class C extends Struct {
@Double()
external int x;
}
常见修复方法
#如果字段的类型正确,则更改注释以匹配。
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
如果注释正确,则更改字段的类型以匹配。
import 'dart:ffi';
final class C extends Struct {
@Double()
external double x;
}
结构体字段上缺少注解
#{1}
子类中类型为“{0}”的字段必须具有一个注释,指示其原生类型。
描述
#当Struct
或Union
子类中需要注释的字段没有注释时,分析器会产生此诊断信息。Dart类型int
、double
和Array
用于表示多个C类型,注释指定字段表示的兼容C类型。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为字段x
没有注释指示整数值的底层宽度。
import 'dart:ffi';
final class C extends Struct {
external int x;
}
常见修复方法
#在字段中添加适当的注释。
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
默认值
void f([int x]) {}
此代码也会产生此诊断信息
void g({int x}) {}
常见修复方法
#如果要使用 null
来指示未提供任何值,则需要将类型设为可空
void f([int? x]) {}
void g({int? x}) {}
如果参数不能为 null,则提供默认值
void f([int x = 1]) {}
void g({int x = 2}) {}
或将参数设为必需参数
void f(int x) {}
void g({required int x}) {}
缺少依赖项
#缺少对导入包 '{0}' 的依赖项。
描述
#当源代码中导入了一个包,但未将其列为导入包的依赖项时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为包 path
未列为依赖项,而包 example
的源代码中有一个导入语句,其中包含包 path
name: example
dependencies:
meta: ^1.0.2
常见修复方法
#将缺少的包 path
添加到 dependencies
字段
name: example
dependencies:
meta: ^1.0.2
path: any
switch 语句中缺少枚举常量
#缺少 '{0}' 的 case 子句。
描述
#当枚举的 switch
语句未包含枚举中某个值的选项时,分析器会产生此诊断信息。
请注意,null
始终是枚举的可能值,因此也必须进行处理。
示例
#以下代码会产生此诊断信息,因为枚举值 e2
未处理
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
}
}
常见修复方法
#如果对缺少的值有特殊处理,则为每个缺少的值添加一个 case
子句
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
case E.e2:
break;
}
}
如果缺少的值应该以相同的方式处理,则添加一个 default
子句
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
default:
break;
}
}
缺少异常值
#方法 {0} 当函数的返回类型既不是 'void'、'Handle' 也不 'Pointer' 时,必须具有异常返回值(第二个参数)。
描述
#当 Pointer.fromFunction
或 NativeCallable.isolateLocal
方法的调用在从调用返回的类型既不是 void
、Handle
也不 Pointer
时没有第二个参数(异常返回值)时,分析器会产生此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为 f
返回的类型预期为 8 位整数,但对 fromFunction
的调用未包含异常返回值参数
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
Pointer.fromFunction<Int8 Function(Int8)>(f);
}
常见修复方法
#添加异常返回类型
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
}
结构体中缺少字段类型
#结构体类中的字段必须显式声明为 'int'、'double' 或 'Pointer' 类型。
描述
#当 Struct
或 Union
子类的字段没有类型注解时,分析器会产生此诊断信息。每个字段都必须具有显式类型,并且类型必须是 int
、double
、Pointer
或 Struct
或 Union
的子类。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为字段 str
没有类型注解
import 'dart:ffi';
final class C extends Struct {
external var str;
@Int32()
external int i;
}
常见修复方法
#显式指定字段的类型
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final class C extends Struct {
external Pointer<Utf8> str;
@Int32()
external int i;
}
缺少名称
#'name' 字段是必需的,但缺失。
描述
#当没有顶层 name
键时,分析器会产生此诊断信息。name
键提供包的名称,这是必需的。
示例
#以下代码会产生此诊断信息,因为包没有名称
dependencies:
meta: ^1.0.2
常见修复方法
#添加顶层键 name
,其值为包的名称
name: example
dependencies:
meta: ^1.0.2
缺少命名模式字段名称
#getter 名称未显式指定,并且模式不是变量。
描述
#当在对象模式中,属性的规范和用于匹配属性值的模式既没有
- 冒号前的 getter 名称
- 可以推断出 getter 名称的变量模式
示例
#以下代码会产生此诊断信息,因为在对象模式 (C(:0)
) 中,冒号前没有 getter 名称,冒号后也没有变量模式
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(:0):
break;
}
}
常见修复方法
#如果需要在模式的作用域内使用属性的实际值,则添加一个变量模式,其中变量的名称与要匹配的属性的名称相同
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(:var f) when f == 0:
print(f);
}
}
如果不需要在模式的作用域内使用属性的实际值,则在冒号前添加要匹配的属性的名称
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(f: 0):
break;
}
}
缺少必须重写的重写
#缺少 '{0}' 的具体实现。
缺少 '{0}' 和 '{1}' 的具体实现。
缺少 '{0}'、'{1}' 和另外 {2} 个的具体实现。
描述
#当具有 @mustBeOverridden
注解的实例成员在子类中未被重写时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为类 B
没有继承方法 A.m
的重写,而 A.m
被 @mustBeOverridden
注解
import 'package:meta/meta.dart';
class A {
@mustBeOverridden
void m() {}
}
class B extends A {}
常见修复方法
#如果注解适合该成员,则在子类中重写该成员
import 'package:meta/meta.dart';
class A {
@mustBeOverridden
void m() {}
}
class B extends A {
@override
void m() {}
}
如果注释不适合成员,则删除注释。
class A {
void m() {}
}
class B extends A {}
缺少必需参数
#命名参数“{0}”是必需的,但没有相应的参数。
描述
#当函数调用缺少必需的命名参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为f
的调用不包含必需的命名参数end
的值。
void f(int start, {required int end}) {}
void g() {
f(3);
}
常见修复方法
#添加与缺少的必需参数相对应的命名参数。
void f(int start, {required int end}) {}
void g() {
f(3, end: 5);
}
缺少必需参数
#参数“{0}”是必需的。
参数“{0}”是必需的。{1}。
描述
#当调用带有命名参数(该参数被注释为必需)的方法或函数时,但没有为该参数提供值,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为命名参数x
是必需的。
import 'package:meta/meta.dart';
void f({@required int? x}) {}
void g() {
f();
}
常见修复方法
#提供必需的值。
import 'package:meta/meta.dart';
void f({@required int? x}) {}
void g() {
f(x: 2);
}
缺少返回值
#此函数的返回类型为“{0}”,但没有以 return 语句结束。
描述
#任何不以显式 return 或 throw 结束的函数或方法都会隐式返回null
。这很少是期望的行为。当分析器发现隐式返回时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为f
没有以 return 结束。
int f(int x) {
if (x < 0) {
return 0;
}
}
常见修复方法
#添加一个return
语句,使返回值显式,即使null
是适当的值。
C 数组缺少大小注解
#类型为“Array”的字段必须恰好有一个“Array”注释。
描述
#当Struct
或Union
的子类的字段类型为Array
,但没有单个Array
注释来指示数组的维度时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为字段a0
没有Array
注释。
import 'dart:ffi';
final class C extends Struct {
external Array<Uint8> a0;
}
常见修复方法
#确保字段上恰好有一个Array
注释。
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
缺少变量模式
#变量模式“{0}”在逻辑或模式的此分支中缺失。
描述
#当逻辑或模式的一个分支没有声明在同一模式的另一个分支上声明的变量时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为逻辑或模式的右侧没有声明变量a
。
void f((int, int) r) {
if (r case (var a, 0) || (0, _)) {
print(a);
}
}
常见修复方法
#如果需要在受控语句中引用该变量,则将该变量的声明添加到逻辑或模式的每个分支。
void f((int, int) r) {
if (r case (var a, 0) || (0, var a)) {
print(a);
}
}
如果变量不需要在受控语句中引用,则从逻辑或模式的每个分支中删除变量的声明。
void f((int, int) r) {
if (r case (_, 0) || (0, _)) {
print('found a zero');
}
}
如果变量需要在模式的一个分支匹配时引用,而在另一个分支匹配时不引用,则将模式分成两部分。
void f((int, int) r) {
switch (r) {
case (var a, 0):
print(a);
case (0, _):
print('found a zero');
}
}
混合应用中具体超类调用的成员类型
#超类调用的成员“{0}”的类型为“{1}”,类中具体成员的类型为“{2}”。
描述
#当使用 `super` 调用方法的 mixin 在类中使用时,分析器会生成此诊断信息,其中该方法的具体实现与 mixin 的 `on` 类型为该方法定义的签名不同。出现此错误的原因是,mixin 中的调用可能会以与实际执行的方法不兼容的方式调用该方法。
示例
#以下代码会生成此诊断信息,因为类 `C` 使用了 mixin `M`,mixin `M` 使用 `super` 调用 `foo`,而 `I`(mixin 的 `on` 类型)中声明的 `foo` 的抽象版本与 `A` 中声明的 `foo` 的具体版本签名不同。
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` 子句中将其删除。
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 预期签名的该方法的具体实现。
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 {}
混合应用未实现接口
#无法将“{0}”混合到“{1}”上,因为“{1}”未实现“{2}”。
描述
#当具有超类约束的 mixin 在 mixin 应用 中使用时,分析器会生成此诊断信息,其中超类未实现所需的约束。
示例
#以下代码会生成此诊断信息,因为 mixin `M` 要求应用它的类是 `A` 的子类,但 `Object` 不是 `A` 的子类。
class A {}
mixin M on A {}
class X = Object with M;
常见修复方法
#如果需要使用 mixin,则将超类更改为与超类约束相同或为其子类。
class A {}
mixin M on A {}
class X = A with M;
混合应用中没有具体超类调用的成员
#该类没有超类调用的成员“{0}”的具体实现。
该类没有超类调用的 setter“{0}”的具体实现。
描述
#当 mixin 应用 包含从其超类调用成员的调用时,分析器会生成此诊断信息,并且 mixin 应用的超类中没有该名称的具体成员。
示例
#以下代码会生成此诊断信息,因为 mixin `M` 包含调用 `super.m()`,而类 `A`(它是 mixin 应用 `A+M` 的超类)没有定义 `m` 的具体实现。
abstract class A {
void m();
}
mixin M on A {
void bar() {
super.m();
}
}
abstract class B extends A with M {}
常见修复方法
#如果您想将 mixin M
应用于另一个类,该类具有 m
的具体实现,那么将 B
的超类更改为该类。
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
的具体实现。
abstract class A {
void m() {}
}
mixin M on A {
void bar() {
super.m();
}
}
abstract class B extends A with M {}
混合类声明扩展非 Object 类
#类 '{0}' 无法声明为 mixin,因为它扩展了除 'Object' 之外的类。
描述
#当使用 mixin
修饰符标记的类扩展了除 Object
之外的类时,分析器会生成此诊断信息。mixin 类不能具有除 Object
之外的超类。
示例
#以下代码会生成此诊断信息,因为类 B
(具有修饰符 mixin
)扩展了 A
。
class A {}
mixin class B extends A {}
常见修复方法
#如果您希望将该类用作 mixin,那么将超类更改为 Object
,无论是显式更改还是通过删除 extends 子句。
class A {}
mixin class B {}
如果该类需要具有除 Object
之外的超类,那么删除 mixin
修饰符。
class A {}
class B extends A {}
如果您需要 mixin 和除 Object
之外的类的子类,那么将子类的成员移动到新的 mixin 中,从子类中删除 mixin
修饰符,并将新的 mixin 应用于子类。
class A {}
class B extends A with M {}
mixin M {}
根据子类的成员,这可能需要在 mixin 中添加 on
子句。
混合类声明构造函数
#类 '{0}' 无法用作 mixin,因为它声明了构造函数。
描述
#当类用作 mixin 并且混合的类定义了构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 A
(定义了构造函数)正在用作 mixin。
//@dart=2.19
class A {
A();
}
class B with A {}
常见修复方法
#如果可以将该类转换为 mixin,那么请执行此操作。
mixin A {
}
class B with A {}
如果该类不能是 mixin,并且可以删除构造函数,那么请执行此操作。
//@dart=2.19
class A {
}
class B with A {}
如果该类不能是 mixin,并且您无法删除构造函数,那么尝试扩展或实现该类,而不是将其混合进来。
class A {
A();
}
class B extends A {}
混合类继承自非 Object 类
#类 '{0}' 无法用作 mixin,因为它扩展了除 'Object' 之外的类。
描述
#当扩展了除 Object
之外的类的类用作 mixin 时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 B
(扩展了 A
)正在被 C
用作 mixin。
//@dart=2.19
class A {}
class B extends A {}
class C with B {}
常见修复方法
#如果用作 mixin 的类可以更改为扩展 Object
,那么请更改它。
//@dart=2.19
class A {}
class B {}
class C with B {}
如果用作 mixin 的类无法更改,并且使用它的类扩展了 Object
,那么请扩展用作 mixin 的类。
class A {}
class B extends A {}
class C extends B {}
如果类没有扩展Object
,或者您希望能够在其他地方混合B
的行为,那么创建一个真正的mixin。
class A {}
mixin M on A {}
class B extends A with M {}
class C extends A with M {}
混合类实例化
#Mixin不能被实例化。
描述
#当实例化mixin时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为mixinM
正在被实例化。
mixin M {}
var m = M();
常见修复方法
#如果您打算使用类的实例,那么使用该类的名称来代替mixin的名称。
混合非类
#类只能混合mixin和类。
描述
#当with
子句中的名称被定义为除mixin或类以外的其他内容时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为F
被定义为函数类型。
typedef F = int Function(String);
class C with F {}
常见修复方法
#从列表中删除无效的名称,可能用目标mixin或类的名称替换它。
typedef F = int Function(String);
class C {}
混合密封类
#类 '{0}' 不应该用作mixin约束,因为它被密封,并且任何混合此mixin的类都必须具有 '{0}' 作为超类。
描述
#当mixin的超类约束是来自不同包的被标记为sealed
的类时,分析器会产生此诊断信息。被密封的类不能被扩展、实现、混合或用作超类约束。
示例
#如果包p
定义了一个密封类
import 'package:meta/meta.dart';
@sealed
class C {}
那么,以下代码(当在除p
以外的包中时)会产生此诊断信息。
import 'package:p/p.dart';
mixin M on C {}
常见修复方法
#如果使用mixin的类不需要是密封类的子类,那么考虑添加一个字段并委托给密封类的包装实例。
混合超类约束延迟类
#延迟类不能用作超类约束。
描述
#当mixin的超类约束从延迟库导入时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为math.Random
的超类约束是从延迟库导入的。
import 'dart:async' deferred as async;
mixin M<T> on async.Stream<T> {}
常见修复方法
#如果导入不需要延迟,那么删除deferred
关键字。
import 'dart:async' as async;
mixin M<T> on async.Stream<T> {}
如果导入需要延迟,那么删除超类约束。
mixin M<T> {}
混合超类约束非接口
#只有类和mixin可以用作超类约束。
描述
#当mixin声明中on
关键字后面的类型既不是类也不是mixin时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断,因为F
既不是类也不是mixin。
typedef F = void Function();
mixin M on F {}
常见修复方法
#如果该类型原本打算为类,但输入错误,则替换名称。
否则,从on
子句中删除该类型。
多个重定向构造函数调用
#构造函数最多只能有一个“this”重定向。
描述
#当构造函数重定向到同一个类中的多个其他构造函数(使用this
)时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为C
中的无名构造函数正在重定向到this.a
和this.b
。
class C {
C() : this.a(), this.b();
C.a();
C.b();
}
常见修复方法
#删除除一个之外的所有重定向。
class C {
C() : this.a();
C.a();
C.b();
}
多个超类初始化器
#构造函数最多只能有一个“super”初始化器。
描述
#当构造函数的初始化列表包含多个来自超类的构造函数调用时,分析器会产生此诊断。初始化列表需要恰好包含一个这样的调用,该调用可以是显式的或隐式的。
示例
#以下代码产生此诊断,因为B
的构造函数的初始化列表调用了超类A
中的构造函数one
和构造函数two
。
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0), super.two('');
}
常见修复方法
#如果其中一个超类构造函数将完全初始化实例,则删除另一个。
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0);
}
如果其中一个超类构造函数实现的初始化可以在构造函数体中执行,则删除其超类调用并在体中执行初始化。
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0) {
s = '';
}
}
如果初始化只能在超类中的构造函数中执行,则要么添加一个新的构造函数,要么修改现有的构造函数之一,以便有一个构造函数允许所有必需的初始化在一个调用中发生。
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, '');
}
必须是原生函数类型
#传递给{1}
的类型{0}
必须是有效的“dart:ffi”原生函数类型。
描述
#当Pointer.fromFunction
、DynamicLibrary.lookupFunction
或NativeCallable
构造函数的调用具有不是原生函数类型的类型参数(无论显式还是推断)时,分析器会产生此诊断。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断,因为类型T
可以是Function
的任何子类,但fromFunction
的类型参数需要是原生函数类型。
import 'dart:ffi';
int f(int i) => i * 2;
class C<T extends Function> {
void g() {
Pointer.fromFunction<T>(f, 0);
}
}
常见修复方法
#使用原生函数类型作为调用的类型参数。
import 'dart:ffi';
int f(int i) => i * 2;
class C<T extends Function> {
void g() {
Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
}
}
必须是子类型
#类型{0}
必须是{1}
的子类型,用于{2}
。
描述
#分析器在两种情况下产生此诊断。
- 在
Pointer.fromFunction
或NativeCallable
构造函数的调用中,类型参数(无论显式还是推断)不是作为第一个参数传递给方法的函数类型的超类型。 - 在
DynamicLibrary.lookupFunction
的调用中,第一个类型参数不是第二个类型参数的超类型。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断,因为函数 f
的类型 (String Function(int)
) 不是类型参数 T
(Int8 Function(Int8)
) 的子类型。
import 'dart:ffi';
typedef T = Int8 Function(Int8);
double f(double i) => i;
void g() {
Pointer.fromFunction<T>(f, 5.0);
}
常见修复方法
#如果函数是正确的,则更改类型参数以匹配。
import 'dart:ffi';
typedef T = Float Function(Float);
double f(double i) => i;
void g() {
Pointer.fromFunction<T>(f, 5.0);
}
如果类型参数是正确的,则更改函数以匹配。
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。
import 'package:meta/meta.dart';
@immutable
class C {
int x;
C(this.x);
}
常见修复方法
#如果类的实例应该是不可变的,则将关键字 final
添加到所有非 final 字段声明中。
import 'package:meta/meta.dart';
@immutable
class C {
final int x;
C(this.x);
}
如果类的实例应该是可变的,则删除注释,或者如果注释是继承的,则选择不同的超类。
class C {
int x;
C(this.x);
}
必须调用 super
#此方法覆盖了在 '{0}' 中被注释为 '@mustCallSuper' 的方法,但没有调用被覆盖的方法。
描述
#当覆盖被注释为 mustCallSuper
的方法的方法没有按要求调用被覆盖的方法时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 B
中的 m
方法没有调用 A
中被覆盖的 m
方法。
import 'package:meta/meta.dart';
class A {
@mustCallSuper
m() {}
}
class B extends A {
@override
m() {}
}
常见修复方法
#在覆盖方法中添加对被覆盖方法的调用。
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
。
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
NativeCallable<Int32 Function(Int32)>.listener(f);
}
常见修复方法
#将函数的返回类型更改为 void
。
import 'dart:ffi';
void f(int i) => print(i * 2);
void g() {
NativeCallable<Void Function(Int32)>.listener(f);
}
名称不是字符串
#'name' 字段的值必须是字符串。
描述
#当顶层 name
键的值不是字符串时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 name
键后面的值是列表。
name:
- example
常见修复方法
#用字符串替换值
name: example
原生字段类型无效
#“{0}”是原生字段不支持的类型。原生字段只支持指针、数组或数字和复合类型。
描述
#当一个标注了 @Native
的字段的类型不是原生字段支持的类型时,分析器会产生此诊断信息。
原生字段支持指针、数组、数值类型和 Compound
的子类型(即结构体或联合体)。其他 NativeType
的子类型,例如 Handle
或 NativeFunction
,不允许作为原生字段。
原生函数应该与外部函数一起使用,而不是外部字段。
句柄不受支持,因为没有办法将 Dart 对象透明地加载和存储到指针中。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为字段 free
使用了不受支持的原生类型 NativeFunction
import 'dart:ffi';
@Native<NativeFunction<Void Function()>>()
external void Function() free;
常见修复方法
#如果你想使用 NativeFunction
字段绑定到现有的原生函数,请使用 @Native
方法代替
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);
要绑定到在 C 中存储函数指针的字段,请对 Dart 字段使用指针类型
import 'dart:ffi';
@Native()
external Pointer<NativeFunction<Void Function(Pointer<Void>)>> free;
原生字段缺少类型
#此字段的原生类型无法推断,必须在注释中指定。
描述
#当一个标注了 @Native
的字段需要在注释上使用类型提示来推断原生类型时,分析器会产生此诊断信息。
像 int
和 double
这样的 Dart 类型有多种可能的原生表示。由于原生类型需要在编译时已知,以便在访问字段时生成正确的加载和存储,因此必须给出显式类型。
示例
#以下代码会产生此诊断信息,因为字段 f
的类型为 int
(它有多种原生表示),但 Native
注释上没有显式类型参数
import 'dart:ffi';
@Native()
external int f;
常见修复方法
#要修复此诊断信息,请从字段的原生声明中找出正确的原生表示。然后,将相应的类型添加到注释中。例如,如果 f
在 C 中声明为 uint8_t
,则 Dart 字段应声明为
import 'dart:ffi';
@Native<Uint8>()
external int f;
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
原生字段不是静态的
#原生字段必须是静态的。
描述
#当类中的实例字段被标注为 @Native
时,分析器会产生此诊断信息。原生字段指的是 C、C++ 或其他原生语言中的全局变量,而 Dart 中的实例字段是特定于该类的实例的。因此,原生字段必须是静态的。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为类 C
中的字段 f
是 @Native
,但不是 static
import 'dart:ffi';
class C {
@Native<Int>()
external int f;
}
常见修复方法
#要么将字段设为静态
import 'dart:ffi';
class C {
@Native<Int>()
external static int f;
}
要么将它移出类,在这种情况下不需要显式的 static
修饰符
import 'dart:ffi';
class C {
}
@Native<Int>()
external int f;
如果你想标注一个应该作为结构体一部分的实例字段,请省略 @Native
注释
import 'dart:ffi';
final class C extends Struct {
@Int()
external int f;
}
带有未定义构造函数默认值的 new
#类“{0}”没有无名构造函数。
描述
#当在定义了命名构造函数的类上调用无名构造函数,但该类没有无名构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为A
没有定义无名构造函数
class A {
A.a();
}
A f() => A();
常见修复方法
#如果其中一个命名构造函数满足您的需求,请使用它。
class A {
A.a();
}
A f() => A.a();
如果没有任何命名构造函数满足您的需求,并且您可以添加无名构造函数,请添加该构造函数。
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
的具体实现。
abstract class A {
void m();
}
class B extends A {}
常见修复方法
#如果子类可以为一些或所有继承的抽象成员提供具体实现,请添加具体实现。
abstract class A {
void m();
}
class B extends A {
void m() {}
}
如果存在一个提供继承方法实现的 mixin,请将该 mixin 应用于子类。
abstract class A {
void m();
}
class B extends A with M {}
mixin M {
void m() {}
}
如果子类无法为所有继承的抽象成员提供具体实现,请将子类标记为抽象类。
abstract class A {
void m();
}
abstract class B extends A {}
非布尔条件
#条件必须具有 'bool' 的静态类型。
描述
#当条件(例如 if
或 while
循环)没有静态类型 bool
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为x
的静态类型为int
。
void f(int x) {
if (x) {
// ...
}
}
常见修复方法
#更改条件,使其生成布尔值。
void f(int x) {
if (x == 0) {
// ...
}
}
非布尔表达式
#断言中的表达式必须为 'bool' 类型。
描述
#当断言中的第一个表达式类型不是 bool
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为p
的类型为int
,但需要bool
。
void f(int p) {
assert(p);
}
常见修复方法
#更改表达式,使其具有 bool
类型。
void f(int p) {
assert(p > 0);
}
非布尔否定表达式
#否定运算符必须具有 'bool' 的静态类型。
描述
#当一元否定运算符 (!
) 的操作数类型不是 bool
时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断是因为x
是int
类型,而它必须是bool
类型。
int x = 0;
bool y = !x;
常见修复方法
#用一个类型为bool
的表达式替换操作数。
int x = 0;
bool y = !(x > 0);
非布尔操作数
#运算符 '{0}' 的操作数必须可赋值为 'bool'。
描述
#当&&
或||
运算符的操作数之一的类型不是bool
时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为a
不是布尔值。
int a = 3;
bool b = a || a > 1;
常见修复方法
#将操作数更改为布尔值。
int a = 3;
bool b = a == 0 || a > 1;
非常量注解构造函数
#注解创建只能调用常量构造函数。
描述
#当注解是现有构造函数的调用,即使调用的构造函数不是常量构造函数时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为C
的构造函数不是常量构造函数。
@C()
void f() {
}
class C {
C();
}
常见修复方法
#如果类可以有常量构造函数,则创建一个可用于注解的常量构造函数。
@C()
void f() {
}
class C {
const C();
}
如果类不能有常量构造函数,则删除注解或使用其他类作为注解。
非常量 case 表达式
#case 表达式必须是常量。
描述
#当case
子句中的表达式不是常量表达式时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为j
不是常量。
void f(int i, int j) {
switch (i) {
case j:
// ...
break;
}
}
常见修复方法
#要么将表达式设为常量表达式,要么将switch
语句重写为一系列if
语句。
void f(int i, int j) {
if (i == j) {
// ...
}
}
来自延迟库的非常量 case 表达式
#来自延迟库的常量值不能用作 case 表达式。
描述
#当 case 子句中的表达式引用了使用延迟导入导入的库中的常量时,分析器会产生此诊断。为了使 switch 语句能够有效地编译,case 子句中引用的常量需要在编译时可用,而延迟库中的常量在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义常量 zero
的文件 a.dart
const zero = 0;
以下代码产生此诊断是因为库a.dart
使用deferred
导入,并且在导入库中声明的常量a.zero
在 case 子句中使用。
import 'a.dart' deferred as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
常见修复方法
#如果需要引用导入库中的常量,则删除deferred
关键字。
import 'a.dart' as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
如果您需要引用从导入的库中导入的常量,并且还需要延迟导入该库,那么请将 switch 语句重写为一系列 if
语句
import 'a.dart' deferred as a;
void f(int x) {
if (x == a.zero) {
// ...
}
}
如果您不需要引用该常量,那么请替换 case 表达式
void f(int x) {
switch (x) {
case 0:
// ...
break;
}
}
非常量默认值
#可选参数的默认值必须是常量。
描述
#当可选参数(命名或位置)的默认值不是编译时常量时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息
var defaultValue = 3;
void f([int value = defaultValue]) {}
常见修复方法
#如果默认值可以转换为常量,则将其转换为常量
const defaultValue = 3;
void f([int value = defaultValue]) {}
如果默认值需要随着时间的推移而改变,那么请在函数内部应用默认值
var defaultValue = 3;
void f([int? value]) {
value ??= defaultValue;
}
来自延迟库的非常量默认值
#来自延迟库的常量值不能用作默认参数值。
描述
#当可选参数的默认值使用来自使用延迟导入导入的库的常量时,分析器会生成此诊断信息。默认值需要在编译时可用,而来自延迟库的常量在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义常量 zero
的文件 a.dart
const zero = 0;
以下代码会生成此诊断信息,因为 zero
在使用延迟导入导入的库中声明
import 'a.dart' deferred as a;
void f({int x = a.zero}) {}
常见修复方法
#如果需要引用导入库中的常量,则删除deferred
关键字。
import 'a.dart' as a;
void f({int x = a.zero}) {}
如果您不需要引用该常量,那么请替换默认值
void f({int x = 0}) {}
非常量列表元素
#const 列表文字中的值必须是常量。
描述
#当常量列表文字中的元素不是常量值时,分析器会生成此诊断信息。列表文字可以是显式常量(因为它以 const
关键字为前缀)或隐式常量(因为它出现在 常量上下文 中)。
示例
#以下代码会生成此诊断信息,因为 x
不是常量,即使它出现在隐式常量列表文字中
var x = 2;
var y = const <int>[0, 1, x];
常见修复方法
#如果列表需要是常量列表,那么请将元素转换为常量。在上面的示例中,您可以向 x
的声明添加 const
关键字
const x = 2;
var y = const <int>[0, 1, x];
如果表达式不能成为常量,那么列表也不能成为常量,因此您必须更改代码,使列表不再是常量。在上面的示例中,这意味着从列表文字之前删除 const
关键字
var x = 2;
var y = <int>[0, 1, x];
非常量映射元素
#const 映射文字中的元素必须是常量。
描述
#当常量映射中的 if
元素或扩展元素不是常量元素时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为它试图扩展非常量映射
var notConst = <int, int>{};
var map = const <int, int>{...notConst};
类似地,以下代码会生成此诊断信息,因为 if
元素中的条件不是常量表达式
bool notConst = true;
var map = const <int, int>{if (notConst) 1 : 2};
常见修复方法
#如果需要将地图设置为常量地图,则需要将元素设置为常量。在展开示例中,可以通过将展开的集合设置为常量来实现。
const notConst = <int, int>{};
var map = const <int, int>{...notConst};
如果不需要将地图设置为常量地图,则删除const
关键字。
bool notConst = true;
var map = <int, int>{if (notConst) 1 : 2};
非常量映射键
#常量地图字面量中的键必须是常量。
描述
#当常量地图字面量中的键不是常量值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为a
不是常量
var a = 'a';
var m = const {a: 0};
常见修复方法
#如果需要将地图设置为常量地图,则需要将键设置为常量。
const a = 'a';
var m = const {a: 0};
如果不需要将地图设置为常量地图,则删除const
关键字。
var a = 'a';
var m = {a: 0};
非常量映射模式键
#地图模式中的键表达式必须是常量。
描述
#当地图模式中的键不是常量表达式时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为键A()
不是常量
void f(Object x) {
if (x case {A(): 0}) {}
}
class A {
const A();
}
常见修复方法
#使用常量作为键。
void f(Object x) {
if (x case {const A(): 0}) {}
}
class A {
const A();
}
非常量映射值
#常量地图字面量中的值必须是常量。
描述
#当常量地图字面量中的值不是常量值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为a
不是常量
var a = 'a';
var m = const {0: a};
常见修复方法
#如果需要将地图设置为常量地图,则需要将键设置为常量。
const a = 'a';
var m = const {0: a};
如果不需要将地图设置为常量地图,则删除const
关键字。
var a = 'a';
var m = {0: a};
非常量关系模式表达式
#关系模式表达式必须是常量。
描述
#当关系模式表达式中的值不是常量表达式时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为>
运算符的操作数a
不是常量
final a = 0;
void f(int x) {
if (x case > a) {}
}
常见修复方法
#用常量表达式替换值。
const a = 0;
void f(int x) {
if (x case > a) {}
}
非常量集合元素
#常量集合字面量中的值必须是常量。
描述
#当常量集合字面量包含不是编译时常量的元素时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为i
不是常量。
var i = 0;
var s = const {i};
常见修复方法
#如果元素可以更改为常量,则更改它。
const i = 0;
var s = const {i};
如果元素不能是常量,则删除关键字const
。
var i = 0;
var s = {i};
非常量类型参数
#'{0}' 的类型参数必须在编译时已知,因此它们不能是类型参数。
描述
#当方法的类型参数需要在编译时已知,但使用了一个在编译时无法确定其值的类型参数作为类型参数时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断信息,因为Pointer.asFunction
的类型参数必须在编译时已知,但类型参数R
在编译时未知,正在用作类型参数
import 'dart:ffi';
typedef T = int Function(int);
class C<R extends T> {
void m(Pointer<NativeFunction<T>> p) {
p.asFunction<R>();
}
}
常见修复方法
#删除所有类型参数的使用
import 'dart:ffi';
class C {
void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
p.asFunction<int Function(int)>();
}
}
常量参数的非常量参数
#参数 '{0}' 必须是常量。
描述
#当参数使用@mustBeConst
注解,而对应参数不是常量表达式时,分析器会产生此诊断信息。
示例
#以下代码在调用函数f
时产生此诊断信息,因为传递给函数g
的参数的值不是常量
import 'package:meta/meta.dart' show mustBeConst;
int f(int value) => g(value);
int g(@mustBeConst int value) => value + 1;
常见修复方法
#如果可以使用合适的常量,则用常量替换参数
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
关键字的情况下被调用,但构造函数的所有参数都是常量时,分析器会产生此诊断信息。该注解表示构造函数应尽可能用于创建常量值。
示例
#以下代码会生成此诊断信息
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
C f() => C();
常见修复方法
#在构造函数调用之前添加关键字const
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
void f() => const C();
非常量生成枚举构造函数
#生成式枚举构造函数必须是“const”。
描述
#当枚举声明包含一个没有标记为const
的生成式构造函数时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为E
中的构造函数没有标记为const
enum E {
e;
E();
}
常见修复方法
#在构造函数之前添加const
关键字
enum E {
e;
const E();
}
表示类型中非协变类型参数位置
#扩展类型参数不能在其表示类型的非协变位置使用。
描述
#当扩展类型的类型参数在该扩展类型的表示类型的非协变位置使用时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为类型参数T
用作函数类型void Function(T)
中的参数类型,而参数不是协变的
extension type A<T>(void Function(T) f) {}
常见修复方法
#删除类型参数的使用
extension type A(void Function(String) f) {}
非详尽的 switch 表达式
#类型“{0}”没有被 switch case 全面匹配,因为它不匹配“{1}”。
描述
#当switch
表达式缺少一个或多个可能流经它的值的 case 时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 switch 表达式没有为值E.three
设置 case
enum E { one, two, three }
String f(E e) => switch (e) {
E.one => 'one',
E.two => 'two',
};
常见修复方法
#如果缺少的值对 switch 表达式有明显的意义,则为每个缺少匹配的值添加一个 case
enum E { one, two, three }
String f(E e) => switch (e) {
E.one => 'one',
E.two => 'two',
E.three => 'three',
};
如果不需要匹配缺失的值,则添加一个返回简单默认值的通配符模式。
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
是一个详尽的类型。
enum E { one, two, three }
void f(E e) {
switch (e) {
case E.one:
case E.two:
}
}
常见修复方法
#为每个当前未匹配的常量添加一个 case。
enum E { one, two, three }
void f(E e) {
switch (e) {
case E.one:
case E.two:
break;
case E.three:
}
}
如果不需要匹配缺失的值,则添加一个 default
子句或通配符模式。
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 字段。
enum E {
c;
int f = 0;
}
常见修复方法
#如果必须为枚举定义字段,则将字段标记为 final
。
enum E {
c;
final int f = 0;
}
如果可以删除字段,则将其删除。
enum E {
c
}
非生成构造函数
#预期生成式构造函数 '{0}',但找到了工厂构造函数。
描述
#当构造函数的初始化列表调用超类中的构造函数,并且调用的构造函数是工厂构造函数时,分析器会生成此诊断信息。只有生成式构造函数可以在初始化列表中调用。
示例
#以下代码会生成此诊断信息,因为调用构造函数 super.one()
正在调用工厂构造函数。
class A {
factory A.one() = B;
A.two();
}
class B extends A {
B() : super.one();
}
常见修复方法
#将超类调用更改为调用生成式构造函数。
class A {
factory A.one() = B;
A.two();
}
class B extends A {
B() : super.two();
}
如果生成式构造函数是无名构造函数,并且没有向其传递任何参数,则可以删除超类调用。
非生成隐式构造函数
#超类 '{0}' 的无名构造函数(由 '{1}' 的默认构造函数调用)必须是生成式构造函数,但找到了工厂构造函数。
描述
#当一个类具有隐式生成式构造函数,而超类具有显式无名工厂构造函数时,分析器会生成此诊断信息。子类中的隐式构造函数隐式调用超类中的无名构造函数,但生成式构造函数只能调用另一个生成式构造函数,而不是工厂构造函数。
示例
#以下代码产生此诊断是因为B
中的隐式构造函数调用了A
中的无名构造函数,但A
中的构造函数是工厂构造函数,而需要生成式构造函数。
class A {
factory A() => throw 0;
A.named();
}
class B extends A {}
常见修复方法
#如果超类中的无名构造函数可以是生成式构造函数,则将其更改为生成式构造函数。
class A {
A();
A.named();
}
class B extends A { }
如果无名构造函数不能是生成式构造函数,并且超类中存在其他生成式构造函数,则显式调用其中一个。
class A {
factory A() => throw 0;
A.named();
}
class B extends A {
B() : super.named();
}
如果没有可用的生成式构造函数,也无法添加任何生成式构造函数,则实现超类而不是扩展它。
class A {
factory A() => throw 0;
A.named();
}
class B implements A {}
非叶子调用不能接受类型化数据
#FFI 非叶调用不能接受类型化数据参数。
描述
#当Pointer.asFunction
、DynamicLibrary.lookupFunction
或@Native
的isLeaf
参数的值为false
,并且 Dart 函数签名包含类型化数据参数时,分析器会产生此诊断。
类型化数据解包仅在叶 FFI 调用的参数上受支持。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为 dart 函数签名包含类型化数据,但isLeaf
参数为false
import 'dart:ffi';
import 'dart:typed_data';
void f(Pointer<NativeFunction<Void Function(Pointer<Uint8>)>> p) {
p.asFunction<void Function(Uint8List)>();
}
常见修复方法
#如果函数至少包含一个类型化数据参数,则添加isLeaf
参数。
import 'dart:ffi';
import 'dart:typed_data';
void f(Pointer<NativeFunction<Void Function(Pointer<Uint8>)>> p) {
p.asFunction<void Function(Uint8List)>(isLeaf: true);
}
如果函数还使用Handle
,则它必须是非叶函数。在这种情况下,使用Pointer
而不是类型化数据。
指向指针的非原生函数类型参数
#无法调用“asFunction”,因为指针的函数签名“{0}”不是有效的 C 函数签名。
描述
#当在指向本机函数的指针上调用asFunction
方法时,但本机函数的签名不是有效的 C 函数签名时,分析器会产生此诊断。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断是因为与指针p
(FNative
)关联的函数签名不是有效的 C 函数签名。
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 签名。
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 互操作。
示例
#以下代码产生此诊断是因为提供了-1
的数组维度。
import 'dart:ffi';
final class MyStruct extends Struct {
@Array(-8)
external Array<Uint8> a0;
}
常见修复方法
#将维度更改为正整数。
import 'dart:ffi';
final class MyStruct extends Struct {
@Array(8)
external Array<Uint8> a0;
}
非大小类型参数
#类型“{1}”不是“{0}”的有效类型参数。类型参数必须是本机整数、'Float'、'Double'、'Pointer'或'Struct'、'Union'或'AbiSpecificInteger'的子类型。
描述
#当Array
类的类型参数不是以下有效类型之一时,分析器会产生此诊断:本机整数、Float
、Double
、Pointer
或Struct
、Union
或AbiSpecificInteger
的子类型。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码产生此诊断是因为Array
的类型参数是Void
,而Void
不是有效类型之一。
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Void> a0;
}
常见修复方法
#将类型参数更改为有效类型之一。
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
非同步工厂
#工厂体不能使用'async'、'async*'或'sync*'。
描述
#当工厂构造函数的函数体用async
、async*
或sync*
标记时,分析器会产生此诊断。所有构造函数,包括工厂构造函数,都必须返回其声明所在的类的实例,而不是Future
、Stream
或Iterator
。
示例
#以下代码产生此诊断是因为工厂构造函数的函数体用async
标记。
class C {
factory C() async {
return C._();
}
C._();
}
常见修复方法
#如果成员必须声明为工厂构造函数,则删除函数体之前的关键字。
class C {
factory C() {
return C._();
}
C._();
}
如果成员必须返回除封闭类实例以外的其他内容,则将成员设为静态方法。
class C {
static Future<C> m() async {
return C._();
}
C._();
}
非类型作为类型参数
#名称'{0}'不是类型,因此不能用作类型参数。
描述
#当标识符不是类型时用作类型参数时,分析器会产生此诊断。
示例
#以下代码会生成此诊断,因为 x
是一个变量,而不是一个类型。
var x = 0;
List<x> xList = [];
常见修复方法
#将类型参数更改为类型。
var x = 0;
List<int> xList = [];
catch 子句中的非类型
#名称'{0}'不是类型,不能在on-catch子句中使用。
描述
#当catch
子句中on
后面的标识符被定义为除类型以外的其他内容时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为f
是函数,而不是类型。
void f() {
try {
// ...
} on f {
// ...
}
}
常见修复方法
#将名称更改为应捕获的对象类型。
void f() {
try {
// ...
} on FormatException {
// ...
}
}
运算符的非 void 返回值
#运算符 []= 的返回类型必须为 'void'。
描述
#当运算符[]=
的声明具有除void
以外的返回类型时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为运算符[]=
的声明具有int
的返回类型。
class C {
int operator []=(int index, int value) => 0;
}
常见修复方法
#将返回类型更改为void
。
class C {
void operator []=(int index, int value) => 0;
}
设置器的非 void 返回值
#设置器的返回类型必须为 'void' 或缺失。
描述
#当设置器定义了除void
以外的返回类型时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为设置器p
具有int
的返回类型。
class C {
int set p(int i) => 0;
}
常见修复方法
#将返回类型更改为void
或省略返回类型。
class C {
set p(int i) => 0;
}
未赋值的潜在非空局部变量
#不可为空的局部变量 '{0}' 必须在使用之前赋值。
描述
#当局部变量被引用并具有以下所有特征时,分析器会产生此诊断。
示例
#以下代码会产生此诊断信息,因为x
不能为null
,但在为其赋值之前就被引用了。
String f() {
int x;
return x.toString();
}
以下代码会产生此诊断信息,因为对x
的赋值可能不会执行,因此它可能为null
。
int g(bool b) {
int x;
if (b) {
x = 1;
}
return x * 2;
}
以下代码会产生此诊断信息,因为分析器无法根据确定性赋值分析证明x
在没有为其赋值的情况下不会被引用。
int h(bool b) {
int x;
if (b) {
x = 1;
}
if (b) {
return x * 2;
}
return 0;
}
常见修复方法
#如果null
是一个有效的值,那么将变量设为可空。
String f() {
int? x;
return x!.toString();
}
如果null
不是一个有效的值,并且存在一个合理的默认值,那么添加一个初始化器。
int g(bool b) {
int x = 2;
if (b) {
x = 1;
}
return x * 2;
}
否则,请确保在访问值之前,在所有可能的代码路径上都为其赋值。
int g(bool b) {
int x;
if (b) {
x = 1;
} else {
x = 2;
}
return x * 2;
}
您也可以将变量标记为late
,这将消除诊断信息,但如果在访问变量之前没有为其赋值,则会导致在运行时抛出异常。此方法仅应在您确定变量将始终被赋值时使用,即使分析器无法根据确定性赋值分析证明这一点。
int h(bool b) {
late int x;
if (b) {
x = 1;
}
if (b) {
return x * 2;
}
return 0;
}
不是类型
#{0}不是一个类型。
描述
#当一个名称用作类型,但声明为非类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为f
是一个函数。
f() {}
g(f v) {}
常见修复方法
#用类型的名称替换名称。
不是二元运算符
#'{0}'不是一个二元运算符。
描述
#当一个只能用作一元运算符的运算符用作二元运算符时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为运算符~
只能用作一元运算符。
var a = 5 ~ 3;
常见修复方法
#用正确的二元运算符替换运算符。
var a = 5 - 3;
位置参数不足
#'{0}'需要 1 个位置参数,但找到 0 个。
需要 1 个位置参数,但找到 0 个。
'{2}'需要 {0} 个位置参数,但找到 {1} 个。
需要 {0} 个位置参数,但找到 {1} 个。
描述
#当方法或函数调用中的位置参数数量少于所需位置参数数量时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为f
声明了两个必需参数,但只提供了一个参数。
void f(int a, int b) {}
void g() {
f(0);
}
常见修复方法
#添加与剩余参数相对应的参数
void f(int a, int b) {}
void g() {
f(0, 1);
}
未初始化的非空实例字段
#不可为空的实例字段“{0}”必须初始化。
描述
#当一个字段被声明并具有以下所有特征时,分析器会产生此诊断
- 具有可能不可为空的类型
- 没有初始化器
- 没有标记为
late
示例
#以下代码会产生此诊断,因为x
被隐式初始化为null
,而它不允许为null
class C {
int x;
}
类似地,以下代码会产生此诊断,因为x
被隐式初始化为null
,而它不允许为null
,由其中一个构造函数初始化,即使它被其他构造函数初始化
class C {
int x;
C(this.x);
C.n();
}
常见修复方法
#如果字段有一个合理的默认值,该值对所有实例都相同,那么添加一个初始化表达式
class C {
int x = 0;
}
如果字段的值应该在创建实例时提供,那么添加一个设置字段值的构造函数,或者更新现有的构造函数
class C {
int x;
C(this.x);
}
你也可以将字段标记为late
,这将消除诊断,但如果字段在被访问之前没有被赋值,那么它会导致在运行时抛出异常。这种方法只应该在你确定字段在被引用之前一定会被赋值时使用。
class C {
late int x;
}
未初始化的非空变量
#不可为空的变量“{0}”必须初始化。
描述
#当一个静态字段或顶级变量具有不可为空的类型并且没有初始化器时,分析器会产生此诊断。没有初始化器的字段和变量通常被初始化为null
,但字段或变量的类型不允许它被设置为null
,因此必须提供显式初始化器。
示例
#以下代码会产生此诊断,因为字段f
不能被初始化为null
class C {
static int f;
}
类似地,以下代码会产生此诊断,因为顶级变量v
不能被初始化为null
int v;
常见修复方法
#如果字段或变量不能被初始化为null
,那么添加一个初始化器,将其设置为一个非空值
class C {
static int f = 0;
}
如果字段或变量应该初始化为null
,则将类型更改为可空类型
int? v;
如果字段或变量不能在声明中初始化,但将在引用之前始终被初始化,则将其标记为late
class C {
static late int f;
}
不可迭代的展开
#列表或集合字面量中的展开元素必须实现 'Iterable'。
描述
#当列表字面量或集合字面量中出现的展开元素的表达式的静态类型未实现类型Iterable
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m};
常见修复方法
#最常见的修复方法是用生成可迭代对象的表达式替换该表达式
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m.keys};
不是 map 展开
#映射字面量中的展开元素必须实现 'Map'。
描述
#当映射字面量中出现的展开元素的表达式的静态类型未实现类型Map
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为l
不是Map
var l = <String>['a', 'b'];
var m = <int, String>{...l};
常见修复方法
#最常见的修复方法是用生成映射的表达式替换该表达式
var l = <String>['a', 'b'];
var m = <int, String>{...l.asMap()};
没有注释构造函数参数
#注解创建必须具有参数。
描述
#当注解由单个标识符组成,但该标识符是类的名称而不是变量的名称时,分析器会生成此诊断信息。要创建类的实例,标识符后面必须跟一个参数列表。
示例
#以下代码会生成此诊断信息,因为C
是一个类,而类不能在不调用类中的const
构造函数的情况下用作注解
class C {
const C();
}
@C
var x;
常见修复方法
#添加缺少的参数列表
class C {
const C();
}
@C()
var x;
没有组合的超类签名
#无法从重写方法中推断 '{0}' 中的缺失类型:{1}。
描述
#当存在一个方法声明,其中需要推断一个或多个类型,并且这些类型无法推断,因为没有一个重写方法的函数类型是所有其他重写方法的超类型时,分析器会生成此诊断信息,如重写推断中所述。
示例
#以下代码会生成此诊断信息,因为类C
中声明的方法m
缺少返回值类型和参数a
的类型,并且无法为其推断任何缺少的类型
abstract class A {
A m(String a);
}
abstract class B {
B m(int a);
}
abstract class C implements A, B {
m(a);
}
在此示例中,无法执行重写推断,因为重写方法在以下方面不兼容
- 参数类型(
String
和int
)都不是对方的超类型。 - 返回值类型都不是对方的子类型。
常见修复方法
#如果可能,请向子类中的方法添加与所有重写方法中的类型一致的类型
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
没有生成式构造函数。
class A {
factory A.none() => throw '';
}
class B extends A {}
常见修复方法
#如果超类应该有一个生成式构造函数,那么添加一个。
class A {
A();
factory A.none() => throw '';
}
class B extends A {}
如果子类不应该有一个生成式构造函数,那么通过添加一个工厂构造函数来删除它。
class A {
factory A.none() => throw '';
}
class B extends A {
factory B.none() => throw '';
}
如果子类必须有一个生成式构造函数,但超类不能有一个,那么实现超类。
class A {
factory A.none() => throw '';
}
class B implements A {}
catch 子句中的可空类型
#潜在可空类型不能在“on”子句中使用,因为抛出可空表达式是无效的。
描述
#当catch
子句中on
后面的类型是可空类型时,分析器会生成此诊断信息。指定可空类型是无效的,因为无法捕获null
(因为抛出null
是运行时错误)。
示例
#以下代码会生成此诊断信息,因为异常类型被指定为允许null
,而null
不能被抛出。
void f() {
try {
// ...
} on FormatException? {
}
}
常见修复方法
#从类型中删除问号。
void f() {
try {
// ...
} on FormatException {
}
}
extends 子句中的可空类型
#类不能扩展可空类型。
描述
#当类声明使用extends
子句指定超类,并且超类后面跟着一个?
时,分析器会生成此诊断信息。
指定可空超类是无效的,因为这样做没有意义;它不会改变包含extends
子句的类的接口或实现。
但是,请注意,将可空类型用作超类的类型参数是有效的,例如class A extends B<C?> {}
。
示例
#以下代码会生成此诊断信息,因为A?
是一个可空类型,而可空类型不能在extends
子句中使用。
class A {}
class B extends A? {}
常见修复方法
#从类型中删除问号。
class A {}
class B extends A {}
implements 子句中的可空类型
#类、mixin或扩展类型不能实现可空类型。
描述
#当类、mixin或扩展类型声明有一个implements
子句,并且接口后面跟着一个?
时,分析器会生成此诊断信息。
指定可空接口是无效的,因为这样做没有意义;它不会改变包含implements
子句的类的接口。
但是,请注意,将可空类型用作接口的类型参数是有效的,例如class A implements B<C?> {}
。
示例
#以下代码会生成此诊断信息,因为A?
是一个可空类型,而可空类型不能在implements
子句中使用。
class A {}
class B implements A? {}
常见修复方法
#从类型中删除问号。
class A {}
class B implements A {}
on 子句中的可空类型
#Mixin 不能使用可空类型作为超类约束。
描述
#当 mixin 声明使用 `on` 子句指定超类约束,并且指定的类后面跟着 `?` 时,分析器会产生此诊断信息。
指定可空超类约束是无效的,因为这样做毫无意义;它不会改变包含 `on` 子句的 mixin 所依赖的接口。
但是,将可空类型用作超类约束的类型参数是有效的,例如 `mixin A on B<C?> {}`。
示例
#以下代码会产生此诊断信息,因为 `A?` 是可空类型,而可空类型不能在 `on` 子句中使用。
class C {}
mixin M on C? {}
常见修复方法
#从类型中删除问号。
class C {}
mixin M on C {}
with 子句中的可空类型
#类或 mixin 不能混合使用可空类型。
描述
#当类或 mixin 声明具有 `with` 子句,并且 mixin 后面跟着 `?` 时,分析器会产生此诊断信息。
指定可空 mixin 是无效的,因为这样做毫无意义;它不会改变包含 `with` 子句的类所继承的接口或实现。
但是,将可空类型用作 mixin 的类型参数是有效的,例如 `class A with B<C?> {}`。
示例
#以下代码会产生此诊断信息,因为 `A?` 是可空类型,而可空类型不能在 `with` 子句中使用。
mixin M {}
class C with M? {}
常见修复方法
#从类型中删除问号。
mixin M {}
class C with M {}
对非空类型的空参数
#'{0}' 不应该使用空参数调用非空类型参数 '{1}'。
描述
#当使用非空类型参数创建实例时,将 `null` 传递给构造函数 `Future.value` 或方法 `Completer.complete` 时,分析器会产生此诊断信息。即使类型系统无法表达此限制,传递 `null` 也会导致运行时异常。
示例
#以下代码会产生此诊断信息,因为 `null` 被传递给构造函数 `Future.value`,即使类型参数是非空类型 `String`。
Future<String> f() {
return Future.value(null);
}
常见修复方法
#传递非空值。
Future<String> f() {
return Future.value('');
}
空检查总是失败
#此空检查将始终抛出异常,因为表达式将始终计算为 `null`。
描述
#当在可能仅为 null
的表达式上使用空检查运算符 (!
) 时,分析器会生成此诊断信息。在这种情况下,运算符始终会抛出异常,这可能不是预期的行为。
示例
#以下代码会生成此诊断信息,因为函数 g
始终会返回 null
,这意味着 f
中的空检查始终会抛出异常
void f() {
g()!;
}
Null g() => null;
常见修复方法
#如果您打算始终抛出异常,则用显式的 throw
表达式替换空检查,以使意图更清晰
void f() {
g();
throw TypeError();
}
Null g() => null;
默认值的过时冒号
#在默认值之前使用冒号作为分隔符不再受支持。
描述
#当使用冒号 (:
) 作为可选命名参数的默认值之前的分隔符时,分析器会生成此诊断信息。虽然此语法以前是允许的,但它已被删除,取而代之的是使用等号 (=
)。
示例
#以下代码会生成此诊断信息,因为在可选参数i
的默认值之前使用了冒号。
void f({int i : 0}) {}
常见修复方法
#用等号替换冒号
void f({int i = 0}) {}
重复 on
#类型“{0}”只能在超类约束中包含一次。
描述
#当在混合的超类约束中多次列出相同的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 A
在 M
的超类约束中包含了两次
mixin M on A, A {
}
class A {}
class B {}
常见修复方法
#如果超类约束中应该包含其他类型,则用其他类型替换其中一个出现。
mixin M on A, B {
}
class A {}
class B {}
如果不需要其他类型,则删除重复的类型名称
mixin M on A {
}
class A {}
class B {}
运算符中的可选参数
#定义运算符时不允许使用可选参数。
描述
#当运算符声明中的一个或多个参数是可选参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为参数 other
是可选参数
class C {
C operator +([C? other]) => this;
}
常见修复方法
#使所有参数都成为必需参数
class C {
C operator +(C other) => this;
}
在非重写成员上重写
#该字段没有覆盖继承的 getter 或 setter。
该 getter 没有覆盖继承的 getter。
该方法没有覆盖继承的方法。
该 setter 没有覆盖继承的 setter。
描述
#当类成员使用 @override
注解进行注释,但该成员未在类的任何超类型中声明时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 m
未在 C
的任何超类型中声明
class C {
@override
String m() => '';
}
常见修复方法
#如果该成员旨在覆盖具有不同名称的成员,则更新该成员以具有相同的名称
class C {
@override
String toString() => '';
}
如果该成员旨在覆盖从超类中移除的成员,则考虑从子类中移除该成员。
如果该成员无法移除,则移除注释。
打包注释
#结构体最多只能有一个“Packed”注释。
描述
#当 Struct
的子类具有多个 Packed
注释时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为类 C
(它是 Struct
的子类)具有两个 Packed
注释
import 'dart:ffi';
@Packed(1)
@Packed(1)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
常见修复方法
#删除除一个以外的所有注解
import 'dart:ffi';
@Packed(1)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
打包注释对齐
#仅支持对 1、2、4、8 和 16 字节进行打包。
描述
#当 Packed
注释的参数不是允许的值之一(1、2、4、8 或 16)时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为 Packed
注释的参数(3
)不是允许的值之一
import 'dart:ffi';
@Packed(3)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
常见修复方法
#将对齐方式更改为允许的值之一。
import 'dart:ffi';
@Packed(4)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
属于不同的库
#预期此库是 '{0}' 的一部分,而不是 '{1}' 的一部分。
描述
#当库尝试将文件作为其自身的一部分包含进来,而该文件是另一个库的一部分时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的文件part.dart
part of 'library.dart';
以下代码(在除 library.dart
之外的任何文件中)会生成此诊断信息,因为它尝试将 part.dart
作为其自身的一部分包含进来,而 part.dart
是另一个库的一部分
part 'package:a/part.dart';
常见修复方法
#如果库应该使用另一个文件作为其一部分,则将部分指令中的 URI 更改为另一个文件的 URI。
如果 部分文件 应该是此库的一部分,则将部分指令中的 URI(或库名称)更新为正确库的 URI(或名称)。
属于非部分
#包含的部分 '{0}' 必须具有部分指令。
描述
#当找到部分指令并且引用的文件没有部分指令时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的文件a.dart
class A {}
以下代码会生成此诊断信息,因为 a.dart
不包含部分指令
part 'a.dart';
常见修复方法
#如果引用的文件旨在成为另一个库的一部分,则向该文件添加部分指令
part of 'test.dart';
class A {}
如果引用的文件旨在成为一个库,则用导入指令替换部分指令
import 'a.dart';
属于未命名的库
#库未命名。部分指令中需要 URI,而不是库名称 '{0}'。
描述
#当没有 library
指令(因此没有名称)的库包含 part
指令,并且 部分文件 中的 part of
指令使用名称来指定它是哪个库的一部分时,分析器会生成此诊断信息。
示例
#给定一个名为 part_file.dart
的 部分文件,其中包含以下代码
part of lib;
以下代码会产生此诊断信息,因为包含 部分文件 的库没有名称,即使 部分文件 使用名称来指定它是哪个库的一部分
part 'part_file.dart';
常见修复方法
#更改 部分文件 中的 part of
指令,通过 URI 指定其库
part of 'test.dart';
路径不存在
#路径 '{0}' 不存在。
描述
#当依赖项的 path
键引用一个不存在的目录时,分析器会产生此诊断信息。
示例
#假设目录 doesNotExist
不存在,以下代码会产生此诊断信息,因为它被列为包的路径
name: example
dependencies:
local_package:
path: doesNotExist
常见修复方法
#如果路径正确,则在该路径上创建一个目录。
如果路径不正确,则更改路径以匹配包根目录的路径。
路径不是 POSIX
#路径 '{0}' 不是 POSIX 风格的路径。
描述
#当依赖项的 path
键的值是一个字符串,但不是 POSIX 风格的路径时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 path
键后面的路径是 Windows 路径
name: example
dependencies:
local_package:
path: E:\local_package
常见修复方法
#将路径转换为 POSIX 路径。
路径 pubspec 不存在
#目录 '{0}' 不包含 pubspec。
描述
#当依赖项的 path
键引用一个不包含 pubspec.yaml
文件的目录时,分析器会产生此诊断信息。
示例
#假设目录 local_package
不包含文件 pubspec.yaml
,以下代码会产生此诊断信息,因为它被列为包的路径
name: example
dependencies:
local_package:
path: local_package
常见修复方法
#如果路径意图是包的根目录,则在目录中添加 pubspec.yaml
文件
name: local_package
如果路径错误,则将其替换为正确的路径。
模式赋值不是局部变量
#只有局部变量可以在模式赋值中赋值。
描述
#当模式赋值将值赋予除局部变量以外的任何事物时,分析器会产生此诊断信息。模式不能赋值给字段或顶层变量。
示例
#如果使用模式解构时代码更简洁,则重写代码以将值赋予模式声明中的局部变量,并分别赋予非局部变量
class C {
var x = 0;
void f((int, int) r) {
(x, _) = r;
}
}
常见修复方法
#如果使用模式赋值时代码更简洁,则重写代码以将值赋予局部变量,并分别赋予非局部变量
class C {
var x = 0;
void f((int, int) r) {
var (a, _) = r;
x = a;
}
}
如果不用模式赋值时代码更简洁,则重写代码以不使用模式赋值
class C {
var x = 0;
void f((int, int) r) {
x = r.$1;
}
}
来自延迟库的模式常量
#来自延迟库的常量值不能在模式中使用。
描述
#当模式包含在不同库中声明的值,并且该库使用延迟导入导入时,分析器会生成此诊断信息。常量在编译时进行评估,但延迟库中的值在编译时不可用。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义常量 zero
的文件 a.dart
const zero = 0;
以下代码会生成此诊断信息,因为常量模式 a.zero
使用延迟导入导入
import 'a.dart' deferred as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
常见修复方法
#如果需要引用导入库中的常量,则删除deferred
关键字。
import 'a.dart' as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
如果您需要引用从导入的库中导入的常量,并且还需要延迟导入该库,那么请将 switch 语句重写为一系列 if
语句
import 'a.dart' deferred as a;
void f(int x) {
if (x == a.zero) {
// ...
}
}
如果您不需要引用该常量,那么请替换 case 表达式
void f(int x) {
switch (x) {
case 0:
// ...
break;
}
}
不可反驳上下文中模式类型不匹配
#类型为 '{0}' 的匹配值无法分配给所需的类型 '{1}'。
描述
#当模式赋值或模式声明右侧的值类型与用于匹配它的模式所需的类型不匹配时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 x
可能不是 String
,因此可能不匹配对象模式
void f(Object x) {
var String(length: a) = x;
print(a);
}
常见修复方法
#更改代码,使右侧表达式的类型与模式所需的类型匹配
void f(String x) {
var String(length: a) = x;
print(a);
}
模式变量赋值在保护内
#模式变量不能在包含的受保护模式的保护条件中赋值。
描述
#当模式变量在保护条件 (when
) 子句中赋值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为变量 a
在保护条件子句中赋值
void f(int x) {
if (x case var a when (a = 1) > 0) {
print(a);
}
}
常见修复方法
#如果需要捕获值,则将其分配给不同的变量
void f(int x) {
var b;
if (x case var a when (b = 1) > 0) {
print(a + b);
}
}
如果没有需要捕获的值,则删除赋值
void f(int x) {
if (x case var a when 1 > 0) {
print(a);
}
}
不允许平台值
#platforms
字段中的键不能有值。
描述
#当 platforms
映射中的键有值时,分析器会生成此诊断信息。要了解有关指定包支持的平台的更多信息,请查看 平台声明文档。
示例
#以下 pubspec.yaml
会生成此诊断信息,因为键 web
有值。
name: example
platforms:
web: "chrome"
常见修复方法
#省略值,并将键保留为无值
name: example
platforms:
web:
platforms
字段中键的值目前保留用于潜在的未来行为。
对象模式中的位置字段
#对象模式只能使用命名字段。
描述
#当对象模式包含没有指定 getter 名称的字段时,分析器会生成此诊断信息。对象模式字段与对象 getter 返回的值匹配。如果没有指定 getter 名称,则模式字段无法访问值以尝试匹配。
示例
#以下代码产生此诊断信息,因为对象模式String(1)
没有指定要访问的String
的哪个 getter 并与值1
进行比较。
void f(Object o) {
if (o case String(1)) {}
}
常见修复方法
#添加 getter 名称以访问值,然后在要匹配的模式之前添加冒号。
void f(Object o) {
if (o case String(length: 1)) {}
}
带位置参数的位置超类形式参数
#当超类构造函数调用具有位置参数时,不能使用位置超参数。
描述
#当向超类构造函数提供的位置参数中,有些使用超参数,但并非全部使用时,分析器会产生此诊断信息。
位置超参数通过其索引与超类构造函数中的位置参数相关联。也就是说,第一个超参数与超类构造函数中的第一个位置参数相关联,第二个与第二个相关联,依此类推。位置参数也是如此。同时具有位置超参数和位置参数意味着超类构造函数中的同一个参数有两个关联的值,因此不允许。
示例
#以下代码产生此诊断信息,因为构造函数B.new
使用超参数将一个必需的位置参数传递给A
中的超类构造函数,但在超类构造函数调用中显式传递了另一个参数。
class A {
A(int x, int y);
}
class B extends A {
B(int x, super.y) : super(x);
}
常见修复方法
#如果所有位置参数都可以是超参数,则将普通位置参数转换为超参数。
class A {
A(int x, int y);
}
class B extends A {
B(super.x, super.y);
}
如果某些位置参数不能是超参数,则将超参数转换为普通参数。
class A {
A(int x, int y);
}
class B extends A {
B(int x, int y) : super(x, y);
}
前缀与顶层成员冲突
#名称“{0}”已用作导入前缀,不能用作顶级元素的名称。
描述
#当一个名称用作导入前缀和同一个库中顶级声明的名称时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为f
用作导入前缀和函数的名称。
import 'dart:math' as f;
int f() => f.min(0, 1);
常见修复方法
#如果要将名称用于导入前缀,请重命名顶级声明。
import 'dart:math' as f;
int g() => f.min(0, 1);
如果要将名称用于顶级声明,请重命名导入前缀。
import 'dart:math' as math;
int f() => math.min(0, 1);
前缀标识符后没有点
#名称“{0}”引用导入前缀,因此必须后跟“.”。
描述
#当导入前缀单独使用,而不访问与前缀关联的库中声明的任何名称时,分析器会产生此诊断信息。前缀不是变量,因此不能用作值。
示例
#以下代码产生此诊断信息,因为前缀math
被用作变量。
import 'dart:math' as math;
void f() {
print(math);
}
常见修复方法
#如果代码不完整,请引用与前缀关联的库中的某个内容。
import 'dart:math' as math;
void f() {
print(math.pi);
}
如果名称错误,请更正名称。
前缀被局部声明遮蔽
#前缀 '{0}' 无法在此处使用,因为它被局部声明遮蔽。
描述
#当导入前缀在不可见的环境中使用时,分析器会生成此诊断信息,因为该前缀被局部声明遮蔽。
示例
#以下代码会生成此诊断信息,因为前缀 a
用于访问类 Future
,但由于被参数 a
遮蔽,因此不可见。
import 'dart:async' as a;
a.Future? f(int a) {
a.Future? x;
return x;
}
常见修复方法
#重命名前缀
import 'dart:async' as p;
p.Future? f(int a) {
p.Future? x;
return x;
}
或重命名局部变量
import 'dart:async' as a;
a.Future? f(int p) {
a.Future? x;
return x;
}
混合应用中的私有冲突
#由 '{1}' 定义的私有名称 '{0}' 与由 '{2}' 定义的相同名称冲突。
描述
#当两个定义了相同私有成员的 mixin 在单个类中一起使用时,分析器会生成此诊断信息,前提是该类不在定义 mixin 的库中。
示例
#给定包含以下代码的文件 a.dart
mixin A {
void _foo() {}
}
mixin B {
void _foo() {}
}
以下代码会生成此诊断信息,因为 mixin A
和 B
都定义了方法 _foo
import 'a.dart';
class C extends Object with A, B {}
常见修复方法
#如果不需要这两个 mixin,请从 with
子句中删除其中一个。
import 'a.dart';
class C extends Object with A, B {}
如果需要这两个 mixin,请在两个 mixin 中的其中一个中重命名冲突的成员。
私有可选参数
#命名参数不能以下划线开头。
描述
#当命名参数的名称以下划线开头时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为命名参数 _x
以下划线开头。
class C {
void m({int _x = 0}) {}
}
常见修复方法
#重命名参数,使其不以下划线开头。
class C {
void m({int x = 0}) {}
}
私有设置器
#setter '{0}' 是私有的,无法在声明它的库之外访问。
描述
#当私有 setter 在不可见的库中使用时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的文件a.dart
class A {
static int _f = 0;
}
以下代码会生成此诊断信息,因为它引用了私有 setter _f
,即使该 setter 不可見。
import 'a.dart';
void f() {
A._f = 0;
}
常见修复方法
#如果可以将 setter 设置为公共,请这样做。
class A {
static int f = 0;
}
如果无法将 setter 设置为公共,请找到其他方法来实现代码。
读取潜在未赋值的 final
#无法读取最终变量 '{0}',因为它在此处可能未赋值。
描述
#当在编译器无法证明变量在引用之前始终初始化的位置读取未在声明位置初始化的最终局部变量时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为在可能尚未初始化最终局部变量 x
的情况下读取了它(在第 3 行)。
int f() {
final int x;
return x;
}
常见修复方法
#确保在读取变量之前已对其进行初始化。
int f(bool b) {
final int x;
if (b) {
x = 0;
} else {
x = 1;
}
return x;
}
记录字面量一个位置没有尾部逗号
#只有一个位置字段的记录字面量需要尾随逗号。
描述
#当只有一个位置字段的记录字面量在字段之后没有尾随逗号时,分析器会生成此诊断信息。
在某些位置,具有单个位置字段的记录字面量也可能是一个带括号的表达式。需要尾随逗号来区分这两种有效的解释。
示例
#以下代码会产生此诊断,因为记录字面量具有一个位置字段,但没有尾随逗号
var r = const (1);
常见修复方法
#添加尾随逗号
var r = const (1,);
记录类型一个位置没有尾部逗号
#具有一个位置字段的记录类型需要尾随逗号。
描述
#当具有单个位置字段的记录类型注释在字段后没有尾随逗号时,分析器会产生此诊断。
在某些位置,具有单个位置字段的记录类型也可能是一个带括号的表达式。需要尾随逗号来区分这两种有效的解释。
示例
#以下代码会产生此诊断,因为记录类型具有一个位置字段,但没有尾随逗号
void f((int) r) {}
常见修复方法
#添加尾随逗号
void f((int,) r) {}
递归编译时常量
#编译时常量表达式依赖于自身。
描述
#当编译时常量的值直接或间接地以自身定义时,分析器会产生此诊断,从而创建无限循环。
示例
#以下代码会产生此诊断两次,因为两个常量都是以对方定义的
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = secondsPerHour / 60;
常见修复方法
#通过找到定义至少一个常量的替代方法来打破循环
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = 60;
递归构造函数重定向
#构造函数不能直接或间接地重定向到自身。
描述
#当构造函数直接或间接地重定向到自身时,分析器会产生此诊断,从而创建无限循环。
示例
#以下代码会产生此诊断,因为生成式构造函数 C.a
和 C.b
互相重定向
class C {
C.a() : this.b();
C.b() : this.a();
}
以下代码会产生此诊断,因为工厂构造函数 A
和 B
互相重定向
abstract class A {
factory A() = B;
}
class B implements A {
factory B() = A;
B.named();
}
常见修复方法
#对于生成式构造函数,通过找到定义至少一个构造函数不重定向到另一个构造函数来打破循环
class C {
C.a() : this.b();
C.b();
}
对于工厂构造函数,通过定义至少一个工厂构造函数执行以下操作之一来打破循环
- 重定向到生成式构造函数
abstract class A {
factory A() = B;
}
class B implements A {
factory B() = B.named;
B.named();
}
- 不重定向到另一个构造函数
abstract class A {
factory A() = B;
}
class B implements A {
factory B() {
return B.named();
}
B.named();
}
- 不是工厂构造函数
abstract class A {
factory A() = B;
}
class B implements A {
B();
B.named();
}
递归接口继承
#'{0}' 不能是自身的超接口:{1}。
'{0}' 不能扩展自身。
'{0}' 不能实现自身。
'{0}' 不能使用自身作为 mixin。
'{0}' 不能使用自身作为超类约束。
描述
#当类型层次结构中存在循环时,分析器会产生此诊断。当类型直接或间接地声明为自身的子类型时,就会发生这种情况。
示例
#以下代码会产生此诊断,因为类 A
声明为 B
的子类型,而 B
是 A
的子类型
class A extends B {}
class B implements A {}
常见修复方法
#更改类型层次结构,使其没有循环。
在非重新声明成员上重新声明
#{0} 没有重新声明在超接口中声明的 {0}。
描述
#当扩展类型的成员使用 @redeclare
注释,但没有实现的接口具有相同名称的成员时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为扩展类型 E
声明的成员 n
使用 @redeclare
注释,但 C
没有名为 n
的成员。
import 'package:meta/meta.dart';
class C {
void m() {}
}
extension type E(C c) implements C {
@redeclare
void n() {}
}
常见修复方法
#如果注释的成员具有正确的名称,则删除注释。
class C {
void m() {}
}
extension type E(C c) implements C {
void n() {}
}
如果注释的成员应该替换来自实现接口的成员,则将注释的成员的名称更改为与要替换的成员匹配。
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
未定义。
class C {
C.a() : this.b();
}
常见修复方法
#如果必须调用缺少的构造函数,则定义它。
class C {
C.a() : this.b();
C.b();
}
如果不需要调用缺少的构造函数,则删除重定向。
class C {
C.a();
}
将生成重定向到非生成构造函数
#生成式构造函数不能重定向到工厂构造函数。
描述
#当生成式构造函数重定向到工厂构造函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为生成式构造函数 C.a
重定向到工厂构造函数 C.b
。
class C {
C.a() : this.b();
factory C.b() => C.a();
}
常见修复方法
#如果生成式构造函数不需要重定向到另一个构造函数,则删除重定向。
class C {
C.a();
factory C.b() => C.a();
}
如果生成式构造函数必须重定向到另一个构造函数,则将另一个构造函数设为生成式(非工厂)构造函数。
class C {
C.a() : this.b();
C.b();
}
重定向到抽象类构造函数
#重定向构造函数 '{0}' 不能重定向到抽象类 '{1}' 的构造函数。
描述
#当构造函数重定向到抽象类中的构造函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 A
中的工厂构造函数重定向到 B
中的构造函数,但 B
是一个抽象类。
class A {
factory A() = B;
}
abstract class B implements A {}
常见修复方法
#如果代码重定向到正确的构造函数,则更改类,使其不再是抽象类。
class A {
factory A() = B;
}
class B implements A {}
否则,更改工厂构造函数,使其要么重定向到具体类中的构造函数,要么具有具体实现。
重定向到无效函数类型
#重定向的构造函数“ {0} ”与“ {1} ”的参数不兼容。
描述
#当工厂构造函数尝试重定向到另一个构造函数,但两者参数不兼容时,分析器会生成此诊断信息。如果重定向构造函数的所有参数都可以传递给另一个构造函数,并且另一个构造函数不需要重定向构造函数未声明的任何参数,则参数兼容。
示例
#以下代码会生成此诊断信息,因为 A
的构造函数没有声明 B
的构造函数所需的参数
abstract class A {
factory A() = B;
}
class B implements A {
B(int x);
B.zero();
}
以下代码会生成此诊断信息,因为 A
的构造函数声明了一个命名参数 (y
),而 B
的构造函数不允许
abstract class A {
factory A(int x, {int y}) = B;
}
class B implements A {
B(int x);
}
常见修复方法
#如果存在与重定向构造函数兼容的其他构造函数,则重定向到该构造函数
abstract class A {
factory A() = B.zero;
}
class B implements A {
B(int x);
B.zero();
}
否则,更新重定向构造函数以使其兼容
abstract class A {
factory A(int x) = B;
}
class B implements A {
B(int x);
}
重定向到无效返回值类型
#重定向构造函数的返回类型“ {0} ”不是“ {1} ”的子类型。
描述
#当工厂构造函数重定向到返回类型不是工厂构造函数声明要生成的类型的子类型的构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 A
不是 C
的子类,这意味着 A()
构造函数返回的值不能从 C()
构造函数返回
class A {}
class B implements C {}
class C {
factory C() = A;
}
常见修复方法
#如果工厂构造函数正在重定向到错误类中的构造函数,则更新工厂构造函数以重定向到正确的构造函数
class A {}
class B implements C {}
class C {
factory C() = B;
}
如果定义要重定向到的构造函数的类是应该返回的类,则使其成为工厂返回类型的子类型
class A implements C {}
class B implements C {}
class C {
factory C() = A;
}
重定向到缺失的构造函数
#在 '{1}' 中找不到构造函数 '{0}'。
描述
#当构造函数重定向到不存在的构造函数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 A
中的工厂构造函数重定向到 B
中不存在的构造函数
class A {
factory A() = B.name;
}
class B implements A {
B();
}
常见修复方法
#如果要重定向到的构造函数是正确的,则定义该构造函数
class A {
factory A() = B.name;
}
class B implements A {
B();
B.name();
}
如果应该调用其他构造函数,则更新重定向
class A {
factory A() = B;
}
class B implements A {
B();
}
重定向到非类
#名称“ {0} ”不是类型,不能在重定向的构造函数中使用。
描述
#实现工厂构造函数的一种方法是通过引用构造函数的名称来重定向到另一个构造函数。当重定向到构造函数以外的其他内容时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为f
是一个函数。
C f() => throw 0;
class C {
factory C() = f;
}
常见修复方法
#如果构造函数未定义,则要么定义它,要么用已定义的构造函数替换它。
如果构造函数已定义,但定义它的类不可见,则可能需要添加导入。
如果您试图返回函数返回的值,那么请重写构造函数以从构造函数体中返回该值。
C f() => throw 0;
class C {
factory C() => f();
}
重定向到非常量构造函数
#常量重定向构造函数不能重定向到非常量构造函数。
描述
#当标记为 const
的构造函数重定向到未标记为 const
的构造函数时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为构造函数 C.a
被标记为 const
,但重定向到构造函数 C.b
,而 C.b
未被标记为 const
。
class C {
const C.a() : this.b();
C.b();
}
常见修复方法
#如果非常量构造函数可以标记为 const
,则将其标记为 const
。
class C {
const C.a() : this.b();
const C.b();
}
如果非常量构造函数不能标记为 const
,则要么删除重定向,要么从重定向构造函数中删除 const
。
class C {
C.a() : this.b();
C.b();
}
重定向到类型别名扩展到类型参数
#重定向构造函数不能重定向到扩展为类型参数的类型别名。
描述
#当重定向工厂构造函数重定向到类型别名,并且类型别名扩展为类型别名的类型参数之一时,分析器会产生此诊断信息。这是不允许的,因为类型参数的值是类型而不是类。
示例
#以下代码会产生此诊断信息,因为重定向到 B<A>
是对类型别名的重定向,其值为 T
,即使它看起来像值应该是 A
。
class A implements C {}
typedef B<T> = T;
abstract class C {
factory C() = B<A>;
}
常见修复方法
#使用类名或定义为类的类型别名,而不是定义为类型参数的类型别名。
class A implements C {}
abstract class C {
factory C() = A;
}
在声明之前引用
#局部变量 '{0}' 在声明之前无法引用。
描述
#当在变量声明之前引用变量时,分析器会产生此诊断信息。在 Dart 中,变量在其声明所在的块中处处可见,但只能在声明之后引用。
分析器还会产生一个上下文消息,指示声明的位置。
示例
#以下代码会产生此诊断信息,因为 i
在声明之前被使用。
void f() {
print(i);
int i = 5;
}
常见修复方法
#如果您打算引用局部变量,请将声明移到第一个引用之前。
void f() {
int i = 5;
print(i);
}
如果您打算引用来自外部作用域的名称,例如参数、实例字段或顶级变量,则重命名局部声明,使其不会隐藏外部变量。
void f(int i) {
print(i);
int x = 5;
print(x);
}
不可反驳上下文中不可反驳的模式
#可证伪模式不能在不可证伪上下文中使用。
描述
#当在只允许使用 不可证伪模式 的上下文中使用 可证伪模式 时,分析器会产生此诊断信息。
不允许使用的可证伪模式是
- 逻辑或
- 关系
- 空检查
- 常量
检查的上下文是
- 基于模式的变量声明
- 基于模式的 for 循环
- 带有左侧模式的赋值
示例
#以下代码会产生此诊断,因为空检查模式(可反驳模式)位于基于模式的变量声明中,而基于模式的变量声明不允许可反驳模式。
void f(int? x) {
var (_?) = x;
}
常见修复方法
#重写代码,不要在不可反驳的上下文中使用可反驳模式。
关系模式操作数类型不可分配
#常量表达式类型“{0}”无法分配给“{2}”运算符的参数类型“{1}”。
描述
#当关系模式的操作数类型无法分配给将要调用的运算符的参数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为关系模式中的操作数(0
)是int
类型,但C
中定义的>
运算符需要C
类型的对象。
class C {
const C();
bool operator >(C other) => true;
}
void f(C c) {
switch (c) {
case > 0:
print('positive');
}
}
常见修复方法
#如果 switch 使用的是正确的值,则更改 case 以将值与正确类型的对象进行比较。
class C {
const C();
bool operator >(C other) => true;
}
void f(C c) {
switch (c) {
case > const C():
print('positive');
}
}
如果 switch 使用的是错误的值,则更改用于计算匹配值的表达式。
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
类型值的运算符时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为关系模式> c2
中使用的运算符>
返回int
类型的值,而不是bool
类型的值。
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) {}
}
常见修复方法
#如果有其他应该使用的运算符,则更改运算符。
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
,则更新运算符的声明。
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) {}
}
映射模式中的剩余元素
#映射模式不能包含剩余模式。
描述
#当映射模式包含剩余模式时,分析器会产生此诊断。映射模式匹配具有比模式中明确给出的键更多的键的映射(只要给定的键匹配),因此剩余模式是不必要的。
示例
#以下代码会产生此诊断,因为映射模式包含剩余模式。
void f(Map<int, String> x) {
if (x case {0: _, ...}) {}
}
常见修复方法
#删除剩余模式。
void f(Map<int, String> x) {
if (x case {0: _}) {}
}
在 catch 外部重新抛出
#重新抛出必须位于 catch 子句中。
描述
#当rethrow
语句位于catch
子句之外时,分析器会产生此诊断。rethrow
语句用于再次抛出捕获的异常,但在catch
子句之外没有捕获的异常。
示例
#以下代码会产生此诊断,因为rethrow
语句位于catch
子句之外。
void f() {
rethrow;
}
常见修复方法
#如果您尝试重新抛出异常,则将rethrow
语句包装在catch
子句中。
void f() {
try {
// ...
} catch (exception) {
rethrow;
}
}
如果您尝试抛出新的异常,则用throw
表达式替换rethrow
语句。
void f() {
throw UnsupportedError('Not yet implemented');
}
在生成式构造函数中返回
#构造函数不能返回值。
描述
#当生成式构造函数包含指定要返回的值的return
语句时,分析器会产生此诊断。生成式构造函数始终返回创建的对象,因此不能返回其他对象。
示例
#以下代码产生此诊断信息,因为return
语句包含表达式。
class C {
C() {
return this;
}
}
常见修复方法
#如果构造函数应该创建一个新实例,则删除return
语句或表达式。
class C {
C();
}
如果构造函数不应该创建一个新实例,则将其转换为工厂构造函数。
class C {
factory C() {
return _instance;
}
static C _instance = C._();
C._();
}
在生成器中返回
#无法从使用 'async*' 或 'sync*' 修饰符的生成器函数中返回值。
描述
#当生成器函数(其主体用async*
或sync*
标记)使用return
语句返回值或由于使用=>
而隐式返回值时,分析器会产生此诊断信息。在任何这些情况下,它们应该使用yield
而不是return
。
示例
#以下代码产生此诊断信息,因为方法f
是一个生成器,并且正在使用return
返回值。
Iterable<int> f() sync* {
return 3;
}
以下代码产生此诊断信息,因为函数f
是一个生成器,并且正在隐式返回值。
Stream<int> f() async* => 3;
常见修复方法
#如果函数使用=>
作为函数主体,则将其转换为块函数主体,并使用yield
返回值。
Stream<int> f() async* {
yield 3;
}
如果方法旨在成为一个生成器,则使用yield
返回值。
Iterable<int> f() sync* {
yield 3;
}
如果方法不打算成为一个生成器,则从主体中删除修饰符(或者如果你要返回一个未来,则使用async
)。
int f() {
return 3;
}
返回非存储值
#'{0}' 被标注为 'doNotStore',不应该被返回,除非 '{1}' 也被标注。
描述
#当一个被标注为 doNotStore
注解的值从没有相同注解的方法、getter 或函数中返回时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为调用f
的结果不应该被存储,但函数g
没有被标注以保留该语义。
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
int g() => f();
常见修复方法
#如果不应该被存储的值是正确的返回值,则用 doNotStore
注解标记该函数。
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
@doNotStore
int g() => f();
否则,从函数中返回一个不同的值。
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
int g() => 0;
返回无效类型
#类型为 '{0}' 的值无法从构造函数 '{2}' 中返回,因为它具有 '{1}' 的返回类型。
类型为 '{0}' 的值无法从函数 '{2}' 中返回,因为它具有 '{1}' 的返回类型。
类型为 '{0}' 的值无法从方法 '{2}' 中返回,因为它具有 '{1}' 的返回类型。
描述
#当方法或函数返回类型不可分配给声明的返回类型的值时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 f
的返回类型为 String
,但它返回的是一个 int
String f() => 3;
常见修复方法
#如果返回类型正确,则用正确类型的返回值替换正在返回的值,可以通过转换现有值来实现。
String f() => 3.toString();
如果值正确,则更改返回类型以匹配。
int f() => 3;
从闭包返回无效类型
#返回类型 '{0}' 不是 '{1}',这是闭包上下文所要求的。
描述
#当返回表达式的静态类型不可分配给闭包所需的返回类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 f
被定义为返回 String
的函数,但分配给它的闭包返回的是一个 int
String Function(String) f = (s) => 3;
常见修复方法
#如果返回类型正确,则用正确类型的返回值替换正在返回的值,可以通过转换现有值来实现。
String Function(String) f = (s) => 3.toString();
无值返回
#在 'return' 之后缺少返回值。
描述
#当分析器在声明了返回类型的函数中找到没有表达式的 return
语句时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为函数 f
预计返回一个 int
,但没有返回值。
int f() {
return;
}
常见修复方法
#添加一个表达式来计算要返回的值。
int f() {
return 0;
}
SDK 版本异步从核心导出
#类 '{0}' 直到版本 2.1 才从 'dart:core' 中导出,但此代码需要能够在早期版本上运行。
描述
#当类 Future
或 Stream
在没有导入 dart:async
的库中被引用,并且代码的 SDK 约束的下限小于 2.1.0 时,分析器会生成此诊断信息。在早期版本中,这些类没有在 dart:core
中定义,因此需要导入。
示例
#以下是一个定义了 SDK 约束,其下限小于 2.1.0 的 pubspec 示例。
environment:
sdk: '>=2.0.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
void f(Future f) {}
常见修复方法
#如果你不需要支持旧版本的 SDK,则可以增加 SDK 约束以允许引用这些类。
environment:
sdk: '>=2.1.0 <2.4.0'
如果你需要支持旧版本的 SDK,则导入 dart:async
库。
import 'dart:async';
void f(Future f) {}
SDK 版本作为常量上下文中的表达式
#在常量表达式中使用 as 表达式直到版本 2.3.2 才被支持,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.3.2 的代码中,在 常量上下文 中找到 as
表达式时,分析器会生成此诊断信息。在早期版本中,在 常量上下文 中使用 as
表达式不受支持,因此此代码无法在早期版本的 SDK 上运行。
示例
#这是一个定义 SDK 约束的 pubspec 示例,其下限小于 2.3.2。
environment:
sdk: '>=2.1.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
const num n = 3;
const int i = n as int;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该表达式。
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支持旧版本的 SDK,则可以重写代码以不使用 `as` 表达式,或者更改代码以使 `as` 表达式不在 常量上下文 中。
num x = 3;
int y = x as int;
SDK 版本布尔运算符在常量上下文中的使用
#在常量上下文中使用运算符 '{0}' 对 'bool' 操作数的支持直到版本 2.3.2 才出现,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.3.2 的代码中发现对类 `bool` 中的 `&`、`|` 或 `^` 运算符的任何使用时,分析器会生成此诊断。在早期版本中不支持在 常量上下文 中使用这些运算符,因此此代码将无法在早期版本的 SDK 上运行。
示例
#这是一个定义 SDK 约束的 pubspec 示例,其下限小于 2.3.2。
environment:
sdk: '>=2.1.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
const bool a = true;
const bool b = false;
const bool c = a & b;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用这些运算符。
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支持旧版本的 SDK,则可以重写代码以不使用这些运算符,或者更改代码以使表达式不在 常量上下文 中。
const bool a = true;
const bool b = false;
bool c = a & b;
SDK 版本构造函数撕裂
#拆解构造函数需要 'constructor-tearoffs' 语言特性。
描述
#当在 SDK 约束的下限小于 2.15 的代码中发现构造函数拆解时,分析器会生成此诊断。在早期版本中不支持构造函数拆解,因此此代码将无法在早期版本的 SDK 上运行。
示例
#这是一个定义 SDK 约束的 pubspec 示例,其下限小于 2.15。
environment:
sdk: '>=2.9.0 <2.15.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
var setConstructor = Set.identity;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。
environment:
sdk: '>=2.15.0 <2.16.0'
如果您需要支持旧版本的 SDK,则重写代码以不使用构造函数拆解。
var setConstructor = () => Set.identity();
SDK 版本 == 运算符在常量上下文中的使用
#在 2.3.2 版本之前,不支持对非基本类型使用 '==' 运算符,但此代码需要能够在早期版本上运行。
描述
#当在代码中发现对非基本类型使用 ==
运算符的 常量上下文,并且该代码的 SDK 约束下限小于 2.3.2 时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用此运算符,因此此代码无法在早期版本的 SDK 上运行。
示例
#这是一个定义 SDK 约束的 pubspec 示例,其下限小于 2.3.2。
environment:
sdk: '>=2.1.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
class C {}
const C a = null;
const C b = null;
const bool same = a == b;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支持旧版本的 SDK,则可以重写代码以不使用 ==
运算符,或者更改代码以使表达式不在 常量上下文 中。
class C {}
const C a = null;
const C b = null;
bool same = a == b;
SDK 版本扩展方法
#扩展方法在 2.6.0 版本之前不受支持,但此代码需要能够在早期版本上运行。
描述
#当在代码中发现扩展声明或扩展覆盖,并且该代码的 SDK 约束下限小于 2.6.0 时,分析器会生成此诊断信息。在早期版本中,不支持使用扩展,因此此代码无法在早期版本的 SDK 上运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.6.0)的 pubspec 示例。
environment:
sdk: '>=2.4.0 <2.7.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
extension E on String {
void sayHello() {
print('Hello $this');
}
}
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该语法。
environment:
sdk: '>=2.6.0 <2.7.0'
如果您需要支持旧版本的 SDK,则重写代码以不使用扩展。最常见的方法是将扩展的成员重写为顶层函数(或方法),这些函数(或方法)将作为参数接受本应绑定到 this
的值。
void sayHello(String s) {
print('Hello $s');
}
SDK 版本 >>> 运算符
#运算符 '>>>' 在 2.14.0 版本之前不受支持,但此代码需要能够在早期版本上运行。
描述
#当在代码中使用 >>>
运算符,并且该代码的 SDK 约束下限小于 2.14.0 时,分析器会生成此诊断信息。此运算符在早期版本中不受支持,因此此代码无法在早期版本的 SDK 上运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.14.0)的 pubspec 示例。
environment:
sdk: '>=2.0.0 <2.15.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
int x = 3 >>> 4;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该运算符。
environment:
sdk: '>=2.14.0 <2.15.0'
如果您需要支持旧版本的 SDK,则重写代码以不使用 >>>
运算符。
int x = logicalShiftRight(3, 4);
int logicalShiftRight(int leftOperand, int rightOperand) {
int divisor = 1 << rightOperand;
if (divisor == 0) {
return 0;
}
return leftOperand ~/ divisor;
}
SDK 版本 is 表达式在常量上下文中的使用
#在 2.3.2 版本之前,不支持在常量上下文中的使用 is 表达式,但此代码需要能够在早期版本上运行。
描述
#当在代码中发现 常量上下文 中的 is
表达式,并且该代码的 SDK 约束下限小于 2.3.2 时,分析器会生成此诊断信息。在早期版本中,不支持在 常量上下文 中使用 is
表达式,因此此代码无法在早期版本的 SDK 上运行。
示例
#这是一个定义 SDK 约束的 pubspec 示例,其下限小于 2.3.2。
environment:
sdk: '>=2.1.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
const Object x = 4;
const y = x is int ? 0 : 1;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该表达式。
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支持旧版本的 SDK,则需要重写代码以不使用 is
运算符,或者,如果无法做到,则更改代码以使 is
表达式不在 常量上下文 中。
const Object x = 4;
var y = x is int ? 0 : 1;
SDK 版本永不
#类型 'Never' 直到版本 2.12.0 才得到支持,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.12.0 的代码中找到对类 Never
的引用时,分析器会生成此诊断信息。此类在早期版本中未定义,因此此代码将无法针对早期版本的 SDK 运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.12.0)的 pubspec 示例。
environment:
sdk: '>=2.5.0 <2.6.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
Never n;
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该类型。
environment:
sdk: '>=2.12.0 <2.13.0'
如果您需要支持旧版本的 SDK,则重写代码以不引用此类。
dynamic x;
SDK 版本集合字面量
#集合字面量直到版本 2.2 才得到支持,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.2.0 的代码中找到集合字面量时,分析器会生成此诊断信息。集合字面量在早期版本中不受支持,因此此代码将无法针对早期版本的 SDK 运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.2.0)的 pubspec 示例。
environment:
sdk: '>=2.1.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
var s = <int>{};
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该语法。
environment:
sdk: '>=2.2.0 <2.4.0'
如果您确实需要支持旧版本的 SDK,则用不使用字面量创建集合的代码替换集合字面量。
var s = new Set<int>();
SDK 版本 UI 作为代码
#for、if 和展开元素直到版本 2.3.0 才得到支持,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.3.0 的代码中找到 for、if 或展开元素时,分析器会生成此诊断信息。在早期版本中,使用 for、if 或展开元素不受支持,因此此代码将无法针对早期版本的 SDK 运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.3.0)的 pubspec 示例。
environment:
sdk: '>=2.2.0 <2.4.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
var digits = [for (int i = 0; i < 10; i++) i];
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该语法。
environment:
sdk: '>=2.3.0 <2.4.0'
如果您需要支持旧版本的 SDK,则重写代码以不使用这些元素。
var digits = _initializeDigits();
List<int> _initializeDigits() {
var digits = <int>[];
for (int i = 0; i < 10; i++) {
digits.add(i);
}
return digits;
}
SDK 版本 UI 作为代码在常量上下文中的使用
#if 和展开元素直到版本 2.5.0 才在常量表达式中得到支持,但此代码需要能够在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.5.0 的代码中找到 常量上下文 中的 if 或展开元素时,分析器会生成此诊断信息。在早期版本中,在 常量上下文 中使用 if 或展开元素不受支持,因此此代码将无法针对早期版本的 SDK 运行。
示例
#以下是一个定义了 SDK 约束(下限小于 2.5.0)的 pubspec 示例。
environment:
sdk: '>=2.4.0 <2.6.0'
在具有该 pubspec 的包中,以下代码会生成此诊断信息。
const a = [1, 2];
const b = [...a];
常见修复方法
#如果您不需要支持旧版本的 SDK,则可以提高 SDK 约束以允许使用该语法。
environment:
sdk: '>=2.5.0 <2.6.0'
如果您需要支持旧版本的 SDK,则重写代码以不使用这些元素。
const a = [1, 2];
const b = [1, 2];
如果无法做到,则更改代码以使元素不在 常量上下文 中。
const a = [1, 2];
var b = [...a];
集合元素类型不可分配
#元素类型“{0}”无法分配给集合类型“{1}”。
描述
#当集合字面量中的元素类型无法分配给集合的元素类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为字符串字面量'0'
的类型为String
,而它无法分配给int
,即集合的元素类型。
var s = <int>{'0'};
常见修复方法
#如果集合字面量的元素类型错误,请更改集合的元素类型。
var s = <String>{'0'};
如果元素的类型错误,请更改元素。
var s = <int>{'0'.length};
共享延迟前缀
#延迟导入的前缀不能在其他导入指令中使用。
描述
#当延迟导入中的前缀也用作其他导入(无论是否延迟)中的前缀时,分析器会生成此诊断信息。延迟导入中的前缀不能与其他导入共享,因为该前缀用于加载导入的库。
示例
#以下代码会生成此诊断信息,因为前缀x
用作延迟导入的前缀,也用作另一个导入的前缀。
import 'dart:math' deferred as x;
import 'dart:convert' as x;
var y = x.json.encode(x.min(0, 1));
常见修复方法
#如果您可以为延迟导入使用不同的名称,请这样做。
import 'dart:math' deferred as math;
import 'dart:convert' as x;
var y = x.json.encode(math.min(0, 1));
如果您可以为其他导入使用不同的名称,请这样做。
import 'dart:math' deferred as x;
import 'dart:convert' as convert;
var y = convert.json.encode(x.min(0, 1));
大小注释维度
#“数组”必须具有与维度匹配的“数组”注释。
描述
#当Array
注释中指定的维度数量与字段类型指定的嵌套数组数量不匹配时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断信息,因为字段a0
的类型具有三个嵌套数组,但Array
注释中只给出了两个维度。
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8)
external Array<Array<Array<Uint8>>> a0;
}
常见修复方法
#如果字段的类型正确,请修复注释以包含所需的维度数量。
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8, 4)
external Array<Array<Array<Uint8>>> a0;
}
如果字段的类型错误,请修复字段的类型。
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8)
external Array<Array<Uint8>> a0;
}
对实例成员的静态访问
#无法使用静态访问方式访问实例成员“{0}”。
描述
#当使用类名访问实例字段时,分析器会生成此诊断信息。实例字段不存在于类上;它们只存在于类的实例上。
示例
#以下代码会生成此诊断信息,因为 x
是一个实例字段
class C {
static int a = 0;
int b = 0;
}
int f() => C.b;
常见修复方法
#如果您打算访问静态字段,请将字段名称更改为现有的静态字段
class C {
static int a = 0;
int b = 0;
}
int f() => C.a;
如果您打算访问实例字段,请使用类的实例来访问该字段
class C {
static int a = 0;
int b = 0;
}
int f(C c) => c.b;
基类或最终类的子类型不是基类、最终类或密封类
#mixin '{0}' 必须是 'base',因为超类型 '{1}' 是 'base'。
mixin '{0}' 必须是 'base',因为超类型 '{1}' 是 'final'。
类型 '{0}' 必须是 'base'、'final' 或 'sealed',因为超类型 '{1}' 是 'base'。
类型 '{0}' 必须是 'base'、'final' 或 'sealed',因为超类型 '{1}' 是 'final'。
描述
#当类或 mixin 具有直接或间接的超类型,该超类型是 base
或 final
,但类或 mixin 本身没有标记为 base
、final
或 sealed
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 B
是 A
的子类型,而 A
是一个 base
类,但 B
既不是 base
、final
也不 sealed
base class A {}
class B extends A {}
常见修复方法
#在类或 mixin 声明中添加 base
、final
或 sealed
base class A {}
final class B extends A {}
延迟类的子类型
#类和 mixin 不能实现延迟类。
类不能扩展延迟类。
类不能混合延迟类。
描述
#当类型(类或 mixin)是使用延迟导入导入的库中类的子类型时,分析器会生成此诊断信息。类型的超类型必须与类型同时编译,而延迟库中的类直到库加载后才会编译。
有关更多信息,请查看 延迟加载库。
示例
#给定一个定义类 A
的文件 a.dart
class A {}
以下代码会生成此诊断信息,因为 B
的超类是在延迟库中声明的
import 'a.dart' deferred as a;
class B extends a.A {}
常见修复方法
#如果您需要创建延迟库中类型的子类型,请删除 deferred
关键字
import 'a.dart' as a;
class B extends a.A {}
不允许类型的子类型
#'{0}' 不能用作超类约束。
类和 mixin 不能实现 '{0}'。
类不能扩展“{0}”。
类不能混合“{0}”。
描述
#当在 extends
、implements
、with
或 on
子句中使用受限类之一时,分析器会生成此诊断。类 bool
、double
、FutureOr
、int
、Null
、num
和 String
在这种情况下都是受限的,以允许更有效的实现。
示例
#以下代码会生成此诊断,因为 String
在 extends
子句中使用
class A extends String {}
以下代码会生成此诊断,因为 String
在 implements
子句中使用
class B implements String {}
以下代码会生成此诊断,因为 String
在 with
子句中使用
class C with String {}
以下代码会生成此诊断,因为 String
在 on
子句中使用
mixin M on String {}
常见修复方法
#如果应该指定不同的类型,则替换类型
class A extends Object {}
如果没有合适的不同类型,则删除该类型,并可能删除整个子句
class B {}
FFI 类的子类型
#类“{0}”不能扩展“{1}”。
类“{0}”不能实现“{1}”。
类“{0}”不能混合“{1}”。
描述
#当类扩展除 Struct
或 Union
之外的任何 FFI 类,或实现或混合任何 FFI 类时,分析器会生成此诊断。Struct
和 Union
是唯一可以进行子类型化的 FFI 类,并且只能通过扩展它们来进行子类型化。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会生成此诊断,因为类 C
扩展了 Double
import 'dart:ffi';
final class C extends Double {}
常见修复方法
#如果类应该扩展 Struct
或 Union
,则更改类的声明
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int i;
}
如果类不应该扩展 Struct
或 Union
,则删除对 FFI 类的任何引用
final class C {}
密封类的子类型
#类“{0}”不应该被扩展、混合或实现,因为它已密封。
描述
#当密封类(具有 sealed
注释或继承或混合密封类的类)在类或混合声明的 extends
、implements
或 with
子句中被引用时,分析器会生成此诊断,前提是该声明不在与密封类相同的包中。
示例
#假设在除正在分析的包之外的包中的库包含以下内容
import 'package:meta/meta.dart';
class A {}
@sealed
class B {}
以下代码会生成此诊断,因为 C
(不在与 B
相同的包中)正在扩展密封类 B
import 'package:a/a.dart';
class C extends B {}
常见修复方法
#如果类不需要是密封类的子类型,则更改声明,使其不再是子类型
import 'package:a/a.dart';
class B extends A {}
如果该类需要成为密封类的子类型,则要么更改密封类使其不再是密封类,要么将子类移到与密封类相同的包中。
结构类的子类型
#类 '{0}' 无法扩展 '{1}',因为 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子类型。
类 '{0}' 无法实现 '{1}',因为 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子类型。
类 '{0}' 无法混合 '{1}',因为 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子类型。
描述
#当一个类扩展、实现或混合一个扩展了 Struct
或 Union
的类时,分析器会产生此诊断信息。类只能直接扩展 Struct
或 Union
。
有关 FFI 的更多信息,请参阅 使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断信息,因为类 C
扩展了 S
,而 S
扩展了 Struct
import 'dart:ffi';
final class S extends Struct {
external Pointer f;
}
final class C extends S {
external Pointer g;
}
常见修复方法
#如果您试图定义一个结构体或联合体,它共享由另一个结构体或联合体声明的一些字段,那么直接扩展 Struct
或 Union
并复制共享字段。
import 'dart:ffi';
final class S extends Struct {
external Pointer f;
}
final class C extends Struct {
external Pointer f;
external Pointer g;
}
超类型扩展到类型参数
#扩展到类型参数的类型别名无法实现。
扩展到类型参数的类型别名无法混合。
扩展到类型参数的类型别名无法用作超类约束。
扩展到类型参数的类型别名无法用作超类。
描述
#当扩展到类型参数的类型别名在 extends
、implements
、with
或 on
子句中使用时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为类型别名 T
(扩展到类型参数 S
)在类 C
的 extends
子句中使用。
typedef T<S> = S;
class C extends T<Object> {}
常见修复方法
#直接使用类型参数的值。
typedef T<S> = S;
class C extends Object {}
超形式参数类型不是关联类型的子类型
#此参数的类型 '{0}' 不是关联的超构造函数参数的类型 '{1}' 的子类型。
描述
#当超参数的类型不是超构造函数中对应参数的子类型时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断是因为类 B
构造函数中超参数 x
的类型不是类 A
构造函数中参数 x
的子类型。
class A {
A(num x);
}
class B extends A {
B(String super.x);
}
常见修复方法
#如果超参数的类型可以与超构造函数中的参数相同,则从超参数中删除类型标注(如果类型是隐式的,则从超构造函数中的类型推断)。
class A {
A(num x);
}
class B extends A {
B(super.x);
}
如果超参数的类型可以是对应参数类型的子类型,则更改超参数的类型。
class A {
A(num x);
}
class B extends A {
B(int super.x);
}
如果超参数的类型无法更改,则使用普通参数而不是超参数。
class A {
A(num x);
}
class B extends A {
B(String x) : super(x.length);
}
没有关联命名参数的超形式参数
#没有关联的命名超构造函数参数。
描述
#当构造函数中存在命名超参数,并且隐式或显式调用的超构造函数没有相同名称的命名参数时,分析器会产生此诊断。
命名超参数通过名称与超构造函数中的命名参数关联。
示例
#以下代码产生此诊断是因为类 A
中的构造函数没有名为 y
的参数。
class A {
A({int? x});
}
class B extends A {
B({super.y});
}
常见修复方法
#如果超参数应该与超构造函数中的现有参数关联,则更改名称以匹配对应参数的名称。
class A {
A({int? x});
}
class B extends A {
B({super.x});
}
如果超参数应该与尚未添加到超构造函数中的参数关联,则添加它。
class A {
A({int? x, int? y});
}
class B extends A {
B({super.y});
}
如果超参数不对应于超构造函数中的命名参数,则将其更改为普通参数。
class A {
A({int? x});
}
class B extends A {
B({int? y});
}
没有关联位置参数的超形式参数
#没有关联的位置超构造函数参数。
描述
#当构造函数中存在位置超参数,并且隐式或显式调用的超构造函数在对应索引处没有位置参数时,分析器会产生此诊断。
位置超参数通过其索引与超构造函数中的位置参数关联。也就是说,第一个超参数与超构造函数中的第一个位置参数关联,第二个与第二个关联,依此类推。
示例
#以下代码产生此诊断是因为类 B
中的构造函数有一个位置超参数,但类 A
中的超构造函数没有位置参数。
class A {
A({int? x});
}
class B extends A {
B(super.x);
}
以下代码产生此诊断是因为类 B
中的构造函数有两个位置超参数,但类 A
中的超构造函数只有一个位置参数,这意味着没有与 y
对应的参数。
class A {
A(int x);
}
class B extends A {
B(super.x, super.y);
}
常见修复方法
#如果父类构造函数应该有一个与父类参数相对应的定位参数,则相应地更新父类构造函数。
class A {
A(int x, int y);
}
class B extends A {
B(super.x, super.y);
}
如果父类构造函数是正确的,或者无法更改,则将父类参数转换为普通参数。
class A {
A(int x);
}
class B extends A {
B(super.x, int y);
}
超调用不是最后一个
#invalid_super_invocation
)
父类构造函数调用必须是初始化列表中的最后一个:'{0}'。
描述
#当构造函数的初始化列表包含对父类中构造函数的调用,但调用不是初始化列表中的最后一项时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为对父类构造函数的调用不是初始化列表中的最后一项
class A {
A(int x);
}
class B extends A {
B(int x) : super(x), assert(x >= 0);
}
常见修复方法
#将对父类构造函数的调用移到初始化列表的末尾。
class A {
A(int x);
}
class B extends A {
B(int x) : assert(x >= 0), super(x);
}
枚举构造函数中的超
#枚举构造函数不能有 'super' 初始化器。
描述
#当枚举中构造函数的初始化列表包含对父类构造函数的调用时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为枚举 E
中的构造函数在初始化列表中有一个父类构造函数调用
enum E {
e;
const E() : super();
}
常见修复方法
#删除父类构造函数调用。
enum E {
e;
const E();
}
扩展中的超
#在扩展中不能使用 'super' 关键字,因为扩展没有父类。
描述
#当扩展中声明的成员使用 super
关键字时,分析器会生成此诊断。扩展不是类,没有父类,因此 super
关键字没有用处。
示例
#以下代码会生成此诊断,因为 super
不能在扩展中使用
extension E on Object {
String get displayString => super.toString();
}
常见修复方法
#删除 super
关键字。
extension E on Object {
String get displayString => toString();
}
扩展类型中的超
#在扩展类型中不能使用 'super' 关键字,因为扩展类型没有父类。
描述
#当在扩展类型的实例成员中使用 super
时,分析器会生成此诊断。扩展类型没有父类,因此没有可以调用的继承成员。
示例
#以下代码会生成此诊断,因为
extension type E(String s) {
void m() {
super.m();
}
}
常见修复方法
#替换或删除 super
调用。
extension type E(String s) {
void m() {
s.toLowerCase();
}
}
无效上下文中的超
#super
调用的无效上下文。
描述
#当在实例方法之外使用 super
关键字时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 super
在顶级函数中使用
void f() {
super.f();
}
常见修复方法
#重写代码以不使用super
。
重定向构造函数中的超
#重定向构造函数不能有“super”初始化器。
描述
#当重定向到另一个构造函数的构造函数也尝试调用超类中的构造函数时,分析器会生成此诊断信息。当调用重定向构造函数重定向到的构造函数时,将调用超类构造函数。
示例
#以下代码会生成此诊断信息,因为构造函数C.a
既重定向到C.b
,又调用了超类中的构造函数
class C {
C.a() : this.b(), super();
C.b();
}
常见修复方法
#删除对super
构造函数的调用
class C {
C.a() : this.b();
C.b();
}
switch case 正常完成
#“case”不应该正常完成。
描述
#当switch
语句中case
标签后的语句可能落入下一个case
或default
标签时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为值为零(0
)的case
标签会落入default
语句
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
)的类型
void f(String s) {
switch (s) {
case 0:
break;
}
}
常见修复方法
#如果case
表达式的类型正确,则更改switch
语句中的表达式以具有正确的类型
void f(String s) {
switch (int.parse(s)) {
case 0:
break;
}
}
如果switch
表达式的类型正确,则更改case
表达式以具有正确的类型
void f(String s) {
switch (s) {
case '0':
break;
}
}
抽象类的生成式构造函数的撕裂
#抽象类的生成构造函数不能被撕裂。
描述
#当抽象类中的生成构造函数被撕裂时,分析器会生成此诊断信息。这是不允许的,因为创建抽象类的实例是无效的,这意味着撕裂的构造函数没有有效的用途。
示例
#以下代码会生成此诊断信息,因为构造函数C.new
被撕裂,而类C
是抽象类
abstract class C {
C();
}
void f() {
C.new;
}
常见修复方法
#撕裂具体类的构造函数。
注释中的文本方向代码点
#Unicode 代码点 'U+{0}' 会改变文本的显示方式,与编译器对其的解释方式不同。
描述
#当分析器遇到包含文本方向 Unicode 代码点的源代码时,会产生此诊断信息。这些代码点会导致字符串文字或注释中的源代码的解释和编译方式与在编辑器中的显示方式不同,从而可能导致安全漏洞。
示例
#以下代码会产生两次此诊断信息,因为标签字符串的开头和结尾处有隐藏字符
var label = 'Interactive text';
常见修复方法
#如果代码点打算包含在字符串文字中,则对其进行转义
var label = '\u202AInteractive text\u202C';
如果代码点不打算包含在字符串文字中,则将其删除
var label = 'Interactive text';
字面量中的文本方向代码点
#Unicode 代码点 'U+{0}' 会改变文本的显示方式,与编译器对其的解释方式不同。
描述
#当分析器遇到包含文本方向 Unicode 代码点的源代码时,会产生此诊断信息。这些代码点会导致字符串文字或注释中的源代码的解释和编译方式与在编辑器中的显示方式不同,从而可能导致安全漏洞。
示例
#以下代码会产生两次此诊断信息,因为标签字符串的开头和结尾处有隐藏字符
var label = 'Interactive text';
常见修复方法
#如果代码点打算包含在字符串文字中,则对其进行转义
var label = '\u202AInteractive text\u202C';
如果代码点不打算包含在字符串文字中,则将其删除
var label = 'Interactive text';
抛出无效类型
#抛出表达式的类型 '{0}' 必须可分配给 'Object'。
描述
#当抛出表达式中的表达式的类型不可分配给 Object
时,分析器会产生此诊断信息。抛出 null
是无效的,因此使用可能计算为 null
的表达式也是无效的。
示例
#以下代码会产生此诊断信息,因为 s
可能为 null
void f(String? s) {
throw s;
}
常见修复方法
#向表达式添加显式空检查
void f(String? s) {
throw s!;
}
顶层循环
#无法推断 '{0}' 的类型,因为它通过循环依赖于自身:{1}。
描述
#当顶层变量没有类型注释,并且变量的初始化程序直接或间接引用该变量时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为变量 x
和 y
是相互定义的,并且都没有显式类型,因此无法推断另一个变量的类型
var x = y;
var y = x;
常见修复方法
#如果这两个变量不需要相互引用,则打破循环
var x = 0;
var y = x;
如果这两个变量需要相互引用,则至少为其中一个变量提供显式类型
int x = y;
var y = x;
但是请注意,虽然此代码不会产生任何诊断信息,但如果在循环中的任何变量被引用之前,至少有一个变量被分配了一个不依赖于其他变量的值,则它会在运行时产生堆栈溢出。
类型别名不能引用自身
#类型定义不能直接或通过另一个类型定义递归地引用自身。
描述
#当类型定义直接或间接引用自身时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 F
通过 G
间接依赖于自身
typedef F = void Function(G);
typedef G = void Function(F);
常见修复方法
#更改循环中的一个或多个类型定义,使它们不再相互引用。
typedef F = void Function(G);
typedef G = void Function(int);
类型注释延迟类
#延迟类型 '{0}' 不能在声明、强制转换或类型测试中使用。
描述
#当类型注释在变量声明中,或者在强制转换 (as
) 或类型测试 (is
) 中使用的类型是在使用延迟导入导入的库中声明的类型时,分析器会生成此诊断信息。这些类型需要在编译时可用,但实际上不可用。
有关更多信息,请查看 延迟加载库。
示例
#以下代码会生成此诊断信息,因为参数 f
的类型是从延迟库中导入的。
import 'dart:io' deferred as io;
void f(io.File f) {}
常见修复方法
#如果需要引用导入的类型,请删除 deferred
关键字。
import 'dart:io' as io;
void f(io.File f) {}
如果导入必须延迟,并且存在其他合适的类型,请使用该类型代替延迟库中的类型。
类型参数不匹配边界
#'{0}' 不符合类型参数 '{1}' 的边界 '{2}'。
描述
#当类型参数与相应类型参数的边界不相同或不是其子类时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 String
不是 num
的子类。
class A<E extends num> {}
var a = A<String>();
常见修复方法
#将类型参数更改为边界的子类。
class A<E extends num> {}
var a = A<int>();
使用 null 进行类型检查
#对非空值的测试应使用 '!= null' 进行。
对空值的测试应使用 '== null' 进行。
描述
#当存在类型检查(使用 as
运算符)且类型为 Null
时,分析器会生成此诊断信息。只有一个值的类型为 Null
,因此当代码显式测试 null
时,代码更易读且性能更高。
示例
#以下代码会生成此诊断信息,因为代码正在使用类型检查来测试 s
的值是否为 null
。
void f(String? s) {
if (s is Null) {
return;
}
print(s);
}
以下代码会生成此诊断信息,因为代码正在使用类型检查来测试 s
的值是否不为 null
。
void f(String? s) {
if (s is! Null) {
print(s);
}
}
常见修复方法
#将类型检查替换为与 null
的等效比较。
void f(String? s) {
if (s == null) {
return;
}
print(s);
}
类型参数被静态引用
#静态成员不能引用类的类型参数。
描述
#当静态成员引用为类声明的类型参数时,分析器会生成此诊断信息。类型参数仅对类的实例有意义。
示例
#以下代码会产生此诊断,因为静态方法hasType
引用了类型参数T
class C<T> {
static bool hasType(Object o) => o is T;
}
常见修复方法
#如果成员可以是实例成员,则删除关键字static
class C<T> {
bool hasType(Object o) => o is T;
}
如果成员必须是静态成员,则将成员设为泛型
class C<T> {
static bool hasType<S>(Object o) => o is S;
}
但是,请注意,T
和S
之间没有关系,因此第二个选项会改变语义,这可能与预期不符。
类型参数是其边界的超类型
#'{0}'不能是其上界的超类型。
描述
#当类型参数的边界(extends
关键字后的类型)直接或间接地是类型参数本身时,分析器会产生此诊断。声明类型参数必须与其自身相同或与其自身或其自身子类型相同,这是没有帮助的,因为它始终与其自身相同。
示例
#以下代码会产生此诊断,因为T
的边界是T
class C<T extends T> {}
以下代码会产生此诊断,因为T1
的边界是T2
,而T2
的边界是T1
,实际上使T1
的边界为T1
class C<T1 extends T2, T2 extends T1> {}
常见修复方法
#如果类型参数需要是某个类型的子类,则用所需类型替换边界
class C<T extends num> {}
如果类型参数可以是任何类型,则删除extends
子句
class C<T> {}
使用非类型进行类型测试
#名称'{0}'不是类型,不能在'is'表达式中使用。
描述
#当is
或is!
测试的右侧不是类型时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为右侧是参数,而不是类型
typedef B = int Function(int);
void f(Object a, B b) {
if (a is b) {
return;
}
}
常见修复方法
#如果您打算使用类型测试,则用类型替换右侧
typedef B = int Function(int);
void f(Object a, B b) {
if (a is B) {
return;
}
}
如果您打算使用其他类型的测试,则更改测试
typedef B = int Function(int);
void f(Object a, B b) {
if (a == b) {
return;
}
}
使用未定义名称进行类型测试
#名称'{0}'未定义,因此不能在'is'表达式中使用。
描述
#当类型测试表达式中is
后的名称未定义时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为名称Srting
未定义
void f(Object o) {
if (o is Srting) {
// ...
}
}
常见修复方法
#将名称替换为类型的名称
void f(Object o) {
if (o is String) {
// ...
}
}
对可空值的未经检查的使用
#可空表达式不能用作条件。
可空表达式不能用作 for-in 循环中的迭代器。
不可在展开运算符中使用可空表达式。
不可在 yield-each 语句中使用可空表达式。
无法无条件调用该函数,因为它可能为“null”。
无法无条件调用方法“{0}”,因为接收者可能为“null”。
无法无条件调用运算符“{0}”,因为接收者可能为“null”。
无法无条件访问属性“{0}”,因为接收者可能为“null”。
描述
#当对类型为 可能非空 的表达式的解引用,而没有先验证其值是否为 null
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 s
在引用时可能为 null
void f(String? s) {
if (s.length > 3) {
// ...
}
}
常见修复方法
#如果该值确实可能为 null
,则添加一个测试以确保仅在该值不为 null
时才访问成员。
void f(String? s) {
if (s != null && s.length > 3) {
// ...
}
}
如果该表达式是一个变量,并且该值永远不会为 null
,则将该变量的类型更改为非空类型。
void f(String s) {
if (s.length > 3) {
// ...
}
}
如果您认为该表达式的值永远不会为 null
,但您无法更改该变量的类型,并且您愿意冒在运行时抛出异常的风险(如果您错了),那么您可以断言该值不为 null。
void f(String? s) {
if (s!.length > 3) {
// ...
}
}
未定义注释
#未定义的名称“{0}”用作注释。
描述
#当使用未定义的名称作为注释时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为名称 undefined
未定义。
@undefined
void f() {}
常见修复方法
#如果名称正确,但尚未声明,则将该名称声明为常量值。
const undefined = 'undefined';
@undefined
void f() {}
如果名称错误,则将该名称替换为有效常量的名称。
@deprecated
void f() {}
否则,删除注释。
未定义类
#未定义的类“{0}”。
描述
#当分析器遇到一个似乎是类名的标识符,但该标识符要么未定义,要么在引用它的作用域中不可见时,会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 Piont
未定义。
class Point {}
void f(Piont p) {}
常见修复方法
#如果该标识符未定义,则要么定义它,要么将其替换为已定义的类的名称。上面的示例可以通过修正类的拼写来纠正。
class Point {}
void f(Point p) {}
如果类已定义但不可见,则可能需要添加导入。
初始化程序中未定义的构造函数
#类 '{0}' 没有名为 '{1}' 的构造函数。
类“{0}”没有无名构造函数。
描述
#当在构造函数的初始化列表中调用超类构造函数,但超类未定义正在调用的构造函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 A
没有无名构造函数
class A {
A.n();
}
class B extends A {
B() : super();
}
以下代码会生成此诊断,因为 A
没有名为 m
的构造函数
class A {
A.n();
}
class B extends A {
B() : super.m();
}
常见修复方法
#如果超类定义了应该调用的构造函数,则更改正在调用的构造函数
class A {
A.n();
}
class B extends A {
B() : super.n();
}
如果超类未定义适当的构造函数,则定义正在调用的构造函数
class A {
A.m();
A.n();
}
class B extends A {
B() : super.m();
}
未定义的枚举常量
#'{1}' 中没有名为 '{0}' 的常量。
描述
#当分析器遇到一个似乎是枚举值名称的标识符时,它会生成此诊断,并且该名称未定义或在引用它的作用域中不可见。
示例
#以下代码会生成此诊断,因为 E
未定义名为 c
的常量
enum E {a, b}
var e = E.c;
常见修复方法
#如果应定义常量,则将其添加到枚举的声明中
enum E {a, b, c}
var e = E.c;
如果不需要定义常量,则将名称更改为现有常量的名称
enum E {a, b}
var e = E.b;
未定义的枚举构造函数
#枚举没有名为 '{0}' 的构造函数。
枚举没有无名构造函数。
描述
#当用于初始化枚举值的构造函数不存在时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为枚举值 c
由无名构造函数初始化,但 E
中没有定义无名构造函数
enum E {
c();
const E.x();
}
以下代码会生成此诊断,因为枚举值 c
由名为 x
的构造函数初始化,但 E
中没有定义名为 x
的构造函数
enum E {
c.x();
const E.y();
}
常见修复方法
#如果枚举值由无名构造函数初始化,并且应该使用其中一个命名构造函数,则添加构造函数的名称
enum E {
c.x();
const E.x();
}
如果枚举值由无名构造函数初始化,并且没有一个命名构造函数是合适的,则定义无名构造函数
enum E {
c();
const E();
}
如果枚举值由命名构造函数初始化,并且应该使用其中一个现有构造函数,则更改正在调用的构造函数的名称(或如果应使用无名构造函数,则将其删除)
enum E {
c.y();
const E();
const E.y();
}
如果枚举值由命名构造函数初始化,并且没有一个现有构造函数是合适的,则定义一个具有所用名称的构造函数
enum E {
c.x();
const E.x();
}
未定义的扩展获取器
#扩展 '{1}' 未定义 getter '{0}'。
描述
#当使用扩展覆盖来调用 getter 时,分析器会生成此诊断,但 getter 未由指定的扩展定义。当引用静态 getter 但未由指定的扩展定义时,分析器也会生成此诊断。
示例
#以下代码产生此诊断信息,因为扩展 E
没有声明名为 b
的实例 getter。
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
E('c').b;
}
以下代码产生此诊断信息,因为扩展 E
没有声明名为 a
的静态 getter。
extension E on String {}
var x = E.a;
常见修复方法
#如果 getter 的名称不正确,则将其更改为现有 getter 的名称。
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
E('c').a;
}
如果 getter 的名称正确,但扩展的名称错误,则将扩展的名称更改为正确的名称。
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
F('c').b;
}
如果 getter 和扩展的名称都正确,但 getter 未定义,则定义 getter。
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;
}
未定义的扩展方法
#方法 '{0}' 在扩展 '{1}' 中未定义。
描述
#当使用扩展重写调用方法,但方法未由指定的扩展定义时,分析器会产生此诊断信息。当引用静态方法但未由指定的扩展定义时,分析器也会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为扩展 E
没有声明名为 b
的实例方法。
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').b();
}
以下代码产生此诊断信息,因为扩展 E
没有声明名为 a
的静态方法。
extension E on String {}
var x = E.a();
常见修复方法
#如果方法的名称不正确,则将其更改为现有方法的名称。
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').a();
}
如果方法的名称正确,但扩展的名称错误,则将扩展的名称更改为正确的名称。
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
F('c').b();
}
如果方法和扩展的名称都正确,但方法未定义,则定义方法。
extension E on String {
String a() => 'a';
String b() => 'z';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').b();
}
未定义的扩展运算符
#运算符 '{0}' 在扩展 '{1}' 中未定义。
描述
#当在特定扩展上调用运算符,而该扩展未实现该运算符时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为扩展 E
未定义运算符 *
。
var x = E('') * 4;
extension E on String {}
常见修复方法
#如果预期扩展实现运算符,则向扩展添加运算符的实现。
var x = E('') * 4;
extension E on String {
int operator *(int multiplier) => length * multiplier;
}
如果运算符由不同的扩展定义,则将扩展的名称更改为定义运算符的扩展的名称。
如果运算符在扩展重写的参数上定义,则删除扩展重写。
var x = '' * 4;
extension E on String {}
未定义的扩展设置器
#setter '{0}' 在扩展 '{1}' 中未定义。
描述
#当使用扩展覆盖调用 setter 时,但 setter 未由指定的扩展定义,分析器会生成此诊断信息。当引用静态 setter 但未由指定的扩展定义时,分析器也会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展 E
未声明名为 b
的实例 setter
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
extension E on String {}
void f() {
E.a = 3;
}
常见修复方法
#如果 setter 的名称不正确,请将其更改为现有 setter 的名称
extension E on String {
set a(String v) {}
}
extension F on String {
set b(String v) {}
}
void f() {
E('c').a = 'd';
}
如果 setter 的名称正确,但扩展的名称错误,请将扩展的名称更改为正确的名称
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
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
未定义
List<int> empty() => [];
void main() {
print(emty());
}
常见修复方法
#如果标识符未定义,请定义它或将其替换为已定义的函数的名称。上面的示例可以通过修正函数的拼写来纠正
List<int> empty() => [];
void main() {
print(empty());
}
如果函数已定义但不可见,则可能需要添加导入或重新排列代码以使函数可见。
未定义获取器
#getter '{0}' 未为 '{1}' 函数类型定义。
getter '{0}' 未为类型 '{1}' 定义。
描述
#当分析器遇到一个看起来像 getter 名称的标识符,但该标识符要么未定义,要么在引用它的作用域中不可见时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 String
没有名为 len
的成员
int f(String s) => s.len;
常见修复方法
#如果标识符未定义,则定义它或将其替换为已定义的 getter 的名称。上面的示例可以通过修正 getter 的拼写来纠正。
int f(String s) => s.length;
未定义的隐藏名称
#库 '{0}' 没有导出具有隐藏名称 '{1}' 的成员。
描述
#当 hide 组合器包含导入库未定义的名称时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 dart:math
未定义名称 String
import 'dart:math' hide String, max;
var x = min(0, 1);
常见修复方法
#如果应隐藏其他名称,请更正名称。否则,从列表中删除名称。
import 'dart:math' hide max;
var x = min(0, 1);
未定义标识符
#未定义名称 '{0}'。
描述
#当分析器遇到未定义或在其引用范围中不可见的标识符时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为名称 rihgt
未定义
int min(int left, int right) => left <= rihgt ? left : right;
常见修复方法
#如果标识符未定义,则定义它或将其替换为已定义的标识符。上面的示例可以通过修正变量的拼写来纠正。
int min(int left, int right) => left <= right ? left : right;
如果标识符已定义但不可见,则可能需要添加导入或重新排列代码以使标识符可见。
未定义标识符 await
#未定义名称 'await',函数体未标记为 'async'。
描述
#当名称 await
在未声明的方法或函数体中使用,并且该体未标记为 async
关键字时,分析器会生成此诊断信息。名称 await
仅在异步函数中引入 await 表达式。
示例
#以下代码会生成此诊断信息,因为名称 await
在 f
的主体中使用,即使 f
的主体未标记为 async
关键字。
void f(p) { await p; }
常见修复方法
#在函数体中添加关键字 async
。
void f(p) async { await p; }
未定义方法
#方法 '{0}' 未为 '{1}' 函数类型定义。
方法 '{0}' 未为类型 '{1}' 定义。
描述
#当分析器遇到似乎是方法名称但未定义或在其引用范围中不可见的标识符时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为标识符 removeMiddle
未定义
int f(List<int> l) => l.removeMiddle();
常见修复方法
#如果标识符未定义,则定义它或将其替换为已定义的方法的名称。上面的示例可以通过修正方法的拼写来纠正。
int f(List<int> l) => l.removeLast();
未定义的命名参数
#命名参数 '{0}' 未定义。
描述
#当方法或函数调用具有命名参数,但调用的方法或函数未定义具有相同名称的参数时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为m
没有声明名为a
的命名参数。
class C {
m({int? b}) {}
}
void f(C c) {
c.m(a: 1);
}
常见修复方法
#如果参数名称拼写错误,请将其替换为正确的名称。上面的示例可以通过将a
更改为b
来修复。
class C {
m({int? b}) {}
}
void f(C c) {
c.m(b: 1);
}
如果子类添加了具有该名称的参数,则将接收者强制转换为子类。
class C {
m({int? b}) {}
}
class D extends C {
m({int? a, int? b}) {}
}
void f(C c) {
(c as D).m(a: 1);
}
如果应将参数添加到函数中,则添加它。
class C {
m({int? a, int? b}) {}
}
void f(C c) {
c.m(a: 1);
}
未定义运算符
#运算符 '{0}' 未为类型 '{1}' 定义。
描述
#当用户定义的运算符在未定义该运算符的对象上调用时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为类C
没有定义运算符+
。
class C {}
C f(C c) => c + 2;
常见修复方法
#如果应为该类定义运算符,则定义它。
class C {
C operator +(int i) => this;
}
C f(C c) => c + 2;
未定义的前缀名称
#名称 '{0}' 正在通过前缀 '{1}' 引用,但它未在使用该前缀导入的任何库中定义。
描述
#当在有效前缀但标识符未在使用该前缀导入的任何库中声明的位置找到带前缀的标识符时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为dart:core
没有定义名为a
的任何内容。
import 'dart:core' as p;
void f() {
p.a;
}
常见修复方法
#如果尚未导入声明名称的库,请添加该库的导入。
如果名称错误,请将其更改为导入库中声明的名称之一。
未定义的引用参数
#参数 '{0}' 未由 '{1}' 定义。
描述
#当形式为 UseResult.unless(parameterDefined: parameterName)
的注释指定未由带注释函数定义的参数名称时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为函数f
没有名为b
的参数。
import 'package:meta/meta.dart';
@UseResult.unless(parameterDefined: 'b')
int f([int? a]) => a ?? 0;
常见修复方法
#将名为parameterDefined
的参数更改为与函数参数之一的名称匹配。
import 'package:meta/meta.dart';
@UseResult.unless(parameterDefined: 'a')
int f([int? a]) => a ?? 0;
未定义设置器
#设置器 '{0}' 未为 '{1}' 函数类型定义。
设置器 '{0}' 未为类型 '{1}' 定义。
描述
#当分析器遇到一个看起来像是 setter 名称的标识符,但该标识符要么未定义,要么在引用标识符的作用域中不可见时,它会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为没有名为 z
的 setter
class C {
int x = 0;
void m(int y) {
this.z = y;
}
}
常见修复方法
#如果标识符未定义,则要么定义它,要么用已定义的 setter 的名称替换它。上面的示例可以通过修正 setter 的拼写来纠正
class C {
int x = 0;
void m(int y) {
this.x = y;
}
}
未定义的显示名称
#库 '{0}' 没有导出具有显示名称 '{1}' 的成员。
描述
#当 show 组合器包含一个未被导入库定义的名称时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 dart:math
未定义名称 String
import 'dart:math' show min, String;
var x = min(0, 1);
常见修复方法
#如果应该显示不同的名称,则更正名称。否则,从列表中删除该名称
import 'dart:math' show min;
var x = min(0, 1);
未定义的超成员
#undefined_super_method
)
getter '{0}' 在 '{1}' 的超类中未定义。
方法 '{0}' 在 '{1}' 的超类中未定义。
运算符 '{0}' 在 '{1}' 的超类中未定义。
setter '{0}' 在 '{1}' 的超类中未定义。
描述
#当使用 super
引用继承的成员(方法、getter、setter 或运算符)时,但超类链中没有该名称的成员时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 Object
未定义名为 n
的方法
class C {
void m() {
super.n();
}
}
以下代码会生成此诊断信息,因为 Object
未定义名为 g
的 getter
class C {
void m() {
super.g;
}
}
常见修复方法
#如果要调用的继承成员具有不同的名称,则使调用的成员名称与继承的成员名称匹配。
如果要调用的成员在同一个类中定义,则删除 super.
。
如果成员未定义,则要么将成员添加到其中一个超类中,要么删除调用。
未知平台
#平台 '{0}' 不是一个已知的平台。
描述
#当在 platforms
映射中使用未知平台名称作为键时,分析器会生成此诊断信息。要了解有关指定包支持的平台的更多信息,请查看 平台声明文档。
示例
#以下 pubspec.yaml
会生成此诊断信息,因为平台 browser
未知。
name: example
platforms:
browser:
常见修复方法
#如果可以依赖自动平台检测,则省略顶层的 platforms
键。
name: example
如果需要手动指定支持的平台列表,则将 platforms
字段写为一个映射,其中已知平台名称作为键。
name: example
platforms:
# These are the known platforms
android:
ios:
linux:
macos:
web:
windows:
不必要的强制转换
#不必要的强制转换。
描述
#当强制转换的值已知为它正在强制转换到的类型时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 n
由于 is
测试,已知是 int
void f(num n) {
if (n is int) {
(n as int).isEven;
}
}
常见修复方法
#删除不必要的强制转换。
void f(num n) {
if (n is int) {
n.isEven;
}
}
不必要的开发依赖项
#由于该包也存在普通依赖项,因此对 {0} 的开发依赖项是不必要的。
描述
#当在 dev_dependencies
下存在一个也在 dependencies
下列出的包时,分析器会生成此诊断信息。dependencies
下的包对包中的所有代码都可用,因此无需在 dev_dependencies
下也列出它们。
示例
#以下代码会生成此诊断信息,因为包 meta
在 dependencies
和 dev_dependencies
下都列出。
name: example
dependencies:
meta: ^1.0.2
dev_dependencies:
meta: ^1.0.2
常见修复方法
#删除 dev_dependencies
下的条目(如果该条目是唯一列出的包,则删除 dev_dependencies
键)。
name: example
dependencies:
meta: ^1.0.2
不必要的 final
#关键字 'final' 不必要,因为参数隐式为 'final'。
描述
#当构造函数中的字段初始化参数或超参数具有关键字 final
时,分析器会生成此诊断信息。在这两种情况下,关键字都是不必要的,因为参数隐式为 final
。
示例
#以下代码会生成此诊断信息,因为字段初始化参数具有关键字 final
。
class A {
int value;
A(final this.value);
}
以下代码会生成此诊断信息,因为 B
中的超参数具有关键字 final
。
class A {
A(int value);
}
class B extends A {
B(final super.value);
}
常见修复方法
#删除不必要的 final
关键字。
class A {
A(int value);
}
class B extends A {
B(super.value);
}
不必要的导入
#导入 '{0}' 是不必要的,因为所有使用的元素也由导入 '{1}' 提供。
描述
#当导入不必要时,分析器会生成此诊断信息,因为在导入库中导入和引用的所有名称也通过另一个导入可见。
示例
#给定一个包含以下内容的文件a.dart
class A {}
并且,给定一个包含以下内容的 b.dart
文件
export 'a.dart';
class B {}
以下代码会生成此诊断信息,因为从 a.dart
导入的类 A
也从 b.dart
导入。删除 a.dart
的导入不会改变语义。
import 'a.dart';
import 'b.dart';
void f(A a, B b) {}
常见修复方法
#如果导入不需要,则将其删除。
如果此导入导入的一些名称旨在使用但尚未使用,并且这些名称未被其他导入导入,则添加对这些名称的缺失引用。
不必要的 NaN 比较
#双精度浮点数不能等于 'double.nan',因此条件始终为 'false'。
双精度浮点数不能等于 'double.nan',因此条件始终为 'true'。
描述
#当使用 ==
或 !=
将值与 double.nan
进行比较时,分析器会生成此诊断信息。
Dart 遵循 IEEE 754 浮点标准来定义浮点运算的语义,该标准指出,对于任何浮点值 x
(包括 NaN、正无穷大和负无穷大),
NaN == x
始终为 falseNaN != x
始终为 true
因此,将任何值与 NaN 进行比较毫无意义,因为结果已经确定(基于所使用的比较运算符)。
示例
#以下代码会生成此诊断信息,因为 d
与 double.nan
进行比较
bool isNaN(double d) => d == double.nan;
常见修复方法
#请改用 getter double.isNaN
bool isNaN(double d) => d.isNaN;
不必要的非空断言
#'!' 将不起作用,因为接收方不能为 null。
描述
#当 !
运算符的操作数不能为 null
时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为x
不能为null
int f(int x) {
return x!;
}
常见修复方法
#删除空检查运算符 (!
)
int f(int x) {
return x;
}
不必要的 NoSuchMethod 错误
#不必要的 'noSuchMethod' 声明。
描述
#当存在 noSuchMethod
的声明,该声明只调用重写声明,并且重写声明不是 Object
中的声明时,分析器会生成此诊断信息。
重写 Object
的 noSuchMethod
的实现(无论实现是什么)都会向分析器发出信号,表明它不应该标记该类中未实现的任何继承的抽象方法。即使重写实现是从超类继承的,这也适用,因此在子类中再次声明它没有意义。
示例
#以下代码会生成此诊断信息,因为 A
中的 noSuchMethod
声明使得 B
中的 noSuchMethod
声明变得不必要
class A {
@override
dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {
@override
dynamic noSuchMethod(y) {
return super.noSuchMethod(y);
}
}
常见修复方法
#删除不必要的声明
class A {
@override
dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {}
不必要的空断言模式
#空断言模式将不起作用,因为匹配的类型不可为空。
描述
#当使用空断言模式匹配不可为空的值时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断是因为变量x
不可为空。
void f(int x) {
if (x case var a! when a > 0) {}
}
常见修复方法
#删除空断言模式。
void f(int x) {
if (x case var a when a > 0) {}
}
不必要的空检查模式
#空检查模式将无效,因为匹配的类型不可为空。
描述
#当使用空检查模式匹配不可为空的值时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为值x
不可为空。
void f(int x) {
if (x case var a? when a > 0) {}
}
常见修复方法
#删除空检查模式。
void f(int x) {
if (x case var a when a > 0) {}
}
不必要的空比较
#操作数不能为 null,因此条件始终为“false”。
操作数不能为 null,因此条件始终为“true”。
描述
#当分析器发现一个操作数为null
,而另一个操作数不能为null
的相等比较(==
或!=
)时,会产生此诊断。此类比较始终为true
或false
,因此毫无意义。
示例
#以下代码产生此诊断是因为x
永远不会为null
,因此比较始终评估为true
。
void f(int x) {
if (x != null) {
print(x);
}
}
以下代码产生此诊断是因为x
永远不会为null
,因此比较始终评估为false
。
void f(int x) {
if (x == null) {
throw ArgumentError("x can't be null");
}
}
常见修复方法
#如果另一个操作数应该可以为null
,则更改操作数的类型。
void f(int? x) {
if (x != null) {
print(x);
}
}
如果另一个操作数确实不能为null
,则删除条件。
void f(int x) {
print(x);
}
不必要的问号
#“?”是多余的,因为“{0}”本身就是可空的。
描述
#当类型dynamic
或类型Null
后面跟着问号时,分析器会产生此诊断。这两种类型本身都是可空的,因此问号不会改变语义。
示例
#以下代码产生此诊断是因为dynamic
后面的问号是多余的。
dynamic? x;
常见修复方法
#删除多余的问号。
dynamic x;
不必要的集合字面量
#大括号不必要地将此表达式包装在集合文字中。
描述
#当一个返回值类型为 void
、Future<void>
或 FutureOr<void>
的函数使用表达式函数体 (=>
) 并且返回值是一个包含单个元素的字面量集合时,分析器会生成此诊断信息。
虽然语言允许这样做,但从 void
函数返回值并没有用,因为它不能在调用点使用。在这种特殊情况下,返回值通常是由于对语法的误解造成的。花括号不是必需的,可以删除。
示例
#以下代码会生成此诊断信息,因为传递给 g
的闭包的返回值类型为 void
,但它返回了一个集合
void f() {
g(() => {1});
}
void g(void Function() p) {}
常见修复方法
#从值周围删除花括号
void f() {
g(() => 1);
}
void g(void Function() p) {}
不必要的类型检查
#不必要的类型检查;结果始终为“false”。
不必要的类型检查;结果始终为“true”。
描述
#当类型检查(使用 is
或 is!
)的值在编译时已知时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为测试 a is Object?
始终为 true
bool f<T>(T a) => a is Object?;
常见修复方法
#如果类型检查没有检查您想要检查的内容,则更改测试
bool f<T>(T a) => a is Object;
如果类型检查确实检查了您想要检查的内容,则用其已知值替换类型检查或完全删除它
bool f<T>(T a) => true;
对非本地静态成员的非限定引用
#来自超类型的静态成员必须由定义类型的名称限定。
描述
#当一个类中的代码引用超类中的静态成员,而没有在成员名称前加上超类的名称时,分析器会生成此诊断信息。静态成员只能在声明它们的类中不带前缀地引用。
示例
#以下代码会生成此诊断信息,因为静态字段 x
在 getter g
中被引用,而没有在它前面加上定义类的名称
class A {
static int x = 3;
}
class B extends A {
int get g => x;
}
常见修复方法
#在静态成员名称前加上声明类的名称
class A {
static int x = 3;
}
class B extends A {
int get g => A.x;
}
对扩展类型静态成员的非限定引用
#来自扩展类型或其超类型之一的静态成员必须由定义类型的名称限定。
描述
#当找到一个未定义的名称,并且该名称与扩展类型或其超类型之一的静态成员相同,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 m
是扩展类型 C
的静态成员
class C {
static void m() {}
}
extension E on C {
void f() {
m();
}
}
常见修复方法
#如果您尝试引用在扩展之外声明的静态成员,则在对成员的引用之前添加类或扩展的名称
class C {
static void m() {}
}
extension E on C {
void f() {
C.m();
}
}
如果您引用了尚未声明的成员,则添加声明
class C {
static void m() {}
}
extension E on C {
void f() {
m();
}
void m() {}
}
无法到达的 switch case
#此案例已被先前案例涵盖。
描述
#当 switch
语句中的 case
子句与任何内容都不匹配时,分析器会生成此诊断信息,因为所有可匹配的值都已在之前的 case
子句中匹配。
示例
#以下代码会生成此诊断信息,因为值 1
在前面的案例中已匹配
void f(int x) {
switch (x) {
case 1:
print('one');
case 1:
print('two');
}
}
常见修复方法
#更改一个或两个冲突的案例以匹配不同的值
void f(int x) {
switch (x) {
case 1:
print('one');
case 2:
print('two');
}
}
未使用的 catch 子句
#异常变量 '{0}' 未使用,因此可以删除 'catch' 子句。
描述
#当找到 catch
子句且 catch
块中未使用异常参数或可选堆栈跟踪参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 e
未被引用
void f() {
try {
int.parse(';');
} on FormatException catch (e) {
// ignored
}
}
常见修复方法
#删除未使用的 catch
子句
void f() {
try {
int.parse(';');
} on FormatException {
// ignored
}
}
未使用的 catch 栈
#堆栈跟踪变量 '{0}' 未使用,可以删除。
描述
#当 catch
子句中的堆栈跟踪参数在 catch
块的主体中未被引用时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 stackTrace
未被引用
void f() {
try {
// ...
} catch (exception, stackTrace) {
// ...
}
}
常见修复方法
#如果需要引用堆栈跟踪参数,请添加对它的引用。否则,请将其删除
void f() {
try {
// ...
} catch (exception) {
// ...
}
}
未使用的元素
#可选参数 '{0}' 的值从未给出。
声明 '{0}' 未被引用。
描述
#当私有声明在包含该声明的库中未被引用时,分析器会生成此诊断信息。以下类型的声明将被分析
- 私有顶层声明及其所有成员
- 公共声明的私有成员
- 从未传递值的私有函数的可选参数
并非对元素的所有引用都会将其标记为“已使用”。
- 将值分配给顶层变量(使用标准
=
赋值或空感知??=
赋值)不计为使用它。 - 在文档注释引用中引用元素不计为使用它。
- 在
is
表达式的右侧引用类、mixin 或枚举不计为使用它。
示例
#假设库中的代码未引用 _C
,以下代码会生成此诊断信息
class _C {}
假设库中的代码在任何调用 _m
时未为 y
传递值,以下代码会生成此诊断信息
class C {
void _m(int x, [int? y]) {}
void n() => _m(0);
}
常见修复方法
#如果不需要声明,请将其删除
class C {
void _m(int x) {}
void n() => _m(0);
}
如果声明旨在使用,请添加使用它的代码。
未使用的字段
#字段 '{0}' 的值未被使用。
描述
#当声明私有字段但从未读取时,即使在多个地方写入,分析器也会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为字段 _originalValue
在库中任何地方都没有被读取。
class C {
final String _originalValue;
final String _currentValue;
C(this._originalValue) : _currentValue = _originalValue;
String get value => _currentValue;
}
看起来字段 _originalValue
在初始化器中被读取 (_currentValue = _originalValue
),但实际上这是对同名参数的引用,而不是对字段的引用。
常见修复方法
#如果不需要该字段,则将其删除。
如果该字段原本打算使用,则添加缺少的代码。
未使用的导入
#未使用导入:'{0}'。
描述
#当导入不需要,因为导入的任何名称都没有在导入库中引用时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为库中没有引用 dart:async
中定义的任何内容。
import 'dart:async';
void main() {}
常见修复方法
#如果导入不需要,则将其删除。
如果打算使用一些导入的名称,则添加缺少的代码。
未使用的标签
#标签 '{0}' 未被使用。
描述
#当发现未使用的标签时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为标签 loop
在方法中任何地方都没有被引用。
void f(int limit) {
loop: for (int i = 0; i < limit; i++) {
print(i);
}
}
常见修复方法
#如果不需要该标签,则将其删除。
void f(int limit) {
for (int i = 0; i < limit; i++) {
print(i);
}
}
如果需要该标签,则使用它。
void f(int limit) {
loop: for (int i = 0; i < limit; i++) {
print(i);
if (i != 0) {
break loop;
}
}
}
未使用的局部变量
#局部变量 '{0}' 的值未被使用。
描述
#当声明局部变量但从未读取时,即使在多个地方写入,分析器也会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 count
的值从未被读取。
void main() {
int count = 0;
}
常见修复方法
#如果不需要该变量,则将其删除。
如果该变量原本打算使用,则添加缺少的代码。
未使用的结果
#'{0}' 应该被使用。{1}。
'{0}' 的值应该被使用。
描述
#当一个用 useResult
注解的函数被调用,并且该函数返回的值没有被使用时,分析器会产生此诊断信息。如果值的成员被调用,如果值被传递给另一个函数,或者如果值被赋值给一个变量或字段,则该值被认为是使用的。
示例
#以下代码会产生此诊断信息,因为调用 c.a()
没有被使用,即使方法 a
用 useResult
注解。
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
c.a();
}
常见修复方法
#如果您打算调用带注解的函数,请使用返回的值。
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
print(c.a());
}
如果您打算调用不同的函数,请更正被调用的函数的名称。
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
c.b();
}
未使用的显示名称
#名称 {0} 被显示,但没有被使用。
描述
#当一个 show 组合器包含一个库中未使用的名称时,分析器会产生此诊断信息。由于它没有被引用,因此可以删除该名称。
示例
#以下代码会产生此诊断信息,因为函数 max
没有被使用。
import 'dart:math' show min, max;
var x = min(0, 1);
常见修复方法
#使用该名称或将其删除。
import 'dart:math' show min;
var x = min(0, 1);
URI 不存在
#URI 的目标不存在:'{0}'。
描述
#当发现一个 import、export 或 part 指令,其中 URI 指向一个不存在的文件时,分析器会产生此诊断信息。
示例
#如果文件 lib.dart
不存在,以下代码会产生此诊断信息。
import 'lib.dart';
常见修复方法
#如果 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
不存在,以下代码会产生此诊断信息。
import 'lib.g.dart';
常见修复方法
#如果该文件是生成的文件,请运行生成该文件的生成器。
如果该文件不是生成的文件,请检查 URI 的拼写或创建该文件。
带有插值的 URI
#URI 不能使用字符串插值。
描述
#当 import
、export
或 part
指令中的字符串字面量包含插值时,分析器会产生此诊断信息。指令中 URI 的解析必须在声明被编译之前发生,因此在确定 URI 的值时不能评估表达式。
示例
#以下代码产生此诊断是因为import
指令中的字符串包含插值
import 'dart:$m';
const m = 'math';
常见修复方法
#从 URI 中删除插值
import 'dart:math';
var zero = min(0, 0);
使用原生扩展
#Dart 本地扩展已弃用,在 Dart 2.15 中不可用。
描述
#当使用dart-ext
方案导入库时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为本地库x
正在使用dart-ext
方案导入
import 'dart-ext:x';
常见修复方法
#重写代码以使用dart:ffi
作为调用本地库内容的方法。
使用 void 结果
#此表达式的类型为“void”,因此其值无法使用。
描述
#当分析器发现类型为void
的表达式,并且该表达式用在需要值的 地方(例如,在成员访问之前或赋值的右侧)时,它会产生此诊断。
示例
#以下代码产生此诊断是因为f
没有产生可以调用toString
的对象
void f() {}
void g() {
f().toString();
}
常见修复方法
#要么重写代码使表达式具有值,要么重写代码使其不依赖于该值。
枚举中的值声明
#枚举中不能声明名为“values”的成员。
描述
#当枚举声明定义名为values
的成员时,分析器会产生此诊断,无论该成员是枚举值、实例成员还是静态成员。
任何此类成员都会与名为values
的隐式声明的静态 getter 冲突,该 getter 返回包含所有枚举常量的列表。
示例
#以下代码产生此诊断是因为枚举E
定义了一个名为values
的实例成员
enum E {
v;
void values() {}
}
常见修复方法
#更改冲突成员的名称。
enum E {
v;
void getValues() {}
}
声明上下文中使用变量模式关键字
#声明上下文中的变量模式不能指定“var”或“final”关键字。
描述
#当在声明上下文中使用变量模式时,分析器会产生此诊断。
示例
#以下代码产生此诊断是因为记录模式中的变量模式位于声明上下文中
void f((int, int) r) {
var (var x, y) = r;
print(x + y);
}
常见修复方法
#从变量模式中删除var
或final
关键字
void f((int, int) r) {
var (x, y) = r;
print(x + y);
}
变量类型不匹配
#类型为“{0}”的值不能分配给类型为“{1}”的常量变量。
描述
#当常量表达式的计算结果会导致 CastException
时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 x
的值为 int
,而 int
不是 String
,因此无法将其赋值给 y
。
const dynamic x = 0;
const String y = x;
常见修复方法
#如果常量声明正确,则更改要赋值的值,使其具有正确的类型。
const dynamic x = 0;
const String y = '$x';
如果赋值的值正确,则更改声明,使其具有正确的类型。
const int x = 0;
const int y = x;
操作符参数数量错误
#运算符 '-' 应声明 0 或 1 个参数,但找到 {0} 个。
运算符 '{0}' 应声明正好 {1} 个参数,但找到 {2} 个。
描述
#当运算符声明的参数数量错误时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为运算符 +
必须有一个参数,对应于右操作数。
class C {
int operator +(a, b) => 0;
}
常见修复方法
#添加或删除参数以匹配所需数量。
class C {
int operator +(a) => 0;
}
setter 参数数量错误
#Setter 必须声明正好一个必需的位置参数。
描述
#当发现 setter 没有声明正好一个必需的位置参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 setter s
声明了两个必需参数。
class C {
set s(int x, int y) {}
}
以下代码会生成此诊断信息,因为 setter s
声明了一个可选参数。
class C {
set s([int? x]) {}
}
常见修复方法
#更改声明,使其只有一个必需的位置参数。
class C {
set s(int x) {}
}
类型参数数量错误
#类型 '{0}' 声明了 {1} 个类型参数,但提供了 {2} 个类型参数。
描述
#当使用具有类型参数的类型并提供类型参数时,但类型参数的数量与类型参数的数量不一致时,分析器会生成此诊断信息。
当调用构造函数并且类型参数的数量与为类声明的类型参数的数量不匹配时,分析器也会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 C
具有一个类型参数,但在将其用作类型注释时提供了两个类型参数。
class C<E> {}
void f(C<int, int> x) {}
以下代码会生成此诊断信息,因为 C
声明了一个类型参数,但在创建实例时提供了两个类型参数。
class C<E> {}
var c = C<int, int>();
常见修复方法
#根据需要添加或删除类型参数,以匹配为类型定义的类型参数数量。
class C<E> {}
void f(C<int> x) {}
构造函数类型参数数量错误
#构造函数 '{0}.{1}' 没有类型参数。
描述
#当在命名构造函数的名称后提供类型参数时,分析器会生成此诊断信息。构造函数不能声明类型参数,因此调用只能提供与类关联的类型参数,并且这些类型参数必须位于类的名称之后,而不是构造函数的名称之后。
示例
#以下代码会生成此诊断信息,因为类型参数 (<String>
) 位于构造函数的名称之后,而不是类的名称之后。
class C<T> {
C.named();
}
C f() => C.named<String>();
常见修复方法
#如果类型参数是针对类的类型参数,则将类型参数移到类名之后。
class C<T> {
C.named();
}
C f() => C<String>.named();
如果类型参数不是针对类的类型参数,则将其删除。
class C<T> {
C.named();
}
C f() => C.named();
枚举类型参数数量错误
#枚举声明了 {0} 个类型参数,但提供了 {1} 个类型参数。
描述
#当在具有类型参数的枚举中实例化枚举值并提供类型参数时,但类型参数的数量与类型参数的数量不同,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为枚举值 c
提供了一个类型参数,即使枚举 E
声明了两个类型参数。
enum E<T, U> {
c<int>()
}
常见修复方法
#如果类型参数的数量正确,则更改类型参数的数量以匹配类型参数的数量。
enum E<T, U> {
c<int, String>()
}
如果类型参数的数量正确,则更改类型参数的数量以匹配类型参数的数量。
enum E<T> {
c<int>()
}
扩展类型参数数量错误
#扩展 '{0}' 声明了 {1} 个类型参数,但提供了 {2} 个类型参数。
描述
#当使用具有类型参数的扩展并提供类型参数时,但类型参数的数量与类型参数的数量不同,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为扩展 E
声明了一个类型参数 (T
),但扩展覆盖具有两个类型参数。
extension E<T> on List<T> {
int get len => length;
}
void f(List<int> p) {
E<int, String>(p).len;
}
常见修复方法
#更改类型参数,以便类型参数的数量与类型参数的数量相同。
extension E<T> on List<T> {
int get len => length;
}
void f(List<int> p) {
E<int>(p).len;
}
方法类型参数数量错误
#方法 '{0}' 声明了 {1} 个类型参数,但提供了 {2} 个类型参数。
描述
#当使用与声明中指定的类型参数数量不同的类型参数数量调用方法或函数时,分析器会生成此诊断信息。必须没有类型参数,或者参数的数量必须与参数的数量匹配。
示例
#以下代码会生成此诊断信息,因为方法 m
的调用具有两个类型参数,但 m
的声明只有一个类型参数。
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m<int, int>(2);
常见修复方法
#如果类型参数是必需的,则通过添加或删除类型参数使它们与类型参数的数量匹配。
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m<int>(2);
如果类型参数不是必需的,则将其删除。
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m(2);
非生成器中的 yield
#yield 语句必须位于生成器函数中(用 'async*' 或 'sync*' 标记的函数)。
yield-each 语句必须位于生成器函数中(用 'async*' 或 'sync*' 标记的函数)。
描述
#当 yield
或 yield*
语句出现在主体没有用 async*
或 sync*
修饰符之一标记的函数中时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 yield
正在主体没有修饰符的函数中使用。
Iterable<int> get digits {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
以下代码会生成此诊断信息,因为 yield*
正在主体具有 async
修饰符而不是 async*
修饰符的函数中使用。
Stream<int> get digits async {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
常见修复方法
#添加修饰符,或将现有修饰符更改为 async*
或 sync*
。
Iterable<int> get digits sync* {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
无效类型的 yield
#类型为 '{0}' 的 yield 值必须可分配给 '{1}'。
由 'yield*' 表达式隐含的类型 '{0}' 必须可分配给 '{1}'。
描述
#当由 yield
或 yield*
表达式产生的对象的类型与从生成器(用 sync*
或 async*
标记的函数或方法)返回的 Iterable
或 Stream
类型要返回的对象类型不匹配时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 getter zero
被声明为返回一个返回整数的 Iterable
,但 yield
从可迭代对象中返回一个字符串。
Iterable<int> get zero sync* {
yield '0';
}
常见修复方法
#如果函数的返回类型正确,则修复 yield
关键字后的表达式以返回正确的类型。
Iterable<int> get zero sync* {
yield 0;
}
如果 yield
后的表达式正确,则更改函数的返回类型以允许它。
Iterable<String> get zero sync* {
yield '0';
}