诊断消息
- 诊断
- ABI 特定整数无效
- ABI 特定整数映射额外
- ABI 特定整数映射缺失
- ABI 特定整数映射不支持
- 抽象字段初始化器
- 抽象密封类
- 抽象超类成员引用
- 不明确的导出
- 不明确的扩展成员访问
- 不明确的导入
- 不明确的 Set 或 Map 字面量(两者)
- 不明确的 Set 或 Map 字面量(任一)
- 指针字段上的注解
- 参数必须是常量
- 参数必须是原生类型
- 参数类型不可赋值
- 参数类型不可分配给错误处理程序
- 重定向构造函数中的 assert
- 资源目录不存在
- 资源不存在
- 资源字段不是列表
- 资源缺少路径
- 资源不是字符串
- 资源不是字符串或 Map
- 资源路径不是字符串
- 赋值 do not store
- 赋值给 const
- 赋值给 final
- 赋值给 final 局部变量
- 赋值给 final (没有 setter)
- 赋值给函数
- 赋值给方法
- 赋值给类型
- 错误上下文中的异步 for in
- 在 late 局部变量初始化器中使用 await
- await 不兼容的类型
- 主体可能正常完成
- 主体可能正常完成(捕获错误)
- 主体可能正常完成(可空)
- switch 成员上的 break 标签
- 内置标识符作为类型
- 声明中的内置标识符
- case 代码块未终止
- case 表达式类型实现 equals
- case 表达式类型不是 switch 表达式子类型
- 从可空类型强制转换总是失败
- 从 null 强制转换总是失败
- 强制转换为非类型
- 类用作 mixin
- 来自延迟库的集合元素
- 复合实现 Finalizable
- 具体类具有枚举超接口
- 具有抽象成员的具体类
- 冲突的构造函数和静态成员
- 冲突的泛型接口
- 冲突的类型变量和容器
- 冲突的类型变量和成员
- 常量模式永远不匹配值类型
- 具有非常量表达式的常量模式
- const 构造函数参数类型不匹配
- const 构造函数具有由非常量初始化的字段
- const 构造函数具有非常量 super
- const 构造函数具有非 final 字段
- const 延迟类
- const 用非常量值初始化
- const 用来自延迟库的非常量值初始化
- const 实例字段
- const Map 键不是原始相等
- const 未初始化
- const Set 元素不是原始相等
- const 展开需要列表或 Set
- const 展开需要 Map
- const 带有非常量
- const 带有非常量参数
- const 带有类型参数
- continue 标签无效
- 创建结构体或联合体
- 创建时没有类型
- 死代码
- 死代码 catch 紧跟 catch
- catch 子类型上的死代码
- 死的空感知表达式
- 默认列表构造函数
- 函数类型中的默认值
- 重定向工厂构造函数中的默认值
- 必需参数的默认值
- 延迟导入扩展
- 明确未赋值的 late 局部变量
- dependencies 字段不是 Map
- 已弃用的冒号表示默认值
- 已弃用的导出使用
- 已弃用的字段
- 已弃用的成员使用
- 来自同一包的已弃用成员使用
- 已弃用的注释引用中的 new
- 已弃用的函数子类型
- 不允许的类型实例化表达式
- 除法优化
- 重复的构造函数
- 重复的定义
- 重复的导出
- 重复的字段形式参数
- 重复的字段名称
- 重复的隐藏名称
- 重复的忽略
- 重复的导入
- 重复的命名参数
- 重复的 part
- 重复的模式赋值变量
- 重复的模式字段
- 模式中重复的剩余元素
- 重复的显示名称
- 重复的变量模式
- 空的 Map 模式
- 带有逗号的空记录字面量
- 空记录类型命名字段列表
- 带有逗号的空记录类型
- 空结构体
- 枚举常量与封闭的名称相同
- 具有非常量构造函数的枚举常量
- 具有实例变量的枚举 mixin
- 具有抽象成员的枚举
- 具有 name values 的枚举
- const Set 中相同的元素
- Set 中相同的元素
- const Map 中相同的键
- Map 中相同的键
- Map 模式中相同的键
- 需要一个列表模式类型参数
- 需要一个列表类型参数
- 需要一个 Set 类型参数
- 需要两个 Map 模式类型参数
- 需要两个 Map 类型参数
- 导出内部库
- 导出旧符号
- 导出非库
- 映射中的表达式
- 继承非类
- 扩展作为表达式
- extension_conflicting_static_and_instance
- extension_declares_abstract_member
- extension_declares_constructor
- extension_declares_instance_field
- extension_declares_member_of_object
- extension_override_access_to_static_member
- extension_override_argument_not_assignable
- extension_override_without_access
- extension_override_with_cascade
- extension_type_constructor_with_super_formal_parameter
- extension_type_constructor_with_super_invocation
- extension_type_declares_instance_field
- extension_type_declares_member_of_object
- extension_type_implements_disallowed_type
- extension_type_implements_itself
- extension_type_implements_not_supertype
- extension_type_implements_representation_not_supertype
- extension_type_inherited_member_conflict
- extension_type_representation_depends_on_itself
- extension_type_representation_type_bottom
- extension_type_with_abstract_member
- external_with_initializer
- extra_annotation_on_struct_field
- extra_positional_arguments
- extra_positional_arguments_could_be_named
- extra_size_annotation_carray
- ffi_native_invalid_duplicate_default_asset
- ffi_native_invalid_multiple_annotations
- ffi_native_must_be_external
- ffi_native_unexpected_number_of_parameters
- ffi_native_unexpected_number_of_parameters_with_receiver
- field_initialized_by_multiple_initializers
- field_initialized_in_initializer_and_declaration
- field_initialized_in_parameter_and_initializer
- field_initializer_factory_constructor
- field_initializer_in_struct
- field_initializer_not_assignable
- field_initializer_outside_constructor
- field_initializer_redirecting_constructor
- field_initializing_formal_not_assignable
- field_in_struct_with_initializer
- field_must_be_external_in_struct
- final_initialized_in_declaration_and_constructor
- final_not_initialized
- final_not_initialized_constructor
- flutter_field_not_map
- for_in_of_invalid_element_type
- for_in_of_invalid_type
- for_in_with_const_variable
- generic_method_type_instantiation_on_dynamic
- generic_struct_subclass
- getter_not_subtype_setter_types
- illegal_async_generator_return_type
- illegal_async_return_type
- illegal_concrete_enum_member
- illegal_enum_values
- illegal_sync_generator_return_type
- implements_non_class
- implements_repeated
- implements_super_class
- implicit_super_initializer_missing_arguments
- implicit_this_reference_in_initializer
- import_deferred_library_with_load_function
- import_internal_library
- import_of_legacy_library_into_null_safe
- import_of_non_library
- inconsistent_inheritance
- inconsistent_language_version_override
- inconsistent_pattern_variable_logical_or
- initializer_for_non_existent_field
- initializer_for_static_field
- initializing_formal_for_non_existent_field
- instance_access_to_static_member
- instance_member_access_from_factory
- instance_member_access_from_static
- instantiate_abstract_class
- instantiate_enum
- instantiate_type_alias_expands_to_type_parameter
- integer_literal_imprecise_as_double
- integer_literal_out_of_range
- invalid_annotation
- invalid_annotation_constant_value_from_deferred_library
- invalid_annotation_from_deferred_library
- invalid_annotation_target
- invalid_assignment
- invalid_dependency
- invalid_exception_value
- invalid_export_of_internal_element
- invalid_export_of_internal_element_indirectly
- invalid_extension_argument_count
- invalid_factory_method_decl
- invalid_factory_method_impl
- invalid_factory_name_not_a_class
- invalid_field_name
- invalid_field_type_in_struct
- invalid_implementation_override
- invalid_inline_function_type
- invalid_internal_annotation
- invalid_language_version_override
- invalid_literal_annotation
- invalid_modifier_on_constructor
- invalid_modifier_on_setter
- invalid_non_virtual_annotation
- invalid_null_aware_operator
- invalid_override
- invalid_override_of_non_virtual_member
- invalid_pattern_variable_in_shared_case_scope
- invalid_platforms_field
- invalid_reference_to_generative_enum_constructor
- invalid_reference_to_this
- invalid_return_type_for_catch_error
- invalid_sealed_annotation
- invalid_super_formal_parameter_location
- invalid_type_argument_in_const_literal
- invalid_uri
- invalid_use_of_covariant_in_extension
- invalid_use_of_internal_member
- invalid_use_of_null_value
- invalid_use_of_type_outside_library
- invalid_use_of_visible_for_overriding_member
- invalid_use_of_visible_for_testing_member
- invalid_visibility_annotation
- invalid_visible_for_overriding_annotation
- invalid_visible_outside_template_annotation
- invocation_of_extension_without_call
- invocation_of_non_function
- invocation_of_non_function_expression
- label_in_outer_scope
- label_undefined
- late_final_field_with_const_constructor
- late_final_local_already_assigned
- leaf_call_must_not_return_handle
- leaf_call_must_not_take_handle
- list_element_type_not_assignable
- main_first_positional_parameter_type
- main_has_required_named_parameters
- main_has_too_many_required_positional_parameters
- main_is_not_function
- map_entry_not_in_map
- map_key_type_not_assignable
- map_value_type_not_assignable
- mismatched_annotation_on_struct_field
- missing_annotation_on_struct_field
- missing_dart_library
- missing_default_value_for_parameter
- missing_dependency
- missing_enum_constant_in_switch
- missing_exception_value
- missing_field_type_in_struct
- missing_name
- missing_named_pattern_field_name
- missing_override_of_must_be_overridden
- missing_required_argument
- missing_required_param
- missing_return
- missing_size_annotation_carray
- missing_variable_pattern
- mixin_application_concrete_super_invoked_member_type
- mixin_application_not_implemented_interface
- mixin_application_no_concrete_super_invoked_member
- mixin_class_declaration_extends_not_object
- mixin_class_declares_constructor
- mixin_inherits_from_not_object
- mixin_instantiate
- mixin_of_non_class
- mixin_on_sealed_class
- mixin_super_class_constraint_deferred_class
- mixin_super_class_constraint_non_interface
- multiple_redirecting_constructor_invocations
- multiple_super_initializers
- must_be_a_native_function_type
- must_be_a_subtype
- must_be_immutable
- must_call_super
- must_return_void
- name_not_string
- native_field_invalid_type
- native_field_missing_type
- native_field_not_static
- new_with_undefined_constructor_default
- non_abstract_class_inherits_abstract_member
- non_bool_condition
- non_bool_expression
- non_bool_negation_expression
- non_bool_operand
- non_constant_annotation_constructor
- non_constant_case_expression
- non_constant_case_expression_from_deferred_library
- non_constant_default_value
- non_constant_default_value_from_deferred_library
- non_constant_list_element
- non_constant_map_element
- non_constant_map_key
- non_constant_map_pattern_key
- non_constant_map_value
- non_constant_relational_pattern_expression
- non_constant_set_element
- non_constant_type_argument
- non_const_argument_for_const_parameter
- non_const_call_to_literal_constructor
- non_const_generative_enum_constructor
- non_covariant_type_parameter_position_in_representation_type
- non_exhaustive_switch_expression
- non_exhaustive_switch_statement
- non_final_field_in_enum
- non_generative_constructor
- non_generative_implicit_constructor
- non_native_function_type_argument_to_pointer
- non_positive_array_dimension
- non_sized_type_argument
- non_sync_factory
- non_type_as_type_argument
- non_type_in_catch_clause
- non_void_return_for_operator
- non_void_return_for_setter
- not_assigned_potentially_non_nullable_local_variable
- not_a_type
- not_binary_operator
- not_enough_positional_arguments
- not_initialized_non_nullable_instance_field
- not_initialized_non_nullable_variable
- not_iterable_spread
- not_map_spread
- no_annotation_constructor_arguments
- no_combined_super_signature
- no_generative_constructors_in_superclass
- nullable_type_in_catch_clause
- nullable_type_in_extends_clause
- nullable_type_in_implements_clause
- nullable_type_in_on_clause
- nullable_type_in_with_clause
- null_argument_to_non_null_type
- null_check_always_fails
- obsolete_colon_for_default_value
- on_repeated
- optional_parameter_in_operator
- override_on_non_overriding_member
- packed_annotation
- packed_annotation_alignment
- part_of_different_library
- part_of_non_part
- part_of_unnamed_library
- path_does_not_exist
- path_not_posix
- path_pubspec_does_not_exist
- pattern_assignment_not_local_variable
- pattern_constant_from_deferred_library
- pattern_type_mismatch_in_irrefutable_context
- pattern_variable_assignment_inside_guard
- platform_value_disallowed
- positional_field_in_object_pattern
- positional_super_formal_parameter_with_positional_argument
- prefix_collides_with_top_level_member
- prefix_identifier_not_followed_by_dot
- prefix_shadowed_by_local_declaration
- private_collision_in_mixin_application
- private_optional_parameter
- private_setter
- read_potentially_unassigned_final
- record_literal_one_positional_no_trailing_comma
- record_type_one_positional_no_trailing_comma
- recursive_compile_time_constant
- recursive_constructor_redirect
- recursive_interface_inheritance
- redeclare_on_non_redeclaring_member
- redirect_generative_to_missing_constructor
- redirect_generative_to_non_generative_constructor
- redirect_to_abstract_class_constructor
- redirect_to_invalid_function_type
- redirect_to_invalid_return_type
- redirect_to_missing_constructor
- redirect_to_non_class
- redirect_to_non_const_constructor
- redirect_to_type_alias_expands_to_type_parameter
- referenced_before_declaration
- refutable_pattern_in_irrefutable_context
- relational_pattern_operand_type_not_assignable
- relational_pattern_operator_return_type_not_assignable_to_bool
- rest_element_in_map_pattern
- rethrow_outside_catch
- return_in_generative_constructor
- return_in_generator
- return_of_do_not_store
- return_of_invalid_type
- return_of_invalid_type_from_closure
- return_without_value
- sdk_version_async_exported_from_core
- sdk_version_as_expression_in_const_context
- sdk_version_bool_operator_in_const_context
- sdk_version_constructor_tearoffs
- sdk_version_eq_eq_operator_in_const_context
- sdk_version_extension_methods
- sdk_version_gt_gt_gt_operator
- sdk_version_is_expression_in_const_context
- sdk_version_never
- sdk_version_set_literal
- sdk_version_ui_as_code
- sdk_version_ui_as_code_in_const_context
- set_element_type_not_assignable
- shared_deferred_prefix
- size_annotation_dimensions
- static_access_to_instance_member
- subtype_of_base_or_final_is_not_base_final_or_sealed
- subtype_of_deferred_class
- subtype_of_disallowed_type
- subtype_of_ffi_class
- subtype_of_sealed_class
- subtype_of_struct_class
- supertype_expands_to_type_parameter
- super_formal_parameter_type_is_not_subtype_of_associated
- super_formal_parameter_without_associated_named
- super_formal_parameter_without_associated_positional
- super_invocation_not_last
- super_in_enum_constructor
- super_in_extension
- super_in_extension_type
- super_in_invalid_context
- super_in_redirecting_constructor
- switch_case_completes_normally
- switch_expression_not_assignable
- tearoff_of_generative_constructor_of_abstract_class
- text_direction_code_point_in_comment
- text_direction_code_point_in_literal
- throw_of_invalid_type
- top_level_cycle
- type_alias_cannot_reference_itself
- type_annotation_deferred_class
- type_argument_not_matching_bounds
- type_check_with_null
- type_parameter_referenced_by_static
- type_parameter_supertype_of_its_bound
- type_test_with_non_type
- type_test_with_undefined_name
- unchecked_use_of_nullable_value
- undefined_annotation
- undefined_class
- undefined_constructor_in_initializer
- undefined_enum_constant
- undefined_enum_constructor
- undefined_extension_getter
- undefined_extension_method
- undefined_extension_operator
- undefined_extension_setter
- undefined_function
- undefined_getter
- undefined_hidden_name
- undefined_identifier
- undefined_identifier_await
- undefined_method
- undefined_named_parameter
- undefined_operator
- undefined_prefixed_name
- undefined_referenced_parameter
- undefined_setter
- undefined_shown_name
- undefined_super_member
- unknown_platform
- unnecessary_cast
- unnecessary_dev_dependency
- unnecessary_final
- unnecessary_import
- unnecessary_nan_comparison
- unnecessary_non_null_assertion
- unnecessary_no_such_method
- unnecessary_null_assert_pattern
- unnecessary_null_check_pattern
- unnecessary_null_comparison
- unnecessary_question_mark
- unnecessary_set_literal
- unnecessary_type_check
- unqualified_reference_to_non_local_static_member
- unqualified_reference_to_static_member_of_extended_type
- unreachable_switch_case
- unreachable_switch_default
- unused_catch_clause
- unused_catch_stack
- unused_element
- unused_element_parameter
- unused_field
- unused_import
- unused_label
- unused_local_variable
- unused_result
- unused_shown_name
- uri_does_not_exist
- uri_does_not_exist_in_doc_import
- uri_has_not_been_generated
- uri_with_interpolation
- use_of_native_extension
- use_of_void_result
- values_declaration_in_enum
- variable_length_array_not_last
- variable_pattern_keyword_in_declaration_context
- variable_type_mismatch
- workspace_field_not_list
- workspace_value_not_string
- workspace_value_not_subdirectory
- wrong_number_of_parameters_for_operator
- wrong_number_of_parameters_for_setter
- wrong_number_of_type_arguments
- wrong_number_of_type_arguments_constructor
- wrong_number_of_type_arguments_enum
- wrong_number_of_type_arguments_extension
- 方法的类型参数数量错误
- 在非生成器中使用 yield
- yield 的类型无效
- 始终声明返回类型
- 始终将控制体放在新行上
- 始终将必需的命名参数放在最前面
- 始终使用包导入
- 注解重写
- 避免空的 else 块
- 避免在 forEach 调用中使用函数字面量
- 避免 FutureOr<void>
- 避免初始化为 null
- 避免使用 print
- 避免使用相对 lib 导入
- 避免重命名方法参数
- 避免在 setter 上使用返回类型
- 避免为 void 返回 null
- 避免遮蔽类型参数
- 避免在表达式语句中使用单个级联
- 避免缓慢的异步 IO
- 避免使用 type.toString
- 避免使用类型作为参数名称
- 避免不必要的容器
- 避免在 Flutter 中使用 Web 库
- 仅 await Future
- 扩展名使用驼峰命名法
- 类型使用驼峰命名法
- 取消订阅
- 关闭 sink
- 集合方法类型不相关
- 常量标识符名称
- 在 finally 块中使用控制流
- 在流控制结构中使用大括号
- 悬空的库文档注释
- 依赖于引用的包
- 空的 catch 块
- 空的构造函数体
- 空语句
- 文件名
- hash 和 equals
- 实现导入
- 隐式调用 tear-off
- 使用 JS 互操作类型进行无效的运行时检查
- 无效地使用 do_not_submit 成员
- 库注解
- 库名称
- 库前缀
- 公共 API 中包含库私有类型
- 仅限字面量布尔表达式
- 列表中没有相邻的字符串
- 没有重复的 case 值
- 库前缀没有前导下划线
- 局部标识符没有前导下划线
- 在 createState 中没有逻辑
- 不使用通配符变量
- 非常量标识符名称
- 对可空类型参数进行 null 检查
- 重写的字段
- 包名
- 带有包前缀的库名称
- 优先使用相邻的字符串连接
- 优先使用集合字面量
- 优先使用条件赋值
- 优先使用 const 构造函数
- 在不可变类中优先使用 const 构造函数
- 优先使用 const 声明
- 优先使用 const 字面量来创建不可变类
- 优先使用 contains
- 优先使用双引号
- 优先使用 final 字段
- 优先使用 for 元素而不是 mapFromIterable
- 优先使用函数声明而不是变量
- 优先使用泛型函数类型别名
- 优先使用 if-null 运算符
- 优先使用初始化形式参数
- 优先使用内联添加
- 优先使用插值来组合字符串
- 优先使用 isEmpty
- 优先使用 isNotEmpty
- 优先使用 is not 运算符
- 优先使用 Iterable.whereType
- 优先使用 null 感知运算符
- 优先使用相对导入
- 优先使用单引号
- 优先为未初始化的变量指定类型
- 优先使用 void 而不是 null
- 提供弃用消息
- 递归 getter
- 安全的 pubspec URL
- 使用 SizedBox 来表示空白
- SizedBox 收缩/扩展
- 使用斜杠表示文档注释
- 将子属性放在最后
- 将构造函数放在最前面
- 对 pub 依赖项进行排序
- 将未命名构造函数放在最前面
- 在 equals 中测试类型
- 在 finally 块中抛出异常
- 类型初始化形式参数
- 常量模式中的类型字面量
- 未等待的 Future
- 文档注释中出现意外的 HTML
- 字符串插值中出现不必要的大括号
- 不必要的 const
- 不必要的构造函数名称
- unnecessary_final
- 不必要的 getter 和 setter
- 不必要的 lambda
- 不必要的 late
- 不必要的库名称
- 不必要的 new
- 不必要的 null 感知赋值
- if-null 运算符中不必要的 null
- 对于 final 变量声明来说不必要的可空性
- 不必要的重写
- 不必要的括号
- 不必要的原始字符串
- 不必要的语句
- 不必要的字符串转义
- 不必要的字符串插值
- 不必要的 this
- 在 spread 语法中不必要的 toList
- 不相关的类型相等性检查
- 不安全的方差
- 同步使用 build context
- 使用 ColoredBox
- 使用 DecoratedBox
- Flutter 颜色使用完整的十六进制值
- 参数使用函数类型语法
- 使用 if-null 将 null 转换为 bool
- 在 widget 构造函数中使用 key
- 为私有字段和变量使用 late
- 使用命名常量
- 使用原始字符串
- 尽可能使用 rethrow
- 使用 setter 来更改属性
- 使用字符串缓冲区
- 在 part of 指令中使用字符串
- 使用 super 参数
- 使用截断除法
- 有效的正则表达式
- void 检查
此页面列出了 Dart 分析器生成的诊断消息,其中包含有关这些消息的含义以及如何修复代码的详细信息。 有关分析器的更多信息,请参阅 自定义静态分析。
诊断
#分析器为不符合语言规范或可能以意外方式工作的代码生成以下诊断信息。
ABI 特定整数无效
#扩展 '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 特定整数映射额外
#扩展 '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 特定整数映射缺失
#扩展 '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 特定整数映射不支持
#到 '{0}' 的映射无效;仅支持映射到 'Int8'、'Int16'、'Int32'、'Int64'、'Uint8'、'Uint16'、'UInt32' 和 'Uint64'。
描述
#当 AbiSpecificIntegerMapping
注解的 map 参数中的值不是以下整数类型之一时,分析器会生成此诊断信息
Int8
Int16
Int32
Int64
Uint8
Uint16
UInt32
Uint64
示例
#以下代码生成此诊断信息,因为 map 条目的值是 Array<Uint8>
,这不是有效的整数类型
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Array<Uint8>(4)})
final class C extends AbiSpecificInteger {
const C();
}
常见修复
#在 map 中使用一个有效类型作为值
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;
不明确的扩展成员访问
#名为 '{0}' 的成员在 '{1}' 和 '{2}' 中定义,并且两者都不更具体。
名为 '{0}' 的成员在 {1} 中定义,并且没有一个更具体。
描述
#当代码引用对象的成员(例如,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) {}
不明确的 Set 或 Map 字面量(两者)
#字面量不能是映射或集合,因为它包含至少一个字面量映射条目或一个扩展 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};
不明确的 Set 或 Map 字面量(任一)
#此字面量必须是映射或集合,但元素没有足够的信息来使类型推断工作。
描述
#由于映射和集合字面量使用相同的分隔符({
和 }
),因此分析器会查看类型参数和元素来确定您指的是哪种字面量。 当没有类型参数并且所有元素都是展开元素(两种字面量都允许)时,分析器会使用正在展开的表达式的类型。 如果所有表达式的类型都是 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 互操作。
示例
#以下代码产生此诊断,因为类型为 Pointer
且在 Struct
的子类中声明的字段 p
具有注解 @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);
}
参数必须是原生类型
#“Native.addressOf”的参数必须使用 @Native 注解
描述
#当传递给 Native.addressOf
的参数没有使用 Native
注解时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 addressOf
的参数是一个字符串,而不是一个字段,并且字符串不能被注解
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf('f'));
}
以下代码产生此诊断,因为函数 f
被传递给 addressOf
,但没有被注解为 Native
import 'dart:ffi';
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
常见修复
#如果参数不是字段或函数,则用使用 Native
注解的字段或函数替换参数
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
如果参数是字段或函数,则使用 Native
注解字段或函数
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
参数类型不可赋值
#参数类型“{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
#重定向构造函数不能具有“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
常见修复
#更改资源映射,使其包含具有字符串值(有效的 POSIX 样式文件路径)的 path
字段
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
资源不是字符串或 Map
#资源值必须是文件路径(字符串)或映射。
描述
#当资源值不是字符串或映射时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为资源值是一个列表
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
映射,使其包含一个字符串类型的 path
值(有效的 POSIX 风格文件路径)。
name: example
flutter:
assets:
- path: image.gif
flavors:
- premium
赋值 do not store
#“{0}”被标记为“doNotStore”,不应赋值给字段或顶级变量。
描述
#当显式或隐式标记为 doNotStore
注解的函数(包括方法和 getter)的值存储在字段或顶级变量中时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为函数 f
的值存储在顶级变量 x
中。
import 'package:meta/meta.dart';
@doNotStore
int f() => 1;
var x = f();
常见修复
#将对字段或变量的引用替换为生成值的函数的调用。
赋值给 const
#常量变量不能被赋值。
描述
#当分析器发现对具有 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 的调用,但由于同名字段声明为 final
或 const
而没有 setter 时,会产生此诊断。
示例
#以下代码会产生此诊断,因为 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
或 async*
的函数或方法中找到 async for-in 循环时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 f
的主体未标记为 async
或 async*
,但 f
包含一个 async 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);
}
}
在 late 局部变量初始化器中使用 await
#“await”表达式不能用于“late”局部变量的初始化器。
描述
#当具有 late
修饰符的局部变量在初始化器中使用 await
表达式时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 await
表达式用于 v
的初始化器,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 不兼容的类型
#“await”表达式不能用于不是“Future”子类型的扩展类型的表达式。
描述
#当 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;
}
如果扩展类型旨在可等待,则将 Future
(或 Future
的子类型)添加到 implements
子句(如果还没有,则添加一个 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;
}
如果函数应沿该路径返回非 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 {}
常见修复
#为声明选择一个不同的名称。
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
关键字为前缀) 或隐式 (因为它出现在常量上下文中) 为常量的集合字面量包含使用延迟导入导入的库中声明的值时,分析器会产生此诊断。常量在编译时进行评估,而延迟库中的值在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#假设有一个文件 a.dart
定义了常量 zero
const zero = 0;
以下代码会产生此诊断,因为常量列表字面量包含使用 deferred
导入导入的 a.zero
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) {}
}
const 构造函数参数类型不匹配
#类型为 '{0}' 的值无法在 const 构造函数中分配给类型为 '{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' 构造函数。
描述
#当构造函数具有关键字 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();
}
const 构造函数具有非常量 super
#常量构造函数不能调用 '{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();
}
const 构造函数具有非 final 字段
#无法为具有非 final 字段的类定义常量构造函数。
描述
#当构造函数标记为常量构造函数,但该构造函数在至少具有一个非 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
对象时,分析器会生成此诊断。常量在编译时计算,而延迟库中的类在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#以下代码会生成此诊断,因为它尝试创建延迟库中的类的 const
实例
import 'dart:convert' deferred as convert;
const json2 = convert.JsonCodec();
常见修复
#如果不需要该对象为常量,则更改代码以便创建非常量实例
import 'dart:convert' deferred as convert;
final json2 = convert.JsonCodec();
如果该对象必须为常量,则从 import 指令中删除 deferred
import 'dart:convert' as convert;
const json2 = convert.JsonCodec();
const 用非常量值初始化
#Const 变量必须使用常量值初始化。
描述
#当将静态已知不是常量的值分配给声明为 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
变量初始化 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;
const 实例字段
#只有静态字段才能声明为 const。
描述
#当实例字段标记为 const 时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 f
是一个实例字段
class C {
const int f = 3;
}
常见修复
#如果字段需要是实例字段,则删除关键字 const
,或将其替换为 final
class C {
final int f = 3;
}
如果字段确实应该是 const 字段,则使其成为静态字段
class C {
static const int f = 3;
}
const Map 键不是原始相等
#常量映射中键的类型不能重写 '==' 运算符或 'hashCode',但类 '{0}' 却可以。
描述
#当用作常量映射文字中键的对象的类实现 ==
运算符、getter hashCode
或两者时,分析器会生成此诊断。常量映射的实现使用 ==
运算符和 hashCode
getter,因此除从 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};
const 未初始化
#必须初始化常量 '{0}'。
描述
#当声明为常量的变量没有初始值设定项时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 c
未初始化
const c;
常见修复
#添加初始值设定项
const c = 'c';
const Set 元素不是原始相等
#const_set_element_type_implements_equals
)
常量集合中的元素不能重写 '==' 运算符或 'hashCode',但类型 '{0}' 却可以。
描述
#当用作常量集合文字中元素的对象的类实现 ==
运算符、getter hashCode
或两者时,分析器会生成此诊断。常量集合的实现使用 ==
运算符和 hashCode
getter,因此除从 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()};
const 展开需要列表或 Set
#此展开中需要列表或集合。
描述
#当常量列表或集合中的展开运算符的表达式计算为列表或集合以外的内容时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 list1
的值是 null
,它既不是列表也不是集合
const dynamic list1 = 42;
const List<int> list2 = [...list1];
常见修复
#将表达式更改为计算为常量列表或常量集合的内容
const dynamic list1 = [42];
const List<int> list2 = [...list1];
const 展开需要 Map
#此展开中需要映射。
描述
#当常量映射中的展开运算符的表达式计算为映射以外的内容时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 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
调用未标记为 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();
const 带有非常量参数
#常量创建的参数必须是常量表达式。
描述
#当使用非常量表达式的参数调用常量构造函数时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 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 带有类型参数
#常量构造函数拆分不能将类型参数用作类型参数。
常量创建不能将类型参数用作类型参数。
常量函数拆分不能将类型参数用作类型参数。
描述
#当在构造函数的 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
语句上的标签时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为标签 l
用于标记 switch
语句,并在 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();
}
死代码
#死代码。
死代码:被赋值的通配符变量被标记为 late,且永远不会被引用,因此此初始化程序永远不会被求值。
描述
#当发现永远不会执行的代码时,分析器会产生此诊断信息,因为执行永远不会到达该代码。
示例
#以下代码会产生此诊断信息,因为 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 紧跟 catch
#死代码:在 '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) {
}
}
catch 子类型上的死代码
#死代码:此 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();
}
明确未赋值的 late 局部变量
#此时,late 局部变量 '{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);
}
dependencies 字段不是 Map
#字段 '{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
的库 a.dart
。
class A {}
以及第二个导出 a.dart
但已将导出标记为已弃用的库 b.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 有一个内置的整数除法运算符,它既更有效率又更简洁。
示例
#以下代码会产生此诊断信息,因为 x
和 y
相除的结果使用 toInt
转换为整数
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 注释,或者如果 ignore 注释忽略了多个诊断信息,则删除不必要的诊断名称
// 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}) {}
}
重复的 part
#该库已经包含一个 URI 为“{0}”的部分。
描述
#当单个文件在多个 part 指令中被引用时,分析器会产生此诊断信息。
示例
#给定一个包含以下内容的 part.dart
文件
part of 'test.dart';
以下代码会产生此诊断信息,因为文件 part.dart
被包含了多次
part 'part.dart';
part 'part.dart';
常见修复
#删除除第一个重复的 part 指令之外的所有指令
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;
}
}
模式中重复的剩余元素
#列表或映射模式中最多允许一个 rest 元素。
描述
#当列表或映射模式中存在多个 rest 模式时,分析器会产生此诊断信息。rest 模式将捕获其他子模式未匹配的任何值,使后续 rest 模式变得不必要,因为没有剩余需要捕获的内容。
示例
#以下代码会产生此诊断信息,因为列表模式中有两个 rest 模式
void f(List<int> x) {
if (x case [0, ..., ...]) {}
}
常见修复
#删除除一个 rest 模式之外的所有 rest 模式
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);
}
}
空的 Map 模式
#映射模式必须至少有一个条目。
描述
#当映射模式为空时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为映射模式为空
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 互操作。
示例
#以下代码会生成此诊断信息,因为扩展 Struct
的类 C
没有声明任何字段
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 {}
如果该类不打算作为结构体使用,则删除或更改 extends 子句
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._();
}
具有实例变量的枚举 mixin
#应用于枚举的 mixin 不能具有实例变量。
描述
#当应用于枚举的 mixin 声明一个或多个实例变量时,分析器会生成此诊断信息。这是不允许的,因为枚举值是常量,并且枚举中的构造函数无法初始化 mixin 的任何字段。
示例
#以下代码会生成此诊断信息,因为 mixin M
定义了实例字段 x
mixin M {
int x = 0;
}
enum E with M {
a
}
常见修复
#如果需要应用 mixin,则将所有实例字段更改为 getter 和 setter 对,并在必要时在枚举中实现它们
mixin M {
int get x => 0;
}
enum E with M {
a
}
如果不需要应用 mixin,则将其删除
enum E {
a
}
具有抽象成员的枚举
#'{0}' 必须具有方法体,因为 '{1}' 是枚举。
描述
#当找到没有具体实现的枚举成员时,分析器会生成此诊断信息。枚举不允许包含抽象成员。
示例
#以下代码会生成此诊断信息,因为 m
是一个抽象方法,而 E
是一个枚举
enum E {
e;
void m();
}
常见修复
#为成员提供实现
enum E {
e;
void m() {}
}
具有 name values 的枚举
#名称 'values' 不是枚举的有效名称。
描述
#当声明的枚举名称为 values
时,分析器会生成此诊断信息。这是不允许的,因为枚举有一个名为 values
的隐式静态字段,并且两者会发生冲突。
示例
#以下代码会生成此诊断信息,因为存在一个名为 values
的枚举声明
enum values {
c
}
常见修复
#将枚举重命名为 values
以外的名称。
const Set 中相同的元素
#常量集合字面量中的两个元素不能相等。
描述
#当常量集合字面量中的两个元素具有相同的值时,分析器会生成此诊断信息。集合只能包含每个值一次,这意味着其中一个值是不必要的。
示例
#以下代码会生成此诊断信息,因为字符串 'a'
指定了两次
const Set<String> set = {'a', 'a'};
常见修复
#删除重复值之一
const Set<String> set = {'a'};
请注意,字面量集合保留其元素的顺序,因此选择删除哪个元素可能会影响迭代器返回元素的顺序。
Set 中相同的元素
#集合字面量中的两个元素不应相等。
描述
#当非常量集合中的元素与同一集合中的前一个元素相同时,分析器会生成此诊断信息。如果两个元素相同,则第二个值将被忽略,这使得同时拥有这两个元素毫无意义,并且可能表示存在错误。
示例
#以下代码会生成此诊断信息,因为元素 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};
请注意,字面量集合保留其元素的顺序,因此选择删除哪个元素可能会影响迭代器返回元素的顺序。
const Map 中相同的键
#常量映射字面量中的两个键不能相等。
描述
#当常量映射中的键与同一映射中的前一个键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得同时拥有这两个键值对毫无意义。
示例
#以下代码会生成此诊断信息,因为键 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'};
请注意,字面量映射保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。
Map 中相同的键
#映射字面量中的两个键不应相等。
描述
#当非常量映射中的键与同一映射中的前一个键相同时,分析器会生成此诊断信息。如果两个键相同,则第二个值将覆盖第一个值,这使得同时拥有这两个键值对毫无意义,并且可能表示存在错误。
示例
#以下代码会生成此诊断信息,因为键 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'};
请注意,字面量映射保留其条目的顺序,因此选择删除哪个条目可能会影响迭代器返回键和值的顺序。
Map 模式中相同的键
#映射模式中的两个键不能相等。
描述
#当映射模式包含多个名称相同的键时,分析器会生成此诊断信息。同一个键不能匹配两次。
示例
#以下代码会生成此诊断信息,因为键 '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>[];
需要一个 Set 类型参数
#集合字面量需要一个或零个类型参数,但找到了 {0} 个。
描述
#当集合字面量具有多个类型参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为集合字面量有三个类型参数,而它最多只能有一个
var s = <int, String, int>{0, 'a', 1};
常见修复
#删除除一个之外的所有类型参数
var s = <int>{0, 1};
需要两个 Map 模式类型参数
#映射模式需要两个或零个类型参数,但找到了 {0} 个。
描述
#当映射模式具有一个类型参数或多于两个类型参数时,分析器会生成此诊断信息。映射模式可以有两个或零个类型参数,但不能有任何其他数量。
示例
#以下代码会生成此诊断信息,因为映射模式 (<int>{}
) 有一个类型参数
void f(Object x) {
if (x case <int>{0: _}) {}
}
常见修复
#添加或删除类型参数,直到有两个或零个
void f(Object x) {
if (x case <int, int>{0: _}) {}
}
需要两个 Map 类型参数
#映射字面量需要两个或零个类型参数,但找到了 {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-of 指令。
描述
#当导出指令引用的是 part 而不是库时,分析器会生成此诊断信息。
示例
#给定一个包含以下内容的 part.dart
文件
part of lib;
以下代码会生成此诊断信息,因为文件 part.dart
是一个 part,而只有库才能被导出
library lib;
export 'part.dart';
常见修复
#要么删除导出指令,要么将 URI 更改为包含该 part 的库的 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();
extension_conflicting_static_and_instance
#扩展不能定义静态成员 '{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;
}
extension_declares_abstract_member
#扩展不能声明抽象成员。
描述
#当抽象声明在扩展中声明时,分析器会产生此诊断信息。扩展只能声明具体成员。
示例
#以下代码会产生此诊断信息,因为方法 a
没有主体
extension E on String {
int a();
}
常见修复
#要么为成员提供一个实现,要么将其删除。
extension_declares_constructor
#扩展不能声明构造函数。
描述
#当在扩展中找到构造函数声明时,分析器会产生此诊断信息。定义构造函数是无效的,因为扩展不是类,并且无法创建扩展的实例。
示例
#以下代码会产生此诊断信息,因为 E
中存在构造函数声明
extension E on String {
E() : super();
}
常见修复
#删除构造函数或将其替换为静态方法。
extension_declares_instance_field
#扩展不能声明实例字段
描述
#当在扩展中找到实例字段声明时,分析器会产生此诊断信息。定义实例字段是无效的,因为扩展只能添加行为,而不能添加状态。
示例
#以下代码会产生此诊断信息,因为 s
是一个实例字段
extension E on String {
String s;
}
常见修复
#删除字段,使其成为静态字段,或将其转换为 getter、setter 或方法。
extension_declares_member_of_object
#扩展不能声明与 'Object' 声明的成员同名的成员。
描述
#当扩展声明声明的成员与类 Object
中声明的成员同名时,分析器会产生此诊断信息。由于始终首先找到 Object
中的成员,因此永远无法使用这样的成员。
示例
#以下代码会产生此诊断信息,因为 toString
由 Object
定义
extension E on String {
String toString() => this;
}
常见修复
#删除成员或将其重命名,使其名称与 Object
中的成员不冲突
extension E on String {
String displayString() => this;
}
extension_override_access_to_static_member
#扩展重写不能用于访问扩展中的静态成员。
描述
#当扩展重写是静态成员调用的接收者时,分析器会产生此诊断信息。与类中的静态成员类似,扩展的静态成员应该使用扩展的名称访问,而不是扩展重写。
示例
#以下代码会产生此诊断信息,因为 m
是静态的
extension E on String {
static void m() {}
}
void f() {
E('').m();
}
常见修复
#将扩展重写替换为扩展的名称
extension E on String {
static void m() {}
}
void f() {
E.m();
}
extension_override_argument_not_assignable
#扩展重写 '{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();
}
如果存在对参数类型有效的其他扩展,则要么替换扩展的名称,要么解包参数以便找到正确的扩展。
extension_override_without_access
#扩展重写只能用于访问实例成员。
描述
#当发现扩展重写没有用于访问扩展的成员之一时,分析器会产生此诊断信息。扩展重写语法没有任何运行时语义;它只控制在编译时选择哪个成员。
示例
#以下代码会产生此诊断信息,因为 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);
}
extension_override_with_cascade
#扩展重写没有值,因此不能用作级联表达式的接收者。
描述
#当扩展重写用作级联表达式的接收者时,分析器会产生此诊断信息。级联表达式 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();
}
如果有多个级联访问,则需要为每个访问重复扩展重写。
extension_type_constructor_with_super_formal_parameter
#扩展类型构造函数不能声明 super 形参。
描述
#当扩展类型中的构造函数具有 super 参数时,分析器会产生此诊断信息。super 参数无效,因为扩展类型没有超类。
示例
#以下代码会产生此诊断信息,因为命名的构造函数 n
包含一个 super 参数
extension type E(int i) {
E.n(this.i, super.foo);
}
常见修复
#如果您需要该参数,请将 super 参数替换为普通参数
extension type E(int i) {
E.n(this.i, String foo);
}
如果您不需要该参数,请删除 super 参数
extension type E(int i) {
E.n(this.i);
}
extension_type_constructor_with_super_invocation
#扩展类型构造函数不能包含 super 初始化器。
描述
#当扩展类型中的构造函数在其初始化列表中包含对 super 构造函数的调用时,分析器会产生此诊断信息。因为扩展类型没有超类,所以没有要调用的构造函数。
示例
#以下代码会产生此诊断信息,因为构造函数 E.n
在其初始化列表中调用 super 构造函数
extension type E(int i) {
E.n() : i = 0, super.n();
}
常见修复
#删除对 super 构造函数的调用
extension type E(int i) {
E.n() : i = 0;
}
extension_type_declares_instance_field
#扩展类型不能声明实例字段。
描述
#当扩展类型声明的主体中存在字段声明时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为扩展类型 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);
}
extension_type_declares_member_of_object
#扩展类型不能声明与 '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) {}
extension_type_implements_disallowed_type
#扩展类型不能实现 '{0}'。
描述
#当扩展类型实现其不允许实现的类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为扩展类型不能实现 dynamic
类型
extension type A(int i) implements dynamic {}
常见修复
#从 implements 子句中删除不允许的类型
extension type A(int i) {}
extension_type_implements_itself
#扩展类型不能实现自身。
描述
#当扩展类型直接或间接地实现自身时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为扩展类型 A
直接实现自身
extension type A(int i) implements A {}
以下代码会产生此诊断信息,因为扩展类型 A
间接地实现自身(通过 B
)
extension type A(int i) implements B {}
extension type B(int i) implements A {}
常见修复
#通过从参与循环的至少一个类型的 implements 子句中删除类型来打破循环
extension type A(int i) implements B {}
extension type B(int i) {}
extension_type_implements_not_supertype
#'{0}' 不是 '{1}' (表示类型) 的超类型。
描述
#当扩展类型实现不是表示类型的超类型的类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为扩展类型 A
实现了 String
,但 String
不是表示类型 int
的超类型
extension type A(int i) implements String {}
常见修复
#如果表示类型正确,则删除或替换 implements 子句中的类型
extension type A(int i) {}
如果表示类型不正确,则将其替换为正确的类型
extension type A(String s) implements String {}
extension_type_implements_representation_not_supertype
#'{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 {}
要么从 implements 子句中删除被实现的类型
extension type A(num i) {}
extension type B(String s) {}
extension_type_inherited_member_conflict
#扩展类型 '{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 {}
extension_type_representation_depends_on_itself
#扩展类型表示不能依赖于自身。
描述
#当扩展类型具有依赖于扩展类型自身的表示类型(直接或间接依赖)时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断,因为扩展类型 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) {}
extension_type_representation_type_bottom
#表示类型不能是底部类型。
描述
#当扩展类型的表示类型是底部类型 Never
时,分析器会产生此诊断。类型 Never
不能作为扩展类型的表示类型,因为没有可以扩展的值。
示例
#以下代码会产生此诊断,因为扩展类型 E
的表示类型为 Never
extension type E(Never n) {}
常见修复
#将扩展类型替换为其他类型
extension type E(String s) {}
extension_type_with_abstract_member
#“{0}” 必须具有方法体,因为“{1}” 是扩展类型。
描述
#当扩展类型声明一个抽象成员时,分析器会产生此诊断。由于扩展类型成员引用是静态解析的,因此永远无法执行扩展类型中的抽象成员。
示例
#以下代码会产生此诊断,因为扩展类型 E
中的方法 m
是抽象的
extension type E(String s) {
void m();
}
常见修复
#如果该成员打算可执行,则提供该成员的实现
extension type E(String s) {
void m() {}
}
如果该成员不打算可执行,则将其删除
extension type E(String s) {}
external_with_initializer
#外部字段不能有初始值设定项。
外部变量不能有初始值设定项。
描述
#当使用关键字 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;
}
extra_annotation_on_struct_field
#结构类中的字段必须只有一个指示本机类型的注解。
描述
#当 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;
}
extra_positional_arguments
#位置参数过多:预期 {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);
}
extra_positional_arguments_could_be_named
#位置参数过多:预期 {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;
}
ffi_native_invalid_duplicate_default_asset
#一个库最多只能有一个 @DefaultAsset 注解。
描述
#当库指令具有多个与之关联的 DefaultAsset
注解时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为库指令具有两个与之关联的 DefaultAsset
注解
@DefaultAsset('a')
@DefaultAsset('b')
library;
import 'dart:ffi';
常见修复
#删除除一个以外的所有 DefaultAsset
注解
@DefaultAsset('a')
library;
import 'dart:ffi';
ffi_native_invalid_multiple_annotations
#本机函数和字段必须只有一个 @Native
注解。
描述
#当单个声明上有多个 Native
注解时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为函数 f
有两个与之关联的 Native
注解
import 'dart:ffi';
@Native<Int32 Function(Int32)>()
@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);
常见修复
#删除除一个以外的所有注解
import 'dart:ffi';
@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);
ffi_native_must_be_external
#本机函数必须声明为外部的。
描述
#当被注解为 @Native
的函数没有标记为 external
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为函数 free
被注解为 @Native
,但该函数没有标记为 external
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
void free(Pointer<Void> ptr) {}
常见修复
#如果该函数是本机函数,则在返回类型之前添加修饰符 external
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);
ffi_native_unexpected_number_of_parameters
#Native 注解参数的数量不符合预期。预期 {0} 个,但有 {1} 个。
描述
#当用作 @Native
注解的类型参数的函数类型中的参数数量与被注解的函数中的参数数量不匹配时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为用作 @Native
注解的类型参数的函数类型 (Void Function(Double)
) 有一个参数,而被注解的函数类型 (void f(double, double)
) 有两个参数
import 'dart:ffi';
@Native<Void Function(Double)>(symbol: 'f')
external void f(double x, double y);
常见修复
#如果被注解的函数是正确的,则更新 @Native
注解中的函数类型以匹配
import 'dart:ffi';
@Native<Void Function(Double, Double)>(symbol: 'f')
external void f(double x, double y);
如果 @Native
注解中的函数类型是正确的,则更新被注解的函数以匹配
import 'dart:ffi';
@Native<Void Function(Double)>(symbol: 'f')
external void f(double x);
ffi_native_unexpected_number_of_parameters_with_receiver
#Native 注解参数的数量不符合预期。预期 {0} 个,但有 {1} 个。本机实例方法注解必须将接收器作为第一个参数。
描述
#当本机方法的 @Native
注解上使用的类型参数不包含该方法的接收器的类型时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 @Native
注解上的类型参数 (Void Function(Double)
) 不包含该方法的接收器的类型
import 'dart:ffi';
class C {
@Native<Void Function(Double)>()
external void f(double x);
}
常见修复
#添加一个初始参数,其类型与声明本机方法的类相同
import 'dart:ffi';
class C {
@Native<Void Function(C, Double)>()
external void f(double x);
}
field_initialized_by_multiple_initializers
#在同一个构造函数中,字段“{0}”不能初始化两次。
描述
#当构造函数的初始值设定项列表多次初始化一个字段时,分析器会产生此诊断。不允许使用两个初始值设定项,因为只保留最后一个值。
示例
#以下代码会产生此诊断,因为字段 f
被初始化两次
class C {
int f;
C() : f = 0, f = 1;
}
常见修复
#删除其中一个初始值设定项
class C {
int f;
C() : f = 0;
}
field_initialized_in_initializer_and_declaration
#如果字段是 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;
}
field_initialized_in_parameter_and_initializer
#字段不能在参数列表和初始值设定项中都初始化。
描述
#当字段在参数列表和构造函数的初始值设定项列表中都初始化时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字段 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;
}
field_initializer_factory_constructor
#初始化形参不能在工厂构造函数中使用。
描述
#当工厂构造函数具有初始化形参时,分析器会产生此诊断。工厂构造函数不能为字段赋值,因为不会创建实例;因此,没有要赋值的字段。
示例
#以下代码会产生此诊断,因为工厂构造函数使用了初始化形参
class C {
int? f;
factory C(this.f) => throw 0;
}
常见修复
#将初始化形参替换为普通参数
class C {
int? f;
factory C(int f) => throw 0;
}
field_initializer_in_struct
#“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();
}
field_initializer_not_assignable
#在常量构造函数中,初始值设定项类型“{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;
}
field_initializer_outside_constructor
#字段形参只能在构造函数中使用。
初始化形参只能在构造函数中使用。
描述
#当初始化形参用于除构造函数之外的任何参数列表时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为初始化形参 this.x
在方法 m
中使用
class A {
int x = 0;
m([this.x = 0]) {}
}
常见修复
#将初始化形参替换为普通参数,并在方法的主体中赋值给该字段
class A {
int x = 0;
m([int x = 0]) {
this.x = x;
}
}
field_initializer_redirecting_constructor
#重定向构造函数不能有字段初始值设定项。
描述
#当重定向构造函数初始化对象中的字段时,分析器会生成此诊断。这是不允许的,因为此时包含该字段的实例尚未被创建,而该字段应该在此处被初始化。
示例
#以下代码会生成此诊断,因为构造函数 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);
}
field_initializing_formal_not_assignable
#参数类型“{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);
}
field_in_struct_with_initializer
#“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;
}
field_must_be_external_in_struct
#“Struct”和“Union”子类的字段必须标记为 external。
描述
#当 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_initialized_in_declaration_and_constructor
#“{0}”是 final 的,并且在声明时已赋值,因此不能设置为新值。
描述
#当 final 字段被初始化两次时,分析器会生成此诊断:一次在声明时,一次通过构造函数的参数。
示例
#以下代码会生成此诊断,因为字段 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_not_initialized
#必须初始化 final 变量“{0}”。
描述
#当 final 字段或变量未初始化时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 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_not_initialized_constructor
#所有 final 变量都必须初始化,但是“{0}”和“{1}”未初始化。
所有 final 变量都必须初始化,但是“{0}”未初始化。
所有 final 变量都必须初始化,但是“{0}”、“{1}”以及其他 {2} 个未初始化。
描述
#当类定义一个或多个没有初始化器的 final 实例字段,并且至少有一个构造函数未初始化这些字段时,分析器会生成此诊断。所有 final 实例字段都必须在创建实例时进行初始化,可以通过字段的初始化器或通过构造函数进行初始化。
示例
#以下代码会产生此诊断
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_field_not_map
#“flutter”字段的值应为映射。
描述
#当 flutter
键的值不是映射时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为顶级 flutter
键的值是字符串。
name: example
flutter: true
常见修复
#如果需要指定特定于 Flutter 的选项,则将该值更改为映射。
name: example
flutter:
uses-material-design: true
如果不需要指定特定于 Flutter 的选项,则删除 flutter
键。
name: example
for_in_of_invalid_element_type
#“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_invalid_type
#“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_with_const_variable
#for-in 循环变量不能是“const”。
描述
#当在 for-in 循环中声明的循环变量被声明为 const
时,分析器会生成此诊断。该变量不能是 const
,因为该值不能在编译时计算。
示例
#以下代码会生成此诊断,因为循环变量 x
被声明为 const
。
void f() {
for (const x in [0, 1, 2]) {
print(x);
}
}
常见修复
#如果存在类型注解,则从声明中删除 const
修饰符。
如果没有类型,则将 const
修饰符替换为 final
、var
或类型注解。
void f() {
for (final x in [0, 1, 2]) {
print(x);
}
}
generic_method_type_instantiation_on_dynamic
#类型为“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;
}
generic_struct_subclass
#类“{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_not_subtype_setter_types
#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) {}
}
illegal_async_generator_return_type
#标记为“async*”的函数必须具有作为“Stream
描述
#当函数的正文具有 async*
修饰符,即使该函数的返回类型不是 Stream
或 Stream
的超类型时,分析器也会生成此诊断。
示例
#以下代码会生成此诊断,因为函数 f
的正文具有“async*”修饰符,即使返回类型 int
不是 Stream
的超类型。
int f() async* {}
常见修复
#如果该函数应该是异步的,则将返回类型更改为 Stream
或 Stream
的超类型。
Stream<int> f() async* {}
如果该函数应该是同步的,则删除 async*
修饰符。
int f() => 0;
illegal_async_return_type
#标记为“async”的函数必须具有作为“Future”超类型的返回类型。
描述
#当函数的正文具有 async
修饰符,即使该函数的返回类型无法分配给 Future
时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为函数 f
的正文具有 async
修饰符,即使返回类型无法分配给 Future
。
int f() async {
return 0;
}
常见修复
#如果该函数应该是异步的,则将返回类型更改为可分配给 Future
的类型。
Future<int> f() async {
return 0;
}
如果该函数应该是同步的,则删除 async
修饰符。
int f() => 0;
illegal_concrete_enum_member
#名为“{0}”的具体实例成员不能在实现“Enum”的类中声明。
名为“{0}”的具体实例成员不能从实现“Enum”的类中的“{1}”继承。
描述
#当枚举声明、实现 Enum
的类或具有 Enum
超类约束的 mixin 声明或继承名为 index
、hashCode
或 ==
的具体实例成员时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为枚举 E
声明了一个名为 index
的实例 getter。
enum E {
v;
int get index => 0;
}
以下代码会生成此诊断,因为实现 Enum
的类 C
声明了一个名为 hashCode
的实例字段。
abstract class C implements Enum {
int hashCode = 0;
}
以下代码会生成此诊断,因为通过类 A
间接实现 Enum
的类 C
声明了一个名为 hashCode
的实例 getter。
abstract class A implements Enum {}
abstract class C implements A {
int get hashCode => 0;
}
以下代码会生成此诊断,因为在 on
子句中具有 Enum
的 mixin M
声明了一个显式运算符 ==
。
mixin M on Enum {
bool operator ==(Object other) => false;
}
常见修复
#重命名冲突的成员。
enum E {
v;
int get getIndex => 0;
}
illegal_enum_values
#名为“values”的实例成员不能在实现“Enum”的类中声明。
名为“values”的实例成员不能从实现“Enum”的类中的“{0}”继承。
描述
#当实现 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;
}
illegal_sync_generator_return_type
#标记为“sync*”的函数必须具有作为“Iterable”的超类型的返回类型。
描述
#当函数的返回类型不是 Iterable
或 Iterable
的超类型时,如果函数体具有 sync*
修饰符,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为函数 f
的函数体具有 sync*
修饰符,即使返回类型 int
不是 Iterable
的超类型。
int f() sync* {}
常见修复
#如果函数应该返回一个可迭代对象,则将返回类型更改为 Iterable
或 Iterable
的超类型。
Iterable<int> f() sync* {}
如果函数应该返回单个值,则删除 sync*
修饰符。
int f() => 0;
implements_non_class
#类和混入只能实现其他类和混入。
描述
#当类或混入声明的 implements
子句中使用的名称被定义为其他类型(而非类或混入)时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 x
是一个变量,而不是类或混入。
var x;
class C implements x {}
常见修复
#如果该名称是已导入的现有类或混入的名称,则向导入添加前缀,以便该名称的本地定义不会遮蔽导入的名称。
如果该名称是未导入的现有类或混入的名称,则为声明该名称的库添加一个带有前缀的导入。
否则,请将 implements
子句中的名称替换为现有类或混入的名称,或者从 implements
子句中删除该名称。
implements_repeated
#“{0}”只能实现一次。
描述
#当一个类在 implements
子句中被指定多次时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 A
在列表中出现了两次。
class A {}
class B implements A, A {}
常见修复
#删除类名的所有重复项,只保留一个。
class A {}
class B implements A {}
implements_super_class
#“{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 {}
implicit_super_initializer_missing_arguments
#从“{0}”隐式调用的未命名构造函数具有必需的参数。
描述
#当构造函数隐式调用超类的未命名构造函数,而超类的未命名构造函数具有必需的参数,并且没有与该必需参数对应的 super 参数时,分析器会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为类 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();
}
常见修复
#如果可以在子类的构造函数中添加参数,则添加与超类构造函数中必需参数对应的 super 参数。新参数可以是必需的
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});
}
如果不能在子类的构造函数中添加参数,则添加带有必需参数的显式 super 构造函数调用。
class A {
A(int x);
}
class B extends A {
B() : super(0);
}
implicit_this_reference_in_initializer
#实例成员“{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;
}
import_deferred_library_with_load_function
#导入的库定义了一个名为“loadLibrary”的顶层函数,该函数被延迟此库的操作隐藏。
描述
#当使用延迟导入导入声明了名为 loadLibrary
的函数的库时,分析器会生成此诊断信息。延迟导入引入一个隐式函数 loadLibrary
。此函数用于加载延迟库的内容,并且隐式函数隐藏了延迟库中的显式声明。
有关详细信息,请查看延迟加载库。
示例
#假设有一个名为 a.dart
的文件,其中定义了一个名为 loadLibrary
的函数:
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();
}
import_internal_library
#库“{0}”是内部库,无法导入。
描述
#当分析器找到其 dart:
URI 引用内部库的导入时,会生成此诊断信息。
示例
#以下代码会生成此诊断信息,因为 _interceptors
是一个内部库
import 'dart:_interceptors';
常见修复
#删除 import 指令。
import_of_legacy_library_into_null_safe
#库“{0}”是旧版库,不应导入到空安全库中。
描述
#当一个空安全库导入一个非空安全库时,分析器会生成此诊断信息。
示例
#假设有一个名为 a.dart
的文件,其中包含以下内容:
// @dart = 2.9
class A {}
以下代码会生成此诊断信息,因为一个空安全库正在导入一个非空安全库。
import 'a.dart';
A? f() => null;
常见修复
#如果可以将导入的库迁移为空安全库,则迁移它并更新或删除迁移后的库的语言版本。
如果无法迁移导入的库,则导入库需要具有 2.12 之前的语言版本,在该版本中,默认情况下启用了空安全。
import_of_non_library
#导入的库“{0}”不能具有 part-of 指令。
描述
#当一个部分文件被导入到库中时,分析器会生成此诊断信息。
示例
#假设有一个名为 part.dart
的 部分文件,其中包含以下内容:
part of lib;
以下代码会生成此诊断信息,因为导入的文件不能具有 part-of 指令。
library lib;
import 'part.dart';
常见修复
#inconsistent_inheritance
#超接口对“{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}) {}
}
inconsistent_language_version_override
#部分必须与库具有完全相同的语言版本覆盖。
描述
#当 部分文件 具有指定的语言版本与该部分所属的库所使用的语言版本不同的语言版本覆盖注释时,分析器会生成此诊断信息。
示例
#假设有一个名为 part.dart
的 部分文件,其中包含以下内容:
// @dart = 2.14
part of 'test.dart';
以下代码会生成此诊断信息,因为库的各个部分必须与定义编译单元具有相同的语言版本。
// @dart = 2.15
part 'part.dart';
常见修复
#从 部分文件 中删除语言版本覆盖,以便它隐式使用与定义编译单元相同的版本。
part of 'test.dart';
如有必要,请调整定义编译单元中的语言版本覆盖以适合该部分中的代码,或者迁移 部分文件 中的代码以与新的语言版本保持一致。
inconsistent_pattern_variable_logical_or
#变量“{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);
}
}
initializer_for_non_existent_field
#“{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;
}
initializer_for_static_field
#“{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;
}
}
initializing_formal_for_non_existent_field
#“{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();
}
instance_access_to_static_member
#静态 {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;
}
instance_member_access_from_factory
#实例成员不能从工厂构造函数访问。
描述
#当工厂构造函数包含对实例成员的非限定引用时,分析器会生成此诊断。在生成构造函数中,类的实例在执行构造函数的主体之前创建并初始化,因此该实例可以绑定到 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);
}
instance_member_access_from_static
#实例成员不能从静态方法访问。
描述
#当静态方法包含对实例成员的非限定引用时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为实例字段 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;
}
}
instantiate_abstract_class
#抽象类不能实例化。
描述
#当分析器找到构造函数调用且该构造函数在抽象类中声明时,分析器会生成此诊断。即使您不能创建抽象类的实例,抽象类也可以声明可以由子类调用的构造函数。
示例
#以下代码会产生此诊断,因为 C
是一个抽象类。
abstract class C {}
var c = new C();
常见修复
#如果存在可以使用的抽象类的具体子类,则创建具体子类的实例。
instantiate_enum
#枚举不能实例化。
描述
#当枚举被实例化时,分析器会生成此诊断。通过调用构造函数来创建枚举的实例是无效的;只有在枚举的声明中命名的实例才能存在。
示例
#以下代码会产生此诊断,因为枚举 E
正在被实例化。
// @dart = 2.16
enum E {a}
var e = E();
常见修复
#如果您打算使用枚举的实例,则引用枚举中定义的常量之一。
// @dart = 2.16
enum E {a}
var e = E.a;
如果您打算使用类的实例,则使用该类的名称代替枚举的名称。
instantiate_type_alias_expands_to_type_parameter
#扩展到类型参数的类型别名不能实例化。
描述
#当发现构造函数调用,且要实例化的类型是类型别名的类型参数之一的类型别名时,分析器会生成此诊断。这是不允许的,因为类型参数的值是一个类型而不是一个类。
示例
#以下代码会产生此诊断,因为它创建了 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();
}
integer_literal_imprecise_as_double
#整数字面量正在用作双精度浮点数,但不能在不溢出或损失精度的情况下表示为 64 位双精度浮点数:“{0}”。
描述
#当整数字面量被隐式转换为双精度浮点数,但不能在不溢出或损失精度的情况下表示为 64 位双精度浮点数时,分析器会生成此诊断。如果上下文需要类型 double
,则整数字面量会隐式转换为双精度浮点数。
示例
#以下代码会产生此诊断,因为整数值 9223372036854775807
不能精确地表示为双精度浮点数。
double x = 9223372036854775807;
常见修复
#如果您需要使用精确的值,则使用类 BigInt
来表示该值。
var x = BigInt.parse('9223372036854775807');
如果您需要使用双精度浮点数,则将该值更改为可以精确表示的值。
double x = 9223372036854775808;
integer_literal_out_of_range
#整数字面量 {0} 不能用 64 位表示。
描述
#当整数字面量的值太大(正数)或太小(负数)而无法用 64 位字表示时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为该值无法用 64 位表示。
var x = 9223372036854775810;
常见修复
#如果您需要表示当前值,则将其包装在类 BigInt
的实例中。
var x = BigInt.parse('9223372036854775810');
invalid_annotation
#注解必须是常量变量引用或常量构造函数调用。
描述
#当发现一个注解正在使用既不是标记为 const
的变量也不是 const
构造函数的调用的东西时,分析器会生成此诊断。
Getter 不能用作注解。
示例
#以下代码会产生此诊断,因为变量 v
不是 const
变量。
var v = 0;
@v
void f() {
}
以下代码会产生此诊断,因为 f
不是变量。
@f
void f() {
}
以下代码会产生此诊断,因为 f
不是构造函数。
@f()
void f() {
}
以下代码会产生此诊断,因为 g
是一个 getter。
@g
int get g => 0;
常见修复
#如果注解引用的是一个不是 const
构造函数的变量,则将关键字 const
添加到变量的声明中。
const v = 0;
@v
void f() {
}
如果注解未引用变量,则将其删除。
int v = 0;
void f() {
}
invalid_annotation_constant_value_from_deferred_library
#延迟库中的常量值不能在注解中使用。
描述
#当在注解的参数列表中引用延迟导入的库中定义的常量时,分析器会生成此诊断。注解在编译时进行评估,并且延迟库中的值在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#以下代码会产生此诊断,因为常量 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 () {}
如果导入必须延迟并且有另一个合适的常量,则使用该常量代替延迟库中的常量。
invalid_annotation_from_deferred_library
#延迟库中的常量值不能用作注解。
描述
#当使用延迟导入导入的库中的常量用作注解时,分析器会生成此诊断。注解在编译时进行评估,并且延迟库中的常量在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#以下代码会产生此诊断,因为当库 dart:math
被导入为 deferred
时,常量 pi
被用作注解。
import 'dart:math' deferred as math;
@math.pi
void f() {}
常见修复
#如果您需要将常量作为注解引用,则从导入中删除关键字 deferred
。
import 'dart:math' as math;
@math.pi
void f() {}
如果您可以使用不同的常量作为注解,则将注解替换为不同的常量。
@deprecated
void f() {}
invalid_annotation_target
#注解“{0}”只能在 {1} 上使用。
描述
#当注解应用于它不支持的声明类型时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为 optionalTypeArgs
注解未定义为对顶级变量有效。
import 'package:meta/meta.dart';
@optionalTypeArgs
int x = 0;
常见修复
#从声明中删除注解。
invalid_assignment
#类型为“{0}”的值不能分配给类型为“{1}”的变量。
描述
#当分配给变量的表达式的静态类型不能分配给该变量的类型时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为初始化器的类型 (int
) 不能分配给变量的类型 (String
)。
int i = 0;
String s = i;
常见修复
#如果被赋值的值在运行时始终可分配,即使静态类型没有反映这一点,则添加显式转换。
否则,更改被赋值的值,使其具有预期的类型。在前面的示例中,这可能看起来像
int i = 0;
String s = i.toString();
如果您无法更改值,则更改变量的类型以使其与被赋值的值的类型兼容。
int i = 0;
int s = i;
invalid_dependency
#可发布的包不能有“{0}”依赖项。
描述
#当可发布的包在其 pubspec.yaml
文件的 dependencies
列表中包含一个不是 pub 托管依赖项的包时,分析器会生成此诊断。
要了解有关不同类型的依赖项来源的更多信息,请查看包依赖项。
示例
#以下代码会产生此诊断,因为对包 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
invalid_exception_value
#当函数的返回类型为 '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);
}
invalid_export_of_internal_element
#成员 '{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;
如果不需要导出,则将其删除。
invalid_export_of_internal_element_indirectly
#成员 '{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
子句中,或删除导出。
invalid_extension_argument_count
#扩展覆盖必须恰好有一个参数:即扩展方法中 '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');
}
invalid_factory_method_decl
#工厂方法 '{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 {}
invalid_factory_method_impl
#工厂方法 '{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 {}
invalid_factory_name_not_a_class
#工厂构造函数的名称必须与直接包围它的类的名称相同。
描述
#当工厂构造函数的名称与周围类的名称不同时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为工厂构造函数的名称 (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;
}
invalid_field_name
#当整数是位置字段的索引时,记录字段名称不能是美元符号后跟一个整数。
记录字段名称不能是私有的。
记录字段名称不能与 '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);
invalid_field_type_in_struct
#结构体类中的字段不能具有 '{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;
}
invalid_implementation_override
#'{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();
}
invalid_inline_function_type
#内联函数类型不能用于泛型函数类型中的参数。
描述
#当泛型函数类型具有使用较旧的内联函数类型语法编写的函数值参数时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为用于定义 F
的泛型函数类型中的参数 f
使用了内联函数类型语法。
typedef F = int Function(int f(String s));
常见修复
#为参数的类型使用泛型函数语法。
typedef F = int Function(int Function(String));
invalid_internal_annotation
#只有软件包私有 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 {}
invalid_language_version_override
#Dart 语言版本覆盖注释后不能跟任何非空白字符。
Dart 语言版本覆盖注释必须在 '=' 字符后指定版本号,例如 '2.0'。
Dart 语言版本覆盖注释必须使用 '=' 字符指定。
Dart 语言版本覆盖注释必须使用两个斜杠指定。
Dart 语言版本覆盖注释必须使用全小写的单词 'dart' 指定。
Dart 语言版本覆盖号不能以字母为前缀。
Dart 语言版本覆盖号必须以 '@dart' 开头。
语言版本覆盖不能指定大于最新已知语言版本的版本:{0}.{1}。
语言版本覆盖必须在任何声明或指令之前指定。
描述
#当注释看起来像是尝试指定语言版本覆盖,但不符合此类注释的要求时,分析器会生成此诊断。有关更多信息,请参阅按库选择语言版本。
示例
#以下代码会生成此诊断,因为在此类注释中,单词 dart
必须为小写,并且单词 dart
和版本号之间没有等号。
// @Dart 2.13
常见修复
#如果注释旨在作为语言版本覆盖,请将注释更改为遵循正确的格式。
// @dart = 2.13
invalid_literal_annotation
#只有 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;
invalid_modifier_on_constructor
#修饰符 '{0}' 不能应用于构造函数的主体。
描述
#当构造函数的主体以以下修饰符之一作为前缀时,分析器会生成此诊断:async
、async*
或 sync*
。构造函数主体必须是同步的。
示例
#以下代码会生成此诊断,因为 C
的构造函数的主体被标记为 async
。
class C {
C() async {}
}
常见修复
#如果构造函数可以是同步的,则删除修饰符。
class C {
C();
}
如果构造函数不能是同步的,则使用静态方法来创建实例。
class C {
C();
static Future<C> c() async {
return C();
}
}
invalid_modifier_on_setter
#Setter 不能使用 'async'、'async*' 或 'sync*'。
描述
#当 setter 的主体以以下修饰符之一作为前缀时,分析器会生成此诊断:async
、async*
或 sync*
。Setter 主体必须是同步的。
示例
#以下代码会生成此诊断,因为 setter x
的主体被标记为 async
。
class C {
set x(int i) async {}
}
常见修复
#如果 setter 可以是同步的,则删除修饰符。
class C {
set x(int i) {}
}
如果 setter 不能是同步的,则使用方法来设置值。
class C {
void x(int i) async {}
}
invalid_non_virtual_annotation
#注解 '@nonVirtual' 只能应用于具体的实例成员。
描述
#当在类、mixin 或枚举的成员之外的声明中找到 nonVirtual
注解时,或者如果成员不是具体的实例成员时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为注解位于类声明而不是类内部的成员上。
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() {}
}
invalid_null_aware_operator
#元素不能为 null,因此 null 感知运算符 '?' 是不必要的。
映射条目的键不能为 null,因此 null 感知运算符 '?' 是不必要的。
映射条目的值不能为 null,因此 null 感知运算符 '?' 是不必要的。
由于短路,接收器不能为 'null',因此不能使用 null 感知运算符 '{0}'。
接收器不能为 null,因此 null 感知运算符 '{0}' 是不必要的。
描述
#当在已知为非空值的接收器上使用 null 感知运算符(?.
、?..
、?[
、?..[
或 ...?
)时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 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
后面的 null 感知运算符会短路 length
和 isEven
的计算。换句话说,如果 s
为 null
,则既不会调用 length
也不会调用 isEven
,如果 s
为非 null
,则 length
不能返回 null
值。无论哪种方式,都不能在 null
值上调用 isEven
,因此 null 感知运算符不是必需的。有关更多详细信息,请参阅了解空安全。
以下代码会生成此诊断,因为 s
不能为 null
。
void f(Object? o) {
var s = o as String;
s?.length;
}
s
不能为 null 的原因是,尽管 o
可以为 null
,但是由于转换为 String
(非可空类型)。如果 o
的值始终为 null
,则转换将失败,并且不会发生 length
的调用。
以下代码会生成此诊断,因为 s
不能为 null
。
List<String> makeSingletonList(String s) {
return <String>[?s];
}
常见修复
#将 null 感知运算符替换为非 null 感知运算符等效项;例如,将 ?.
更改为 .
。
int getLength(String s) {
return s.length;
}
(请注意,返回类型也更改为了非可空,这在某些情况下可能不合适。)
invalid_override
#'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效重写。
setter '{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) {}
}
invalid_override_of_non_virtual_member
#成员 '{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() {}
}
invalid_pattern_variable_in_shared_case_scope
#变量 '{0}' 在共享此主体的所有情况下不具有相同的类型和/或最终性。
变量 '{0}' 在共享此主体的某些情况下可用,但在并非所有情况下都可用。
变量 '{0}' 不可用,因为存在标签或“default”情况。
描述
#当 switch 语句中的多个 case 子句共享一个主体,并且至少其中一个声明了一个在共享语句中引用的变量,但该变量不是在所有 case 子句中声明的,或者声明方式不一致时,分析器会生成此诊断。
如果变量不是在所有 case 子句中声明的,那么如果与未声明该变量的子句匹配并执行主体,则该变量将没有值。这包括 case 子句之一是 default
子句的情况。
如果变量的声明方式不一致,即在某些情况下是 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;
}
}
以下代码会生成此诊断,因为如果一组不同的 case 导致控制在标签处继续,则变量 a
将没有值。
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;
}
}
invalid_platforms_field
#'platforms' 字段必须是具有平台作为键的映射。
描述
#当指定了顶级 platforms
字段,但其值不是具有键的映射时,分析器会生成此诊断。要了解有关指定软件包支持的平台的更多信息,请查看有关平台声明的文档。
示例
#以下 pubspec.yaml
会产生此诊断,因为 platforms
应该是一个映射(map)。
name: example
platforms:
- android
- web
- ios
常见修复
#如果您可以依赖自动平台检测,则省略顶级的 platforms
字段。
name: example
如果您需要手动指定支持的平台列表,请将 platforms
字段写成一个映射,其中平台名称作为键。
name: example
platforms:
android:
web:
ios:
invalid_reference_to_generative_enum_constructor
#生成式枚举构造函数只能用作重定向的目标。
描述
#当枚举上定义的生成式构造函数在除创建枚举常量或作为同一枚举中另一个构造函数的重定向目标之外的任何地方使用时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 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);
invalid_reference_to_this
#对 'this' 表达式的引用无效。
描述
#当在实例方法或生成式构造函数之外使用 this
时,分析器会产生此诊断。保留字 this
仅在实例方法、生成式构造函数或 late 实例字段声明的初始化器上下文中定义。
示例
#以下代码会产生此诊断,因为 v
是一个顶级变量。
C f() => this;
class C {}
常见修复
#使用适当类型的变量来代替 this
,如有必要,则声明它。
C f(C c) => c;
class C {}
invalid_return_type_for_catch_error
#类型为 '{0}' 的值不能由 'onError' 处理程序返回,因为它必须可赋值给 '{1}'。
根据 'Future.catchError' 的要求,返回类型 '{0}' 不可赋值给 '{1}'。
描述
#当 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);
}
invalid_sealed_annotation
#注解 '@sealed' 只能应用于类。
描述
#当除类声明之外的声明带有 @sealed
注解时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 @sealed
注解位于方法声明上。
import 'package:meta/meta.dart';
class A {
@sealed
void m() {}
}
常见修复
#删除注解。
class A {
void m() {}
}
invalid_super_formal_parameter_location
#Super 参数只能在非重定向的生成式构造函数中使用。
描述
#当 super 参数在非重定向的生成式构造函数之外的任何地方使用时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 super 参数 x
位于重定向的生成式构造函数中。
class A {
A(int x);
}
class B extends A {
B.b(super.x) : this._();
B._() : super(0);
}
以下代码会产生此诊断,因为 super 参数 x
不在生成式构造函数中。
class A {
A(int x);
}
class C extends A {
factory C.c(super.x) => C._();
C._() : super(0);
}
以下代码会产生此诊断,因为 super 参数 x
位于方法中。
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(super.x) {}
}
常见修复
#如果包含 super 参数的函数可以更改为非重定向的生成式构造函数,则执行此操作。
class A {
A(int x);
}
class B extends A {
B.b(super.x);
}
如果包含 super 参数的函数不能更改为非重定向的生成式构造函数,则删除 super
。
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(int x) {}
}
invalid_type_argument_in_const_literal
#常量列表字面量不能在类型参数中使用类型参数,例如 '{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>[];
invalid_uri
#URI 语法无效:'{0}'。
描述
#当指令中的 URI 不符合有效 URI 的语法时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 '#'
不是有效的 URI。
import '#';
常见修复
#将无效的 URI 替换为有效的 URI。
invalid_use_of_covariant_in_extension
#扩展中不能有修饰符 '{0}'。
描述
#当在扩展内部声明的成员在参数声明中使用关键字 covariant
时,分析器会产生此诊断。扩展不是类,没有子类,因此关键字不起作用。
示例
#以下代码会产生此诊断,因为 i
被标记为协变。
extension E on String {
void a(covariant int i) {}
}
常见修复
#删除 covariant
关键字。
extension E on String {
void a(int i) {}
}
invalid_use_of_internal_member
#成员 '{0}' 只能在其包内使用。
描述
#当在包含声明的包之外发现对用 internal
注解的声明的引用时,分析器会产生此诊断。
示例
#给定一个包 p
,它定义了一个库,其中包含一个用 internal
注解标记的声明
import 'package:meta/meta.dart';
@internal
class C {}
以下代码会产生此诊断,因为它引用了类 C
,该类不打算在包 p
之外使用
import 'package:p/src/p.dart';
void f(C c) {}
常见修复
#删除对内部声明的引用。
invalid_use_of_null_value
#值始终为 'null' 的表达式不能被解引用。
描述
#当值始终为 null
的表达式被解引用时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 x
将始终为 null
。
int f(Null x) {
return x.length;
}
常见修复
#如果允许该值不是 null
,则更改表达式的类型。
int f(String? x) {
return x!.length;
}
invalid_use_of_type_outside_library
#类 '{0}' 不能在其库之外扩展,因为它是一个 final 类。
类 '{0}' 不能在其库之外扩展,因为它是一个接口类。
类 '{0}' 不能在其库之外扩展、实现或混合使用,因为它是一个密封类。
类 '{0}' 不能在其库之外实现,因为它是一个基类。
类 '{0}' 不能在其库之外实现,因为它是一个 final 类。
类 '{0}' 不能在其库之外用作混入超类约束,因为它是一个 final 类。
混入 '{0}' 不能在其库之外实现,因为它是一个基本混入。
描述
#当 extends
、implements
、with
或 on
子句以不允许的方式使用类或混入时,分析器会产生此诊断,这取决于该类或混入声明上的修饰符。
消息指定了声明的使用方式以及为什么不允许使用。
示例
#给定一个文件 a.dart
,它定义了一个基类 A
base class A {}
以下代码会产生此诊断,因为类 B
实现了类 A
,但是 base
修饰符阻止了在定义 A
的库之外实现 A
。
import 'a.dart';
final class B implements A {}
常见修复
#此类型的使用限制在其声明库之外。如果可以使用不同的、不受限制的类型来提供类似的功能,则替换该类型。
class B implements C {}
class C {}
如果没有合适的其他类型,则删除该类型,并可能删除整个子句。
class B {}
invalid_use_of_visible_for_overriding_member
#成员 '{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();
}
}
常见修复
#删除对成员的无效使用。
invalid_use_of_visible_for_testing_member
#成员 '{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() {}
}
invalid_visibility_annotation
#成员 '{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();
invalid_visible_for_overriding_annotation
#注解 'visibleForOverriding' 只能应用于可以被重写的公共实例成员。
描述
#当类中的公共实例成员之外的任何内容被标注 visibleForOverriding
时,分析器会生成此诊断信息。因为只有公共实例成员才能在定义库之外被重写,所以标注任何其他声明没有任何意义。
示例
#以下代码产生此诊断信息,因为注解位于类上,而类不能被重写。
import 'package:meta/meta.dart';
@visibleForOverriding
class C {}
常见修复
#删除注解。
class C {}
invalid_visible_outside_template_annotation
#注解 'visibleOutsideTemplate' 只能应用于带有 'visibleForTemplate' 注解的类、枚举或混入的成员。
描述
#当 @visibleOutsideTemplate
注解被错误使用时,分析器会生成此诊断信息。此注解仅用于标注具有 @visibleForTemplate
注解的类、枚举或混入的成员,以使这些成员不受 @visibleForTemplate
施加的可见性限制。
示例
#以下代码产生此诊断信息,因为类级别没有 @visibleForTemplate
注解。
import 'package:angular_meta/angular_meta.dart';
class C {
@visibleOutsideTemplate
int m() {
return 1;
}
}
以下代码产生此诊断信息,因为注解位于类声明上,而不是类、枚举或混入的成员上。
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
注解,请移除该注解。
class C {}
invocation_of_extension_without_call
#扩展 '{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
方法。
invocation_of_non_function
#'{0}' 不是函数。
描述
#当分析器发现函数调用,但被调用函数的名称定义为不是函数的东西时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为 Binary
是函数类型的名称,而不是函数。
typedef Binary = int Function(int, int);
int f() {
return Binary(1, 2);
}
常见修复
#将名称替换为函数的名称。
invocation_of_non_function_expression
#该表达式未计算为函数,因此无法调用。
描述
#当发现函数调用,但被引用的名称不是函数的名称,或者计算函数的表达式未计算出函数时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为 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();
label_in_outer_scope
#无法引用在外部方法中声明的标签 '{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;
}
}
}
label_undefined
#无法引用未定义的标签 '{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;
}
}
}
}
late_final_field_with_const_constructor
#具有生成 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();
}
late_final_local_already_assigned
#延迟 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;
}
leaf_call_must_not_return_handle
#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);
}
leaf_call_must_not_take_handle
#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);
}
list_element_type_not_assignable
#元素类型 '{0}' 不能赋值给列表类型 '{1}'。
描述
#当列表字面量中的元素的类型不能赋值给列表的元素类型时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为 2.5
是 double 类型,而列表只能容纳整数。
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_first_positional_parameter_type
#'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_has_required_named_parameters
#函数 'main' 不能有任何必需的命名参数。
描述
#当名为 main
的函数具有一个或多个必需的命名参数时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为名为 main
的函数具有必需的命名参数 (x
)。
void main({required int x}) {}
常见修复
#如果该函数是入口点,则删除 required
关键字。
void main({int? x}) {}
如果该函数不是入口点,则更改该函数的名称。
void f({required int x}) {}
main_has_too_many_required_positional_parameters
#函数 '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_is_not_function
#名为 'main' 的声明必须是函数。
描述
#当库包含名称为 main
的声明,但该声明不是顶级函数的声明时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为名称 main
被用于声明顶级变量。
var main = 3;
常见修复
#对声明使用不同的名称。
var mainIndex = 3;
map_entry_not_in_map
#Map 条目只能在 Map 字面量中使用。
描述
#当在 Set 字面量中找到 Map 条目(键/值对)时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为字面量具有 Map 条目,即使它是 Set 字面量。
var collection = <String>{'a' : 'b'};
常见修复
#如果打算将集合作为 Map,则更改代码使其成为 Map。在之前的示例中,可以通过添加另一个类型参数来实现。
var collection = <String, String>{'a' : 'b'};
在其他情况下,您可能需要将显式类型从 Set
更改为 Map
。
如果打算将集合作为 Set,则删除 Map 条目,如果两个值都应包含在 Set 中,则可以用逗号替换冒号。
var collection = <String>{'a', 'b'};
map_key_type_not_assignable
#元素类型 '{0}' 不能赋值给 Map 键类型 '{1}'。
描述
#当 Map 字面量中键值对的键的类型不能赋值给 Map 的键类型时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为 2
是 int
类型,但 Map 的键必须是 String
类型。
var m = <String, String>{2 : 'a'};
常见修复
#如果 Map 的类型正确,则将键更改为正确的类型。
var m = <String, String>{'2' : 'a'};
如果键的类型正确,则更改 Map 的键类型。
var m = <int, String>{2 : 'a'};
map_value_type_not_assignable
#元素类型 '{0}' 不能赋值给 Map 值类型 '{1}'。
描述
#当 Map 字面量中键值对的值的类型不能赋值给 Map 的值类型时,分析器会生成此诊断信息。
示例
#以下代码产生此诊断信息,因为 2
是 int
类型,但 Map 的值必须是 String
类型。
var m = <String, String>{'a' : 2};
常见修复
#如果映射的类型正确,则将值更改为具有正确的类型
var m = <String, String>{'a' : '2'};
如果值的类型正确,则更改映射的值类型
var m = <String, int>{'a' : 2};
mismatched_annotation_on_struct_field
#注解与字段的声明类型不匹配。
描述
#当 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;
}
missing_annotation_on_struct_field
#'{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;
}
missing_dart_library
#缺少必需的库“{0}”。
描述
#当 Dart 或 Flutter SDK 未正确安装,并且因此无法找到某个 dart:
库时,分析器会生成此诊断信息。
常见修复
#重新安装 Dart 或 Flutter SDK。
missing_default_value_for_parameter
#参数“{0}”由于其类型不能为“null”,但隐式默认值为“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}) {}
missing_dependency
#缺少对导入的包“{0}”的依赖。
描述
#当源代码中导入了一个包,但该包未在导入包的依赖项中列出时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为包 path
未列为依赖项,而包 example
的源代码中存在带有包 path
的 import 语句
name: example
dependencies:
meta: ^1.0.2
常见修复
#将缺少的包 path
添加到 dependencies
字段
name: example
dependencies:
meta: ^1.0.2
path: any
missing_enum_constant_in_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;
}
}
missing_exception_value
#当函数的返回类型既不是“void”、“Handle”也不是“Pointer”时,方法 {0} 必须具有异常返回值(第二个参数)。
描述
#当方法 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);
}
missing_field_type_in_struct
#结构类中的字段必须具有显式声明的类型“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;
}
missing_name
#“name”字段是必需的,但缺失。
描述
#当没有顶层 name
键时,分析器会生成此诊断信息。name
键提供包的名称,这是必需的。
示例
#以下代码会产生此诊断信息,因为包没有名称
dependencies:
meta: ^1.0.2
常见修复
#添加顶层键 name
,其值为包的名称
name: example
dependencies:
meta: ^1.0.2
missing_named_pattern_field_name
#未显式指定 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;
}
}
missing_override_of_must_be_overridden
#缺少“{0}”的具体实现。
缺少“{0}”和“{1}”的具体实现。
缺少“{0}”、“{1}”和另外 {2} 个的具体实现。
描述
#当具有 @mustBeOverridden
注解的实例成员未在子类中重写时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为当 A.m
使用 @mustBeOverridden
注解时,类 B
没有对继承的方法 A.m
的重写
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 {}
missing_required_argument
#命名参数“{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);
}
missing_required_param
#参数“{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);
}
missing_return
#此函数的返回类型为“{0}”,但未以 return 语句结尾。
描述
#任何不以显式返回或抛出结尾的函数或方法都会隐式返回 null
。这很少是所需的行为。当分析器发现隐式返回时,会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 f
没有以 return 结尾
int f(int x) {
if (x < 0) {
return 0;
}
}
常见修复
#添加一个 return
语句,使返回值显式,即使 null
是适当的值。
missing_size_annotation_carray
#类型为“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;
}
missing_variable_pattern
#逻辑或模式的此分支中缺少变量模式“{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');
}
}
mixin_application_concrete_super_invoked_member_type
#超调用的成员“{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 {}
mixin_application_not_implemented_interface
#无法将“{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;
mixin_application_no_concrete_super_invoked_member
#该类没有对超调用成员“{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 {}
mixin_class_declaration_extends_not_object
#类“{0}”不能声明为 mixin,因为它继承的类不是“Object”。
描述
#当使用 mixin
修饰符标记的类继承的类不是 Object
时,分析器会产生此诊断。mixin 类不能有除 Object
以外的超类。
示例
#以下代码产生此诊断,因为具有修饰符 mixin
的类 B
继承了 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
子句。
mixin_class_declares_constructor
#类“{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 {}
mixin_inherits_from_not_object
#类“{0}”不能用作 mixin,因为它继承的类不是“Object”。
描述
#当一个继承的类不是 Object
的类被用作 mixin 时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为继承了 A
的类 B
被 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_instantiate
#Mixins 不能被实例化。
描述
#当 mixin 被实例化时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 mixin M
正在被实例化。
mixin M {}
var m = M();
常见修复
#如果打算使用类的实例,则使用该类的名称代替 mixin 的名称。
mixin_of_non_class
#类只能混合 mixins 和类。
描述
#当 with
子句中的名称被定义为除 mixin 或类以外的其他内容时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 F
被定义为函数类型。
typedef F = int Function(String);
class C with F {}
常见修复
#从列表中删除无效的名称,可能将其替换为预期的 mixin 或类的名称。
typedef F = int Function(String);
class C {}
mixin_on_sealed_class
#类“{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_super_class_constraint_deferred_class
#延迟类不能用作超类约束。
描述
#当 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_super_class_constraint_non_interface
#只有类和 mixins 才能用作超类约束。
描述
#当 mixin 声明中 on
关键字后面的类型既不是类也不是 mixin 时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 F
既不是类也不是 mixin。
typedef F = void Function();
mixin M on F {}
常见修复
#如果该类型本意是类但输入错误,则替换该名称。
否则,从 on
子句中删除该类型。
multiple_redirecting_constructor_invocations
#构造函数最多只能有一个 '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();
}
multiple_super_initializers
#构造函数最多只能有一个 '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, '');
}
must_be_a_native_function_type
#为 '{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);
}
}
must_be_a_subtype
#对于 '{2}',类型 '{0}' 必须是 '{1}' 的子类型。
描述
#在以下两种情况下,分析器会产生此诊断:
- 在
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);
}
must_be_immutable
#此类(或此类继承的类)被标记为 '@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);
}
must_call_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();
}
}
must_return_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_not_string
#'name' 字段的值必须是字符串。
描述
#当顶层 name
键的值不是字符串时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 name
键后面的值是一个列表。
name:
- example
常见修复
#将值替换为字符串。
name: example
native_field_invalid_type
#'{0}' 是原生字段不支持的类型。原生字段仅支持指针、数组或数字和复合类型。
描述
#当 @Native
注解字段具有原生字段不支持的类型时,分析器会产生此诊断。
原生字段支持指针、数组、数值类型以及Compound
(即结构体或联合体)的子类型。其他 NativeType
的子类型,如 Handle
或 NativeFunction
不允许作为原生字段。
原生函数应该与外部函数一起使用,而不是与外部字段一起使用。
不支持句柄(Handles),因为没有办法透明地将 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_field_missing_type
#无法推断此字段的原生类型,必须在注解中指定。
描述
#当带有 @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_field_not_static
#原生字段必须是静态的。
描述
#当类中的实例字段被注解为 @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_with_undefined_constructor_default
#类 '{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();
non_abstract_class_inherits_abstract_member
#缺少“{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),则将该混入应用于子类
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 {}
non_bool_condition
#条件必须具有 'bool' 的静态类型。
描述
#当条件(例如 if
或 while
循环)没有静态类型 bool
时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 x
的静态类型为 int
void f(int x) {
if (x) {
// ...
}
}
常见修复
#更改条件,使其产生布尔值
void f(int x) {
if (x == 0) {
// ...
}
}
non_bool_expression
#断言中的表达式必须是 'bool' 类型。
描述
#当断言中的第一个表达式的类型不是 bool
时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 p
的类型是 int
,但需要 bool
void f(int p) {
assert(p);
}
常见修复
#更改表达式,使其具有 bool
类型
void f(int p) {
assert(p > 0);
}
non_bool_negation_expression
#取反操作数必须具有 'bool' 的静态类型。
描述
#当一元取反运算符 (!
) 的操作数不具有 bool
类型时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 x
是一个 int
,而它必须是一个 bool
int x = 0;
bool y = !x;
常见修复
#将操作数替换为具有 bool
类型的表达式
int x = 0;
bool y = !(x > 0);
non_bool_operand
#运算符 '{0}' 的操作数必须可赋值给 'bool'。
描述
#当 &&
或 ||
运算符的其中一个操作数不具有 bool
类型时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 a
不是布尔值
int a = 3;
bool b = a || a > 1;
常见修复
#将操作数更改为布尔值
int a = 3;
bool b = a == 0 || a > 1;
non_constant_annotation_constructor
#注解创建只能调用 const 构造函数。
描述
#当注解是对现有构造函数的调用,即使调用的构造函数不是 const 构造函数时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 C
的构造函数不是 const 构造函数
@C()
void f() {
}
class C {
C();
}
常见修复
#如果该类可以有一个 const 构造函数,则创建一个可用于注解的 const 构造函数
@C()
void f() {
}
class C {
const C();
}
如果该类不能有 const 构造函数,则删除注解或使用不同的类作为注解。
non_constant_case_expression
#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) {
// ...
}
}
non_constant_case_expression_from_deferred_library
#来自延迟库的常量值不能用作 case 表达式。
描述
#当 case 子句中的表达式引用使用延迟导入的库中的常量时,分析器会产生此诊断信息。为了有效地编译 switch 语句,case 子句中引用的常量需要在编译时可用,而来自延迟库的常量在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#假设有一个文件 a.dart
定义了常量 zero
const zero = 0;
以下代码产生此诊断信息,因为库 a.dart
使用 deferred
导入,并且在 case 子句中使用了导入库中声明的常量 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;
}
}
non_constant_default_value
#可选参数的默认值必须是常量。
描述
#当可选参数(命名或位置)具有非编译时常量的默认值时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断
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;
}
non_constant_default_value_from_deferred_library
#来自延迟库的常量值不能用作默认参数值。
描述
#当可选参数的默认值使用从使用延迟导入的库导入的常量时,分析器会产生此诊断信息。默认值需要在编译时可用,而来自延迟库的常量在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#假设有一个文件 a.dart
定义了常量 zero
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}) {}
non_constant_list_element
#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];
non_constant_map_element
#const map 字面量中的元素必须是常量。
描述
#当 const map 中的 if
元素或展开元素不是常量元素时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为它试图展开一个非常量 map
var notConst = <int, int>{};
var map = const <int, int>{...notConst};
同样,以下代码产生此诊断信息,因为 if
元素中的条件不是常量表达式
bool notConst = true;
var map = const <int, int>{if (notConst) 1 : 2};
常见修复
#如果 map 需要是常量 map,则使元素成为常量。在展开示例中,您可以通过使展开的集合成为常量来做到这一点
const notConst = <int, int>{};
var map = const <int, int>{...notConst};
如果 map 不需要是常量 map,则删除 const
关键字
bool notConst = true;
var map = <int, int>{if (notConst) 1 : 2};
non_constant_map_key
#常量映射字面量中的键必须是常量。
描述
#当常量映射字面量中的键不是常量值时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 a
不是常量。
var a = 'a';
var m = const {a: 0};
常见修复
#如果映射需要是常量映射,则将键设为常量。
const a = 'a';
var m = const {a: 0};
如果 map 不需要是常量 map,则删除 const
关键字
var a = 'a';
var m = {a: 0};
non_constant_map_pattern_key
#映射模式中的键表达式必须是常量。
描述
#当映射模式中的键不是常量表达式时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为键 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();
}
non_constant_map_value
#常量映射字面量中的值必须是常量。
描述
#当常量映射字面量中的值不是常量值时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 a
不是常量。
var a = 'a';
var m = const {0: a};
常见修复
#如果映射需要是常量映射,则将键设为常量。
const a = 'a';
var m = const {0: a};
如果 map 不需要是常量 map,则删除 const
关键字
var a = 'a';
var m = {0: a};
non_constant_relational_pattern_expression
#关系模式表达式必须是常量。
描述
#当关系模式表达式中的值不是常量表达式时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 >
运算符的操作数 a
不是常量。
final a = 0;
void f(int x) {
if (x case > a) {}
}
常见修复
#将该值替换为常量表达式。
const a = 0;
void f(int x) {
if (x case > a) {}
}
non_constant_set_element
#常量集合字面量中的值必须是常量。
描述
#当常量集合字面量包含一个不是编译时常量的元素时,分析器会产生此诊断信息。
示例
#以下代码会生成此诊断,因为 i
不是常量
var i = 0;
var s = const {i};
常见修复
#如果该元素可以更改为常量,则将其更改。
const i = 0;
var s = const {i};
如果该元素不能是常量,则删除关键字 const
。
var i = 0;
var s = {i};
non_constant_type_argument
#“{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)>();
}
}
non_const_argument_for_const_parameter
#参数“{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;
non_const_call_to_literal_constructor
#此实例创建必须是“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();
non_const_generative_enum_constructor
#生成枚举构造函数必须是 'const'。
描述
#当枚举声明包含一个未标记为 const
的生成构造函数时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 E
中的构造函数未标记为 const
。
enum E {
e;
E();
}
常见修复
#在构造函数之前添加 const
关键字。
enum E {
e;
const E();
}
non_covariant_type_parameter_position_in_representation_type
#扩展类型参数不能在其表示类型的非协变位置中使用。
描述
#当扩展类型的类型参数在该扩展类型的表示类型的非协变位置中使用时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为类型参数 T
在函数类型 void Function(T)
中用作参数类型,而参数不是协变的。
extension type A<T>(void Function(T) f) {}
常见修复
#删除对类型参数的使用。
extension type A(void Function(String) f) {}
non_exhaustive_switch_expression
#类型“{0}”未被 switch case 完全匹配,因为它不匹配“{1}”。
描述
#当 switch
表达式缺少一个或多个可能流经它的值的情况时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 switch 表达式没有 E.three
值的情况。
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
需要更新以考虑新添加的类型,您将失去让编译器警告您的能力。
non_exhaustive_switch_statement
#类型“{0}”未被 switch case 完全匹配,因为它不匹配“{1}”。
描述
#当 switch
语句切换到穷举类型时,缺少一个或多个可能流经它的值的情况时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 switch 语句没有 E.three
值的情况,并且 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
的能力。
non_final_field_in_enum
#枚举只能声明 final 字段。
描述
#当枚举中的实例字段未标记为 final
时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为字段 f
不是 final 字段。
enum E {
c;
int f = 0;
}
常见修复
#如果必须为枚举定义该字段,则将该字段标记为 final
。
enum E {
c;
final int f = 0;
}
如果可以删除该字段,则将其删除。
enum E {
c
}
non_generative_constructor
#需要生成构造函数“{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();
}
如果生成构造函数是未命名的构造函数,并且没有传递给它的参数,则可以删除超类调用。
non_generative_implicit_constructor
#超类“{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 {}
non_native_function_type_argument_to_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>();
}
}
non_positive_array_dimension
#数组维度必须是正数。
描述
#当 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;
}
如果这是一个可变长度的内联数组,请将注释更改为 Array.variable()
。
import 'dart:ffi';
final class MyStruct extends Struct {
@Array.variable()
external Array<Uint8> a0;
}
non_sized_type_argument
#类型“{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;
}
non_sync_factory
#工厂主体不能使用 '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._();
}
non_type_as_type_argument
#名称“{0}”不是类型,因此不能用作类型参数。
描述
#当一个不是类型的标识符用作类型参数时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断,因为 x
是一个变量,而不是类型
var x = 0;
List<x> xList = [];
常见修复
#将类型参数更改为类型。
var x = 0;
List<int> xList = [];
non_type_in_catch_clause
#名称“{0}”不是类型,不能在 on-catch 子句中使用。
描述
#当 catch
子句中的 on
之后的标识符被定义为类型以外的内容时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 f
是一个函数,而不是类型。
void f() {
try {
// ...
} on f {
// ...
}
}
常见修复
#将名称更改为应捕获的对象的类型。
void f() {
try {
// ...
} on FormatException {
// ...
}
}
non_void_return_for_operator
#运算符 []= 的返回类型必须为 'void'。
描述
#当运算符 []=
的声明具有 void
以外的返回类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为运算符 []=
的声明具有 int
的返回类型。
class C {
int operator []=(int index, int value) => 0;
}
常见修复
#将返回类型更改为 void
。
class C {
void operator []=(int index, int value) => 0;
}
non_void_return_for_setter
#setter 的返回类型必须为 'void' 或省略。
描述
#当 setter 定义为具有 void
以外的返回类型时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为 setter p
的返回类型为 int
。
class C {
int set p(int i) => 0;
}
常见修复
#将返回类型更改为 void
或省略返回类型。
class C {
set p(int i) => 0;
}
not_assigned_potentially_non_nullable_local_variable
#必须先分配不可为空的局部变量“{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;
}
not_a_type
#“{0}”不是类型。
描述
#当名称用作类型但声明为类型以外的其他内容时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为 f
是一个函数。
f() {}
g(f v) {}
常见修复
#将名称替换为类型名称。
not_binary_operator
#“{0}”不是二元运算符。
描述
#当只能用作一元运算符的运算符用作二元运算符时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为运算符 ~
只能用作一元运算符。
var a = 5 ~ 3;
常见修复
#将运算符替换为正确的二元运算符。
var a = 5 - 3;
not_enough_positional_arguments
#“{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);
}
not_initialized_non_nullable_instance_field
#非可空实例字段“{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;
}
not_initialized_non_nullable_variable
#非可空变量“{0}”必须初始化。
描述
#当静态字段或顶层变量的类型为不可空且没有初始化器时,分析器会生成此诊断。 没有初始化器的字段和变量通常初始化为 null
,但是字段或变量的类型不允许将其设置为 null
,因此必须提供显式初始化器。
示例
#以下代码会产生此诊断,因为字段 f
不能初始化为 null
。
class C {
static int f;
}
同样,以下代码会产生此诊断,因为顶层变量 v
不能初始化为 null
。
int v;
常见修复
#如果字段或变量不能初始化为 null
,则添加一个初始化器,将其设置为非 null 值。
class C {
static int f = 0;
}
如果字段或变量应初始化为 null
,则将类型更改为可空类型。
int? v;
如果字段或变量不能在声明中初始化,但总会在被引用之前初始化,则将其标记为 late
。
class C {
static late int f;
}
not_iterable_spread
#列表或集合字面量中的散布元素必须实现“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};
not_map_spread
#映射字面量中的散布元素必须实现“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()};
no_annotation_constructor_arguments
#注释创建必须包含参数。
描述
#当注释由单个标识符组成,但该标识符是类名而不是变量名时,分析器会生成此诊断。 要创建类的实例,标识符后必须跟一个参数列表。
示例
#以下代码会产生此诊断,因为 C
是一个类,并且类不能用作注释,除非调用该类的 const
构造函数。
class C {
const C();
}
@C
var x;
常见修复
#添加缺失的参数列表。
class C {
const C();
}
@C()
var x;
no_combined_super_signature
#无法从重写的方法:{1} 推断“{0}”中缺少的类型。
描述
#当方法声明缺少一个或多个需要推断的类型时,并且这些类型无法推断,因为根据 重写推断,没有任何重写方法具有所有其他重写方法的超类型的函数类型时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为在类 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);
}
no_generative_constructors_in_superclass
#类“{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 {}
nullable_type_in_catch_clause
#潜在可空类型不能在“on”子句中使用,因为抛出可空表达式无效。
描述
#当 catch
子句中 on
后面的类型是可空类型时,分析器会生成此诊断。 指定可空类型无效,因为无法捕获 null
(因为抛出 null
是运行时错误)。
示例
#以下代码会产生此诊断,因为异常类型被指定为允许 null
,而 null
不能被抛出。
void f() {
try {
// ...
} on FormatException? {
}
}
常见修复
#从类型中删除问号。
void f() {
try {
// ...
} on FormatException {
}
}
nullable_type_in_extends_clause
#类不能扩展可空类型。
描述
#当类声明使用 extends
子句指定超类,并且超类后面跟一个 ?
时,分析器会生成此诊断。
指定可空超类是无效的,因为这样做没有任何意义;它不会更改包含 extends
子句的类所继承的接口或实现。
但是,请注意,将可空类型用作超类的类型参数是有效的,例如 class A extends B<C?> {}
。
示例
#以下代码会产生此诊断,因为 A?
是可空类型,并且可空类型不能在 extends
子句中使用。
class A {}
class B extends A? {}
常见修复
#从类型中删除问号。
class A {}
class B extends A {}
nullable_type_in_implements_clause
#类、Mixin 或扩展类型不能实现可空类型。
描述
#当类、mixin 或扩展类型声明具有 implements
子句,并且接口后面跟一个 ?
时,分析器会生成此诊断。
指定可空接口是无效的,因为这样做没有任何意义;它不会更改包含 implements
子句的类所继承的接口。
但是,请注意,将可空类型用作接口的类型参数是有效的,例如 class A implements B<C?> {}
。
示例
#以下代码会产生此诊断,因为 A?
是可空类型,并且可空类型不能在 implements
子句中使用。
class A {}
class B implements A? {}
常见修复
#从类型中删除问号。
class A {}
class B implements A {}
nullable_type_in_on_clause
#Mixin 不能将可空类型作为超类约束。
描述
#当 mixin 声明使用 on
子句指定超类约束,并且指定的类后面跟一个 ?
时,分析器会生成此诊断。
指定可空超类约束无效,因为这样做没有任何意义;它不会更改包含 on
子句的 mixin 所依赖的接口。
但是请注意,将可空类型用作超类约束的类型参数是有效的,例如 mixin A on B<C?> {}
。
示例
#以下代码会生成此诊断,因为 A?
是可空类型,而可空类型不能在 on
子句中使用。
class C {}
mixin M on C? {}
常见修复
#从类型中删除问号。
class C {}
mixin M on C {}
nullable_type_in_with_clause
#类或 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 {}
null_argument_to_non_null_type
#不应使用 'null' 参数调用非空类型参数 '{1}' 的 '{0}'。
描述
#当将 null
传递给构造函数 Future.value
或方法 Completer.complete
时,如果用于创建实例的类型参数是非空的,则分析器会生成此诊断。即使类型系统无法表达此限制,传入 null
也会导致运行时异常。
示例
#以下代码会生成此诊断,因为即使类型参数是非空类型 String
,也正在将 null
传递给构造函数 Future.value
。
Future<String> f() {
return Future.value(null);
}
常见修复
#传入一个非 null 值。
Future<String> f() {
return Future.value('');
}
null_check_always_fails
#此 null 检查将始终抛出异常,因为表达式将始终计算为 'null'。
描述
#当 null 检查运算符 (!
) 用于其值只能为 null
的表达式时,分析器会生成此诊断。在这种情况下,运算符始终会抛出异常,这可能不是预期的行为。
示例
#以下代码会生成此诊断,因为函数 g
将始终返回 null
,这意味着 f
中的 null 检查将始终抛出异常。
void f() {
g()!;
}
Null g() => null;
常见修复
#如果您打算始终抛出异常,请将 null 检查替换为显式 throw
表达式,以使意图更清晰。
void f() {
g();
throw TypeError();
}
Null g() => null;
obsolete_colon_for_default_value
#不再支持在默认值之前使用冒号作为分隔符。
描述
#当冒号 (:
) 用作可选命名参数的默认值之前的分隔符时,分析器会生成此诊断。虽然以前允许使用此语法,但它已被删除,取而代之的是使用等号 (=
)。
示例
#以下代码会产生此诊断信息,因为在可选参数 i
的默认值之前使用了冒号。
void f({int i : 0}) {}
常见修复
#将冒号替换为等号。
void f({int i = 0}) {}
on_repeated
#类型 '{0}' 只能在超类约束中包含一次。
描述
#当 mixin 的超类约束中多次列出同一类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 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 {}
optional_parameter_in_operator
#定义运算符时不允许使用可选参数。
描述
#当运算符声明中的一个或多个参数是可选的时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为参数 other
是一个可选参数。
class C {
C operator +([C? other]) => this;
}
常见修复
#使所有参数都成为必需参数。
class C {
C operator +(C other) => this;
}
override_on_non_overriding_member
#该字段没有覆盖继承的 getter 或 setter。
getter 没有覆盖继承的 getter。
该方法没有覆盖继承的方法。
setter 没有覆盖继承的 setter。
描述
#当类成员使用 @override
注释进行注释,但该成员未在类的任何超类型中声明时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 m
未在 C
的任何超类型中声明。
class C {
@override
String m() => '';
}
常见修复
#如果成员打算覆盖具有不同名称的成员,请更新该成员以具有相同的名称。
class C {
@override
String toString() => '';
}
如果成员打算覆盖从超类中删除的成员,请考虑从子类中删除该成员。
如果无法删除该成员,请删除该注释。
packed_annotation
#结构最多只能有一个“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;
}
packed_annotation_alignment
#仅支持打包为 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;
}
part_of_different_library
#预期此库是 '{0}' 的一部分,而不是 '{1}'。
描述
#当一个库尝试将一个文件作为自身的一部分包含,而另一个文件是不同库的一部分时,分析器会生成此诊断。
示例
#给定一个包含以下内容的 part.dart
文件
part of 'library.dart';
以下代码在 library.dart
以外的任何文件中都会生成此诊断,因为它尝试将 part.dart
作为自身的一部分包含,而 part.dart
是不同库的一部分。
part 'package:a/part.dart';
常见修复
#如果库应使用不同的文件作为一部分,请更改 part 指令中的 URI 以使其成为另一个文件的 URI。
如果 part 文件 应属于此库的一部分,请更新 part-of 指令中的 URI(或库名称)以使其成为正确库的 URI(或名称)。
part_of_non_part
#包含的 part '{0}' 必须具有 part-of 指令。
描述
#当找到 part 指令并且引用的文件没有 part-of 指令时,分析器会生成此诊断。
示例
#给定一个包含以下内容的 a.dart
文件
class A {}
以下代码会生成此诊断,因为 a.dart
不包含 part-of 指令。
part 'a.dart';
常见修复
#如果引用的文件打算成为另一个库的一部分,请将 part-of 指令添加到该文件中。
part of 'test.dart';
class A {}
如果引用的文件打算成为一个库,请将 part 指令替换为 import 指令。
import 'a.dart';
part_of_unnamed_library
#该库是未命名的。在 part-of 指令中,应使用 URI,而不是库名称 '{0}'。
描述
#当没有 library
指令(因此没有名称)的库包含 part
指令,并且 part 文件 中的 part of
指令使用名称来指定它所属的库时,分析器会生成此诊断。
示例
#给定一个名为 part_file.dart
的 part 文件,其中包含以下代码:
part of lib;
以下代码会生成此诊断,因为包含 part 文件 的库没有名称,即使 part 文件 使用名称来指定它属于哪个库。
part 'part_file.dart';
常见修复
#更改 part 文件 中的 part of
指令,以通过 URI 指定其库。
part of 'test.dart';
path_does_not_exist
#路径 '{0}' 不存在。
描述
#当依赖项的 path
键引用不存在的目录时,分析器会生成此诊断。
示例
#假设目录 doesNotExist
不存在,则以下代码会生成此诊断,因为它被列为包的路径。
name: example
dependencies:
local_package:
path: doesNotExist
常见修复
#如果路径正确,则在该路径下创建一个目录。
如果路径不正确,请更改路径以使其与包的根路径匹配。
path_not_posix
#路径 '{0}' 不是 POSIX 样式的路径。
描述
#当依赖项的 path
键的值是字符串,但不是 POSIX 样式的路径时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 path
键后面的路径是 Windows 路径。
name: example
dependencies:
local_package:
path: E:\local_package
常见修复
#将路径转换为 POSIX 路径。
path_pubspec_does_not_exist
#目录 '{0}' 不包含 pubspec。
描述
#当依赖项的 path
键引用不包含 pubspec.yaml
文件的目录时,分析器会生成此诊断。
示例
#假设目录 local_package
不包含文件 pubspec.yaml
,则以下代码会生成此诊断,因为它被列为包的路径。
name: example
dependencies:
local_package:
path: local_package
常见修复
#如果该路径打算作为包的根目录,请在该目录中添加 pubspec.yaml
文件。
name: local_package
如果路径错误,请将其替换为正确的路径。
pattern_assignment_not_local_variable
#只能在模式赋值中分配局部变量。
描述
#当模式赋值将值分配给局部变量以外的任何内容时,分析器会生成此诊断。模式不能分配给字段或顶层变量。
示例
#如果在使用模式进行解构时代码更简洁,请重写代码以在模式声明中将值分配给局部变量,并单独分配非局部变量。
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;
}
}
pattern_constant_from_deferred_library
#延迟库中的常量值不能在模式中使用。
描述
#当模式包含在不同库中声明的值,并且该库使用延迟导入进行导入时,分析器会生成此诊断。常量在编译时进行计算,但延迟库中的值在编译时不可用。
有关详细信息,请查看延迟加载库。
示例
#假设有一个文件 a.dart
定义了常量 zero
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;
}
}
pattern_type_mismatch_in_irrefutable_context
#类型为 '{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);
}
pattern_variable_assignment_inside_guard
#模式变量不能在封闭的受保护模式的 guard 中赋值。
描述
#当在 guard (when
) 子句中为模式变量赋值时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为变量 a
在 guard 子句中被赋值。
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);
}
}
platform_value_disallowed
#platforms
字段中的键不能有值。
描述
#当 platforms
映射中的键具有值时,分析器会生成此诊断。要了解有关指定包支持的平台的更多信息,请查看关于平台声明的文档。
示例
#以下 pubspec.yaml
产生此诊断信息,因为键 web
有一个值。
name: example
platforms:
web: "chrome"
常见修复
#省略该值,使键没有值
name: example
platforms:
web:
platforms
字段中键的值目前保留以供未来可能的行为使用。
positional_field_in_object_pattern
#对象模式只能使用具名字段。
描述
#当对象模式包含一个未指定 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)) {}
}
positional_super_formal_parameter_with_positional_argument
#当超类构造函数调用具有位置参数时,不能使用位置超参数。
描述
#当提供给超类的构造函数的部分(但不是全部)位置参数正在使用超参数时,分析器会产生此诊断信息。
位置超参数通过它们的索引与超类构造函数中的位置参数相关联。也就是说,第一个超参数与超类构造函数中的第一个位置参数相关联,第二个超参数与第二个位置参数相关联,依此类推。位置参数也是如此。同时拥有位置超参数和位置参数意味着超类的构造函数中的同一参数关联了两个值,因此是不允许的。
示例
#以下代码产生此诊断信息,因为构造函数 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);
}
prefix_collides_with_top_level_member
#名称“{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);
prefix_identifier_not_followed_by_dot
#名称“{0}”引用导入前缀,因此后面必须跟“.”。
描述
#当导入前缀单独使用时,分析器会产生此诊断信息,而没有访问与该前缀关联的库中声明的任何名称。前缀不是变量,因此不能用作值。
示例
#以下代码产生此诊断信息,因为前缀 math
被当作变量使用
import 'dart:math' as math;
void f() {
print(math);
}
常见修复
#如果代码不完整,则引用与前缀关联的库中的某个内容
import 'dart:math' as math;
void f() {
print(math.pi);
}
如果名称错误,则更正名称。
prefix_shadowed_by_local_declaration
#前缀“{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;
}
private_collision_in_mixin_application
#由“{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 之一中重命名冲突的成员。
private_optional_parameter
#命名参数不能以下划线开头。
描述
#当命名参数的名称以下划线开头时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为命名参数 _x
以下划线开头
class C {
void m({int _x = 0}) {}
}
常见修复
#重命名参数,使其不以下划线开头
class C {
void m({int x = 0}) {}
}
private_setter
#setter“{0}”是私有的,不能在声明它的库外部访问。
描述
#当在不可见的库中使用私有 setter 时,分析器会产生此诊断信息。
示例
#假设有一个名为 a.dart
的文件,其中包含以下内容:
class A {
static int _f = 0;
}
以下代码产生此诊断信息,因为它引用了私有 setter _f
,即使 setter 不可见
import 'a.dart';
void f() {
A._f = 0;
}
常见修复
#如果可以将 setter 设置为 public,则执行此操作
class A {
static int f = 0;
}
如果不能将 setter 设置为 public,则找到实现代码的不同方法。
read_potentially_unassigned_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;
}
record_literal_one_positional_no_trailing_comma
#正好具有一个位置字段的记录文字需要一个尾随逗号。
描述
#当具有单个位置字段的记录文字在该字段后没有尾随逗号时,分析器会产生此诊断信息。
在某些位置,具有单个位置字段的记录文字也可能是一个带括号的表达式。需要一个尾随逗号来消除这两种有效解释的歧义。
示例
#以下代码产生此诊断信息,因为记录文字有一个位置字段,但没有尾随逗号
var r = const (1);
常见修复
#添加尾随逗号
var r = const (1,);
record_type_one_positional_no_trailing_comma
#正好具有一个位置字段的记录类型需要一个尾随逗号。
描述
#当具有单个位置字段的记录类型注释在该字段后没有尾随逗号时,分析器会产生此诊断信息。
在某些位置,具有单个位置字段的记录类型也可能是一个带括号的表达式。需要一个尾随逗号来消除这两种有效解释的歧义。
示例
#以下代码产生此诊断信息,因为记录类型有一个位置字段,但没有尾随逗号
void f((int) r) {}
常见修复
#添加尾随逗号
void f((int,) r) {}
recursive_compile_time_constant
#编译时常量表达式依赖于自身。
描述
#当编译时常量的值根据自身定义(直接或间接),从而创建无限循环时,分析器会产生此诊断信息。
示例
#以下代码产生两次此诊断信息,因为两个常量都根据另一个常量定义
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = secondsPerHour / 60;
常见修复
#通过找到定义至少一个常量的替代方法来打破循环
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = 60;
recursive_constructor_redirect
#构造函数不能直接或间接地重定向到自身。
描述
#当构造函数直接或间接地重定向到自身,从而创建无限循环时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为生成构造函数 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();
}
recursive_interface_inheritance
#“{0}”不能是它自己的超接口:{1}。
“{0}”不能扩展自身。
“{0}”不能实现自身。
“{0}”不能将自身用作 mixin。
“{0}”不能将自身用作超类约束。
描述
#当类型层次结构中存在循环时,分析器会产生此诊断信息。当类型(直接或间接)被声明为自身的子类型时,会发生这种情况。
示例
#以下代码产生此诊断信息,因为类 A
被声明为 B
的子类型,而 B
是 A
的子类型
class A extends B {}
class B implements A {}
常见修复
#更改类型层次结构,使其没有循环。
redeclare_on_non_redeclaring_member
#{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() {}
}
redirect_generative_to_missing_constructor
#在“{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();
}
redirect_generative_to_non_generative_constructor
#生成构造函数不能重定向到工厂构造函数。
描述
#当生成构造函数重定向到工厂构造函数时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为生成构造函数 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();
}
redirect_to_abstract_class_constructor
#重定向构造函数“{0}”不能重定向到抽象类“{1}”的构造函数。
描述
#当构造函数重定向到抽象类中的构造函数时,分析器会产生此诊断信息。
示例
#以下代码产生此诊断信息,因为 A
中的工厂构造函数重定向到 B
中的构造函数,但 B
是一个抽象类
class A {
factory A() = B;
}
abstract class B implements A {}
常见修复
#如果代码重定向到正确的构造函数,则更改类,使其不是抽象的
class A {
factory A() = B;
}
class B implements A {}
否则,更改工厂构造函数,使其要么重定向到具体类中的构造函数,要么具有具体实现。
redirect_to_invalid_function_type
#重定向的构造函数“{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);
}
redirect_to_invalid_return_type
#重定向的构造函数的返回类型“{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;
}
redirect_to_missing_constructor
#在“{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();
}
redirect_to_non_class
#名称“{0}”不是类型,不能在重定向的构造函数中使用。
描述
#实现工厂构造函数的一种方法是通过引用构造函数的名称重定向到另一个构造函数。当重定向到构造函数之外的其他内容时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 f
是一个函数。
C f() => throw 0;
class C {
factory C() = f;
}
常见修复
#如果未定义构造函数,则定义它或将其替换为已定义的构造函数。
如果定义构造函数的类不可见,则可能需要添加导入。
如果您尝试返回函数返回的值,请重写构造函数以从构造函数的主体返回该值。
C f() => throw 0;
class C {
factory C() => f();
}
redirect_to_non_const_constructor
#常量重定向构造函数不能重定向到非常量构造函数。
描述
#当标记为 const
的构造函数重定向到未标记为 const
的构造函数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为构造函数 C.a
被标记为 const
,但重定向到未标记为 const
的构造函数 C.b
。
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();
}
redirect_to_type_alias_expands_to_type_parameter
#重定向构造函数不能重定向到扩展为类型参数的类型别名。
描述
#当重定向的工厂构造函数重定向到类型别名,并且该类型别名扩展为类型别名的类型参数之一时,分析器会产生此诊断。这是不允许的,因为类型参数的值是类型而不是类。
示例
#以下代码会产生此诊断,因为重定向到 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;
}
referenced_before_declaration
#局部变量“{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);
}
refutable_pattern_in_irrefutable_context
#可反驳模式不能在不可反驳的上下文中使用。
描述
#当 可反驳模式 用在只允许 不可反驳模式 的上下文中时,分析器会产生此诊断。
不允许使用的可反驳模式是
- 逻辑或
- 关系
- 空检查
- 常量
检查的上下文是
- 基于模式的变量声明
- 基于模式的 for 循环
- 左侧带有模式的赋值
示例
#以下代码会产生此诊断,因为空检查模式(即可反驳模式)在基于模式的变量声明中,而基于模式的变量声明不允许使用可反驳模式。
void f(int? x) {
var (_?) = x;
}
常见修复
#重写代码,以便不在不可反驳的上下文中使用可反驳模式。
relational_pattern_operand_type_not_assignable
#常量表达式类型“{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');
}
}
relational_pattern_operator_return_type_not_assignable_to_bool
#关系模式中使用的运算符的返回类型必须可赋值给“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) {}
}
rest_element_in_map_pattern
#映射模式不能包含剩余模式。
描述
#当映射模式包含剩余模式时,分析器会产生此诊断。映射模式匹配具有比模式中明确给出的键更多的键的映射(只要给定的键匹配),因此剩余模式是不必要的。
示例
#以下代码会产生此诊断,因为映射模式包含剩余模式。
void f(Map<int, String> x) {
if (x case {0: _, ...}) {}
}
常见修复
#删除剩余模式。
void f(Map<int, String> x) {
if (x case {0: _}) {}
}
rethrow_outside_catch
#重新抛出必须位于 catch 子句内。
描述
#当 rethrow
语句位于 catch
子句之外时,分析器会产生此诊断。 rethrow
语句用于再次抛出捕获的异常,但在 catch
子句之外没有捕获的异常。
示例
#以下代码会产生此诊断,因为 rethrow
语句位于 catch
子句之外。
void f() {
rethrow;
}
常见修复
#如果您尝试重新抛出异常,请将 rethrow
语句包装在 catch
子句中。
void f() {
try {
// ...
} catch (exception) {
rethrow;
}
}
如果您尝试抛出新异常,请将 rethrow
语句替换为 throw
表达式。
void f() {
throw UnsupportedError('Not yet implemented');
}
return_in_generative_constructor
#构造函数不能返回值。
描述
#当生成构造函数包含指定要返回的值的 return
语句时,分析器会产生此诊断。生成构造函数始终返回已创建的对象,因此不能返回不同的对象。
示例
#以下代码会产生此诊断,因为 return
语句有一个表达式。
class C {
C() {
return this;
}
}
常见修复
#如果构造函数应该创建新实例,则删除 return
语句或表达式。
class C {
C();
}
如果构造函数不应该创建新实例,则将其转换为工厂构造函数。
class C {
factory C() {
return _instance;
}
static C _instance = C._();
C._();
}
return_in_generator
#不能从使用“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;
}
如果该方法不打算成为生成器,则从主体中删除修饰符(或者如果您要返回 future,则使用 async
)。
int f() {
return 3;
}
return_of_do_not_store
#“{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;
return_of_invalid_type
#类型为“{0}”的值不能从构造函数“{2}”返回,因为它具有返回类型“{1}”。
类型为“{0}”的值不能从函数“{2}”返回,因为它具有返回类型“{1}”。
类型为“{0}”的值不能从方法“{2}”返回,因为它具有返回类型“{1}”。
描述
#当方法或函数返回的值的类型不可赋值给声明的返回类型时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 f
的返回类型为 String
,但正在返回 int
。
String f() => 3;
常见修复
#如果返回类型正确,则将要返回的值替换为正确类型的值,可能会通过转换现有值。
String f() => 3.toString();
如果该值正确,则更改返回类型以匹配。
int f() => 3;
return_of_invalid_type_from_closure
#返回类型“{0}”不能从“{1}”函数返回,因为闭包的上下文需要。
描述
#当返回表达式的静态类型不能赋值给闭包所需返回类型时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 f
被定义为返回 String
的函数,但分配给它的闭包返回 int
。
String Function(String) f = (s) => 3;
常见修复
#如果返回类型正确,则将返回值替换为正确类型的值,可以通过转换现有值来实现。
String Function(String) f = (s) => 3.toString();
return_without_value
#“return”后缺少返回值。
描述
#当分析器在声明了返回类型的函数中找到没有表达式的 return
语句时,会产生此诊断。
示例
#以下代码会产生此诊断,因为函数 f
应该返回 int
,但没有返回任何值。
int f() {
return;
}
常见修复
#添加一个计算要返回值的表达式。
int f() {
return 0;
}
sdk_version_async_exported_from_core
#类“{0}”直到 2.1 版本才从“dart:core”导出,但此代码需要在更早的版本上运行。
描述
#当在没有导入 dart:async
的库中引用类 Future
或 Stream
,并且 SDK 约束的下限小于 2.1.0 时,分析器会产生此诊断。在早期版本中,这些类未在 dart:core
中定义,因此导入是必要的。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.1.0
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_version_as_expression_in_const_context
#直到 2.3.2 版本才支持在常量表达式中使用 as 表达式,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.3.2 的代码中发现 常量上下文 中的 as
表达式时,分析器会产生此诊断。在 常量上下文 中使用 as
表达式在早期版本中不受支持,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 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_version_bool_operator_in_const_context
#直到 2.3.2 版本才支持在常量上下文中使用运算符“{0}”用于“bool”操作数,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.3.2 的代码中发现对 bool
类在 常量上下文 中使用 &
、|
或 ^
运算符时,分析器会产生此诊断。在 常量上下文 中使用这些运算符在早期版本中不受支持,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 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_version_constructor_tearoffs
#分离构造函数需要“constructor-tearoffs”语言特性。
描述
#当在 SDK 约束下限小于 2.15 的代码中发现构造函数分离时,分析器会产生此诊断。在早期版本中不支持构造函数分离,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 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_version_eq_eq_operator_in_const_context
#直到 2.3.2 版本才支持对非原始类型使用运算符“==”,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.3.2 的代码中发现对非原始类型在 常量上下文 中使用运算符 ==
时,分析器会产生此诊断。在 常量上下文 中使用此运算符在早期版本中不受支持,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 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_version_extension_methods
#直到 2.6.0 版本才支持扩展方法,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.6.0 的代码中发现扩展声明或扩展覆盖时,分析器会产生此诊断。在早期版本中不支持使用扩展,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.6.0
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_version_gt_gt_gt_operator
#直到 2.14.0 版本才支持运算符“>>>”,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.14.0 的代码中使用运算符 >>>
时,分析器会产生此诊断。在早期版本中不支持此运算符,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.14.0
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_version_is_expression_in_const_context
#直到 2.3.2 版本才支持在常量上下文中使用 is 表达式,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.3.2 的代码中发现 常量上下文 中的 is
表达式时,分析器会产生此诊断。在 常量上下文 中使用 is
表达式在早期版本中不受支持,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 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_version_never
#直到 2.12.0 版本才支持类型“Never”,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.12.0 的代码中发现对类 Never
的引用时,分析器会产生此诊断。在早期版本中未定义此类,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.12.0
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_version_set_literal
#直到 2.2 版本才支持集合字面量,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.2.0 的代码中发现集合字面量时,分析器会产生此诊断。在早期版本中不支持集合字面量,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.2.0
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_version_ui_as_code
#直到 2.3.0 版本才支持 for、if 和 spread 元素,但此代码需要在更早的版本上运行。
描述
#当在 SDK 约束下限小于 2.3.0 的代码中发现 for、if 或 spread 元素时,分析器会产生此诊断。在早期版本中不支持使用 for、if 或 spread 元素,因此此代码将无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 示例,它定义了 SDK 约束,下限小于 2.3.0
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_version_ui_as_code_in_const_context
#在 2.5.0 版本之前,常量表达式不支持 if 和 spread 元素,但此代码需要在早期版本上运行。
描述
#当在 SDK 约束的下限小于 2.5.0 的代码中发现位于常量上下文中的 if 或 spread 元素时,分析器会产生此诊断。在早期版本中,不支持在常量上下文中使用 if 或 spread 元素,因此此代码无法在早期版本的 SDK 上运行。
示例
#以下是一个 pubspec 的示例,其中定义了下限小于 2.5.0 的 SDK 约束
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];
set_element_type_not_assignable
#元素类型“{0}”无法赋值给集合类型“{1}”。
描述
#当集合字面量中的元素类型无法赋值给该集合的元素类型时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字符串字面量 '0'
的类型是 String
,无法赋值给集合的元素类型 int
var s = <int>{'0'};
常见修复
#如果集合字面量的元素类型错误,则更改集合的元素类型
var s = <String>{'0'};
如果元素的类型错误,则更改元素
var s = <int>{'0'.length};
shared_deferred_prefix
#延迟导入的前缀不能用于其他导入指令。
描述
#当延迟导入中的前缀也用作其他导入(无论是延迟导入还是非延迟导入)中的前缀时,分析器会产生此诊断。延迟导入中的前缀不能与其他导入共享,因为该前缀用于加载导入的库。
示例
#以下代码会产生此诊断,因为前缀 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));
size_annotation_dimensions
#“数组”必须具有与维度匹配的“数组”注解。
描述
#当 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;
}
static_access_to_instance_member
#无法使用静态访问来访问实例成员“{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;
subtype_of_base_or_final_is_not_base_final_or_sealed
#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 {}
常见修复
#将 base
、final
或 sealed
添加到类或 mixin 的声明中
base class A {}
final class B extends A {}
subtype_of_deferred_class
#类和 mixin 不能实现延迟类。
类不能扩展延迟类。
类不能混入延迟类。
描述
#当一个类型(类或 mixin)是使用延迟导入导入的库中的类的子类型时,分析器会产生此诊断。类型的超类型必须与类型同时编译,而延迟库中的类在库加载之前不会被编译。
有关详细信息,请查看延迟加载库。
示例
#假设有一个文件 a.dart
定义了类 A
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 {}
subtype_of_disallowed_type
#“{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 {}
subtype_of_ffi_class
#类 “{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 {}
subtype_of_sealed_class
#类 “{0}” 不应被扩展、混入或实现,因为它已密封。
描述
#当一个密封类(具有 sealed
注解或继承或混入密封类的类)在类或 mixin 声明的 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 {}
如果该类需要是密封类的子类型,则要么更改密封类使其不再密封,要么将子类移动到与密封类相同的包中。
subtype_of_struct_class
#类 “{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;
}
supertype_expands_to_type_parameter
#扩展为类型参数的类型别名不能被实现。
扩展为类型参数的类型别名不能被混入。
扩展为类型参数的类型别名不能用作超类约束。
扩展为类型参数的类型别名不能用作超类。
描述
#当扩展为类型参数的类型别名用于 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 {}
super_formal_parameter_type_is_not_subtype_of_associated
#此参数的类型“{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);
}
super_formal_parameter_without_associated_named
#没有关联的命名超构造函数参数。
描述
#当构造函数中存在命名超参数,并且隐式或显式调用的超构造函数没有具有相同名称的命名参数时,分析器会产生此诊断。
命名超参数按名称与超构造函数中的命名参数关联。
示例
#以下代码会产生此诊断,因为 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});
}
super_formal_parameter_without_associated_positional
#没有关联的位置超类构造函数参数。
描述
#当构造函数中存在位置超参数,而隐式或显式调用的超类构造函数在相应索引处没有位置参数时,分析器会产生此诊断。
位置超参数通过它们的索引与超类构造函数中的位置参数关联。也就是说,第一个超参数与超类构造函数中的第一个位置参数关联,第二个与第二个关联,依此类推。
示例
#以下代码会产生此诊断,因为 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);
}
super_invocation_not_last
#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_in_enum_constructor
#枚举构造函数不能有 'super' 初始化器。
描述
#当枚举中构造函数的初始化列表包含对超类构造函数的调用时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为枚举 E
中的构造函数在初始化列表中具有超类构造函数调用
enum E {
e;
const E() : super();
}
常见修复
#删除超类构造函数调用
enum E {
e;
const E();
}
super_in_extension
#'super' 关键字不能在扩展中使用,因为扩展没有超类。
描述
#当在扩展中声明的成员使用 super
关键字时,分析器会产生此诊断。扩展不是类,也没有超类,因此 super
关键字没有意义。
示例
#以下代码会产生此诊断,因为 super
不能在扩展中使用
extension E on Object {
String get displayString => super.toString();
}
常见修复
#删除 super
关键字
extension E on Object {
String get displayString => toString();
}
super_in_extension_type
#'super' 关键字不能在扩展类型中使用,因为扩展类型没有超类。
描述
#当在扩展类型的实例成员中使用 super
时,分析器会产生此诊断。扩展类型没有超类,因此没有可以调用的继承成员。
示例
#以下代码会产生此诊断,因为
extension type E(String s) {
void m() {
super.m();
}
}
常见修复
#替换或删除 super
调用
extension type E(String s) {
void m() {
s.toLowerCase();
}
}
super_in_invalid_context
#'super' 调用的上下文无效。
描述
#当关键字 super
在实例方法之外使用时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 super
在顶层函数中使用
void f() {
super.f();
}
常见修复
#重写代码以不使用 super
。
super_in_redirecting_constructor
#重定向构造函数不能有 '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_completes_normally
#'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_expression_not_assignable
#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;
}
}
tearoff_of_generative_constructor_of_abstract_class
#抽象类的生成构造函数不能被撕裂。
描述
#当抽象类的生成构造函数被撕裂时,分析器会产生此诊断。这是不允许的,因为创建抽象类的实例是无效的,这意味着被撕裂的构造函数没有任何有效的用途。
示例
#以下代码会产生此诊断,因为构造函数 C.new
被撕裂,而类 C
是一个抽象类
abstract class C {
C();
}
void f() {
C.new;
}
常见修复
#撕裂具体类的构造函数。
text_direction_code_point_in_comment
#Unicode 代码点 'U+{0}' 改变了文本的外观,使其与编译器解释的方式不同。
描述
#当分析器遇到包含文本方向 Unicode 代码点的源代码时,会产生此诊断。这些代码点会导致字符串文字或注释中的源代码以与编辑器中显示的方式不同地解释和编译,从而导致可能的安全漏洞。
示例
#以下代码产生此诊断两次,因为标签字符串的开头和结尾处有隐藏字符
var label = 'Interactive text';
常见修复
#如果代码点旨在包含在字符串文字中,则对其进行转义
var label = '\u202AInteractive text\u202C';
如果代码点不旨在包含在字符串文字中,则将其删除
var label = 'Interactive text';
text_direction_code_point_in_literal
#Unicode 代码点 'U+{0}' 改变了文本的外观,使其与编译器解释的方式不同。
描述
#当分析器遇到包含文本方向 Unicode 代码点的源代码时,会产生此诊断。这些代码点会导致字符串文字或注释中的源代码以与编辑器中显示的方式不同地解释和编译,从而导致可能的安全漏洞。
示例
#以下代码产生此诊断两次,因为标签字符串的开头和结尾处有隐藏字符
var label = 'Interactive text';
常见修复
#如果代码点旨在包含在字符串文字中,则对其进行转义
var label = '\u202AInteractive text\u202C';
如果代码点不旨在包含在字符串文字中,则将其删除
var label = 'Interactive text';
throw_of_invalid_type
#抛出表达式的类型 '{0}' 必须可赋值给 'Object'。
描述
#当 throw 表达式中表达式的类型不能赋值给 Object
时,分析器会产生此诊断。抛出 null
是无效的,因此使用可能评估为 null
的表达式是无效的。
示例
#以下代码产生此诊断,因为 s
可能为 null
void f(String? s) {
throw s;
}
常见修复
#向表达式添加显式的 null 检查
void f(String? s) {
throw s!;
}
top_level_cycle
#无法推断 '{0}' 的类型,因为它通过循环 {1} 依赖于自身。
描述
#当顶级变量没有类型注释并且变量的初始化器直接或间接地引用该变量时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为变量 x
和 y
是根据彼此定义的,并且两者都没有显式类型,因此无法推断另一个的类型
var x = y;
var y = x;
常见修复
#如果两个变量不需要相互引用,则打破循环
var x = 0;
var y = x;
如果两个变量需要相互引用,则至少给其中一个变量一个显式类型
int x = y;
var y = x;
但是请注意,虽然此代码不会产生任何诊断,但它会在运行时产生堆栈溢出,除非在引用循环中的任何变量之前,至少有一个变量被分配了一个不依赖于其他变量的值。
type_alias_cannot_reference_itself
#类型定义不能直接或通过另一个类型定义递归地引用自身。
描述
#当类型定义直接或间接地引用自身时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 F
通过 G
间接地依赖于自身
typedef F = void Function(G);
typedef G = void Function(F);
常见修复
#更改循环中的一个或多个类型定义,使其都不引用自身
typedef F = void Function(G);
typedef G = void Function(int);
type_annotation_deferred_class
#延迟类型 '{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) {}
如果要求导入是延迟的,并且有另一个合适的类型,则使用该类型代替来自延迟库的类型。
type_argument_not_matching_bounds
#' {0} '不符合类型参数 '{1}' 的边界 '{2}'。
描述
#当类型参数与相应类型参数的边界不同或不是其子类时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 String
不是 num
的子类
class A<E extends num> {}
var a = A<String>();
常见修复
#将类型参数更改为边界的子类
class A<E extends num> {}
var a = A<int>();
type_check_with_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);
}
type_parameter_referenced_by_static
#静态成员不能引用类的类型参数。
描述
#当静态成员引用为类声明的类型参数时,分析器会产生此诊断。类型参数仅对类的实例有意义。
示例
#以下代码产生此诊断,因为静态方法 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
之间没有关系,因此第二个选项会改变可能预期的语义。
type_parameter_supertype_of_its_bound
#'{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> {}
type_test_with_non_type
#名称 '{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;
}
}
type_test_with_undefined_name
#名称 '{0}' 未定义,因此不能在 'is' 表达式中使用。
描述
#当类型测试表达式中 is
后面的名称未定义时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为名称 Srting
未定义
void f(Object o) {
if (o is Srting) {
// ...
}
}
常见修复
#将名称替换为类型的名称
void f(Object o) {
if (o is String) {
// ...
}
}
unchecked_use_of_nullable_value
#可空表达式不能用作条件。
可空表达式不能在 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) {
// ...
}
}
undefined_annotation
#未定义的名称 '{0}' 用作注释。
描述
#当未定义的名称用作注释时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为名称 undefined
未定义
@undefined
void f() {}
常见修复
#如果名称正确,但尚未声明,则将该名称声明为常量值
const undefined = 'undefined';
@undefined
void f() {}
如果名称错误,则将该名称替换为有效的常量名称
@deprecated
void f() {}
否则,删除该注释。
undefined_class
#未定义的类 '{0}'。
描述
#当分析器遇到看起来像类名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会生成此诊断。
示例
#以下代码会产生此诊断,因为 Piont
未定义
class Point {}
void f(Piont p) {}
常见修复
#如果该标识符未定义,则定义该标识符或将其替换为已定义的类的名称。可以通过修复类的拼写来纠正上面的示例
class Point {}
void f(Point p) {}
如果类已定义但不可见,则您可能需要添加导入。
undefined_constructor_in_initializer
#类 '{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();
}
undefined_enum_constant
#在 '{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;
undefined_enum_constructor
#枚举没有名为 '{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();
}
undefined_extension_getter
#扩展 '{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;
}
undefined_extension_method
#扩展 '{1}' 未定义方法 '{0}'。
描述
#当使用扩展覆盖来调用方法,但指定的扩展未定义该方法时,分析器会生成此诊断。当引用静态方法但指定的扩展未定义时,分析器也会生成此诊断。
示例
#以下代码会产生此诊断,因为扩展 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();
}
undefined_extension_operator
#扩展 '{1}' 未定义运算符 '{0}'。
描述
#当在特定扩展上调用运算符,而该扩展未实现该运算符时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为扩展 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 {}
undefined_extension_setter
#扩展 '{1}' 未定义 setter '{0}'。
描述
#当使用扩展覆盖来调用 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';
}
undefined_function
#未定义函数 '{0}'。
描述
#当分析器遇到看起来像是函数名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会生成此诊断。
示例
#以下代码会产生此诊断,因为名称 emty
未定义
List<int> empty() => [];
void main() {
print(emty());
}
常见修复
#如果该标识符未定义,则定义该标识符或将其替换为已定义的函数的名称。可以通过修复函数的拼写来纠正上面的示例
List<int> empty() => [];
void main() {
print(empty());
}
如果函数已定义但不可见,则您可能需要添加导入或重新排列代码以使该函数可见。
undefined_getter
#getter '{0}' 未为 '{1}' 函数类型定义。
getter '{0}' 未为类型 '{1}' 定义。
描述
#当分析器遇到看起来像是 getter 的名称的标识符,但该标识符未定义或在被引用的作用域中不可见时,会生成此诊断。
示例
#以下代码会产生此诊断,因为 String
没有名为 len
的成员
int f(String s) => s.len;
常见修复
#如果该标识符未定义,则定义该标识符或将其替换为已定义的 getter 的名称。可以通过修复 getter 的拼写来纠正上面的示例
int f(String s) => s.length;
undefined_hidden_name
#库 '{0}' 没有导出具有隐藏名称 '{1}' 的成员。
描述
#当隐藏组合器包含一个未由正在导入的库定义的名称时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为 dart:math
未定义名称 String
import 'dart:math' hide String, max;
var x = min(0, 1);
常见修复
#如果要隐藏不同的名称,则更正该名称。否则,从列表中删除该名称
import 'dart:math' hide max;
var x = min(0, 1);
undefined_identifier
#未定义的名称 '{0}'。
描述
#当分析器遇到未定义或在被引用的作用域中不可见的标识符时,会生成此诊断。
示例
#以下代码会产生此诊断,因为名称 rihgt
未定义
int min(int left, int right) => left <= rihgt ? left : right;
常见修复
#如果标识符未定义,则需要定义它,或将其替换为已定义的标识符。上面的示例可以通过修复变量的拼写来更正。
int min(int left, int right) => left <= right ? left : right;
如果标识符已定义但不可见,则可能需要添加导入或重新排列代码以使标识符可见。
undefined_identifier_await
#未用 'async' 标记的函数体中存在未定义的名称 'await'。
描述
#当在未声明且未使用 async
关键字标记的方法或函数体中使用名称 await
时,分析器会生成此诊断信息。名称 await
仅在异步函数中引入 await 表达式。
示例
#以下代码会产生此诊断信息,因为名称 await
在 f
的主体中使用,即使 f
的主体未使用 async
关键字标记。
void f(p) { await p; }
常见修复
#将关键字 async
添加到函数体。
void f(p) async { await p; }
undefined_method
#方法 '{0}' 未为 '{1}' 函数类型定义。
方法 '{0}' 未为类型 '{1}' 定义。
描述
#当分析器遇到一个看起来像方法名称的标识符,但该标识符未定义或在它被引用的范围内不可见时,会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为标识符 removeMiddle
未定义。
int f(List<int> l) => l.removeMiddle();
常见修复
#如果标识符未定义,则需要定义它,或将其替换为已定义的方法名称。上面的示例可以通过修复方法的拼写来更正。
int f(List<int> l) => l.removeLast();
undefined_named_parameter
#未定义名为 '{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);
}
undefined_operator
#运算符 '{0}' 未为类型 '{1}' 定义。
描述
#当在未定义该运算符的对象上调用用户可定义的运算符时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为类 C
未定义运算符 +
。
class C {}
C f(C c) => c + 2;
常见修复
#如果应该为该类定义运算符,则定义它。
class C {
C operator +(int i) => this;
}
C f(C c) => c + 2;
undefined_prefixed_name
#名称 '{0}' 正在通过前缀 '{1}' 引用,但它未在使用该前缀导入的任何库中定义。
描述
#当发现带有前缀的标识符,且该前缀有效,但该标识符未在使用该前缀导入的任何库中声明时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 dart:core
未定义任何名为 a
的内容。
import 'dart:core' as p;
void f() {
p.a;
}
常见修复
#如果声明该名称的库尚未导入,请为该库添加导入。
如果名称错误,则将其更改为在导入库中声明的名称之一。
undefined_referenced_parameter
#参数 '{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;
undefined_setter
#setter '{0}' 未为 '{1}' 函数类型定义。
setter '{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;
}
}
undefined_shown_name
#库 '{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_member
#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.
。
如果成员未定义,则将成员添加到其中一个超类或删除调用。
unknown_platform
#平台 '{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:
unnecessary_cast
#不必要的强制转换。
描述
#当要强制转换的值已知已是它要被强制转换成的类型时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为由于 is
测试,n
已知是 int
。
void f(num n) {
if (n is int) {
(n as int).isEven;
}
}
常见修复
#删除不必要的强制转换
void f(num n) {
if (n is int) {
n.isEven;
}
}
unnecessary_dev_dependency
#对 {0} 的 dev 依赖项是不必要的,因为该包也有正常的依赖项。
描述
#当 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
unnecessary_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);
}
unnecessary_import
#对 '{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) {}
常见修复
#如果不需要导入,则删除它。
如果此导入导入的一些名称打算使用但尚未被使用,并且这些名称没有被其他导入导入,则将缺失的引用添加到这些名称。
unnecessary_nan_comparison
#double 不能等于 'double.nan',因此条件始终为 'false'。
double 不能等于 '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;
unnecessary_non_null_assertion
#'!' 将不起作用,因为接收器不能为 null。
描述
#当 !
运算符的操作数不能为 null
时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 x
不能为 null
。
int f(int x) {
return x!;
}
常见修复
#删除 null 检查运算符(!
)。
int f(int x) {
return x;
}
unnecessary_no_such_method
#不必要的 '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 {}
unnecessary_null_assert_pattern
#空断言模式将不起作用,因为匹配的类型不可为空。
描述
#当使用空断言模式来匹配不可为空的值时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为变量 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) {}
}
unnecessary_null_check_pattern
#空检查模式将不起作用,因为匹配的类型不可为空。
描述
#当使用空检查模式来匹配不可为空的值时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为值 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) {}
}
unnecessary_null_comparison
#操作数不能为 'null',因此条件始终为 'false'。
操作数不能为 'null',因此条件始终为 'true'。
操作数必须为 '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);
}
unnecessary_question_mark
#'?' 是不必要的,因为 '{0}' 本身就是可为空的。
描述
#当类型 dynamic
或类型 Null
后跟问号时,分析器会产生此诊断。这两种类型本身都是可为空的,因此问号不会更改语义。
示例
#以下代码产生此诊断,因为 dynamic
后面的问号是不必要的
dynamic? x;
常见修复
#删除不需要的问号
dynamic x;
unnecessary_set_literal
#大括号不必要地将此表达式包装在集合字面量中。
描述
#当返回类型为 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) {}
unnecessary_type_check
#不必要的类型检查;结果始终为 '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;
unqualified_reference_to_non_local_static_member
#超类型的静态成员必须由定义类型的名称限定。
描述
#当一个类中的代码引用超类中的静态成员,而没有在该成员名称前面加上超类的名称时,分析器会产生此诊断。静态成员只能在其声明的类中不带前缀引用。
示例
#以下代码产生此诊断,因为在 getter g
中引用了静态字段 x
,而没有在其前面加上定义类的名称
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;
}
unqualified_reference_to_static_member_of_extended_type
#扩展类型或其超类之一的静态成员必须由定义类型的名称限定。
描述
#当找到未定义的名称,并且该名称与扩展类型或其超类之一的静态成员相同时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 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() {}
}
unreachable_switch_case
#此情况包含在前面的情况中。
描述
#当 switch
语句中的 case
子句由于所有可匹配的值都被之前的 case
子句匹配而无法匹配任何内容时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为值 1
在前面的 case 中匹配
void f(int x) {
switch (x) {
case 1:
print('one');
case 1:
print('two');
}
}
常见修复
#更改一个或两个冲突的 case 以匹配不同的值
void f(int x) {
switch (x) {
case 1:
print('one');
case 2:
print('two');
}
}
unreachable_switch_default
#此 default 子句包含在前面的情况中。
描述
#当 switch
语句中的 default
子句由于所有可匹配的值都被之前的 case
子句匹配而无法匹配任何内容时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为值 E.e1
和 E.e2
在前面的 case 中匹配
enum E { e1, e2 }
void f(E x) {
switch (x) {
case E.e1:
print('one');
case E.e2:
print('two');
default:
print('other');
}
}
常见修复
#删除不必要的 default
子句
enum E { e1, e2 }
void f(E x) {
switch (x) {
case E.e1:
print('one');
case E.e2:
print('two');
}
}
unused_catch_clause
#未使用异常变量 '{0}',因此可以删除 'catch' 子句。
描述
#当找到 catch
子句,并且异常参数和可选的堆栈跟踪参数都未在 catch
块中使用时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 e
未被引用
void f() {
try {
int.parse(';');
} on FormatException catch (e) {
// ignored
}
}
常见修复
#删除未使用的 catch
子句
void f() {
try {
int.parse(';');
} on FormatException {
// ignored
}
}
unused_catch_stack
#未使用的堆栈跟踪变量 '{0}' 可以删除。
描述
#当 catch
子句中的堆栈跟踪参数未在 catch
块的主体内引用时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 stackTrace
未被引用
void f() {
try {
// ...
} catch (exception, stackTrace) {
// ...
}
}
常见修复
#如果您需要引用堆栈跟踪参数,则添加对其的引用。否则,请删除它
void f() {
try {
// ...
} catch (exception) {
// ...
}
}
unused_element
#未引用声明 '{0}'。
描述
#当私有声明未在包含该声明的库中引用时,分析器会产生此诊断。分析以下类型的声明
- 私有顶级声明及其所有成员
- 公共声明的私有成员
并非对元素的所有引用都会将其标记为“已使用”
- 将值分配给顶级变量(使用标准的
=
赋值或空感知??=
赋值)不计为使用它。 - 在文档注释引用中引用元素不计为使用它。
- 在
is
表达式的右侧引用类、mixin 或枚举不计为使用它。
示例
#假设库中没有代码引用 _C
,则以下代码会产生此诊断
class _C {}
常见修复
#如果不需要该声明,则删除它。
如果该声明旨在被使用,则添加代码来使用它。
unused_element_parameter
#从未给出可选参数 '{0}' 的值。
描述
#当从未为私有声明中声明的可选参数传递值时,分析器会产生此诊断。
示例
#假设库中没有任何代码在 _m
的任何调用中为 y
传递值,则以下代码会产生此诊断
class C {
void _m(int x, [int? y]) {}
void n() => _m(0);
}
常见修复
#如果不需要该声明,则删除它
class C {
void _m(int x) {}
void n() => _m(0);
}
如果该声明旨在被使用,则添加代码来使用它。
unused_field
#未使用字段 '{0}' 的值。
描述
#当声明了私有字段但从未读取时,即使它在一个或多个位置写入,分析器也会产生此诊断。
示例
#以下代码产生此诊断,因为字段 _originalValue
未在库中的任何位置读取
class C {
final String _originalValue;
final String _currentValue;
C(this._originalValue) : _currentValue = _originalValue;
String get value => _currentValue;
}
看起来字段 _originalValue
正在初始化器 (_currentValue = _originalValue
) 中读取,但这实际上是对同名参数的引用,而不是对字段的引用。
常见修复
#如果不需要该字段,则删除它。
如果该字段旨在被使用,则添加缺失的代码。
unused_import
#未使用的导入:'{0}'。
描述
#当不需要导入时,因为导入的名称都没有在导入库中引用,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 dart:async
中定义的任何内容都没有在库中引用
import 'dart:async';
void main() {}
常见修复
#如果不需要导入,则删除它。
如果打算使用某些导入的名称,则添加缺失的代码。
unused_label
#未使用标签 '{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;
}
}
}
unused_local_variable
#未使用局部变量 '{0}' 的值。
描述
#当声明了局部变量但从未读取时,即使它在一个或多个位置写入,分析器也会产生此诊断。
示例
#以下代码产生此诊断,因为从未读取 count
的值
void main() {
int count = 0;
}
常见修复
#如果不需要该变量,则删除它。
如果该变量旨在被使用,则添加缺失的代码。
unused_result
#' {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();
}
unused_shown_name
#显示了名称 {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_does_not_exist
#URI 的目标不存在:'{0}'。
描述
#当发现 import、export 或 part 指令中 URI 指向一个不存在的文件时,分析器会生成此诊断信息。
示例
#如果文件 lib.dart
不存在,则以下代码会产生此诊断信息
import 'lib.dart';
常见修复
#如果 URI 输入错误或无效,请更正 URI。
如果 URI 正确,则创建该文件。
uri_does_not_exist_in_doc_import
#URI 的目标不存在:'{0}'。
描述
#当发现 doc-import 指令中 URI 指向一个不存在的文件时,分析器会生成此诊断信息。
示例
#如果文件 lib.dart
不存在,则以下代码会产生此诊断信息
/// @docImport 'lib.dart';
library;
常见修复
#如果 URI 输入错误或无效,请更正 URI。
如果 URI 正确,则创建该文件。
uri_has_not_been_generated
#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_with_interpolation
#URI 不能使用字符串插值。
描述
#当 import
、export
或 part
指令中的字符串字面量包含插值时,分析器会生成此诊断信息。指令中 URI 的解析必须在编译声明之前进行,因此在确定 URI 的值时不能评估表达式。
示例
#以下代码会产生此诊断信息,因为 import
指令中的字符串包含插值
import 'dart:$m';
const m = 'math';
常见修复
#从 URI 中删除插值
import 'dart:math';
var zero = min(0, 0);
use_of_native_extension
#Dart 原生扩展已弃用,并且在 Dart 2.15 中不可用。
描述
#当使用 dart-ext
方案导入库时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为原生库 x
是使用 dart-ext
方案导入的
import 'dart-ext:x';
常见修复
#重写代码以使用 dart:ffi
作为调用原生库内容的方式。
use_of_void_result
#此表达式的类型为 'void',因此其值不能使用。
描述
#当分析器发现类型为 void
的表达式,并且该表达式用于期望值的位置(例如在成员访问之前或赋值的右侧)时,会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 f
没有生成可以调用 toString
的对象
void f() {}
void g() {
f().toString();
}
常见修复
#重写代码以使表达式具有值,或重写代码以使其不依赖于该值。
values_declaration_in_enum
#名为 'values' 的成员不能在枚举中声明。
描述
#当枚举声明定义名为 values
的成员(无论该成员是枚举值、实例成员还是静态成员)时,分析器会生成此诊断信息。
任何此类成员都与隐式声明的静态 getter(名为 values
)冲突,该 getter 返回包含所有枚举常量的列表。
示例
#以下代码会产生此诊断信息,因为枚举 E
定义了一个名为 values
的实例成员
enum E {
v;
void values() {}
}
常见修复
#更改冲突成员的名称。
enum E {
v;
void getValues() {}
}
variable_length_array_not_last
#可变长度的 'Array' 只能作为 Struct 的最后一个字段出现。
描述
#当可变长度的内联 Array
不是 Struct
的最后一个成员时,分析器会生成此诊断信息。
有关 FFI 的更多信息,请参阅使用 dart:ffi 进行 C 互操作。
示例
#以下代码会产生此诊断,因为字段 a0
的类型具有三个嵌套数组,但在 Array
注解中仅给出了两个维度
import 'dart:ffi';
final class C extends Struct {
@Array.variable()
external Array<Uint8> a0;
@Uint8()
external int a1;
}
常见修复
#将可变长度的内联 Array
移动到结构中的最后一个字段。
import 'dart:ffi';
final class C extends Struct {
@Uint8()
external int a1;
@Array.variable()
external Array<Uint8> a0;
}
如果内联数组具有固定大小,请使用大小对其进行注释
import 'dart:ffi';
final class C extends Struct {
@Array(10)
external Array<Uint8> a0;
@Uint8()
external int a1;
}
variable_pattern_keyword_in_declaration_context
#声明上下文中的变量模式不能指定 '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);
}
variable_type_mismatch
#类型为 '{0}' 的值不能分配给类型为 '{1}' 的常量变量。
描述
#当常量表达式的评估会导致 CastException
时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 x
的值是一个 int
,不能将其分配给 y
,因为 int
不是 String
const dynamic x = 0;
const String y = x;
常见修复
#如果常量的声明正确,则更改要分配的值以使其具有正确的类型
const dynamic x = 0;
const String y = '$x';
如果分配的值正确,则更改声明以使其具有正确的类型
const int x = 0;
const int y = x;
workspace_field_not_list
#'workspace' 字段的值必须是相对文件路径的列表。
描述
#当 workspace
键的值不是列表时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 workspace
键的值是一个字符串,而此处应该是一个列表
name: example
workspace: notPaths
常见修复
#更改 workspace 字段的值,使其成为列表
name: example
workspace:
- pkg/package_1
- pkg/package_2
workspace_value_not_string
#工作区条目必须是目录路径(字符串)。
描述
#当 workspace
列表包含一个不是字符串的值时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 workspace
列表包含一个映射
name: example
workspace:
- image.gif: true
常见修复
#更改 workspace
列表,使其仅包含有效的 POSIX 样式目录路径
name: example
workspace:
- pkg/package_1
- pkg/package_2
workspace_value_not_subdirectory
#工作区值必须是 '{0}' 子目录的相对路径。
描述
#当 workspace
列表包含一个不是包含 `pubspec.yaml` 文件的目录的子目录的值时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为 workspace
列表中的值不是包含 'pubspec.yaml' 文件的目录的子目录的相对路径
name: example
workspace:
- /home/my_package
常见修复
#更改 workspace
列表,使其仅包含子目录路径。
name: example
workspace:
- pkg/package_1
- pkg/package_2
wrong_number_of_parameters_for_operator
#运算符 '-' 应声明 0 个或 1 个参数,但找到 {0} 个。
运算符 '{0}' 应精确声明 {1} 个参数,但找到 {2} 个。
描述
#当运算符的声明具有错误的参数数量时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为运算符 +
必须有一个与右操作数对应的参数
class C {
int operator +(a, b) => 0;
}
常见修复
#添加或删除参数以匹配所需的数量
class C {
int operator +(a) => 0;
}
wrong_number_of_parameters_for_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) {}
}
wrong_number_of_type_arguments
#类型 '{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) {}
wrong_number_of_type_arguments_constructor
#构造函数 '{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();
wrong_number_of_type_arguments_enum
#枚举使用 {0} 个类型参数声明,但提供了 {1} 个类型参数。
描述
#当实例化具有类型参数的枚举中的枚举值并提供类型参数时,但类型参数的数量与类型参数的数量不相同时,分析器会生成此诊断信息。
示例
#以下代码会产生此诊断信息,因为枚举值 c
提供了一个类型参数,即使枚举 E
被声明为有两个类型参数
enum E<T, U> {
c<int>()
}
常见修复
#如果类型参数的数量正确,则更改类型参数的数量以匹配类型参数的数量
enum E<T, U> {
c<int, String>()
}
如果类型参数的数量正确,则更改类型参数的数量以匹配类型参数的数量
enum E<T> {
c<int>()
}
wrong_number_of_type_arguments_extension
#扩展 '{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*
表达式产生的对象的类型与从生成器返回的 Iterable
或 Stream
类型返回的对象的类型不匹配时,分析器会生成此诊断信息(使用 sync*
或 async*
标记的函数或方法)。
示例
#以下代码会产生此诊断信息,因为 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';
}
始终声明返回类型
#函数 '{0}' 应该具有返回类型,但没有。
方法 '{0}' 应该具有返回类型,但没有。
描述
#当方法或函数没有显式返回类型时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为函数 f
没有返回类型
f() {}
常见修复
#添加显式返回类型
void f() {}
始终将控制体放在新行上
#语句应该在单独的行上。
描述
#当受控制流语句(if
、for
、while
或 do
)控制的代码与控制流语句位于同一行时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 return
语句与控制 return
是否执行的 if
语句位于同一行
void f(bool b) {
if (b) return;
}
常见修复
#将受控语句放到单独的缩进行上
void f(bool b) {
if (b)
return;
}
始终将必需的命名参数放在最前面
#必需的命名参数应在可选的命名参数之前。
描述
#当必需的命名参数出现在可选的命名参数之后时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为必需的参数 x
在可选的参数 y
之后
void f({int? y, required int x}) {}
常见修复
#重新排列参数,使所有必需的命名参数都在任何可选的命名参数之前
void f({required int x, int? y}) {}
始终使用包导入
#对于“lib”目录中的文件,请使用“package:”导入。
描述
#当 lib
目录内的库中的 import
使用相对路径导入同一包的 lib
目录内的另一个库时,分析器会生成此诊断。
示例
#假设一个名为 a.dart
的文件和下面的代码都在同一包的 lib
目录中,则以下代码会生成此诊断,因为使用了相对 URI 来导入 a.dart
import 'a.dart';
常见修复
#使用包导入
import 'package:p/a.dart';
注解重写
#成员“{0}”覆盖了一个继承的成员,但没有用“@override”注解。
描述
#当一个成员覆盖了一个继承的成员,但没有用 @override
注解时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为类 B
中的方法 m
覆盖了类 A
中具有相同名称的方法,但没有标记为有意覆盖
class A {
void m() {}
}
class B extends A {
void m() {}
}
常见修复
#如果子类中的成员旨在覆盖超类中的成员,则添加 @override
注解
class A {
void m() {}
}
class B extends A {
@override
void m() {}
}
如果子类中的成员不旨在覆盖超类中的成员,则重命名其中一个成员
class A {
void m() {}
}
class B extends A {
void m2() {}
}
避免空的 else 块
#在“else”子句中不允许使用空语句。
描述
#当 else
之后的语句为空语句(分号)时,分析器会生成此诊断。
有关更多信息,请参阅 avoid_empty_else
的文档。
示例
#以下代码会生成此诊断,因为 else
之后的语句为空语句
void f(int x, int y) {
if (x > y)
print("1");
else ;
print("2");
}
常见修复
#如果空语句之后的语句旨在仅在条件为 false
时执行,则删除空语句
void f(int x, int y) {
if (x > y)
print("1");
else
print("2");
}
如果没有代码旨在仅在条件为 false
时执行,则删除整个 else
子句
void f(int x, int y) {
if (x > y)
print("1");
print("2");
}
避免在 forEach 调用中使用函数字面量
#不应将函数字面量传递给“forEach”。
描述
#当 Iterable.forEach
的参数是一个闭包时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为调用 forEach
的参数是一个闭包
void f(Iterable<String> s) {
s.forEach((e) => print(e));
}
常见修复
#如果可以用撕裂(tear-off)替换闭包,则替换闭包
void f(Iterable<String> s) {
s.forEach(print);
}
如果闭包不能用撕裂替换,则使用 for
循环来迭代元素
void f(Iterable<String> s) {
for (var e in s) {
print(e);
}
}
避免 FutureOr<void>
#不要使用类型“FutureOr
描述
#当类型 FutureOr<void>
用作结果的类型时(确切地说:它用在非逆变的位置),分析器会生成此诊断。类型 FutureOr<void>
有问题,因为它可能看起来编码了结果是 Future<void>
,或者应该丢弃结果(当它是 void
时)。但是,没有安全的方法来检测我们是哪种情况,因为类型为 void
的表达式可以评估为任何对象,包括任何类型的 Future。
拥有一个含义类似于“忽略此对象;另外,请查看一下,因为它可能是一个 Future”的类型在概念上也是不合理的。
对于类型 FutureOr<void>
的逆变出现情况(例如,对于形式参数的类型)进行了例外处理,并且对于这些出现情况不会发出警告。此例外的原因是该类型没有描述结果,而是描述了其他人提供的值的约束。类似地,对于类型别名声明进行了例外处理,因为它们很可能用在逆变位置(例如,作为形式参数的类型)。因此,在类型别名声明中,仅检查类型参数的边界。
示例
#import 'dart:async';
FutureOr<void> m() => null;
常见修复
#通常有用的类型 FutureOr<void>
的替代品是 Future<void>?
。此类型编码结果是 Future<void>
或 null,并且在运行时没有歧义,因为没有对象可以同时具有两种类型。
可能并不总是可以使用类型 Future<void>?
作为类型 FutureOr<void>
的替代品,因为后者是所有类型的超类型,而前者不是。在这种情况下,将 FutureOr<void>
替换为类型 void
可能是一个有用的补救措施。
避免初始化为 null
#多余地初始化为“null”。
描述
#当可空变量显式初始化为 null
时,分析器会生成此诊断。该变量可以是局部变量、字段或顶层变量。
未显式初始化的变量或字段会自动初始化为 null
。在 Dart 中没有“未初始化的内存”的概念。
示例
#以下代码会生成此诊断,因为变量 f
显式初始化为 null
class C {
int? f = null;
void m() {
if (f != null) {
print(f);
}
}
}
常见修复
#删除不必要的初始化
class C {
int? f;
void m() {
if (f != null) {
print(f);
}
}
}
避免使用 print
#不要在生产代码中调用“print”。
描述
#当在生产代码中调用函数 print
时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为不能在生产环境中调用函数 print
void f(int x) {
print('x = $x');
}
常见修复
#如果编写的代码使用 Flutter,则使用函数 debugPrint
,并使用 kDebugMode
进行测试保护
import 'package:flutter/foundation.dart';
void f(int x) {
if (kDebugMode) {
debugPrint('x = $x');
}
}
如果编写的代码不使用 Flutter,则使用日志服务(例如 package:logging
)来写入信息。
避免使用相对 lib 导入
#不能使用相对路径导入“lib”中的库。
描述
#当 import
指令中的 URI 的路径中包含 lib
时,分析器会生成此诊断。
示例
#假设 lib
目录中有一个名为 a.dart
的文件
class A {}
以下代码会生成此诊断,因为导入包含一个包含 lib
的路径
import '../lib/a.dart';
常见修复
#重写导入,使 URI 中不包含 lib
import 'a.dart';
避免重命名方法参数
#参数名称“{0}”与覆盖的方法中的名称“{1}”不匹配。
描述
#当从超类覆盖方法的方法更改参数名称时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为 B
中的方法 m
的参数名为 b
,这与 A
中覆盖方法的参数名称不同
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int b) {}
}
常见修复
#重命名其中一个参数,使它们相同
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int a) {}
}
避免在 setter 上使用返回类型
#设置器上不必要的返回类型。
描述
#当设置器具有显式返回类型时,分析器会生成此诊断。
设置器从不返回值,因此声明设置器的返回类型是多余的。
示例
#以下代码会生成此诊断,因为设置器 s
具有显式返回类型 (void
)
void set s(int p) {}
常见修复
#删除返回类型
set s(int p) {}
避免为 void 返回 null
#不要从返回类型为“void”的函数返回“null”。
不要从返回类型为“void”的方法返回“null”。
描述
#当返回类型为 void
的函数显式返回 null
时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为在 void
函数中有显式的 null
返回
void f() {
return null;
}
常见修复
#删除不必要的显式 null
void f() {
return;
}
避免遮蔽类型参数
#类型参数“{0}”隐藏了封闭的 {1} 的类型参数。
描述
#当类型参数隐藏了封闭声明中的类型参数时,分析器会生成此诊断。
用不同的类型参数隐藏类型参数可能会导致难以调试的微妙错误。
示例
#以下代码会生成此诊断,因为方法 m
定义的类型参数 T
隐藏了类 C
定义的类型参数 T
class C<T> {
void m<T>() {}
}
常见修复
#重命名其中一个类型参数
class C<T> {
void m<S>() {}
}
避免在表达式语句中使用单个级联
#不必要的级联表达式。
描述
#当使用单个级联运算符,且表达式的值未用于任何用途时(例如,分配给变量或作为参数传递),分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为未用到级联表达式 s..length
的值
void f(String s) {
s..length;
}
常见修复
#将级联运算符替换为简单的访问运算符
void f(String s) {
s.length;
}
避免缓慢的异步 IO
#使用异步“dart:io”方法。
描述
#当使用具有同步等效项的异步文件 I/O 方法时,分析器会生成此诊断。
以下是特定标记的异步方法
Directory.exists
Directory.stat
File.lastModified
File.exists
File.stat
FileSystemEntity.isDirectory
FileSystemEntity.isFile
FileSystemEntity.isLink
FileSystemEntity.type
示例
#以下代码会生成此诊断,因为调用了异步方法 exists
import 'dart:io';
Future<void> g(File f) async {
await f.exists();
}
常见修复
#使用方法的同步版本
import 'dart:io';
void g(File f) {
f.existsSync();
}
避免使用 type.toString
#在生产代码中对“Type”使用“toString”是不安全的。
描述
#当在静态类型为 Type
的值上调用方法 toString
时,分析器会生成此诊断。
示例
#以下代码会生成此诊断,因为在 runtimeType
返回的 Type
上调用了方法 toString
bool isC(Object o) => o.runtimeType.toString() == 'C';
class C {}
常见修复
#如果必须完全相同,则使用显式比较
bool isC(Object o) => o.runtimeType == C;
class C {}
如果该类型的子类型实例返回 true
可以接受,则使用类型检查
bool isC(Object o) => o is C;
class C {}
避免使用类型作为参数名称
#参数名称“{0}”与可见类型名称匹配。
描述
#当参数列表中的参数名称与可见类型(名称在作用域内的类型)相同时,分析器会产生此诊断。
这通常表示参数的预期名称丢失,导致将类型名称用作参数名称而不是参数类型。即使并非如此(参数名称是故意的),参数名称也会遮蔽现有类型,这可能导致难以诊断的错误。
示例
#以下代码会产生此诊断,因为函数 f
有一个名为 int
的参数,它遮蔽了来自 dart:core
的类型 int
。
void f(int) {}
常见修复
#如果缺少参数名称,则为参数添加一个名称
void f(int x) {}
如果参数的预期隐式类型为 dynamic
,则重命名参数,使其不会遮蔽任何可见类型的名称
void f(int_) {}
避免不必要的容器
#不必要的“Container”实例。
描述
#当小部件树包含 Container
的实例,并且构造函数的唯一参数为 child:
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为对 Container
构造函数的调用仅具有 child:
参数。
import 'package:flutter/material.dart';
Widget buildRow() {
return Container(
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
常见修复
#如果你打算为构造函数提供其他参数,则添加它们
import 'package:flutter/material.dart';
Widget buildRow() {
return Container(
color: Colors.red.shade100,
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
如果不需要其他参数,则解包子小部件
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: [
Text('a'),
Text('b'),
],
);
}
避免在 Flutter 中使用 Web 库
#不要在 Flutter Web 插件之外使用仅限 Web 的库。
描述
#当不是 Web 插件的包中的库包含对仅限 Web 的库的导入时,分析器会产生此诊断。
dart:html
dart:js
dart:js_util
dart:js_interop
dart:js_interop_unsafe
package:js
package:web
示例
#当在不是 Web 插件的包中找到时,以下代码会产生此诊断,因为它导入了 dart:html
。
import 'dart:html';
import 'package:flutter/material.dart';
class C {}
常见修复
#如果该包不打算作为 Web 插件,则删除导入
import 'package:flutter/material.dart';
class C {}
如果该包打算作为 Web 插件,则将以下行添加到该包的 pubspec.yaml
文件中
flutter:
plugin:
platforms:
web:
pluginClass: HelloPlugin
fileName: hello_web.dart
有关更多信息,请参阅开发包和插件。
仅 await Future
#在 '{0}' 的实例上使用了“await”,它不是“Future”的子类型。
描述
#当 await
之后的表达式具有除 Future<T>
、FutureOr<T>
、Future<T>?
、FutureOr<T>?
或 dynamic
以外的任何类型时,分析器会产生此诊断。
对于表达式 await null
,有一个例外,因为它是一种引入微任务延迟的常见方法。
除非表达式可以产生 Future
,否则 await
是不必要的,并且可能导致读者假设存在实际不存在的异步级别。
示例
#以下代码会产生此诊断,因为 await
之后的表达式的类型为 int
。
void f() async {
await 23;
}
常见修复
#删除 await
void f() async {
23;
}
扩展名使用驼峰命名法
#扩展名“{0}”不是 UpperCamelCase 标识符。
描述
#当扩展名的名称未使用“UpperCamelCase”命名约定时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为扩展名的名称不是以大写字母开头的。
extension stringExtension on String {}
常见修复
#如果扩展名需要一个名称(需要在该库外部可见),则重命名扩展名,使其具有有效的名称
extension StringExtension on String {}
如果扩展名不需要名称,则删除扩展名的名称
extension on String {}
类型使用驼峰命名法
#类型名称“{0}”不是 UpperCamelCase 标识符。
描述
#当类型(类、mixin、枚举或 typedef)的名称未使用“UpperCamelCase”命名约定时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为类的名称不是以大写字母开头的。
class c {}
常见修复
#重命名类型,使其具有有效的名称
class C {}
取消订阅
#未取消的“StreamSubscription”实例。
描述
#当创建 StreamSubscription
的实例但未调用方法 cancel
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 subscription
没有被取消。
import 'dart:async';
void f(Stream stream) {
// ignore: unused_local_variable
var subscription = stream.listen((_) {});
}
常见修复
#取消订阅
import 'dart:async';
void f(Stream stream) {
var subscription = stream.listen((_) {});
subscription.cancel();
}
关闭 sink
#未关闭的“Sink”实例。
描述
#当创建 Sink
的实例但未调用方法 close
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 sink
没有被关闭。
import 'dart:io';
void g(File f) {
var sink = f.openWrite();
sink.write('x');
}
常见修复
#关闭 sink
import 'dart:io';
void g(File f) {
var sink = f.openWrite();
sink.write('x');
sink.close();
}
集合方法类型不相关
#参数类型“{0}”与“{1}”不相关。
描述
#当核心库中的几个方法中的任何一个使用不适当类型的参数调用时,分析器会产生此诊断。这些方法没有为参数提供足够具体的类型来允许正常的类型检查捕获错误。
检查的参数为
Iterable<E>.contains
的参数应与E
相关List<E>.remove
的参数应与E
相关Map<K, V>.containsKey
的参数应与K
相关Map<K, V>.containsValue
的参数应与V
相关Map<K, V>.remove
的参数应与K
相关Map<K, V>.[]
的参数应与K
相关Queue<E>.remove
的参数应与E
相关Set<E>.lookup
的参数应与E
相关Set<E>.remove
的参数应与E
相关
示例
#以下代码会产生此诊断,因为 contains
的参数是一个 String
,它不可分配给 int
,即列表 l
的元素类型。
bool f(List<int> l) => l.contains('1');
常见修复
#如果元素类型正确,则将参数更改为具有相同的类型
bool f(List<int> l) => l.contains(1);
如果参数类型正确,则更改元素类型
bool f(List<String> l) => l.contains('1');
常量标识符名称
#常量名称“{0}”不是 lowerCamelCase 标识符。
描述
#当常量的名称不遵循 lowerCamelCase 命名约定时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为顶级变量的名称不是 lowerCamelCase 标识符。
const EMPTY_STRING = '';
常见修复
#重写名称以遵循 lowerCamelCase 命名约定
const emptyString = '';
在 finally 块中使用控制流
#在“finally”子句中使用“{0}”。
描述
#当 finally
子句包含 return
、break
或 continue
语句时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 finally
块内有一个 return
语句。
int f() {
try {
return 1;
} catch (e) {
print(e);
} finally {
return 0;
}
}
常见修复
#如果不需要该语句,则删除该语句,如果该块为空,则删除 finally
子句
int f() {
try {
return 1;
} catch (e) {
print(e);
}
}
如果需要该语句,则将该语句移到 finally
块之外
int f() {
try {
return 1;
} catch (e) {
print(e);
}
return 0;
}
在流控制结构中使用大括号
#{0} 中的语句应包含在块中。
描述
#当控制结构(if
、for
、while
或 do
语句)具有除块之外的语句时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 then
语句未包含在块中。
int f(bool b) {
if (b)
return 1;
return 0;
}
常见修复
#在应为块的语句周围添加花括号
int f(bool b) {
if (b) {
return 1;
}
return 0;
}
悬空的库文档注释
#悬挂的库文档注释。
描述
#当一个看起来是库文档的文档注释之后没有 library
指令时,分析器会产生此诊断。更具体地说,当文档注释出现在库中的第一个指令之前(假设它不是 library
指令),或者在第一个顶级声明之前,并且与该声明之间用一个或多个空行隔开时,会产生此诊断。
示例
#以下代码会产生此诊断,因为第一个 import
指令之前有一个文档注释。
/// This is a great library.
import 'dart:core';
以下代码会产生此诊断,因为第一个类声明之前有一个文档注释,但注释和声明之间有一个空行。
/// This is a great library.
class C {}
常见修复
#如果注释是库文档,则添加一个没有名称的 library
指令
/// This is a great library.
library;
import 'dart:core';
如果注释是以下声明的文档,则删除空行
/// This is a great library.
class C {}
依赖于引用的包
#导入的包“{0}”不是导入包的依赖项。
描述
#当包导入引用了未在 pubspec.yaml
文件中指定的包时,分析器会产生此诊断。
显式依赖于你引用的包可确保它们始终存在,并允许你对它们设置依赖关系约束,以防止发生重大更改。
示例
#给定一个包含以下内容的 pubspec.yaml
文件
dependencies:
meta: ^3.0.0
以下代码会产生此诊断,因为没有对包 a
的依赖。
import 'package:a/a.dart';
常见修复
#依赖项应该是常规依赖项还是开发依赖项,取决于包是从公共库(在 lib
或 bin
下)还是仅从私有库(例如在 test
下的库)引用的。
如果包至少从一个公共库引用,则在 pubspec.yaml
文件中的 dependencies
字段下添加对该包的常规依赖
dependencies:
a: ^1.0.0
meta: ^3.0.0
如果包仅从私有库引用,则在 pubspec.yaml
文件中的 dev_dependencies
字段下添加对该包的开发依赖
dependencies:
meta: ^3.0.0
dev_dependencies:
a: ^1.0.0
空的 catch 块
#空的 catch 块。
描述
#当 catch
子句中的块为空时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 catch 块为空。
void f() {
try {
print('Hello');
} catch (exception) {}
}
常见修复
#如果异常不应被忽略,则添加代码来处理该异常
void f() {
try {
print('We can print.');
} catch (exception) {
print("We can't print.");
}
}
如果异常打算被忽略,则添加注释说明原因
void f() {
try {
print('We can print.');
} catch (exception) {
// Nothing to do.
}
}
如果异常打算被忽略,并且没有任何充分的解释,则重命名异常参数
void f() {
try {
print('We can print.');
} catch (_) {}
}
空的构造函数体
#空的构造函数主体应该使用“;”而不是“{}”编写。
描述
#当构造函数具有空的块主体时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 C
的构造函数具有一个空的块主体。
class C {
C() {}
}
常见修复
#用分号替换该块
class C {
C();
}
空语句
#不必要的空语句。
描述
#当找到一个空语句时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 while
循环控制的语句是一个空语句。
void f(bool condition) {
while (condition);
g();
}
void g() {}
常见修复
#如果没有需要控制的语句,则删除空语句及其所属的控制结构(注意删除的任何其他代码是否具有需要保留的副作用)
void f(bool condition) {
g();
}
void g() {}
如果没有需要控制的语句,但出于其他原因仍然需要控制结构,则将空语句替换为块,以使代码结构更清晰
void f(bool condition) {
while (condition) {}
g();
}
void g() {}
如果存在需要控制的语句,则删除空语句并调整代码,使相应的语句受到控制,可能需要添加一个块
void f(bool condition) {
while (condition) {
g();
}
}
void g() {}
文件名
#文件名“{0}”不是 lower_case_with_underscores 标识符。
描述
#当 .dart
文件的名称未使用 lower_case_with_underscores 时,分析器会产生此诊断。
示例
#名为 SliderMenu.dart
的文件会产生此诊断信息,因为该文件名使用了 UpperCamelCase 约定。
常见修复
#将文件名重命名为使用 lower_case_with_underscores 约定,例如 slider_menu.dart
。
hash 和 equals
#缺少对“{0}”的相应覆盖。
描述
#当类或 mixin 覆盖了 ==
的定义但没有覆盖 hashCode
的定义,或者反过来,覆盖了 hashCode
的定义但没有覆盖 ==
的定义时,分析器会产生此诊断信息。
为了使常见的哈希映射实现正常工作,对象的 ==
运算符和 hashCode
属性必须保持一致。因此,在覆盖任一方法时,都应该覆盖两者。
示例
#以下代码会产生此诊断信息,因为类 C
覆盖了 ==
运算符,但没有覆盖 getter hashCode
class C {
final int value;
C(this.value);
@override
bool operator ==(Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
}
常见修复
#如果您需要覆盖其中一个成员,则添加对另一个成员的覆盖
class C {
final int value;
C(this.value);
@override
bool operator ==(Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
@override
int get hashCode => value.hashCode;
}
如果您不需要覆盖任何一个成员,则删除不必要的覆盖
class C {
final int value;
C(this.value);
}
实现导入
#导入另一个包的 'lib/src' 目录中的库。
描述
#当导入引用了位于不同包的 lib/src
目录中的库时,分析器会产生此诊断信息,这违反了 pub 包的约定。
示例
#以下代码,假设它不是 ffi
包的一部分,会产生此诊断信息,因为导入的库位于顶级的 src
目录中
import 'package:ffi/src/allocation.dart';
常见修复
#如果导入的库包含属于公共 API 的代码,则导入导出公共 API 的公共库
import 'package:ffi/ffi.dart';
如果导入的库不是包的公共 API 的一部分,那么要么找到另一种方法来实现您的目标(假设这是可能的),要么提出问题,要求包作者将其设为公共 API 的一部分。
隐式调用 tear-off
#隐式提取 ‘call’ 方法。
描述
#当带有 call
方法的对象被赋值给函数类型变量时,分析器会产生此诊断信息,隐式提取了 call
方法。
示例
#以下代码会产生此诊断信息,因为 Callable
的实例被传递给期望 Function
的函数
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt(Callable());
}
常见修复
#显式提取 call
方法
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt(Callable().call);
}
使用 JS 互操作类型进行无效的运行时检查
#从 '{0}' 到 '{1}' 的转换将 Dart 值转换为 JS 互操作类型,这可能不具有跨平台一致性。
从 '{0}' 到 '{1}' 的转换将 JS 互操作值转换为 Dart 类型,这可能不具有跨平台一致性。
从 '{0}' 到 '{1}' 的转换将 JS 互操作值转换为不兼容的 JS 互操作类型,这可能不具有跨平台一致性。
'{0}' 和 '{1}' 之间的运行时检查会检查 Dart 值是否为 JS 互操作类型,这可能不具有跨平台一致性。
'{0}' 和 '{1}' 之间的运行时检查会检查 JS 互操作值是否为 Dart 类型,这可能不具有跨平台一致性。
'{0}' 和 '{1}' 之间的运行时检查涉及两个 JS 互操作类型之间的非平凡运行时检查,这可能不具有跨平台一致性。
'{0}' 和 '{1}' 之间的运行时检查涉及 JS 互操作值和不相关的 JS 互操作类型之间的运行时检查,该检查将始终为真,并且不会检查底层类型。
描述
#当 is
测试具有以下情况之一时,分析器会产生此诊断信息
- 右侧是 JS 互操作类型,无论是直接的还是作为另一个类型的类型参数,或者
- 左侧是 JS 互操作值。
示例
#以下代码会产生此诊断信息,因为 JS 互操作类型 JSBoolean
位于 is
测试的右侧
import 'dart:js_interop';
bool f(Object b) => b is JSBoolean;
以下代码会产生此诊断信息,因为 JS 互操作类型 JSString
用作 is
测试右侧的类型参数
import 'dart:js_interop';
bool f(List<Object> l) => l is List<JSString>;
以下代码会产生此诊断信息,因为 JS 互操作值 a
位于 is
测试的左侧
import 'dart:js_interop';
bool f(JSAny a) => a is String;
常见修复
#使用 JS 互操作助手(例如 isA
)来检查 JS 互操作值的底层类型
import 'dart:js_interop';
void f(Object b) => b.jsify()?.isA<JSBoolean>();
无效地使用 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.
}
库注解
#此注释应附加到库指令。
描述
#当应用于整个库的注释未与 library
指令关联时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为应用于整个库的 TestOn
注释与 import
指令而不是 library
指令关联
@TestOn('browser')
import 'package:test/test.dart';
void main() {}
常见修复
#将注释与 library
指令关联,必要时添加一个
@TestOn('browser')
library;
import 'package:test/test.dart';
void main() {}
库名称
#库名称“{0}”不是 lower_case_with_underscores 标识符。
描述
#当库的名称未使用 lower_case_with_underscores 命名约定 时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为库名称 libraryName
不是 lower_case_with_underscores 标识符
library libraryName;
常见修复
#如果不需要库名称,则删除库名称
library;
如果需要库名称,则将其转换为使用 lower_case_with_underscores 命名约定
library library_name;
库前缀
#前缀“{0}”不是 lower_case_with_underscores 标识符。
描述
#当导入前缀未使用 lower_case_with_underscores 命名约定 时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为前缀 ffiSupport
不是 lower_case_with_underscores 标识符
import 'package:ffi/ffi.dart' as ffiSupport;
常见修复
#将前缀转换为使用 lower_case_with_underscores 命名约定
import 'package:ffi/ffi.dart' as ffi_support;
公共 API 中包含库私有类型
#在公共 API 中无效使用私有类型。
描述
#当库的公共 API 中引用了不属于该库的公共 API 的类型时,分析器会产生此诊断信息。
在公共 API 中使用私有类型会导致该 API 在定义库外部不可用。
示例
#以下代码会产生此诊断信息,因为公共函数 f
的参数 c
具有库私有类型 (_C
)
void f(_C c) {}
class _C {}
常见修复
#如果 API 不需要在定义库外部使用,则将其设为私有
void _f(_C c) {}
class _C {}
如果 API 需要成为库公共 API 的一部分,则使用不同的公共类型,或者使引用的类型公开
void f(C c) {}
class C {}
仅限字面量布尔表达式
#布尔表达式具有常量值。
描述
#当 if
或循环语句中的条件的值已知始终为 true
或始终为 false
时,分析器会产生此诊断信息。如果 while
循环的条件是布尔字面量 true
,则会做出例外处理。
示例
#以下代码会产生此诊断信息,因为该条件将始终评估为 true
void f() {
if (true) {
print('true');
}
}
此 lint 将评估由常量组成的表达式的子集,因此以下代码也会产生此诊断信息,因为该条件将始终评估为 false
void g(int i) {
if (1 == 0 || 3 > 4) {
print('false');
}
}
常见修复
#如果条件错误,则更正条件,使其值无法在编译时确定
void g(int i) {
if (i == 0 || i > 4) {
print('false');
}
}
如果条件正确,则简化代码以不评估条件
void f() {
print('true');
}
列表中没有相邻的字符串
#请勿在列表字面量中使用相邻的字符串。
描述
#当两个字符串字面量在列表字面量中相邻时,分析器会产生此诊断信息。Dart 中的相邻字符串会连接在一起形成单个字符串,但意图可能是使每个字符串成为列表中的单独元素。
示例
#以下代码会产生此诊断信息,因为字符串 'a'
和 'b'
是相邻的
List<String> list = ['a' 'b', 'c'];
常见修复
#如果这两个字符串旨在成为列表的单独元素,则在它们之间添加逗号
List<String> list = ['a', 'b', 'c'];
如果这两个字符串旨在成为单个连接的字符串,则手动合并字符串
List<String> list = ['ab', 'c'];
或使用 +
运算符连接字符串
List<String> list = ['a' + 'b', 'c'];
没有重复的 case 值
#case 子句的值 ('{0}') 等于较早的 case 子句的值 ('{1}')。
描述
#当同一个 switch
语句中的两个或多个 case
子句具有相同的值时,分析器会产生此诊断信息。
第一个之后的任何 case
子句都无法执行,因此具有重复的 case
子句会产生误导。
此诊断信息通常是由于拼写错误或常量值更改导致的。
示例
#以下代码会产生此诊断信息,因为两个 case 子句具有相同的值 (1)
// @dart = 2.14
void f(int v) {
switch (v) {
case 1:
break;
case 1:
break;
}
}
常见修复
#如果其中一个子句应具有不同的值,则更改子句的值
void f(int v) {
switch (v) {
case 1:
break;
case 2:
break;
}
}
如果该值正确,则将语句合并到一个子句中
void f(int v) {
switch (v) {
case 1:
break;
}
}
库前缀没有前导下划线
#库前缀“{0}”以下划线开头。
描述
#当导入声明的前缀的名称以下划线开头时,分析器会产生此诊断信息。
库前缀本质上在声明库外部不可见,因此指示私有的前导下划线没有任何价值。
示例
#以下代码会产生此诊断信息,因为前缀 _core
以下划线开头
import 'dart:core' as _core;
常见修复
#删除下划线
import 'dart:core' as core;
局部标识符没有前导下划线
#局部变量“{0}”以下划线开头。
描述
#当局部变量的名称以下划线开头时,分析器会产生此诊断信息。
局部变量本质上在声明库外部不可见,因此指示私有的前导下划线没有任何价值。
示例
#以下代码会产生此诊断信息,因为参数 _s
以下划线开头
int f(String _s) => _s.length;
常见修复
#删除下划线
int f(String s) => s.length;
在 createState 中没有逻辑
#请勿在“createState”中放置任何逻辑。
描述
#当 StatefulWidget
的子类中的 createState
实现包含除调用无参数构造函数的结果之外的任何逻辑时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为构造函数调用具有参数
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => MyState(0);
}
class MyState extends State {
int x;
MyState(this.x);
}
常见修复
#重写代码,使 createState
不包含任何逻辑
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => MyState();
}
class MyState extends State {
int x = 0;
MyState();
}
不使用通配符变量
#引用的标识符是通配符。
描述
#当引用名称仅由下划线组成的参数或局部变量时,分析器会产生此诊断信息。此类名称将在未来版本的 Dart 语言中变为非绑定,从而使引用非法。
示例
#以下代码会产生此诊断信息,因为参数的名称由两个下划线组成
// @dart = 3.6
void f(int __) {
print(__);
}
以下代码会产生此诊断信息,因为局部变量的名称由单个下划线组成
// @dart = 3.6
void f() {
int _ = 0;
print(_);
}
常见修复
#如果要引用变量或参数,请为其指定一个至少包含一个非下划线字符的名称
void f(int p) {
print(p);
}
如果不想引用变量或参数,则将引用替换为其他表达式
void f() {
print(0);
}
非常量标识符名称
#变量名称“{0}”不是 lowerCamelCase 标识符。
描述
#当声明为非 const
的类成员、顶层声明、变量、参数、命名参数或命名构造函数的名称未使用 lowerCamelCase 约定 时,分析器会产生此诊断信息。
示例
#以下代码会产生此诊断信息,因为顶层变量 Count
不是以小写字母开头的
var Count = 0;
常见修复
#更改声明中的名称以遵循 lowerCamelCase 约定
var count = 0;
对可空类型参数进行 null 检查
#不应在类型为可能为空的类型参数的变量上使用 null 检查运算符。
描述
#当在类型为 T?
的变量上使用 null 检查运算符时,分析器会产生此诊断信息,其中 T
是允许类型参数为空的类型参数(要么没有绑定,要么具有为空的绑定)。
给定一个具有可空绑定的泛型类型参数 T
,在处理类型为 T?
的变量时,很容易引入错误的 null 检查。具体来说,经常会遇到 T? x;
并且想要断言 x
已设置为类型 T
的有效值的情况。一个常见的错误是使用 x!
这样做。这几乎总是错误的,因为如果 T
是可空类型,则 x
可以合法地将 null
作为类型 T
的值。
示例
#以下代码会产生此诊断,因为 t
的类型为 T?
,且 T
允许类型参数为空(因为它没有 extends
子句)
T f<T>(T? t) => t!;
常见修复
#使用类型参数来强制转换变量
T f<T>(T? t) => t as T;
重写的字段
#字段覆盖了从 '{0}' 继承的字段。
描述
#当一个类定义了一个覆盖超类字段的字段时,分析器会产生此诊断。
用另一个字段覆盖一个字段会导致对象拥有两个不同的字段,但由于这些字段具有相同的名称,因此在给定的作用域中只能引用其中一个字段。这可能会导致混淆,即对其中一个字段的引用可能会被误认为是另一个字段的引用。
示例
#以下代码会产生此诊断,因为 B
中的字段 f
遮蔽了 A
中的字段 f
class A {
int f = 1;
}
class B extends A {
@override
int f = 2;
}
常见修复
#如果这两个字段表示相同的属性,则从子类中删除该字段
class A {
int f = 1;
}
class B extends A {}
如果这两个字段应该是不同的,则重命名其中一个字段
class A {
int f = 1;
}
class B extends A {
int g = 2;
}
如果这两个字段在某种程度上相关,但不能相同,则找到另一种方式来实现所需的语义。
包名
#包名 '{0}' 不是 lower_case_with_underscores 标识符。
描述
#当包的名称不使用 lower_case_with_underscores 命名约定的时候,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为包的名称使用了 lowerCamelCase 命名约定
name: somePackage
常见修复
#使用 lower_case_with_underscores 命名约定重写包的名称
name: some_package
带有包前缀的库名称
#库名称不是以包名称为前缀的点分隔路径。
描述
#当库的名称不符合这些指导原则时,分析器会产生此诊断。
- 所有库名称都以包名称为前缀。
- 使入口库的名称与包的名称相同。
- 对于包中的所有其他库,在包名称之后添加库的 Dart 文件的点分隔路径。
- 对于
lib
下的库,省略顶层目录名称。
例如,给定一个名为 my_package
的包,以下是包中各种文件的库名称
示例
#假设包含以下代码的文件不在名为 special.dart
的文件中,而 special.dart
文件位于名为 something
的包的 lib
目录中(这将是规则的例外),则分析器会产生此诊断,因为库的名称不符合上述准则
library something.special;
常见修复
#更改库的名称以符合准则。
优先使用相邻的字符串连接
#字符串字面量不应使用 '+' 运算符连接。
描述
#当 +
运算符用于连接两个字符串字面量时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为两个字符串字面量正在使用 +
运算符连接
var s = 'a' + 'b';
常见修复
#删除运算符
var s = 'a' 'b';
优先使用集合字面量
#不必要的构造函数调用。
描述
#当使用构造函数创建列表、映射或集合,但字面量可以产生相同的结果时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为正在使用 Map
的构造函数来创建一个也可以使用字面量创建的映射
var m = Map<String, String>();
常见修复
#使用字面量表示法
var m = <String, String>{};
优先使用条件赋值
#'if' 语句可以用空感知赋值替换。
描述
#当对变量的赋值基于变量是否具有值 null
时是条件性的,并且可以使用 ??=
运算符时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为将参数 s
与 null
进行比较,以确定是否分配不同的值
int f(String? s) {
if (s == null) {
s = '';
}
return s.length;
}
常见修复
#使用 ??=
运算符代替显式的 if
语句
int f(String? s) {
s ??= '';
return s.length;
}
优先使用 const 构造函数
#使用 'const' 和构造函数来提高性能。
描述
#当 const 构造函数的调用前面没有 const
或者不在常量上下文中时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 const
构造函数的调用既没有以 const
为前缀,也不在常量上下文中
class C {
const C();
}
C c = C();
常见修复
#如果可以将上下文设置为常量上下文,则执行此操作
class C {
const C();
}
const C c = C();
如果无法将上下文设置为常量上下文,则在构造函数调用之前添加 const
class C {
const C();
}
C c = const C();
在不可变类中优先使用 const 构造函数
#'@immutable' 类中的构造函数应声明为 'const'。
描述
#当在具有 @immutable
注解的类中找到非 const
构造函数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 C
中的构造函数未声明为 const
,即使 C
具有 @immutable
注解
import 'package:meta/meta.dart';
@immutable
class C {
final f;
C(this.f);
}
常见修复
#如果该类确实打算不可变,则将 const
修饰符添加到构造函数
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
如果该类是可变的,则删除 @immutable
注解
class C {
final f;
C(this.f);
}
优先使用 const 声明
#对于初始化为常量值的 final 变量,请使用 'const'。
描述
#当顶层变量、静态字段或局部变量标记为 final
并且初始化为常量值时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为顶层变量 v
既是 final
又初始化为常量值
final v = const <int>[];
以下代码产生此诊断,因为静态字段 f
既是 final
又初始化为常量值
class C {
static final f = const <int>[];
}
以下代码产生此诊断,因为局部变量 v
既是 final
又初始化为常量值
void f() {
final v = const <int>[];
print(v);
}
常见修复
#将关键字 final
替换为 const
,并从初始化程序中删除 const
class C {
static const f = <int>[];
}
优先使用 const 字面量来创建不可变类
#使用 'const' 字面量作为 '@immutable' 类的构造函数的参数。
描述
#当将非 const 列表、映射或集合字面量作为参数传递给在用 @immutable
注释的类中声明的构造函数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为列表字面量 ([1]
) 被传递到不可变类中的构造函数,但不是常量列表
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C([1]);
常见修复
#如果可以将上下文设置为常量上下文,则执行此操作
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
const C c = C([1]);
如果上下文不能设为常量上下文,但可以使用 const
调用构造函数,则在构造函数调用之前添加 const
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = const C([1]);
如果上下文不能设为常量上下文,并且不能使用 const
调用构造函数,则在集合字面量之前添加关键字 const
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C(const [1]);
优先使用 contains
#始终为 'false',因为 'indexOf' 始终大于或等于 -1。
始终为 'true',因为 'indexOf' 始终大于或等于 -1。
不必要地使用 'indexOf' 来测试包含性。
描述
#当使用 indexOf
方法,并且结果仅与 -1
或 0
进行比较时,分析器会产生此诊断,其中语义等效于使用 contains
。
示例
#以下代码产生此诊断,因为 if
语句中的条件正在检查列表是否包含该字符串
void f(List<String> l, String s) {
if (l.indexOf(s) < 0) {
// ...
}
}
常见修复
#使用 contains
代替,并在必要时否定条件
void f(List<String> l, String s) {
if (l.contains(s)) {
// ...
}
}
优先使用双引号
#不必要地使用单引号。
描述
#当字符串字面量使用单引号 ('
) 时,如果可以使用双引号 ("
) 而无需额外的转义,并且不会损害可读性,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为字符串字面量使用了单引号,但没有必要这样做
void f(String name) {
print('Hello $name');
}
常见修复
#使用双引号代替单引号
void f(String name) {
print("Hello $name");
}
优先使用 final 字段
#私有字段 {0} 可以是 'final'。
描述
#当私有字段仅被赋值一次时,分析器会产生此诊断。该字段可以在多个构造函数中初始化,并且仍然会被标记,因为只能运行其中一个构造函数。
示例
#以下代码产生此诊断,因为字段 _f
仅被赋值一次,在字段的初始化程序中
class C {
int _f = 1;
int get f => _f;
}
常见修复
#将字段标记为 final
class C {
final int _f = 1;
int get f => _f;
}
优先使用 for 元素而不是 mapFromIterable
#当从可迭代对象构建映射时,请使用 'for' 元素。
描述
#当使用 Map.fromIterable
构建可以使用 for
元素构建的映射时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为正在使用 fromIterable
构建可以使用 for
元素构建的映射
void f(Iterable<String> data) {
Map<String, int>.fromIterable(
data,
key: (element) => element,
value: (element) => element.length,
);
}
常见修复
#使用 for
元素来构建映射
void f(Iterable<String> data) {
<String, int>{
for (var element in data)
element: element.length
};
}
优先使用函数声明而不是变量
#使用函数声明而不是变量赋值来将函数绑定到名称。
描述
#当闭包分配给局部变量且局部变量未在任何位置重新分配时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为局部变量 f
初始化为一个闭包,并且未被赋值任何其他值
void g() {
var f = (int i) => i * 2;
f(1);
}
常见修复
#将局部变量替换为局部函数
void g() {
int f(int i) => i * 2;
f(1);
}
优先使用泛型函数类型别名
#在 'typedef' 中使用泛型函数类型语法。
描述
#当 typedef 使用较旧的函数类型别名语法编写时,其中声明的名称嵌入到函数类型中时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为它使用了较旧的语法
typedef void F<T>();
常见修复
#重写 typedef 以使用较新的语法
typedef F<T> = void Function();
优先使用 if-null 运算符
#在测试 'null' 时,请使用 '??' 运算符而不是 '?:'。
描述
#当使用条件表达式(使用 ?:
运算符)在局部变量为 null
时选择不同的值时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为正在将变量 s
与 null
进行比较,以便在 s
为 null
时返回不同的值
String f(String? s) => s == null ? '' : s;
常见修复
#改用 if-null 运算符
String f(String? s) => s ?? '';
优先使用初始化形式参数
#使用初始化形式参数将参数赋值给字段。
描述
#当构造函数参数用于初始化未修改的字段时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为参数 c
仅用于设置字段 c
。
class C {
int c;
C(int c) : this.c = c;
}
常见修复
#使用初始化形参来初始化字段。
class C {
int c;
C(this.c);
}
优先使用内联添加
#可以内联添加列表项的操作。
可以内联添加多个列表项的操作。
描述
#当在列表字面量上调用 add
和 addAll
方法,并且要添加的元素可以包含在列表字面量中时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 add
方法被用来添加 b
,而它本可以直接包含在列表字面量中。
List<String> f(String a, String b) {
return [a]..add(b);
}
以下代码产生此诊断,因为 addAll
方法被用来添加 b
的元素,而它们本可以直接包含在列表字面量中。
List<String> f(String a, List<String> b) {
return [a]..addAll(b);
}
常见修复
#如果正在使用 add
方法,则将参数作为列表的元素并删除调用。
List<String> f(String a, String b) {
return [a, b];
}
如果正在使用 addAll
方法,则对参数使用展开运算符以将其元素添加到列表中并删除调用。
List<String> f(String a, List<String> b) {
return [a, ...b];
}
优先使用插值来组合字符串
#使用插值来组合字符串和值。
描述
#当使用 +
运算符连接字符串字面量和计算字符串时,分析器会产生此诊断,但字符串插值可以实现相同的结果。
示例
#以下代码产生此诊断,因为字符串 s
使用 +
运算符与其他字符串连接。
String f(String s) {
return '(' + s + ')';
}
常见修复
#使用字符串插值。
String f(List<String> l) {
return '(${l[0]}, ${l[1]})';
}
优先使用 isEmpty
#比较始终为“false”,因为长度始终大于或等于 0。
比较始终为“true”,因为长度始终大于或等于 0。
使用 'isEmpty' 而不是 'length' 来测试集合是否为空。
使用 'isNotEmpty' 而不是 'length' 来测试集合是否为空。
描述
#当将调用 Iterable.length
或 Map.length
的结果与零 (0
) 进行相等性比较时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为调用 length
的结果被检查是否等于零。
int f(Iterable<int> p) => p.length == 0 ? 0 : p.first;
常见修复
#将对 length
的使用替换为对 isEmpty
或 isNotEmpty
的使用。
void f(Iterable<int> p) => p.isEmpty ? 0 : p.first;
优先使用 isNotEmpty
#使用 'isNotEmpty' 而不是取反 'isEmpty' 的结果。
描述
#当对调用 Iterable.isEmpty
或 Map.isEmpty
的结果取反时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为调用 Iterable.isEmpty
的结果被取反。
void f(Iterable<int> p) => !p.isEmpty ? p.first : 0;
常见修复
#重写代码以使用 isNotEmpty
。
void f(Iterable<int> p) => p.isNotEmpty ? p.first : 0;
优先使用 is not 运算符
#使用 'is!' 运算符而不是取反 'is' 运算符的值。
描述
#当使用前缀 !
运算符来取反 is
测试的结果时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为测试 o
是否为 String
的结果使用前缀 !
运算符取反。
String f(Object o) {
if (!(o is String)) {
return o.toString();
}
return o;
}
常见修复
#使用 is!
运算符代替。
String f(Object o) {
if (o is! String) {
return o.toString();
}
return o;
}
优先使用 Iterable.whereType
#使用 'whereType' 选择给定类型的元素。
描述
#当方法 Iterable.where
用于根据元素的类型过滤元素时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为方法 where
用于仅访问可迭代对象中的字符串。
Iterable<Object> f(Iterable<Object> p) => p.where((e) => e is String);
常见修复
#重写代码以使用 whereType
。
Iterable<String> f(Iterable<Object> p) => p.whereType<String>();
这也可能允许您收紧代码中的类型或删除其他类型检查。
优先使用 null 感知运算符
#使用空感知运算符 '?.' 而不是显式的 'null' 比较。
描述
#当使用与 null
的比较来保护成员引用,并且当受保护的目标为 null
时使用 null
作为结果时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为对 length
的调用受到 null
比较的保护,即使默认值为 null
。
int? f(List<int>? p) {
return p == null ? null : p.length;
}
常见修复
#改为使用空感知访问运算符。
int? f(List<int>? p) {
return p?.length;
}
优先使用相对导入
#对 'lib' 目录中的文件使用相对导入。
描述
#当 lib
目录内的库中的 import
使用 package:
URI 来引用同一包中的另一个库时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为它使用了 package:
URI,而可以使用相对 URI。
import 'package:my_package/bar.dart';
常见修复
#使用相对 URI 导入库。
import 'bar.dart';
优先使用单引号
#不必要地使用双引号。
描述
#当字符串字面量使用双引号 ("
),但它可以使用单引号 ('
) 而无需额外的转义且不会损害可读性时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为字符串字面量使用了双引号,但没有必要这样做。
void f(String name) {
print("Hello $name");
}
常见修复
#使用单引号代替双引号。
void f(String name) {
print('Hello $name');
}
优先为未初始化的变量指定类型
#未初始化的字段应具有显式的类型注释。
未初始化的变量应具有显式的类型注释。
描述
#当没有初始化器的变量没有显式的类型注释时,分析器会产生此诊断。
如果没有类型注释或初始化器,变量将具有 dynamic
类型,这允许将任何值赋给该变量,通常会导致难以识别的错误。
示例
#以下代码产生此诊断,因为变量 r
没有类型注释或初始化器。
Object f() {
var r;
r = '';
return r;
}
常见修复
#如果可以初始化变量,则添加一个初始化器。
Object f() {
var r = '';
return r;
}
如果无法初始化变量,则添加显式的类型注释。
Object f() {
String r;
r = '';
return r;
}
优先使用 void 而不是 null
#不必要地使用类型 'Null'。
描述
#当在 void
是有效选择的位置使用 Null
时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为函数 f
被声明为返回 null
(在将来的某个时间)。
Future<Null> f() async {}
常见修复
#将对 Null
的使用替换为对 void
的使用。
Future<void> f() async {}
提供弃用消息
#缺少弃用消息。
描述
#当使用 deprecated
注解而不是 Deprecated
注解时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为函数 f
用 deprecated
注解。
@deprecated
void f() {}
常见修复
#将代码转换为使用较长的形式。
@Deprecated('Use g instead. Will be removed in 4.0.0.')
void f() {}
递归 getter
#getter '{0}' 递归返回自身。
描述
#当 getter 调用自身时,分析器会产生此诊断,这会导致无限循环。
示例
#以下代码产生此诊断,因为 getter count
调用自身。
class C {
int _count = 0;
int get count => count;
}
常见修复
#更改 getter 以使其不调用自身。
class C {
int _count = 0;
int get count => _count;
}
安全的 pubspec URL
#不应使用“{0}”协议,因为它不安全。
描述
#当 pubspec.yaml
文件中的 URL 使用不安全的方案(例如 http
)时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 pubspec.yaml
文件包含一个 http
URL。
dependencies:
example: any
repository: http://github.com/dart-lang/example
常见修复
#更改 URL 的方案以使用安全的方案,例如 https
。
dependencies:
example: any
repository: https://github.com/dart-lang/example
使用 SizedBox 来表示空白
#使用 'SizedBox' 将空白添加到布局中。
描述
#当仅使用 height
和/或 width
参数创建 Container
时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 Container
仅具有 width
参数。
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
const Text('...'),
Container(
width: 4,
child: Text('...'),
),
const Expanded(
child: Text('...'),
),
],
);
}
常见修复
#将 Container
替换为具有相同尺寸的 SizedBox
。
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
Text('...'),
SizedBox(
width: 4,
child: Text('...'),
),
Expanded(
child: Text('...'),
),
],
);
}
SizedBox 收缩/扩展
#使用 'SizedBox.{0}' 以避免需要指定 'height' 和 'width'。
描述
#当 SizedBox
构造函数调用将 height
和 width
的值都指定为 0.0
或 double.infinity
时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 height
和 width
均为 0.0
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox(
height: 0.0,
width: 0.0,
child: const Text(''),
);
}
以下代码产生此诊断,因为 height
和 width
均为 double.infinity
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: const Text(''),
);
}
常见修复
#如果两者均为 0.0
,则使用 SizedBox.shrink
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.shrink(
child: const Text(''),
);
}
如果两者均为 double.infinity
,则使用 SizedBox.expand
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.expand(
child: const Text(''),
);
}
使用斜杠表示文档注释
#对文档注释使用行尾形式 ('///')。
描述
#当文档注释使用块注释样式(由 /**
和 */
分隔)时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 f
的文档注释使用块注释样式。
/**
* Example.
*/
void f() {}
常见修复
#使用行尾注释样式。
/// Example.
void f() {}
将子属性放在最后
#'{0}' 参数应在 Widget 构造函数调用中放在最后。
描述
#当 child
或 children
参数不是 Widget 类构造函数调用中的最后一个参数时,分析器会产生此诊断。如果 child
或 children
参数之后的所有参数都是函数表达式,则会有一个例外。
示例
#以下代码产生此诊断,因为 child
参数不是 Center
构造函数调用中的最后一个参数。
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
child: Text('...'),
widthFactor: 0.5,
);
}
常见修复
#将 child
或 children
参数移动到最后。
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
widthFactor: 0.5,
child: Text('...'),
);
}
将构造函数放在最前面
#构造函数声明应在非构造函数声明之前。
描述
#当构造函数声明前面有一个或多个非构造函数声明时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 C
的构造函数出现在方法 m
之后。
class C {
void m() {}
C();
}
常见修复
#将所有构造函数声明移动到任何其他声明之前。
class C {
C();
void m() {}
}
对 pub 依赖项进行排序
#依赖项未按字母顺序排序。
描述
#当 pubspec.yaml
文件中依赖项映射中的键未按字母顺序排序时,分析器会产生此诊断。要检查的依赖项映射是 dependencies
、dev_dependencies
和 dependency_overrides
映射。
示例
#以下代码产生此诊断,因为 dependencies
映射中的条目未排序。
dependencies:
path: any
collection: any
常见修复
#对条目进行排序。
dependencies:
collection: any
path: any
将未命名构造函数放在最前面
#未命名构造函数的无效位置。
描述
#当未命名构造函数出现在命名构造函数之后时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为未命名构造函数位于命名构造函数之后。
class C {
C.named();
C();
}
常见修复
#将未命名构造函数移动到任何其他构造函数之前。
class C {
C();
C.named();
}
在 equals 中测试类型
#在 '==' 中缺少对 '{0}' 的类型测试。
描述
#当 ==
运算符的重写不包括对参数值的类型测试时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 other
没有进行类型测试。
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return (other as C).f == f;
}
}
常见修复
#执行 is
测试作为计算返回值的步骤。
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return other is C && other.f == f;
}
}
在 finally 块中抛出异常
#在 'finally' 块中使用 '{0}'。
描述
#当在 finally
块中找到 throw
语句时,分析器会产生此诊断。
示例
#以下代码产生此诊断,因为 finally
块中有一个 throw
语句。
void f() {
try {
// ...
} catch (e) {
// ...
} finally {
throw 'error';
}
}
常见修复
#重写代码,使 throw
语句不在 finally
块内。
void f() {
try {
// ...
} catch (e) {
// ...
}
throw 'error';
}
类型初始化形式参数
#不要不必要地对初始化形参进行类型注释。
描述
#当初始化形参 (this.x
) 或超级参数 (super.x
) 具有与字段或重写参数相同的显式类型注释时,分析器会产生此诊断。
如果构造函数参数使用 this.x
初始化字段,则参数的类型隐式地与字段的类型相同。如果构造函数参数使用 super.x
转发到超级构造函数,则参数的类型隐式地与超级构造函数参数相同。
示例
#以下代码会产生此诊断,因为参数 this.c
具有与字段 c
相同的显式类型。
class C {
int c;
C(int this.c);
}
以下代码会产生此诊断,因为参数 super.a
具有与超类中的参数 a
相同的显式类型。
class A {
A(int a);
}
class B extends A {
B(int super.a);
}
常见修复
#从参数中删除类型注释。
class C {
int c;
C(this.c);
}
常量模式中的类型字面量
#使用 'TypeName _' 而不是类型字面量。
描述
#当类型字面量作为模式出现时,分析器会生成此诊断。
示例
#以下代码会产生此诊断,因为类型字面量被用作常量模式。
void f(Object? x) {
if (x case num) {
// ...
}
}
常见修复
#如果类型字面量旨在匹配给定类型的对象,则使用变量模式。
void f(Object? x) {
if (x case num _) {
// ...
}
}
或者使用对象模式。
void f(Object? x) {
if (x case num()) {
// ...
}
}
如果类型字面量旨在匹配类型字面量,则将其写为常量模式。
void f(Object? x) {
if (x case const (num)) {
// ...
}
}
未等待的 Future
#此表达式计算的 'Future' 缺少 'await'。
描述
#当 Future
的实例从 async
(或 async*
)方法或函数内的调用返回,并且该 future 既没有被 await,也没有传递给 unawaited
函数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为函数 g
返回一个 future,但该 future 没有被 await。
Future<void> f() async {
g();
}
Future<int> g() => Future.value(0);
常见修复
#如果 future 需要在执行以下代码之前完成,则在调用之前添加 await
。
Future<void> f() async {
await g();
}
Future<int> g() => Future.value(0);
如果 future 不需要在执行以下代码之前完成,则将返回 Future
的调用包装在 unawaited
函数的调用中。
import 'dart:async';
Future<void> f() async {
unawaited(g());
}
Future<int> g() => Future.value(0);
文档注释中出现意外的 HTML
#尖括号将被解释为 HTML。
描述
#当文档注释包含尖括号括起来的文本 (<...>
) 且该文本不是允许的例外之一时,分析器会产生此诊断。
此类文本会被 markdown 解释为 HTML 标签,这很少是预期的结果。
有关允许的例外列表,请参阅lint 规则描述。
示例
#以下代码会产生此诊断,因为文档注释包含文本 <int>
,这不是允许的例外之一。
/// Converts a List<int> to a comma-separated String.
String f(List<int> l) => '';
常见修复
#如果文本旨在成为代码段的一部分,则在代码周围添加反引号。
/// Converts a `List<int>` to a comma-separated String.
String f(List<int> l) => '';
如果文本旨在成为链接的一部分,则在代码周围添加方括号。
/// Converts a [List<int>] to a comma-separated String.
String f(List<int> l) => '';
如果文本旨在按原样打印(包括尖括号),则在尖括号前添加反斜杠转义符。
/// Converts a List\<int\> to a comma-separated String.
String f(List<int> l) => '';
字符串插值中出现不必要的大括号
#字符串插值中不必要的大括号。
描述
#当使用带大括号的字符串插值来插值一个简单的标识符,并且后面没有字母数字文本时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为插值元素 ${s}
在不需要时使用了大括号。
String f(String s) {
return '"${s}"';
}
常见修复
#删除不必要的大括号。
String f(String s) {
return '"$s"';
}
不必要的 const
#不必要的 'const' 关键字。
描述
#当在常量上下文中使用关键字 const
时,分析器会产生此诊断。该关键字不是必需的,因为它是隐含的。
示例
#以下代码会产生此诊断,因为列表字面量中的关键字 const
是不需要的。
const l = const <int>[];
由于变量声明中的关键字 const
,该列表是隐式的 const
。
常见修复
#删除不必要的关键字。
const l = <int>[];
不必要的构造函数名称
#不必要的 '.new' 构造函数名称。
描述
#当对未命名构造函数的引用使用 .new
时,分析器会产生此诊断。 .new
唯一需要的场合是在构造函数拆卸中。
示例
#以下代码会产生此诊断,因为 .new
被用来引用不需要它的未命名构造函数。
var o = Object.new();
常见修复
#删除不必要的 .new
。
var o = Object();
unnecessary_final
#局部变量不应标记为 'final'。
描述
#当局部变量被标记为 final
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为局部变量 c
被标记为 final
。
void f(int a, int b) {
final c = a + b;
print(c);
}
常见修复
#如果变量没有类型注释,则将 final
替换为 var
。
void f(int a, int b) {
var c = a + b;
print(c);
}
如果变量有类型注释,则删除 final
修饰符。
void f(int a, int b) {
int c = a + b;
print(c);
}
不必要的 getter 和 setter
#不必要地使用 getter 和 setter 来包装字段。
描述
#当 getter 和 setter 对返回并设置字段的值而不进行任何额外处理时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为名为 c
的 getter/setter 对仅公开名为 _c
的字段。
class C {
int? _c;
int? get c => _c;
set c(int? v) => _c = v;
}
常见修复
#将字段设为 public 并删除 getter 和 setter。
class C {
int? c;
}
不必要的 lambda
#闭包应为拆卸。
描述
#当闭包 (lambda) 可以被拆卸替换时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为传递给 forEach
的闭包仅包含对函数 print
的调用,并使用闭包的参数。
void f(List<String> strings) {
strings.forEach((string) {
print(string);
});
}
常见修复
#将闭包替换为使用闭包调用的函数或方法的拆卸。
void f(List<String> strings) {
strings.forEach(print);
}
不必要的 late
#不必要的 'late' 修饰符。
描述
#当具有初始化器的顶层变量或静态字段被标记为 late
时,分析器会产生此诊断。顶层变量和静态字段是隐式的 late,因此不需要显式标记。
示例
#以下代码会产生此诊断,因为静态字段 c
具有修饰符 late
,即使它有初始化器。
class C {
static late String c = '';
}
常见修复
#删除关键字 late
。
class C {
static String c = '';
}
不必要的库名称
#库名称不是必需的。
描述
#当 library
指令指定名称时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 library
指令包含一个名称。
library some.name;
class C {}
常见修复
#从 library
指令中删除名称。
library;
class C {}
如果库有任何部分,则任何使用库名称的 part of
声明都应更新为使用库的 URI。
不必要的 new
#不必要的 'new' 关键字。
描述
#当使用关键字 new
调用构造函数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为关键字 new
被用来从 Object
调用未命名的构造函数。
var o = new Object();
常见修复
#删除关键字 new
。
var o = Object();
不必要的 null 感知赋值
#不必要的 'null' 赋值。
描述
#当可空感知赋值的右侧是 null
字面量时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为当 s
已经为 null
时,正在使用可空感知运算符将 null
赋值给 s
。
void f(String? s) {
s ??= null;
}
常见修复
#如果应将非 null 值赋值给左侧操作数,则更改右侧。
void f(String? s) {
s ??= '';
}
如果没有要赋值给左侧操作数的非 null 值,则删除赋值。
void f(String? s) {
}
if-null 运算符中不必要的 null
#不必要地使用 '??' 和 'null'。
描述
#当 ??
运算符的右操作数是字面量 null
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 ??
运算符的右侧操作数是 null
。
String? f(String? s) => s ?? null;
常见修复
#如果应将非 null 值用于右侧操作数,则更改右侧。
String f(String? s) => s ?? '';
如果没有要用于右侧操作数的非 null 值,则删除运算符和右侧操作数。
String? f(String? s) => s;
对于 final 变量声明来说不必要的可空性
#类型可以是非可空的。
描述
#当 final 字段或变量具有可空类型但初始化为非可空值时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 final 变量 i
具有可空类型 (int?
),但永远不能为 null
。
final int? i = 1;
常见修复
#使类型变为非可空类型。
final int i = 1;
不必要的重写
#不必要的重写。
描述
#当实例成员覆盖继承的成员,但仅使用完全相同的参数调用被覆盖的成员时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为方法 D.m
除了调用被覆盖的方法之外没有做任何其他事情。
class C {
int m(int x) => x;
}
class D extends C {
@override
int m(int x) => super.m(x);
}
常见修复
#如果该方法应执行比被覆盖的方法更多的操作,则实现缺少的功能。
class C {
int m(int x) => x;
}
class D extends C {
@override
int m(int x) => super.m(x) + 1;
}
如果应通过更改返回类型或一个或多个参数类型、使其中一个参数为 covariant
、添加文档注释或具有其他注释来修改被覆盖的方法,则更新代码。
import 'package:meta/meta.dart';
class C {
int m(int x) => x;
}
class D extends C {
@mustCallSuper
@override
int m(int x) => super.m(x);
}
如果覆盖方法没有更改或增强代码的语义,则将其删除。
class C {
int m(int x) => x;
}
class D extends C {}
不必要的括号
#不必要地使用括号。
描述
#当在不影响代码语义的地方使用括号时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为二进制表达式周围的括号不是必需的。
int f(int a, int b) => (a + b);
常见修复
#删除不必要的括号。
int f(int a, int b) => a + b;
不必要的原始字符串
#不必要地使用原始字符串。
描述
#当字符串字面量被标记为原始字符串(以 r
作为前缀)时,但使字符串成为原始字符串不会更改字符串的值,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为在没有 r
的情况下,字符串字面量的值与带有 r
时相同。
var s = r'abc';
常见修复
#删除字符串字面量前面的 r
。
var s = 'abc';
不必要的语句
#不必要的语句。
描述
#当表达式语句没有明显效果时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为两次调用返回的值的加法没有明显效果。
void f(int Function() first, int Function() second) {
first() + second();
}
常见修复
#如果不需要计算表达式,则将其删除。
void f(int Function() first, int Function() second) {
}
如果需要表达式的值,则使用它,可能先将其赋值给局部变量。
void f(int Function() first, int Function() second) {
print(first() + second());
}
如果需要执行表达式的某些部分,则删除不必要的部分。
void f(int Function() first, int Function() second) {
first();
second();
}
不必要的字符串转义
#字符串字面量中不必要的转义符。
描述
#当字符串中的字符被转义,而转义它们是不必要的时候,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为单引号不需要在用双引号分隔的字符串内转义。
var s = "Don\'t use a backslash here.";
常见修复
#删除不必要的反斜杠。
var s = "Don't use a backslash here.";
不必要的字符串插值
#不必要地使用字符串插值。
描述
#当字符串字面量包含对 String
值变量的单个插值且没有其他字符时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字符串字面量包含单个插值,并且插值之外不包含任何字符。
String f(String s) => '$s';
常见修复
#将字符串字面量替换为插值的内容。
String f(String s) => s;
不必要的 this
#不必要的 'this.' 限定符。
描述
#当使用关键字 this
来访问未被阴影的成员时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为使用 this
来访问字段 _f
不是必需的。
class C {
int _f = 2;
int get f => this._f;
}
常见修复
#删除 this.
。
class C {
int _f = 2;
int get f => _f;
}
在 spread 语法中不必要的 toList
#在 spread 中不必要地使用 'toList'。
描述
#当在 spread 运算符应用于列表之前,使用 toList
将 Iterable
转换为 List
时,分析器会产生此诊断。 spread 运算符可以应用于任何 Iterable
,因此不需要转换。
示例
#以下代码会产生此诊断,因为 toList
在 map
的结果上调用,map
的结果是 spread 运算符可以直接应用于的 Iterable
。
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()).toList(),
];
}
常见修复
#删除对 toList
的调用。
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()),
];
}
不相关的类型相等性检查
#操作数的类型 ('{0}') 不是被匹配的值 ('{1}') 的子类型或超类型。
右操作数的类型 ('{0}') 不是左操作数 ('{1}') 的子类型或超类型。
描述
#当比较两个对象时,如果两个对象的静态类型都不是对方的子类型,分析器会产生此诊断。
这种比较通常会返回 false
,可能无法反映程序员的意图。
可能会出现误报。例如,名为 Point
的类可能具有名为 CartesianPoint
和 PolarPoint
的子类,它们都不是对方的子类型,但测试实例的相等性可能仍然是合适的。
作为一个具体的例子,来自 package:fixnum
的 Int64
和 Int32
类允许将实例与 int
进行比较,前提是 int
在右侧。此情况被诊断明确允许,但其他类似情况则不允许。
示例
#以下代码会产生此诊断,因为字符串 s
正在与整数 1
进行比较
bool f(String s) {
return s == 1;
}
常见修复
#将其中一个操作数替换为与另一个操作数兼容的内容
bool f(String s) {
return s.length == 1;
}
不安全的方差
#此类型是不安全的:类型参数出现在非协变位置。
描述
#此 lint 会警告不要声明非协变成员。
实例变量的类型在封闭的类、mixin 或枚举的类型参数中以非协变位置出现,这很可能导致由于类型检查失败而导致的运行时故障。例如,在 class C<X> {...}
中,形式为 void Function(X) myVariable;
的实例变量可能会导致这种运行时故障。
对于其返回类型具有封闭声明的类型参数的非协变出现的 getter 或方法也是如此。
此 lint 会标记这种成员声明。
示例
#错误示例
class C<X> {
final bool Function(X) fun; // LINT
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Throws.
}
问题在于 X
在 fun
的类型中作为参数类型出现。
常见修复
#减少运行时类型错误可能的一种方法是确保非协变成员 fun
*仅* 在 this
上使用。我们无法严格强制执行此操作,但我们可以将其设为私有,并添加一个转发方法 fun
,以便我们可以在同一库中本地检查是否满足此约束
较好示例
class C<X> {
// ignore: unsafe_variance
final bool Function(X) _fun;
bool fun(X x) => _fun(x);
C(this._fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
完全安全的方法需要 Dart 尚未拥有的功能,即静态检查的方差。有了它,我们可以指定类型参数 X
是不变的 (inout X
)。
可以在不支持静态检查的方差的情况下模拟不变性。这会对子类型的创建施加一些限制,但忠实地提供了 inout
将提供的类型
良好示例
typedef Inv<X> = X Function(X);
typedef C<X> = _C<X, Inv<X>>;
class _C<X, Invariance extends Inv<X>> {
// ignore: unsafe_variance
final bool Function(X) fun; // Safe!
_C(this.fun);
}
void main() {
C<int> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
通过这种方法,C<int>
不是 C<num>
的子类型,因此 c
必须具有不同的声明类型。
另一种可能性是将变量声明为具有安全但更通用的类型。然后,使用变量本身是安全的,但每次调用都必须在运行时进行检查
诚实示例
class C<X> {
final bool Function(Never) fun;
C(this.fun);
}
void main() {
C<num> c = C<int>((int i) => i.isEven);
var cfun = c.fun; // Local variable, enables promotion.
if (cfun is bool Function(int)) cfun(10); // Succeeds.
if (cfun is bool Function(bool)) cfun(true); // Not called.
}
同步使用 build context
#不要在异步间隙中使用 'BuildContext',并由不相关的 'mounted' 检查保护。
不要在异步间隙中使用 'BuildContext'。
描述
#当 StatefulWidget
在异步间隙之后引用 BuildContext
而未先检查 mounted
属性时,分析器会产生此诊断。
存储 BuildContext
以供以后使用可能会导致难以诊断的崩溃。异步间隙隐式存储 BuildContext
,使其在诊断时很容易被忽略。
示例
#以下代码会产生此诊断,因为 context
在 await
之后传递给构造函数
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
}
}
常见修复
#如果可以删除异步间隙,请执行此操作
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
}
如果无法删除异步间隙,请使用 mounted
来保护 context
的使用
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
if (context.mounted) {
Navigator.of(context).pop();
}
}
}
使用 ColoredBox
#使用 'ColoredBox' 而不是仅具有 'Color' 的 'Container'。
描述
#当创建仅设置颜色的 Container
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为容器唯一设置的属性是 color
import 'package:flutter/material.dart';
Widget build() {
return Container(
color: Colors.red,
child: const Text('hello'),
);
}
常见修复
#将 Container
替换为 ColoredBox
import 'package:flutter/material.dart';
Widget build() {
return ColoredBox(
color: Colors.red,
child: const Text('hello'),
);
}
使用 DecoratedBox
#使用 'DecoratedBox' 而不是仅具有 'Decoration' 的 'Container'。
描述
#当创建仅设置装饰的 Container
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为容器唯一设置的属性是 decoration
import 'package:flutter/material.dart';
Widget buildArea() {
return Container(
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
常见修复
#将 Container
替换为 DecoratedBox
import 'package:flutter/material.dart';
Widget buildArea() {
return DecoratedBox(
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
Flutter 颜色使用完整的十六进制值
#'Color' 的实例应使用 8 位十六进制整数(例如 '0xFFFFFFFF')创建。
描述
#当 Color
类的构造函数的参数是一个未表示为 8 位十六进制整数的字面整数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为参数 (1
) 未表示为 8 位十六进制整数
import 'package:flutter/material.dart';
Color c = Color(1);
常见修复
#将表示形式转换为 8 位十六进制整数
import 'package:flutter/material.dart';
Color c = Color(0x00000001);
参数使用函数类型语法
#使用泛型函数类型语法来声明参数 '{0}'。
描述
#当使用较旧的函数值参数语法时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为函数值参数 f
是使用较旧的语法声明的
void g(bool f(String s)) {}
常见修复
#使用泛型函数类型语法来声明参数
void g(bool Function(String) f) {}
使用 if-null 将 null 转换为 bool
#使用 if-null 运算符将 'null' 转换为 'bool'。
描述
#当将可为空的 bool
值表达式与布尔文字进行比较(使用 ==
或 !=
)时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为可为空的布尔变量 b
与 true
进行比较
void f(bool? b) {
if (b == true) {
// Treats `null` as `false`.
}
}
常见修复
#重写条件以使用 ??
代替
void f(bool? b) {
if (b ?? false) {
// Treats `null` as `false`.
}
}
在 widget 构造函数中使用 key
#公共小部件的构造函数应具有名为 'key' 的命名参数。
描述
#当 Widget
子类中不属于其库私有的构造函数没有名为 key
的参数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 MyWidget
类的构造函数没有名为 key
的参数
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget({required int height});
}
以下代码会产生此诊断,因为 MyWidget
类的默认构造函数没有名为 key
的参数
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {}
常见修复
#将名为 key
的参数添加到构造函数,如有必要,显式声明构造函数
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget({super.key, required int height});
}
为私有字段和变量使用 late
#对具有不可为空类型的私有成员使用 'late'。
描述
#当私有字段或变量被标记为可为空,但每次引用都假定该变量永远不为 null
时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为私有顶层变量 _i
可为空,但每次引用都假定它不会为 null
void f() {
_i!.abs();
}
int? _i;
常见修复
#将变量或字段标记为既不可为空又 late
,以指示它始终会被分配一个非 null 值
void f() {
_i.abs();
}
late int _i;
使用命名常量
#使用常量 '{0}' 而不是返回相同对象的构造函数。
描述
#当创建的常量与已知的 const
变量具有相同的值时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为存在一个已知的 const
字段 (Duration.zero
),其值与构造函数调用将评估为的值相同
Duration d = const Duration(seconds: 0);
常见修复
#将构造函数调用替换为对已知 const
变量的引用
Duration d = Duration.zero;
使用原始字符串
#使用原始字符串以避免使用转义符。
描述
#当包含转义符且没有插值的字符串文字可以标记为原始字符串以避免需要转义符时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字符串包含转义字符,如果将字符串设为原始字符串,则不需要转义这些字符
var s = 'A string with only \\ and \$';
常见修复
#将字符串标记为原始字符串并删除不必要的分隔符
var s = r'A string with only \ and $';
尽可能使用 rethrow
#使用 'rethrow' 重新抛出捕获的异常。
描述
#当使用 throw
表达式而不是 rethrow
语句抛出捕获的异常时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为捕获的异常 e
是使用 throw
表达式抛出的
void f() {
try {
// ...
} catch (e) {
throw e;
}
}
常见修复
#使用 rethrow
代替 throw
void f() {
try {
// ...
} catch (e) {
rethrow;
}
}
使用 setter 来更改属性
#该方法用于更改属性。
描述
#当方法用于设置字段的值,或者函数用于设置顶层变量的值,而没有其他操作时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为方法 setF
用于设置字段 _f
的值,并且没有其他操作
class C {
int _f = 0;
void setF(int value) => _f = value;
}
常见修复
#将该方法转换为 setter
class C {
int _f = 0;
set f(int value) => _f = value;
}
使用字符串缓冲区
#使用字符串缓冲区而不是 '+' 来组合字符串。
描述
#当在循环内将值连接到字符串而未使用 StringBuffer
进行连接时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为字符串 result
是在 for
循环中通过重复连接计算的
String f() {
var result = '';
for (int i = 0; i < 10; i++) {
result += 'a';
}
return result;
}
常见修复
#使用 StringBuffer
计算结果
String f() {
var buffer = StringBuffer();
for (int i = 0; i < 10; i++) {
buffer.write('a');
}
return buffer.toString();
}
在 part of 指令中使用字符串
#part-of 指令使用库名称。
描述
#当 part of
指令使用库名称来引用该部分所属的库时,分析器会产生此诊断。
示例
#给定一个名为 lib.dart
的文件,其中包含以下内容
library lib;
part 'test.dart';
以下代码会产生此诊断,因为 part of
指令使用库的名称而不是它所属库的 URI
part of lib;
常见修复
#使用 URI 引用库
part of 'lib.dart';
使用 super 参数
#参数 '{0}' 可以是超级参数。
参数 '{0}' 可以是超级参数。
描述
#当构造函数的参数传递给超类构造函数而没有被引用或修改,并且未使用 super
参数时,分析器会产生此诊断。
示例
#以下代码会产生此诊断,因为 B
构造函数的参数仅用作超类构造函数的参数
class A {
A({int? x, int? y});
}
class B extends A {
B({int? x, int? y}) : super(x: x, y: y);
}
常见修复
#使用 super
参数传递参数
class A {
A({int? x, int? y});
}
class B extends A {
B({super.x, super.y});
}
使用截断除法
#使用截断除法。
描述
#当使用 toInt
将两个数字相除的结果转换为整数时,分析器会产生此诊断。
Dart 具有内置的整数除法运算符,它既更高效又更简洁。
示例
#以下代码会产生此诊断信息,因为 x
和 y
相除的结果使用 toInt
转换为整数
int divide(int x, int y) => (x / y).toInt();
常见修复
#使用整数除法运算符 (~/
)
int divide(int x, int y) => x ~/ y;
有效的正则表达式
#正则表达式语法无效。
描述
#当传递给 RegExp
类的默认构造函数的字符串不包含有效的正则表达式时,分析器会产生此诊断。
使用无效语法创建的正则表达式会在运行时抛出 FormatException
异常。
示例
#以下代码会产生此诊断,因为正则表达式无效
var r = RegExp(r'(');
常见修复
#修复正则表达式
var r = RegExp(r'\(');
void 检查
#赋值给类型为 'void' 的变量。
描述
#当一个值被赋给类型为 void
的变量时,分析器会产生此诊断。
无法访问此类变量的值,因此赋值没有意义。
示例
#以下代码会产生此诊断,因为字段 value
的类型为 void
,但却被赋予了一个值
class A<T> {
T? value;
}
void f(A<void> a) {
a.value = 1;
}
以下代码会产生此诊断,因为方法 m
中参数 p
的类型为 void
,但在调用时却被赋予了一个值
class A<T> {
void m(T p) { }
}
void f(A<void> a) {
a.m(1);
}
常见修复
#如果变量的类型不正确,则更改变量的类型
class A<T> {
T? value;
}
void f(A<int> a) {
a.value = 1;
}
如果变量的类型正确,则删除赋值
class A<T> {
T? value;
}
void f(A<void> a) {}
除非另有说明,本网站上的文档反映的是 Dart 3.6.0 版本。页面最后更新于 2024-12-10。 查看源代码 或 报告问题。