From bd2e954f647995c45dcb5bdc90ce0f1b8aee79bb Mon Sep 17 00:00:00 2001 From: Gilles Grousset Date: Thu, 16 May 2024 20:15:37 +0200 Subject: [PATCH] feat(Rules): rules update --- CHANGELOG.md | 1 + .../dartanalyzer/analysis_options.yaml | 220 +- .../main/resources/dartanalyzer/rules.json | 2091 +---------------- 3 files changed, 71 insertions(+), 2241 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58711d7..7979bab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - [#212](https://github.com/insideapp-oss/sonar-flutter/issues/212) source file not indexed with SonarQube 10.4+ - [PR #201](https://github.com/insideapp-oss/sonar-flutter/pull/201) bump snakeyaml and jackson-databind to latest versions - Updated Apache Ivy to 2.5.2 +- Analyzer rules update (1 added) ## 0.5.0 diff --git a/dart-lang/src/main/resources/dartanalyzer/analysis_options.yaml b/dart-lang/src/main/resources/dartanalyzer/analysis_options.yaml index 3818e3a..1e42cf3 100644 --- a/dart-lang/src/main/resources/dartanalyzer/analysis_options.yaml +++ b/dart-lang/src/main/resources/dartanalyzer/analysis_options.yaml @@ -1,224 +1,5 @@ linter: rules: - - always_use_package_imports - - avoid_dynamic_calls - - avoid_empty_else - - avoid_print - - avoid_relative_lib_imports - - avoid_slow_async_io - - avoid_type_to_string - - avoid_types_as_parameter_names - - avoid_web_libraries_in_flutter - - cancel_subscriptions - - close_sinks - - collection_methods_unrelated_type - - comment_references - - control_flow_in_finally - - deprecated_member_use_from_same_package - - diagnostic_describe_all_properties - - discarded_futures - - empty_statements - - hash_and_equals - - implicit_reopen - - invalid_case_patterns - - invariant_booleans - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - literal_only_boolean_expressions - - no_adjacent_strings_in_list - - no_duplicate_case_values - - no_logic_in_create_state - - prefer_relative_imports - - prefer_void_to_null - - test_types_in_equals - - throw_in_finally - - unnecessary_statements - - unrelated_type_equality_checks - - unsafe_html - - use_build_context_synchronously - - use_key_in_widget_constructors - - always_declare_return_types - - always_put_control_body_on_new_line - - always_put_required_named_parameters_first - - always_specify_types - - annotate_overrides - - avoid_annotating_with_dynamic - - avoid_as - - avoid_bool_literals_in_conditional_expressions - - avoid_catches_without_on_clauses - - avoid_catching_errors - - avoid_classes_with_only_static_members - - avoid_double_and_int_checks - - avoid_equals_and_hash_code_on_mutable_classes - - avoid_escaping_inner_quotes - - avoid_field_initializers_in_const_classes - - avoid_final_parameters - - avoid_function_literals_in_foreach_calls - - avoid_implementing_value_types - - avoid_init_to_null - - avoid_js_rounded_ints - - avoid_multiple_declarations_per_line - - avoid_null_checks_in_equality_operators - - avoid_positional_boolean_parameters - - avoid_private_typedef_functions - - avoid_redundant_argument_values - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - - avoid_returning_null_for_void - - avoid_returning_this - - avoid_setters_without_getters - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_types_on_closure_parameters - - avoid_unnecessary_containers - - avoid_unused_constructor_parameters - - avoid_void_async - - await_only_futures - - camel_case_extensions - - camel_case_types - - cascade_invocations - - cast_nullable_to_non_nullable - - combinators_ordering - - conditional_uri_does_not_exist - - constant_identifier_names - - curly_braces_in_flow_control_structures - - dangling_library_doc_comments - - deprecated_consistency - - directives_ordering - - do_not_use_environment - - empty_catches - - empty_constructor_bodies - - enable_null_safety - - eol_at_end_of_file - - exhaustive_cases - - file_names - - flutter_style_todos - - implementation_imports - - implicit_call_tearoffs - - join_return_with_assignment - - leading_newlines_in_multiline_strings - - library_annotations - - library_names - - library_prefixes - - library_private_types_in_public_api - - lines_longer_than_80_chars - - matching_super_parameters - - missing_whitespace_between_adjacent_strings - - no_default_cases - - no_leading_underscores_for_library_prefixes - - no_leading_underscores_for_local_identifiers - - no_literal_bool_comparisons - - no_runtimeType_toString - - non_constant_identifier_names - - noop_primitive_operations - - null_check_on_nullable_type_parameter - - null_closures - - omit_local_variable_types - - one_member_abstracts - - only_throw_errors - - overridden_fields - - package_api_docs - - package_prefixed_library_names - - parameter_assignments - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_asserts_with_message - - prefer_bool_in_asserts - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - - prefer_constructors_over_static_methods - - prefer_contains - - prefer_double_quotes - - prefer_equal_for_default_values - - prefer_expression_function_bodies - - prefer_final_fields - - prefer_final_in_for_each - - prefer_final_locals - - prefer_final_parameters - - prefer_for_elements_to_map_fromIterable - - prefer_foreach - - prefer_function_declarations_over_variables - - prefer_generic_function_type_aliases - - prefer_if_elements_to_conditional_expressions - - prefer_if_null_operators - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_int_literals - - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - prefer_is_not_operator - - prefer_iterable_whereType - - prefer_mixin - - prefer_null_aware_method_calls - - prefer_null_aware_operators - - prefer_single_quotes - - prefer_spread_collections - - prefer_typing_uninitialized_variables - - provide_deprecation_message - - public_member_api_docs - - recursive_getters - - require_trailing_commas - - sized_box_for_whitespace - - sized_box_shrink_expand - - slash_for_doc_comments - - sort_child_properties_last - - sort_constructors_first - - sort_unnamed_constructors_first - - super_goes_last - - tighten_type_of_initializing_formals - - type_annotate_public_apis - - type_init_formals - - type_literal_in_constant_pattern - - unawaited_futures - - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_breaks - - unnecessary_const - - unnecessary_constructor_name - - unnecessary_final - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_late - - unnecessary_library_directive - - unnecessary_new - - unnecessary_null_aware_assignments - - unnecessary_null_aware_operator_on_extension_on_nullable - - unnecessary_null_checks - - unnecessary_null_in_if_null_operators - - unnecessary_nullable_for_final_variable_declarations - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_raw_strings - - unnecessary_string_escapes - - unnecessary_string_interpolations - - unnecessary_this - - unnecessary_to_list_in_spreads - - unreachable_from_main - - use_colored_box - - use_decorated_box - - use_enums - - use_full_hex_values_for_flutter_colors - - use_function_type_syntax_for_parameters - - use_if_null_to_convert_nulls_to_bools - - use_is_even_rather_than_modulo - - use_late_for_private_fields_and_variables - - use_named_constants - - use_raw_strings - - use_rethrow_when_possible - - use_setters_to_change_properties - - use_string_buffers - - use_string_in_part_of_directives - - use_super_parameters - - use_test_throws_matchers - - use_to_and_as_if_applicable - - depend_on_referenced_packages - - package_names - - secure_pubspec_urls - abi_specific_integer_invalid - abstract_field_initializer - argument_type_not_assignable_to_error_handler @@ -247,6 +28,7 @@ linter: - invalid_return_type_for_catch_error - invalid_super_formal_parameter_location - invalid_type_argument_in_const_literal + - invalid_visible_outside_template_annotation - invocation_of_non_function_expression - missing_default_value_for_parameter - non_constant_map_element diff --git a/dart-lang/src/main/resources/dartanalyzer/rules.json b/dart-lang/src/main/resources/dartanalyzer/rules.json index a1b01d8..8b8e5f8 100644 --- a/dart-lang/src/main/resources/dartanalyzer/rules.json +++ b/dart-lang/src/main/resources/dartanalyzer/rules.json @@ -1,1980 +1,9 @@ [ - { - "key": "always_use_package_imports", - "name": "Always use package imports", - "severity": "MINOR", - "description": "
\n

\n DO\n avoid relative imports for files in \n lib/\n .\n

\n

\n When mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use absolute imports for files within the\n\n lib/\n directory.\n

\n

This is the opposite of 'prefer_relative_imports'.

\n

\n You can also use 'avoid_relative_lib_imports' to disallow relative imports of\nfiles within \n lib/\n directory outside of it (for example \n test/\n ).\n

\n

\n BAD:\n

\n
\nimport 'baz.dart';\n\nimport 'src/bag.dart'\n\nimport '../lib/baz.dart';\n\n...\n\n  
\n

\n GOOD:\n

\n
\nimport 'package:foo/bar.dart';\n\nimport 'package:foo/baz.dart';\n\nimport 'package:foo/src/baz.dart';\n...\n\n  
\n

\n Incompatible with: \n prefer_relative_imports\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_dynamic_calls", - "name": "Avoid dynamic calls", - "severity": "MAJOR", - "description": "
\n

\n DO\n avoid method calls or accessing properties on an object that is either\nexplicitly or implicitly statically typed \"dynamic\". Dynamic calls are treated\nslightly different in every runtime environment and compiler, but most\nproduction modes (and even some development modes) have both compile size and\nruntime performance penalties associated with dynamic calls.\n

\n

Additionally, targets typed \"dynamic\" disables most static analysis, meaning it\nis easier to lead to a runtime \"NoSuchMethodError\" or \"NullError\" than properly\nstatically typed Dart code.

\n

There is an exception to methods and properties that exist on \"Object?\":

\n \n

\n ... these members are dynamically dispatched in the web-based runtimes, but not\nin the VM-based ones. Additionally, they are so common that it would be very\npunishing to disallow \n any.toString()\n or \n any == true\n , for example.\n

\n

Note that despite \"Function\" being a type, the semantics are close to identical\nto \"dynamic\", and calls to an object that is typed \"Function\" will also trigger\nthis lint.

\n

\n BAD:\n

\n
\nvoid explicitDynamicType(dynamic object) {\n  print(object.foo());\n}\n\nvoid implicitDynamicType(object) {\n  print(object.foo());\n}\n\nabstract class SomeWrapper {\n  T doSomething<T>();\n}\n\nvoid inferredDynamicType(SomeWrapper wrapper) {\n  var object = wrapper.doSomething();\n  print(object.foo());\n}\n\nvoid callDynamic(dynamic function) {\n  function();\n}\n\nvoid functionType(Function function) {\n  function();\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid explicitType(Fooable object) {\n  object.foo();\n}\n\nvoid castedType(dynamic object) {\n  (object as Fooable).foo();\n}\n\nabstract class SomeWrapper {\n  T doSomething<T>();\n}\n\nvoid inferredType(SomeWrapper wrapper) {\n  var object = wrapper.doSomething<Fooable>();\n  object.foo();\n}\n\nvoid functionTypeWithParameters(Function() function) {\n  function();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_empty_else", - "name": "Avoid empty else", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n empty else statements.\n

\n

\n BAD:\n

\n
\nif (x > y)\n  print(\"1\");\nelse ;\n  print(\"2\");\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_print", - "name": "Avoid print", - "severity": "MAJOR", - "description": "
\n

\n DO\n avoid \n print\n calls in production code.\n

\n

\n For production code, consider using a logging framework.\nIf you are using Flutter, you can use \n debugPrint\n or surround \n print\n calls with a check for \n kDebugMode\n

\n

\n BAD:\n

\n
\nvoid f(int x) {\n  print('debug: $x');\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f(int x) {\n  debugPrint('debug: $x');\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f(int x) {\n  log('log: $x');\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f(int x) {\n  if (kDebugMode) {\n      print('debug: $x');\n  }\n  ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_relative_lib_imports", - "name": "Avoid relative lib imports", - "severity": "MINOR", - "description": "
\n

\n DO\n avoid relative imports for files in \n lib/\n .\n

\n

\n When mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. An easy way to avoid\nthat is to ensure you have no relative imports that include \n lib/\n in their\npaths.\n

\n

\n You can also use 'always_use_package_imports' to disallow relative imports\nbetween files within \n lib/\n .\n

\n

\n BAD:\n

\n
\nimport 'package:foo/bar.dart';\n\nimport '../lib/baz.dart';\n\n...\n\n  
\n

\n GOOD:\n

\n
\nimport 'package:foo/bar.dart';\n\nimport 'baz.dart';\n\n...\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "avoid_slow_async_io", - "name": "Avoid slow async io", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n using the following asynchronous file I/O methods because they are\nmuch slower than their synchronous counterparts.\n

\n \n

\n BAD:\n

\n
\nimport 'dart:io';\n\nFuture<Null> someFunction() async {\n  var file = File('/path/to/my/file');\n  var now = DateTime.now();\n  if ((await file.lastModified()).isBefore(now)) print('before'); // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nimport 'dart:io';\n\nFuture<Null> someFunction() async {\n  var file = File('/path/to/my/file');\n  var now = DateTime.now();\n  if (file.lastModifiedSync().isBefore(now)) print('before'); // OK\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_type_to_string", - "name": "Avoid type to string", - "severity": "MAJOR", - "description": "
\n

\n DO\n avoid calls to \n .toString() in production code, since it does not\ncontractually return the user-defined name of the Type (or underlying class).\nDevelopment-mode compilers where code size is not a concern use the full name,\nbut release-mode compilers often choose to minify these symbols.\n

\n

\n BAD:\n

\n
\nvoid bar(Object other) {\n  if (other.runtimeType.toString() == 'Bar') {\n    doThing();\n  }\n}\n\nObject baz(Thing myThing) {\n  return getThingFromDatabase(key: myThing.runtimeType.toString());\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid bar(Object other) {\n  if (other is Bar) {\n    doThing();\n  }\n}\n\nclass Thing {\n  String get thingTypeKey => ...\n}\n\nObject baz(Thing myThing) {\n  return getThingFromDatabase(key: myThing.thingTypeKey);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_types_as_parameter_names", - "name": "Avoid types as parameter names", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n using a parameter name that is the same as an existing type.\n

\n

\n BAD:\n

\n
\nm(f(int));\n\n  
\n

\n GOOD:\n

\n
\nm(f(int v));\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_web_libraries_in_flutter", - "name": "Avoid web libraries in flutter", - "severity": "CRITICAL", - "description": "
\n

\n AVOID\n using web libraries, \n dart:html\n , \n dart:js\n and\n\n dart:js_util\n in Flutter packages that are not web plugins. These libraries are\nnot supported outside a web context; functionality that depends on them will\nfail at runtime in Flutter mobile, and their use is generally discouraged in\nFlutter web.\n

\n

\n Web library access \n is\n allowed in:\n

\n \n

\n otherwise, imports of \n dart:html\n , \n dart:js\n and \n dart:js_util\n are disallowed.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "cancel_subscriptions", - "name": "Cancel subscriptions", - "severity": "CRITICAL", - "description": "
\n

\n DO\n invoke \n cancel\n on instances of \n dart.async.StreamSubscription\n .\n

\n

Cancelling instances of StreamSubscription prevents memory leaks and unexpected\nbehavior.

\n

\n BAD:\n

\n
\nclass A {\n  StreamSubscription _subscriptionA; // LINT\n  void init(Stream stream) {\n    _subscriptionA = stream.listen((_) {});\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction() {\n  StreamSubscription _subscriptionF; // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nclass B {\n  StreamSubscription _subscriptionB; // OK\n  void init(Stream stream) {\n    _subscriptionB = stream.listen((_) {});\n  }\n\n  void dispose(filename) {\n    _subscriptionB.cancel();\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunctionOK() {\n  StreamSubscription _subscriptionB; // OK\n  _subscriptionB.cancel();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "close_sinks", - "name": "Close sinks", - "severity": "CRITICAL", - "description": "
\n

\n DO\n invoke \n close\n on instances of \n dart.core.Sink\n .\n

\n

Closing instances of Sink prevents memory leaks and unexpected behavior.

\n

\n BAD:\n

\n
\nclass A {\n  IOSink _sinkA;\n  void init(filename) {\n    _sinkA = File(filename).openWrite(); // LINT\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction() {\n  IOSink _sinkF; // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nclass B {\n  IOSink _sinkB;\n  void init(filename) {\n    _sinkB = File(filename).openWrite(); // OK\n  }\n\n  void dispose(filename) {\n    _sinkB.close();\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunctionOK() {\n  IOSink _sinkFOK; // OK\n  _sinkFOK.close();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "collection_methods_unrelated_type", - "name": "Collection methods unrelated type", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n invoke certain collection method with an argument with an unrelated\ntype.\n

\n

\n Doing this will invoke \n ==\n on the collection's elements and most likely will\nreturn \n false\n .\n

\n

An argument passed to a collection method should relate to the collection type\nas follows:

\n \n

\n BAD:\n

\n
\nvoid someFunction() {\n  var list = <int>[];\n  if (list.contains('1')) print('someFunction'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction() {\n  var set = <int>{};\n  set.remove('1'); // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction() {\n  var list = <int>[];\n  if (list.contains(1)) print('someFunction'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction() {\n  var set = <int>{};\n  set.remove(1); // OK\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "comment_references", - "name": "Comment references", - "severity": "MINOR", - "description": "
\n

\n DO\n reference only in scope identifiers in doc comments.\n

\n

\n If you surround things like variable, method, or type names in square brackets,\nthen \n \n dart doc\n \n will look\nup the name and link to its docs. For this all to work, ensure that all\nidentifiers in docs wrapped in brackets are in scope.\n

\n

\n For example, assuming \n outOfScopeId\n is out of scope:\n

\n

\n BAD:\n

\n
\n/// Return true if [value] is larger than [outOfScopeId].\nbool isOutOfRange(int value) { ... }\n\n  
\n

\n GOOD:\n

\n
\n/// Return the larger of [a] or [b].\nint max_int(int a, int b) { ... }\n\n  
\n

\n Note that the square bracket comment format is designed to allow\ncomments to refer to declarations using a fairly natural format\nbut does not allow \n arbitrary expressions\n . In particular, code\nreferences within square brackets can consist of either\n

\n \n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "control_flow_in_finally", - "name": "Control flow in finally", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n control flow leaving finally blocks.\n

\n

Using control flow in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.

\n

\n BAD:\n

\n
\nclass BadReturn {\n  double nonCompliantMethod() {\n    try {\n      return 1 / 0;\n    } catch (e) {\n      print(e);\n    } finally {\n      return 1.0; // LINT\n    }\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nclass BadContinue {\n  double nonCompliantMethod() {\n    for (var o in [1, 2]) {\n      try {\n        print(o / 0);\n      } catch (e) {\n        print(e);\n      } finally {\n        continue; // LINT\n      }\n    }\n    return 1.0;\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nclass BadBreak {\n  double nonCompliantMethod() {\n    for (var o in [1, 2]) {\n      try {\n        print(o / 0);\n      } catch (e) {\n        print(e);\n      } finally {\n        break; // LINT\n      }\n    }\n    return 1.0;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Ok {\n  double compliantMethod() {\n    var i = 5;\n    try {\n      i = 1 / 0;\n    } catch (e) {\n      print(e); // OK\n    }\n    return i;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "deprecated_member_use_from_same_package", - "name": "Deprecated member use from same package", - "severity": "MINOR", - "description": "
\n

\n Elements which are annotated with \n @deprecated\n should not be referenced from\nwithin the package in which they are declared.\n

\n

\n AVOID\n using deprecated elements.\n

\n

...

\n

\n BAD:\n

\n
\n// Declared in one library:\nclass Foo {\n  @Deprecated(\"Use 'm2' instead\")\n  void m1() {}\n\n  void m2({\n      @Deprecated('This is an old parameter') int? p,\n  })\n}\n\n@Deprecated('Do not use')\nint x = 0;\n\n// In the same or another library, but within the same package:\nvoid m(Foo foo) {\n  foo.m1();\n  foo.m2(p: 7);\n  x = 1;\n}\n\n  
\n

\n Deprecated elements can be used from within \n other\n deprecated elements, in\norder to allow for the deprecation of a collection of APIs together as one unit.\n

\n

\n GOOD:\n

\n
\n// Declared in one library:\nclass Foo {\n  @Deprecated(\"Use 'm2' instead\")\n  void m1() {}\n\n  void m2({\n      @Deprecated('This is an old parameter') int? p,\n  })\n}\n\n@Deprecated('Do not use')\nint x = 0;\n\n// In the same or another library, but within the same package:\n@Deprecated('Do not use')\nvoid m(Foo foo) {\n  foo.m1();\n  foo.m2(p: 7);\n  x = 1;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "diagnostic_describe_all_properties", - "name": "Diagnostic describe all properties", - "severity": "MAJOR", - "description": "
\n

\n DO\n reference all public properties in \n debug\n method implementations.\n

\n

\n Implementers of \n Diagnosticable\n should reference all public properties in\na \n debugFillProperties(...)\n or \n debugDescribeChildren(...)\n method\nimplementation to improve debuggability at runtime.\n

\n

Public properties are defined as fields and getters that are

\n \n

\n In addition, the \"debug\" prefix is treated specially for properties in Flutter.\nFor the purposes of diagnostics, a property \n foo\n and a prefixed property\n\n debugFoo\n are treated as effectively describing the same property and it is\nsufficient to refer to one or the other.\n

\n

\n BAD:\n

\n
\nclass Absorber extends Widget {\n  bool get absorbing => _absorbing;\n  bool _absorbing;\n  bool get ignoringSemantics => _ignoringSemantics;\n  bool _ignoringSemantics;\n  @override\n  void debugFillProperties(DiagnosticPropertiesBuilder properties) {\n    super.debugFillProperties(properties);\n    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));\n    // Missing reference to ignoringSemantics\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Absorber extends Widget {\n  bool get absorbing => _absorbing;\n  bool _absorbing;\n  bool get ignoringSemantics => _ignoringSemantics;\n  bool _ignoringSemantics;\n  @override\n  void debugFillProperties(DiagnosticPropertiesBuilder properties) {\n    super.debugFillProperties(properties);\n    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));\n    properties.add(DiagnosticsProperty<bool>('ignoringSemantics', ignoringSemantics));\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "discarded_futures", - "name": "Discarded futures", - "severity": "MAJOR", - "description": "
\n

\n Making asynchronous calls in non-\n async\n functions is usually the sign of a\nprogramming error. In general these functions should be marked \n async\n and such\nfutures should likely be awaited (as enforced by \n unawaited_futures\n ).\n

\n

\n DON'T\n invoke asynchronous functions in non-\n async\n blocks.\n

\n

\n BAD:\n

\n
\nvoid recreateDir(String path) {\n  deleteDir(path);\n  createDir(path);\n}\n\nFuture<void> deleteDir(String path) async {}\n\nFuture<void> createDir(String path) async {}\n\n  
\n

\n GOOD:\n

\n
\nFuture<void> recreateDir(String path) async {\n  await deleteDir(path);\n  await createDir(path);\n}\n\nFuture<void> deleteDir(String path) async {}\n\nFuture<void> createDir(String path) async {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "empty_statements", - "name": "Empty statements", - "severity": "CRITICAL", - "description": "
\n

\n AVOID\n empty statements.\n

\n

Empty statements almost always indicate a bug.

\n

For example,

\n

\n BAD:\n

\n
\nif (complicated.expression.foo());\n  bar();\n\n  
\n

\n Formatted with \n dart format\n the bug becomes obvious:\n

\n
\nif (complicated.expression.foo()) ;\nbar();\n\n\n  
\n

Better to avoid the empty statement altogether.

\n

\n GOOD:\n

\n
\nif (complicated.expression.foo())\n  bar();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "hash_and_equals", - "name": "Hash and equals", - "severity": "CRITICAL", - "description": "
\n

\n DO\n override \n hashCode\n if overriding \n ==\n and prefer overriding \n ==\n if\noverriding \n hashCode\n .\n

\n

\n Every object in Dart has a \n hashCode\n . Both the \n ==\n operator and the\n\n hashCode\n property of objects must be consistent in order for a common hash\nmap implementation to function properly. Thus, when overriding \n ==\n , the\n\n hashCode\n should also be overridden to maintain consistency. Similarly, if\n\n hashCode\n is overridden, \n ==\n should be also.\n

\n

\n BAD:\n

\n
\nclass Bad {\n  final int value;\n  Bad(this.value);\n\n  @override\n  bool operator ==(Object other) => other is Bad && other.value == value;\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Better {\n  final int value;\n  Better(this.value);\n\n  @override\n  bool operator ==(Object other) =>\n      other is Better &&\n      other.runtimeType == runtimeType &&\n      other.value == value;\n\n  @override\n  int get hashCode => value.hashCode;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "implicit_reopen", - "name": "Implicit reopen", - "severity": "MAJOR", - "description": "
\n

\n Using an \n interface\n , \n base\n , \n final\n , or \n sealed\n modifier on a class,\nor a \n base\n modifier on a mixin,\nauthors can control whether classes and mixins allow being implemented,\nextended, and/or mixed in from outside of the library where they're defined.\nIn some cases, it's possible for an author to inadvertently relax these controls\nand implicitly \"reopen\" a class. (A similar reopening cannot occur with a mixin.)\n

\n

\n This lint guards against unintentionally reopening a class by requiring such\ncases to be made explicit with the\n\n \n @reopen\n \n annotation in \n package:meta\n .\n

\n

\n BAD:\n

\n
\ninterface class I {}\n\nclass C extends I {} // LINT\n\n  
\n

\n GOOD:\n

\n
\ninterface class I {}\n\nfinal class C extends I {}\n\n  
\n
\ninterface class I {}\n\nfinal class C extends I {}\n\n  
\n
\nimport 'package:meta/meta.dart';\n\ninterface class I {}\n\n@reopen\nclass C extends I {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "invalid_case_patterns", - "name": "Invalid case patterns", - "severity": "MAJOR", - "description": "
\n

Some case expressions that are valid in Dart 2.19 and below will become an error\nor have changed semantics when a library is upgraded to 3.0. This lint flags\nthose expressions in order to ease migration to Dart 3.0.

\n

Some valid switch cases in 2.19 will become compile errors in Dart 3.0:

\n \n

Examples of all of them:

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

Some valid switch cases in 2.19 are also syntactically valid patterns, but the\npattern matching behavior may be different from the current constant equality\nbehavior. They are:

\n

\n List and map literals.\n A list or map literal can appear as a constant in a\ncase:\n

\n
\nswitch (obj) {\n  case [1, 2]: ...\n  case {'k': 'v'}: ...\n}\n\n  
\n

Currently, the case will only match if the incoming value has the same identity\nas the constant. So:

\n
\ntest(List<int> list) {\n  switch (list) {\n    case [1, 2]: print('Matched'); break;\n    default: print('Did not match'); break;\n  }\n}\n\nmain() {\n  test(const [1, 2]); // Prints \"Matched\".\n  test([1, 2]); // Prints \"Did not match\".\n}\n\n  
\n

With patterns, a list or map literal becomes a list or map pattern. The pattern\ndestructures the incoming object and matches if the subpatterns all match. In\nother words, list and map pattern match using something more like deep equality.

\n

With Dart 3.0, the above program prints \"Matched\" twice.

\n

\n Constant constructor calls.\n Similar to collections, you can construct a\nconstant instance of a class in a case:\n

\n
\nclass Point {\n  final int x;\n  final int y;\n  const Point({this.x, this.y});\n}\n\ntest(Point p) {\n  switch (p) {\n    case Point(x: 1, y: 2): print('Matched'); break;\n    default: print('Did not match'); break;\n  }\n}\n\nmain() {\n  test(const Point(1, 2)); // Prints \"Matched\".\n  test(Point(1, 2)); // Prints \"Did not match\".\n}\n\n  
\n

\n Again, like collections, the case currently only matches if the incoming value\nhas the same identity. With patterns, the \n Point(...)\n syntax becomes an object\npattern that destructures the incoming point, calls the \n x\n and \n y\n getters on\nit and then matches the results of those against the corresponding subpatterns.\n

\n

In this example, it will print \"Matched\" twice.

\n

Note that object patterns only support named fields. So any constant constructor\nin a case today that has positional arguments will become a compile-time error\nwhen parsed as a pattern. A constant constructor call with no arguments is a\nvalid object pattern and only does a type test:

\n
\nclass Thing {\n  const Thing();\n}\n\ntest(Thing t) {\n  switch (t) {\n    case Thing(): print('Matched'); break;\n    default: print('Did not match'); break;\n  }\n}\n\nmain() {\n  test(const Thing()); // Prints \"Matched\".\n  test(Thing()); // Prints \"Did not match\".\n}\n\n  
\n

When interpreted as a pattern, this prints \"Matched\" twice.

\n

\n Wildcards.\n Today, you can have a constant named \n _\n :\n

\n
\ntest(int n) {\n  const _ = 3;\n  switch (n) {\n    case _: print('Matched'); break;\n    default: print('Did not match'); break;\n  }\n}\n\nmain() {\n  test(3); // Prints \"Matched\".\n  test(5); // Prints \"Did not match\".\n}\n\n  
\n

\n With patterns, the identifier \n _\n is treated as a pattern that matches all\nvalues, so this prints \"Matched\" twice.\n

\n

\n Logic operators.\n The logic operators \n &&\n and \n ||\n are valid constant\nexpressions and also valid patterns. As a constant expression, they simply\nevaluate the expression to a boolean and match if the incoming value is equal to\nthat boolean value. So:\n

\n
\ntest(bool b) {\n  switch (b) {\n    case true && false: print('Matched'); break;\n    default: print('Did not match'); break;\n  }\n}\n\nmain() {\n  test(false); // Prints \"Matched\".\n  test(true); // Prints \"Did not match\".\n}\n\n  
\n

With Dart 3.0, these become patterns. The above example prints \"Did not match\"\ntwice because no boolean value can be both true and false.

\n

Many of invalid cases can be mechanically changed to something that is valid\nboth in Dart today and valid and means the same in Dart 3.0.

\n

\n Parenthesized expressions:\n Provided the inner expression is one that's not\nbroken in Dart 3.0, just discard the parentheses.\n

\n

\n List literals, map literals, set literals, and constant constructor calls:\n Put \n const\n before the literal or call. This turns it into a constant pattern\nwhich preserves the current behavior:\n

\n

\n BAD:\n

\n
\ncase [1, 2]:\ncase {'k': 'v'}:\ncase {1, 2}:\ncase Point(1, 2):\n\n  
\n

\n GOOD:\n

\n
\ncase const [1, 2]:\ncase const {'k': 'v'}:\ncase const {1, 2}:\ncase const Point(1, 2):\n\n  
\n \n

\n BAD:\n

\n
\nswitch (n) {\n  case 1 + 2: ...\n}\n\n  
\n

It can be fixed by changing it to:

\n

\n GOOD:\n

\n
\nconst three = 1 + 2;\n\nswitch (n) {\n case three: ...\n}\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "invariant_booleans", - "name": "Invariant booleans", - "severity": "MAJOR", - "description": "
\n

\n Unsupported since Dart language version 3.0.0.\n

\n

\n DON'T\n test for conditions that can be inferred at compile time or test the\nsame condition twice.\n

\n

\n Conditional statements using a condition which cannot be anything but \n false\n have the effect of making blocks of code non-functional. If the condition\ncannot evaluate to anything but \n true\n , the conditional statement is completely\nredundant, and makes the code less readable.\nIt is quite likely that the code does not match the programmer's intent.\nEither the condition should be removed or it should be updated so that it does\nnot always evaluate to \n true\n or \n false\n and does not perform redundant tests.\nThis rule will hint to the test conflicting with the linted one.\n

\n

\n BAD:\n

\n
\n// foo can't be both equal and not equal to bar in the same expression\nif(foo == bar && something && foo != bar) {...}\n\n  
\n

\n BAD:\n

\n
\nvoid compute(int foo) {\n  if (foo == 4) {\n    doSomething();\n    // we know foo is equal to 4 at this point, so the next condition is always false\n    if (foo > 4) {...}\n    ...\n  }\n  ...\n}\n\n  
\n

\n BAD:\n

\n
\nvoid compute(bool foo) {\n  if (foo) {\n    return;\n  }\n  doSomething();\n  // foo is always false here\n  if (foo){...}\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid nestedOK() {\n  if (foo == bar) {\n    foo = baz;\n    if (foo != bar) {...}\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid nestedOk2() {\n  if (foo == bar) {\n    return;\n  }\n\n  foo = baz;\n  if (foo == bar) {...} // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid nestedOk5() {\n  if (foo != null) {\n    if (bar != null) {\n      return;\n    }\n  }\n\n  if (bar != null) {...} // OK\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "iterable_contains_unrelated_type", - "name": "Iterable contains unrelated type", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n invoke \n contains\n on \n Iterable\n with an instance of different type\nthan the parameter type.\n

\n

\n Doing this will invoke \n ==\n on its elements and most likely will return \n false\n .\n

\n

\n BAD:\n

\n
\nvoid someFunction() {\n  var list = <int>[];\n  if (list.contains('1')) print('someFunction'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction3() {\n  List<int> list = <int>[];\n  if (list.contains('1')) print('someFunction3'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction8() {\n  List<DerivedClass2> list = <DerivedClass2>[];\n  DerivedClass3 instance;\n  if (list.contains(instance)) print('someFunction8'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nabstract class SomeIterable<E> implements Iterable<E> {}\n\nabstract class MyClass implements SomeIterable<int> {\n  bool badMethod(String thing) => this.contains(thing); // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction10() {\n  var list = [];\n  if (list.contains(1)) print('someFunction10'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction1() {\n  var list = <int>[];\n  if (list.contains(1)) print('someFunction1'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction4() {\n  List<int> list = <int>[];\n  if (list.contains(1)) print('someFunction4'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction5() {\n  List<ClassBase> list = <ClassBase>[];\n  DerivedClass1 instance;\n  if (list.contains(instance)) print('someFunction5'); // OK\n}\n\nabstract class ClassBase {}\n\nclass DerivedClass1 extends ClassBase {}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction6() {\n  List<Mixin> list = <Mixin>[];\n  DerivedClass2 instance;\n  if (list.contains(instance)) print('someFunction6'); // OK\n}\n\nabstract class ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass2 extends ClassBase with Mixin {}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction7() {\n  List<Mixin> list = <Mixin>[];\n  DerivedClass3 instance;\n  if (list.contains(instance)) print('someFunction7'); // OK\n}\n\nabstract class ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass3 extends ClassBase implements Mixin {}\n\n  
\n
\n", - "type": "BUG", - "debt": "1min", - "active": true - }, - { - "key": "list_remove_unrelated_type", - "name": "List remove unrelated type", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n invoke \n remove\n on \n List\n with an instance of different type than\nthe parameter type.\n

\n

\n Doing this will invoke \n ==\n on its elements and most likely will\nreturn \n false\n .\n

\n

\n BAD:\n

\n
\nvoid someFunction() {\n  var list = <int>[];\n  if (list.remove('1')) print('someFunction'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction3() {\n  List<int> list = <int>[];\n  if (list.remove('1')) print('someFunction3'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction8() {\n  List<DerivedClass2> list = <DerivedClass2>[];\n  DerivedClass3 instance;\n  if (list.remove(instance)) print('someFunction8'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nabstract class SomeList<E> implements List<E> {}\n\nabstract class MyClass implements SomeList<int> {\n  bool badMethod(String thing) => this.remove(thing); // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction10() {\n  var list = [];\n  if (list.remove(1)) print('someFunction10'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction1() {\n  var list = <int>[];\n  if (list.remove(1)) print('someFunction1'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction4() {\n  List<int> list = <int>[];\n  if (list.remove(1)) print('someFunction4'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction5() {\n  List<ClassBase> list = <ClassBase>[];\n  DerivedClass1 instance;\n  if (list.remove(instance)) print('someFunction5'); // OK\n}\n\nabstract class ClassBase {}\n\nclass DerivedClass1 extends ClassBase {}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction6() {\n  List<Mixin> list = <Mixin>[];\n  DerivedClass2 instance;\n  if (list.remove(instance)) print('someFunction6'); // OK\n}\n\nabstract class ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass2 extends ClassBase with Mixin {}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction7() {\n  List<Mixin> list = <Mixin>[];\n  DerivedClass3 instance;\n  if (list.remove(instance)) print('someFunction7'); // OK\n}\n\nabstract class ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass3 extends ClassBase implements Mixin {}\n\n  
\n
\n", - "type": "BUG", - "debt": "1min", - "active": true - }, - { - "key": "literal_only_boolean_expressions", - "name": "Literal only boolean expressions", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n test for conditions composed only by literals, since the value can be\ninferred at compile time.\n

\n

\n Conditional statements using a condition which cannot be anything but FALSE have\nthe effect of making blocks of code non-functional. If the condition cannot\nevaluate to anything but \n true\n , the conditional statement is completely\nredundant, and makes the code less readable.\nIt is quite likely that the code does not match the programmer's intent.\nEither the condition should be removed or it should be updated so that it does\nnot always evaluate to \n true\n or \n false\n .\n

\n

\n BAD:\n

\n
\nvoid bad() {\n  if (true) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (true && 1 != 0) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (1 != 0 && true) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (1 < 0 && true) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (true && false) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (1 != 0) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (true && 1 != 0 || 3 < 4) {} // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid bad() {\n  if (1 != 0 || 3 < 4 && true) {} // LINT\n}\n\n  
\n

\n NOTE:\n that an exception is made for the common \n while (true) { }\n idiom,\nwhich is often reasonably preferred to the equivalent \n for (;;)\n .\n

\n

\n GOOD:\n

\n
\nvoid good() {\n  while (true) {\n    // Do stuff.\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "no_adjacent_strings_in_list", - "name": "No adjacent strings in list", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n use adjacent strings in a list.\n

\n

This can indicate a forgotten comma.

\n

\n BAD:\n

\n
\nList<String> list = <String>[\n  'a'\n  'b',\n  'c',\n];\n\n  
\n

\n GOOD:\n

\n
\nList<String> list = <String>[\n  'a' +\n  'b',\n  'c',\n];\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "no_duplicate_case_values", - "name": "No duplicate case values", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n use more than one case with same value.\n

\n

This is usually a typo or changed value of constant.

\n

\n BAD:\n

\n
\nconst int A = 1;\nswitch (v) {\n  case 1:\n  case 2:\n  case A:\n  case 2:\n}\n\n  
\n

\n GOOD:\n

\n
\nconst int A = 1;\nswitch (v) {\n  case A:\n  case 2:\n}\n\n  
\n

NOTE: this lint only reports duplicate cases in libraries opted in to Dart 2.19\nand below. In Dart 3.0 and after, duplicate cases are reported as dead code\nby the analyzer.

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "no_logic_in_create_state", - "name": "No logic in create state", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n put any logic in \n createState()\n .\n

\n

\n Implementations of \n createState()\n should return a new instance\nof a State object and do nothing more. Since state access is preferred\nvia the \n widget\n field, passing data to \n State\n objects using custom\nconstructor parameters should also be avoided and so further, the State\nconstructor is required to be passed no arguments.\n

\n

\n BAD:\n

\n
\nMyState global;\n\nclass MyStateful extends StatefulWidget {\n  @override\n  MyState createState() {\n    global = MyState();\n    return global;\n  } \n}\n\n  
\n
\nclass MyStateful extends StatefulWidget {\n  @override\n  MyState createState() => MyState()..field = 42;\n}\n\n  
\n
\nclass MyStateful extends StatefulWidget {\n  @override\n  MyState createState() => MyState(42);\n}\n\n  
\n

\n GOOD:\n

\n
\nclass MyStateful extends StatefulWidget {\n  @override\n  MyState createState() {\n    return MyState();\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_relative_imports", - "name": "Prefer relative imports", - "severity": "MINOR", - "description": "
\n

\n PREFER\n relative imports for files in \n lib/\n .\n

\n

\n When mixing relative and absolute imports it's possible to create confusion\nwhere the same member gets imported in two different ways. One way to avoid\nthat is to ensure you consistently use relative imports for files within the\n\n lib/\n directory.\n

\n

\n BAD:\n

\n
\nimport 'package:my_package/bar.dart';\n\n  
\n

\n GOOD:\n

\n
\nimport 'bar.dart';\n\n  
\n

\n Incompatible with: \n always_use_package_imports\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_void_to_null", - "name": "Prefer void to null", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n use the type Null where void would work.\n

\n

\n BAD:\n

\n
\nNull f() {}\nFuture<Null> f() {}\nStream<Null> f() {}\nf(Null x) {}\n\n  
\n

\n GOOD:\n

\n
\nvoid f() {}\nFuture<void> f() {}\nStream<void> f() {}\nf(void x) {}\n\n  
\n

Some exceptions include formulating special function types:

\n
\nNull Function(Null, Null);\n\n  
\n

and for making empty literals which are safe to pass into read-only locations\nfor any type of map or list:

\n
\n<Null>[];\n<int, Null>{};\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "test_types_in_equals", - "name": "Test types in equals", - "severity": "CRITICAL", - "description": "
\n

\n DO\n test type arguments in operator ==(Object other).\n

\n

Not testing types might result in null pointer exceptions which will be\nunexpected for consumers of your class.

\n

\n BAD:\n

\n
\nclass Field {\n}\n\nclass Bad {\n  final Field someField;\n\n  Bad(this.someField);\n\n  @override\n  bool operator ==(Object other) {\n    Bad otherBad = other as Bad; // LINT\n    bool areEqual = otherBad != null && otherBad.someField == someField;\n    return areEqual;\n  }\n\n  @override\n  int get hashCode {\n    return someField.hashCode;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Field {\n}\n\nclass Good {\n  final Field someField;\n\n  Good(this.someField);\n\n  @override\n  bool operator ==(Object other) {\n    if (identical(this, other)) {\n      return true;\n    }\n    return other is Good &&\n        this.someField == other.someField;\n  }\n\n  @override\n  int get hashCode {\n    return someField.hashCode;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "throw_in_finally", - "name": "Throw in finally", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n throwing exceptions in finally blocks.\n

\n

Throwing exceptions in finally blocks will inevitably cause unexpected behavior\nthat is hard to debug.

\n

\n BAD:\n

\n
\nclass BadThrow {\n  double nonCompliantMethod() {\n    try {\n      print('hello world! ${1 / 0}');\n    } catch (e) {\n      print(e);\n    } finally {\n      throw 'Find the hidden error :P'; // LINT\n    }\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Ok {\n  double compliantMethod() {\n    var i = 5;\n    try {\n      i = 1 / 0;\n    } catch (e) {\n      print(e); // OK\n    }\n    return i;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "unnecessary_statements", - "name": "Unnecessary statements", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using unnecessary statements.\n

\n

Statements which have no clear effect are usually unnecessary, or should be\nbroken up.

\n

For example,

\n

\n BAD:\n

\n
\nmyvar;\nlist.clear;\n1 + 2;\nmethodOne() + methodTwo();\nfoo ? bar : baz;\n\n  
\n

Though the added methods have a clear effect, the addition itself does not\nunless there is some magical overload of the + operator.

\n

Usually code like this indicates an incomplete thought, and is a bug.

\n

\n GOOD:\n

\n
\nsome.method();\nconst SomeClass();\nmethodOne();\nmethodTwo();\nfoo ? bar() : baz();\nreturn myvar;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unrelated_type_equality_checks", - "name": "Unrelated type equality checks", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n Compare references of unrelated types for equality.\n

\n

\n Comparing references of a type where neither is a subtype of the other most\nlikely will return \n false\n and might not reflect programmer's intent.\n

\n

\n Int64\n and \n Int32\n from \n package:fixnum\n allow comparing to \n int\n provided\nthe \n int\n is on the right hand side. The lint allows this as a special case.\n

\n

\n BAD:\n

\n
\nvoid someFunction() {\n  var x = '1';\n  if (x == 1) print('someFunction'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction1() {\n  String x = '1';\n  if (x == 1) print('someFunction1'); // LINT\n}\n\n  
\n

\n BAD:\n

\n
\nvoid someFunction13(DerivedClass2 instance) {\n  var other = DerivedClass3();\n\n  if (other == instance) print('someFunction13'); // LINT\n}\n\nclass ClassBase {}\n\nclass DerivedClass1 extends ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass2 extends ClassBase with Mixin {}\n\nclass DerivedClass3 extends ClassBase implements Mixin {}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction2() {\n  var x = '1';\n  var y = '2';\n  if (x == y) print(someFunction2); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction3() {\n  for (var i = 0; i < 10; i++) {\n    if (i == 0) print(someFunction3); // OK\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction4() {\n  var x = '1';\n  if (x == null) print(someFunction4); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction7() {\n  List someList;\n\n  if (someList.length == 0) print('someFunction7'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction8(ClassBase instance) {\n  DerivedClass1 other;\n\n  if (other == instance) print('someFunction8'); // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction10(unknown) {\n  var what = unknown - 1;\n  for (var index = 0; index < unknown; index++) {\n    if (what == index) print('someFunction10'); // OK\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid someFunction11(Mixin instance) {\n  var other = DerivedClass2();\n\n  if (other == instance) print('someFunction11'); // OK\n  if (other != instance) print('!someFunction11'); // OK\n}\n\nclass ClassBase {}\n\nabstract class Mixin {}\n\nclass DerivedClass2 extends ClassBase with Mixin {}\n\n  
\n
\n", - "type": "BUG", - "debt": "1min", - "active": true - }, - { - "key": "unsafe_html", - "name": "Unsafe html", - "severity": "CRITICAL", - "description": "
\n

\n AVOID\n

\n \n

\n BAD:\n

\n
\nvar script = ScriptElement()..src = 'foo.js';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_build_context_synchronously", - "name": "Use build context synchronously", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use BuildContext across asynchronous gaps.\n

\n

\n Storing \n BuildContext\n for later usage can easily lead to difficult to diagnose\ncrashes. Asynchronous gaps are implicitly storing \n BuildContext\n and are some of\nthe easiest to overlook when writing code.\n

\n

\n When a \n BuildContext\n is used, its \n mounted\n property must be checked after an\nasynchronous gap.\n

\n

\n BAD:\n

\n
\nvoid onButtonTapped(BuildContext context) async {\n  await Future.delayed(const Duration(seconds: 1));\n  Navigator.of(context).pop();\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid onButtonTapped(BuildContext context) {\n  Navigator.of(context).pop();\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid onButtonTapped() async {\n  await Future.delayed(const Duration(seconds: 1));\n\n  if (!context.mounted) return;\n  Navigator.of(context).pop();\n}\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "use_key_in_widget_constructors", - "name": "Use key in widget constructors", - "severity": "MAJOR", - "description": "
\n

\n DO\n use key in widget constructors.\n

\n

It's a good practice to expose the ability to provide a key when creating public\nwidgets.

\n

\n BAD:\n

\n
\nclass MyPublicWidget extends StatelessWidget {\n}\n\n  
\n

\n GOOD:\n

\n
\nclass MyPublicWidget extends StatelessWidget {\n  MyPublicWidget({super.key});\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "always_declare_return_types", - "name": "Always declare return types", - "severity": "MAJOR", - "description": "
\n

\n DO\n declare method return types.\n

\n

\n When declaring a method or function \n always\n specify a return type.\nDeclaring return types for functions helps improve your codebase by allowing the\nanalyzer to more adequately check your code for errors that could occur during\nruntime.\n

\n

\n BAD:\n

\n
\nmain() { }\n\n_bar() => _Foo();\n\nclass _Foo {\n  _foo() => 42;\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid main() { }\n\n_Foo _bar() => _Foo();\n\nclass _Foo {\n  int _foo() => 42;\n}\n\ntypedef predicate = bool Function(Object o);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "always_put_control_body_on_new_line", - "name": "Always put control body on new line", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide for the flutter repo\n :\n

\n

\n DO\n separate the control structure expression from its statement.\n

\n

\n Don't put the statement part of an \n if\n , \n for\n , \n while\n , \n do\n on the same line\nas the expression, even if it is short. Doing so makes it unclear that there\nis relevant code there. This is especially important for early returns.\n

\n

\n BAD:\n

\n
\nif (notReady) return;\n\nif (notReady)\n  return;\nelse print('ok')\n\nwhile (condition) i += 1;\n\n  
\n

\n GOOD:\n

\n
\nif (notReady)\n  return;\n\nif (notReady)\n  return;\nelse\n  print('ok')\n\nwhile (condition)\n  i += 1;\n\n  
\n

\n Note that this rule can conflict with the\n\n Dart formatter\n , and should not be enabled\nwhen the Dart formatter is used.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "always_put_required_named_parameters_first", - "name": "Always put required named parameters first", - "severity": "MINOR", - "description": "
\n

\n DO\n specify \n required\n on named parameter before other named parameters.\n

\n

\n BAD:\n

\n
\nm({b, c, required a}) ;\n\n  
\n

\n GOOD:\n

\n
\nm({required a, b, c}) ;\n\n  
\n

\n BAD:\n

\n
\nm({b, c, @required a}) ;\n\n  
\n

\n GOOD:\n

\n
\nm({@required a, b, c}) ;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "always_specify_types", - "name": "Always specify types", - "severity": "MAJOR", - "description": "
\n

\n From the \n style guide for the flutter repo\n :\n

\n

\n DO\n specify type annotations.\n

\n

\n Avoid \n var\n when specifying that a type is unknown and short-hands that elide\ntype annotations. Use \n dynamic\n if you are being explicit that the type is\nunknown. Use \n Object\n if you are being explicit that you want an object that\nimplements \n ==\n and \n hashCode\n .\n

\n

\n BAD:\n

\n
\nvar foo = 10;\nfinal bar = Bar();\nconst quux = 20;\n\n  
\n

\n GOOD:\n

\n
\nint foo = 10;\nfinal Bar bar = Bar();\nString baz = 'hello';\nconst int quux = 20;\n\n  
\n

\n NOTE: Using the the \n @optionalTypeArgs\n annotation in the \n meta\n package, API\nauthors can special-case type variables whose type needs to by dynamic but whose\ndeclaration should be treated as optional. For example, suppose you have a\n\n Key\n object whose type parameter you'd like to treat as optional. Using the\n\n @optionalTypeArgs\n would look like this:\n

\n
\nimport 'package:meta/meta.dart';\n\n@optionalTypeArgs\nclass Key<T> {\n ...\n}\n\nmain() {\n  Key s = Key(); // OK!\n}\n\n  
\n

\n Incompatible with: \n avoid_types_on_closure_parameters\n , \n omit_local_variable_types\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "annotate_overrides", - "name": "Annotate overrides", - "severity": "MAJOR", - "description": "
\n

\n DO\n annotate overridden methods and fields.\n

\n

This practice improves code readability and helps protect against\nunintentionally overriding superclass members.

\n

\n BAD:\n

\n
\nclass Cat {\n  int get lives => 9;\n}\n\nclass Lucky extends Cat {\n  final int lives = 14;\n}\n\n  
\n

\n GOOD:\n

\n
\nabstract class Dog {\n  String get breed;\n  void bark() {}\n}\n\nclass Husky extends Dog {\n  @override\n  final String breed = 'Husky';\n  @override\n  void bark() {}\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_annotating_with_dynamic", - "name": "Avoid annotating with dynamic", - "severity": "MINOR", - "description": "
\n

\n AVOID\n annotating with dynamic when not required.\n

\n

\n As \n dynamic\n is the assumed return value of a function or method, it is usually\nnot necessary to annotate it.\n

\n

\n BAD:\n

\n
\ndynamic lookUpOrDefault(String name, Map map, dynamic defaultValue) {\n  var value = map[name];\n  if (value != null) return value;\n  return defaultValue;\n}\n\n  
\n

\n GOOD:\n

\n
\nlookUpOrDefault(String name, Map map, defaultValue) {\n  var value = map[name];\n  if (value != null) return value;\n  return defaultValue;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_as", - "name": "Avoid as", - "severity": "MINOR", - "description": "
\n

\n Unsupported since Dart language version 2.12.0.\n

\n

\n AVOID\n using \n as\n .\n

\n

\n If you know the type is correct, use an assertion or assign to a more\nnarrowly-typed variable (this avoids the type check in release mode; \n as\n is not\ncompiled out in release mode). If you don't know whether the type is\ncorrect, check using \n is\n (this avoids the exception that \n as\n raises).\n

\n

\n BAD:\n

\n
\n(pm as Person).firstName = 'Seth';\n\n  
\n

\n GOOD:\n

\n
\nif (pm is Person)\n  pm.firstName = 'Seth';\n\n  
\n

but certainly not

\n

\n BAD:\n

\n
\ntry {\n   (pm as Person).firstName = 'Seth';\n} on CastError { }\n\n  
\n

\n Note that an exception is made in the case of \n dynamic\n since the cast has no\nperformance impact.\n

\n

\n OK:\n

\n
\nHasScrollDirection scrollable = renderObject as dynamic;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_bool_literals_in_conditional_expressions", - "name": "Avoid bool literals in conditional expressions", - "severity": "MINOR", - "description": "
\n

\n AVOID\n bool literals in conditional expressions.\n

\n

\n BAD:\n

\n
\ncondition ? true : boolExpression\ncondition ? false : boolExpression\ncondition ? boolExpression : true\ncondition ? boolExpression : false\n\n  
\n

\n GOOD:\n

\n
\ncondition || boolExpression\n!condition && boolExpression\n!condition || boolExpression\ncondition && boolExpression\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_catches_without_on_clauses", - "name": "Avoid catches without on clauses", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n catches without on clauses.\n

\n

Using catch clauses without on clauses make your code prone to encountering\nunexpected errors that won't be thrown (and thus will go unnoticed).

\n

\n BAD:\n

\n
\ntry {\n somethingRisky()\n}\ncatch(e) {\n  doSomething(e);\n}\n\n  
\n

\n GOOD:\n

\n
\ntry {\n somethingRisky()\n}\non Exception catch(e) {\n  doSomething(e);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_catching_errors", - "name": "Avoid catching errors", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n explicitly catch Error or types that implement it.\n

\n

Errors differ from Exceptions in that Errors can be analyzed and prevented prior\nto runtime. It should almost never be necessary to catch an error at runtime.

\n

\n BAD:\n

\n
\ntry {\n  somethingRisky();\n} on Error catch(e) {\n  doSomething(e);\n}\n\n  
\n

\n GOOD:\n

\n
\ntry {\n  somethingRisky();\n} on Exception catch(e) {\n  doSomething(e);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_classes_with_only_static_members", - "name": "Avoid classes with only static members", - "severity": "MINOR", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

\n AVOID\n defining a class that contains only static members.\n

\n

Creating classes with the sole purpose of providing utility or otherwise static\nmethods is discouraged. Dart allows functions to exist outside of classes for\nthis very reason.

\n

\n BAD:\n

\n
\nclass DateUtils {\n  static DateTime mostRecent(List<DateTime> dates) {\n    return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n  }\n}\n\nclass _Favorites {\n  static const mammal = 'weasel';\n}\n\n  
\n

\n GOOD:\n

\n
\nDateTime mostRecent(List<DateTime> dates) {\n  return dates.reduce((a, b) => a.isAfter(b) ? a : b);\n}\n\nconst _favoriteMammal = 'weasel';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_double_and_int_checks", - "name": "Avoid double and int checks", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n to check if type is double or int.\n

\n

\n When compiled to JS, integer values are represented as floats. That can lead to\nsome unexpected behavior when using either \n is\n or \n is!\n where the type is\neither \n int\n or \n double\n .\n

\n

\n BAD:\n

\n
\nf(num x) {\n  if (x is double) {\n    ...\n  } else if (x is int) {\n    ...\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nf(dynamic x) {\n  if (x is num) {\n    ...\n  } else {\n    ...\n  }\n}\n\n  
\n
\n", - "type": "BUG", - "debt": "1min", - "active": false - }, - { - "key": "avoid_equals_and_hash_code_on_mutable_classes", - "name": "Avoid equals and hash code on mutable classes", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n overloading operator == and hashCode on classes not marked \n @immutable\n .\n

\n

If a class is not immutable, overloading operator == and hashCode can lead to\nunpredictable and undesirable behavior when used in collections. See\nhttps://dart.dev/guides/language/effective-dart/design#avoid-defining-custom-equality-for-mutable-classes\nfor more information.

\n

\n BAD:\n

\n
\nclass B {\n  String key;\n  const B(this.key);\n  @override\n  operator ==(other) => other is B && other.key == key;\n  @override\n  int get hashCode => key.hashCode;\n}\n\n  
\n

\n GOOD:\n

\n
\n@immutable\nclass A {\n  final String key;\n  const A(this.key);\n  @override\n  operator ==(other) => other is A && other.key == key;\n  @override\n  int get hashCode => key.hashCode;\n}\n\n  
\n

\n NOTE: The lint checks the use of the \n @immutable\n annotation, and will trigger\neven if the class is otherwise not mutable. Thus:\n

\n

\n BAD:\n

\n
\nclass C {\n  final String key;\n  const C(this.key);\n  @override\n  operator ==(other) => other is C && other.key == key;\n  @override\n  int get hashCode => key.hashCode;\n}\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "avoid_escaping_inner_quotes", - "name": "Avoid escaping inner quotes", - "severity": "MINOR", - "description": "
\n

Avoid escaping inner quotes by converting surrounding quotes.

\n

\n BAD:\n

\n
\nvar s = 'It\\'s not fun';\n\n  
\n

\n GOOD:\n

\n
\nvar s = \"It's not fun\";\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_field_initializers_in_const_classes", - "name": "Avoid field initializers in const classes", - "severity": "MINOR", - "description": "
\n

\n AVOID\n field initializers in const classes.\n

\n

\n Instead of \n final x = const expr;\n , you should write \n get x => const expr;\n and\nnot allocate a useless field. As of April 2018 this is true for the VM, but not\nfor code that will be compiled to JS.\n

\n

\n BAD:\n

\n
\nclass A {\n  final a = const [];\n  const A();\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  get a => const [];\n  const A();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_final_parameters", - "name": "Avoid final parameters", - "severity": "MINOR", - "description": "
\n

\n AVOID\n declaring parameters as final.\n

\n

Declaring parameters as final can lead to unnecessarily verbose code, especially\nwhen using the \"parameter_assignments\" rule.

\n

\n BAD:\n

\n
\nvoid goodParameter(final String label) { // LINT\n  print(label);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid badParameter(String label) { // OK\n  print(label);\n}\n\n  
\n

\n BAD:\n

\n
\nvoid goodExpression(final int value) => print(value); // LINT\n\n  
\n

\n GOOD:\n

\n
\nvoid badExpression(int value) => print(value); // OK\n\n  
\n

\n BAD:\n

\n
\n[1, 4, 6, 8].forEach((final value) => print(value + 2)); // LINT\n\n  
\n

\n GOOD:\n

\n
\n[1, 4, 6, 8].forEach((value) => print(value + 2)); // OK\n\n  
\n

\n Incompatible with: \n prefer_final_parameters\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_function_literals_in_foreach_calls", - "name": "Avoid function literals in foreach calls", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using \n forEach\n with a function literal.\n

\n

\n The \n for\n loop enables a developer to be clear and explicit as to their intent.\nA return in the body of the \n for\n loop returns from the body of the function,\nwhere as a return in the body of the \n forEach\n closure only returns a value\nfor that iteration of the \n forEach\n . The body of a \n for\n loop can contain\n\n await\n s, while the closure body of a \n forEach\n cannot.\n

\n

\n BAD:\n

\n
\npeople.forEach((person) {\n  ...\n});\n\n  
\n

\n GOOD:\n

\n
\nfor (var person in people) {\n  ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_implementing_value_types", - "name": "Avoid implementing value types", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n implement classes that override \n ==\n .\n

\n

\n The \n ==\n operator is contractually required to be an equivalence relation;\nthat is, symmetrically for all objects \n o1\n and \n o2\n , \n o1 == o2\n and \n o2 == o1\n must either both be true, or both be false.\n

\n
\n

\n NOTE\n : Dart does not have true \n value types\n , so instead we consider a class\nthat implements \n ==\n as a \n proxy\n for identifying value types.\n

\n
\n

\n When using \n implements\n , you do not inherit the method body of \n ==\n , making it\nnearly impossible to follow the contract of \n ==\n . Classes that override \n ==\n typically are usable directly in tests \n without\n creating mocks or fakes as\nwell. For example, for a given class \n Size\n :\n

\n
\nclass Size {\n  final int inBytes;\n  const Size(this.inBytes);\n\n  @override\n  bool operator ==(Object other) => other is Size && other.inBytes == inBytes;\n\n  @override\n  int get hashCode => inBytes.hashCode;\n}\n\n  
\n

\n BAD:\n

\n
\nclass CustomSize implements Size {\n  final int inBytes;\n  const CustomSize(this.inBytes);\n\n  int get inKilobytes => inBytes ~/ 1000;\n}\n\n  
\n

\n BAD:\n

\n
\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nclass FakeSize implements Size {\n  int inBytes = 0;\n}\n\nvoid main() {\n  test('should not throw on a size >1Kb', () {\n    expect(() => someFunction(FakeSize()..inBytes = 1001), returnsNormally);\n  });\n}\n\n  
\n

\n GOOD:\n

\n
\nclass ExtendedSize extends Size {\n  ExtendedSize(int inBytes) : super(inBytes);\n\n  int get inKilobytes => inBytes ~/ 1000;\n}\n\n  
\n

\n GOOD:\n :\n

\n
\nimport 'package:test/test.dart';\nimport 'size.dart';\n\nvoid main() {\n  test('should not throw on a size >1Kb', () {\n    expect(() => someFunction(Size(1001)), returnsNormally);\n  });\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_init_to_null", - "name": "Avoid init to null", - "severity": "MINOR", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

\n DON'T\n explicitly initialize variables to \n null\n .\n

\n

\n If a variable has a non-nullable type or is \n final\n ,\nDart reports a compile error if you try to use it\nbefore it has been definitely initialized.\nIf the variable is nullable and not \n const\n or \n final\n ,\nthen it is implicitly initialized to \n null\n for you.\nThere's no concept of \"uninitialized memory\" in Dart\nand no need to explicitly initialize a variable to \n null\n to be \"safe\".\nAdding \n = null\n is redundant and unneeded.\n

\n

\n BAD:\n

\n
\nItem? bestDeal(List<Item> cart) {\n  Item? bestItem = null;\n\n  for (final item in cart) {\n    if (bestItem == null || item.price < bestItem.price) {\n      bestItem = item;\n    }\n  }\n\n  return bestItem;\n}\n\n  
\n

\n GOOD:\n

\n
\nItem? bestDeal(List<Item> cart) {\n  Item? bestItem;\n\n  for (final item in cart) {\n    if (bestItem == null || item.price < bestItem.price) {\n      bestItem = item;\n    }\n  }\n\n  return bestItem;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_js_rounded_ints", - "name": "Avoid js rounded ints", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n integer literals that cannot be represented exactly when compiled to\nJavaScript.\n

\n

\n When a program is compiled to JavaScript \n int\n and \n double\n become JavaScript\nNumbers. Too large integers (\n value < Number.MIN_SAFE_INTEGER\n or\n\n value > Number.MAX_SAFE_INTEGER\n ) may be rounded to the closest Number value.\n

\n

\n For instance \n 1000000000000000001\n cannot be represented exactly as a JavaScript\nNumber, so \n 1000000000000000000\n will be used instead.\n

\n

\n BAD:\n

\n
\nint value = 9007199254740995;\n\n  
\n

\n GOOD:\n

\n
\nBigInt value = BigInt.parse('9007199254740995');\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "avoid_multiple_declarations_per_line", - "name": "Avoid multiple declarations per line", - "severity": "MINOR", - "description": "
\n

\n DON'T\n declare multiple variables on a single line.\n

\n

\n BAD:\n

\n
\nString? foo, bar, baz;\n\n  
\n

\n GOOD:\n

\n
\nString? foo;\nString? bar;\nString? baz;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_null_checks_in_equality_operators", - "name": "Avoid null checks in equality operators", - "severity": "MINOR", - "description": "
\n

\n DON'T\n check for null in custom == operators.\n

\n

\n As null is a special value, no instance of any class (other than \n Null\n ) can be\nequivalent to it. Thus, it is redundant to check whether the other instance is\nnull.\n

\n

\n BAD:\n

\n
\nclass Person {\n  final String? name;\n\n  @override\n  operator ==(Object? other) =>\n      other != null && other is Person && name == other.name;\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Person {\n  final String? name;\n\n  @override\n  operator ==(Object? other) => other is Person && name == other.name;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_positional_boolean_parameters", - "name": "Avoid positional boolean parameters", - "severity": "MINOR", - "description": "
\n

\n AVOID\n positional boolean parameters.\n

\n

Positional boolean parameters are a bad practice because they are very\nambiguous. Using named boolean parameters is much more readable because it\ninherently describes what the boolean value represents.

\n

\n BAD:\n

\n
\nTask(true);\nTask(false);\nListBox(false, true, true);\nButton(false);\n\n  
\n

\n GOOD:\n

\n
\nTask.oneShot();\nTask.repeating();\nListBox(scroll: true, showScrollbars: true);\nButton(ButtonState.enabled);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_private_typedef_functions", - "name": "Avoid private typedef functions", - "severity": "MINOR", - "description": "
\n

\n AVOID\n private typedef functions used only once. Prefer inline function\nsyntax.\n

\n

\n BAD:\n

\n
\ntypedef void _F();\nm(_F f);\n\n  
\n

\n GOOD:\n

\n
\nm(void Function() f);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "10min", - "active": false - }, - { - "key": "avoid_redundant_argument_values", - "name": "Avoid redundant argument values", - "severity": "MINOR", - "description": "
\n

\n DON'T\n pass an argument that matches the corresponding parameter's default\nvalue.\n

\n

\n BAD:\n

\n
\nvoid f({bool valWithDefault = true, bool? val}) {\n  ...\n}\n\nvoid main() {\n  f(valWithDefault: true);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f({bool valWithDefault = true, bool? val}) {\n  ...\n}\n\nvoid main() {\n  f(valWithDefault: false);\n  f();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_renaming_method_parameters", - "name": "Avoid renaming method parameters", - "severity": "MINOR", - "description": "
\n

\n DON'T\n rename parameters of overridden methods.\n

\n

\n Methods that override another method, but do not have their own documentation\ncomment, will inherit the overridden method's comment when \n dart doc\n produces\ndocumentation. If the inherited method contains the name of the parameter (in\nsquare brackets), then \n dart doc\n cannot link it correctly.\n

\n

\n BAD:\n

\n
\nabstract class A {\n  m(a);\n}\n\nabstract class B extends A {\n  m(b);\n}\n\n  
\n

\n GOOD:\n

\n
\nabstract class A {\n  m(a);\n}\n\nabstract class B extends A {\n  m(a);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_return_types_on_setters", - "name": "Avoid return types on setters", - "severity": "MINOR", - "description": "
\n

\n AVOID\n return types on setters.\n

\n

As setters do not return a value, declaring the return type of one is redundant.

\n

\n BAD:\n

\n
\nvoid set speed(int ms);\n\n  
\n

\n GOOD:\n

\n
\nset speed(int ms);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_returning_null_for_void", - "name": "Avoid returning null for void", - "severity": "MINOR", - "description": "
\n

\n AVOID\n returning null for void.\n

\n

\n In a large variety of languages \n void\n as return type is used to indicate that\na function doesn't return anything. Dart allows returning \n null\n in functions\nwith \n void\n return type but it also allow using \n return;\n without specifying any\nvalue. To have a consistent way you should not return \n null\n and only use an\nempty return.\n

\n

\n BAD:\n

\n
\nvoid f1() {\n  return null;\n}\nFuture<void> f2() async {\n  return null;\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f1() {\n  return;\n}\nFuture<void> f2() async {\n  return;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_returning_this", - "name": "Avoid returning this", - "severity": "MINOR", - "description": "
\n

\n AVOID\n returning this from methods just to enable a fluent interface.\n

\n

\n Returning \n this\n from a method is redundant; Dart has a cascade operator which\nallows method chaining universally.\n

\n

\n Returning \n this\n is allowed for:\n

\n \n

\n BAD:\n

\n
\nvar buffer = StringBuffer()\n  .write('one')\n  .write('two')\n  .write('three');\n\n  
\n

\n GOOD:\n

\n
\nvar buffer = StringBuffer()\n  ..write('one')\n  ..write('two')\n  ..write('three');\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_setters_without_getters", - "name": "Avoid setters without getters", - "severity": "MINOR", - "description": "
\n

\n DON'T\n define a setter without a corresponding getter.\n

\n

Defining a setter without defining a corresponding getter can lead to logical\ninconsistencies. Doing this could allow you to set a property to some value,\nbut then upon observing the property's value, it could easily be different.

\n

\n BAD:\n

\n
\nclass Bad {\n  int l, r;\n\n  set length(int newLength) {\n    r = l + newLength;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Good {\n  int l, r;\n\n  int get length => r - l;\n\n  set length(int newLength) {\n    r = l + newLength;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_shadowing_type_parameters", - "name": "Avoid shadowing type parameters", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n shadowing type parameters.\n

\n

\n BAD:\n

\n
\nclass A<T> {\n  void fn<T>() {}\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A<T> {\n  void fn<U>() {}\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_single_cascade_in_expression_statements", - "name": "Avoid single cascade in expression statements", - "severity": "MINOR", - "description": "
\n

\n AVOID\n single cascade in expression statements.\n

\n

\n BAD:\n

\n
\no..m();\n\n  
\n

\n GOOD:\n

\n
\no.m();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "avoid_types_on_closure_parameters", - "name": "Avoid types on closure parameters", - "severity": "MINOR", - "description": "
\n

\n AVOID\n annotating types for function expression parameters.\n

\n

Annotating types for function expression parameters is usually unnecessary\nbecause the parameter types can almost always be inferred from the context,\nthus making the practice redundant.

\n

\n BAD:\n

\n
\nvar names = people.map((Person person) => person.name);\n\n  
\n

\n GOOD:\n

\n
\nvar names = people.map((person) => person.name);\n\n  
\n

\n Incompatible with: \n always_specify_types\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_unnecessary_containers", - "name": "Avoid unnecessary containers", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n wrapping widgets in unnecessary containers.\n

\n

\n Wrapping a widget in \n Container\n with no other parameters set has no effect\nand makes code needlessly more complex.\n

\n

\n BAD:\n

\n
\nWidget buildRow() {\n  return Container(\n      child: Row(\n        children: <Widget>[\n          const MyLogo(),\n          const Expanded(\n            child: Text('...'),\n          ),\n        ],\n      )\n  );\n}\n\n  
\n

\n GOOD:\n

\n
\nWidget buildRow() {\n  return Row(\n    children: <Widget>[\n      const MyLogo(),\n      const Expanded(\n        child: Text('...'),\n      ),\n    ],\n  );\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "avoid_unused_constructor_parameters", - "name": "Avoid unused constructor parameters", - "severity": "MINOR", - "description": "
\n

\n AVOID\n defining unused parameters in constructors.\n

\n

\n BAD:\n

\n
\nclass BadOne {\n  BadOne(int unusedParameter, [String unusedPositional]);\n}\n\nclass BadTwo {\n  int c;\n\n  BadTwo(int a, int b, int x) {\n    c = a + b;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "avoid_void_async", - "name": "Avoid void async", - "severity": "MINOR", - "description": "
\n

\n DO\n mark async functions as returning Future\n .\n

\n

\n When declaring an async method or function which does not return a value,\ndeclare that it returns \n Future<void>\n and not just \n void\n .\n

\n

\n BAD:\n

\n
\nvoid f() async {}\nvoid f2() async => null;\n\n  
\n

\n GOOD:\n

\n
\nFuture<void> f() async {}\nFuture<void> f2() async => null;\n\n  
\n

\n EXCEPTION:\n

\n

\n An exception is made for top-level \n main\n functions, where the \n Future\n annotation \n can\n (and generally should) be dropped in favor of \n void\n .\n

\n

\n GOOD:\n

\n
\nFuture<void> f() async {}\n\nvoid main() async {\n  await f();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "await_only_futures", - "name": "Await only futures", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using await on anything which is not a future.\n

\n

\n Await is allowed on the types: \n Future<X>\n , \n FutureOr<X>\n , \n Future<X>?\n ,\n\n FutureOr<X>?\n and \n dynamic\n .\n

\n

\n Further, using \n await null\n is specifically allowed as a way to introduce a\nmicrotask delay.\n

\n

\n BAD:\n

\n
\nmain() async {\n  print(await 23);\n}\n\n  
\n

\n GOOD:\n

\n
\nmain() async {\n  await null; // If a delay is really intended.\n  print(23);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "camel_case_extensions", - "name": "Camel case extensions", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n DO\n name extensions using \n UpperCamelCase\n .\n

\n

Extensions should capitalize the first letter of each word (including\nthe first word), and use no separators.

\n

\n GOOD:\n

\n
\nextension MyFancyList<T> on List<T> { \n  // ... \n}\n\nextension SmartIterable<T> on Iterable<T> {\n  // ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "camel_case_types", - "name": "Camel case types", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n DO\n name types using UpperCamelCase.\n

\n

Classes and typedefs should capitalize the first letter of each word (including\nthe first word), and use no separators.

\n

\n GOOD:\n

\n
\nclass SliderMenu {\n  // ...\n}\n\nclass HttpRequest {\n  // ...\n}\n\ntypedef num Adder(num x, num y);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "cascade_invocations", - "name": "Cascade invocations", - "severity": "MINOR", - "description": "
\n

\n DO\n Use the cascading style when successively invoking methods on the same\nreference.\n

\n

\n BAD:\n

\n
\nSomeClass someReference = SomeClass();\nsomeReference.firstMethod();\nsomeReference.secondMethod();\n\n  
\n

\n BAD:\n

\n
\nSomeClass someReference = SomeClass();\n...\nsomeReference.firstMethod();\nsomeReference.aProperty = value;\nsomeReference.secondMethod();\n\n  
\n

\n GOOD:\n

\n
\nSomeClass someReference = SomeClass()\n    ..firstMethod()\n    ..aProperty = value\n    ..secondMethod();\n\n  
\n

\n GOOD:\n

\n
\nSomeClass someReference = SomeClass();\n...\nsomeReference\n    ..firstMethod()\n    ..aProperty = value\n    ..secondMethod();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "cast_nullable_to_non_nullable", - "name": "Cast nullable to non nullable", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n cast a nullable value to a non nullable type. This hides a null check\nand most of the time it is not what is expected.\n

\n

\n BAD:\n

\n
\nclass A {}\nclass B extends A {}\n\nA? a;\nvar v = a as B;\nvar v = a as A;\n\n  
\n

\n GOOD:\n

\n
\nclass A {}\nclass B extends A {}\n\nA? a;\nvar v = a! as B;\nvar v = a!;\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "combinators_ordering", - "name": "Combinators ordering", - "severity": "MINOR", - "description": "
\n

\n DO\n sort combinator names alphabetically.\n

\n

\n BAD:\n

\n
\nimport 'a.dart' show B, A hide D, C;\nexport 'a.dart' show B, A hide D, C;\n\n  
\n

\n GOOD:\n

\n
\nimport 'a.dart' show A, B hide C, D;\nexport 'a.dart' show A, B hide C, D;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "conditional_uri_does_not_exist", - "name": "Conditional uri does not exist", - "severity": "BLOCKER", - "description": "
\n

\n DON'T\n reference files that do not exist in conditional imports.\n

\n

Code may fail at runtime if the condition evaluates such that the missing file\nneeds to be imported.

\n

\n BAD:\n

\n
\nimport 'file_that_does_exist.dart'\n  if (condition) 'file_that_does_not_exist.dart';\n\n  
\n

\n GOOD:\n

\n
\nimport 'file_that_does_exist.dart'\n  if (condition) 'file_that_also_does_exist.dart';\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "constant_identifier_names", - "name": "Constant identifier names", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using lowerCamelCase for constant names.\n

\n

\n In new code, use \n lowerCamelCase\n for constant variables, including enum values.\n

\n

\n In existing code that uses \n ALL_CAPS_WITH_UNDERSCORES\n for constants, you may\ncontinue to use all caps to stay consistent.\n

\n

\n BAD:\n

\n
\nconst PI = 3.14;\nconst kDefaultTimeout = 1000;\nfinal URL_SCHEME = RegExp('^([a-z]+):');\n\nclass Dice {\n  static final NUMBER_GENERATOR = Random();\n}\n\n  
\n

\n GOOD:\n

\n
\nconst pi = 3.14;\nconst defaultTimeout = 1000;\nfinal urlScheme = RegExp('^([a-z]+):');\n\nclass Dice {\n  static final numberGenerator = Random();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "curly_braces_in_flow_control_structures", - "name": "Curly braces in flow control structures", - "severity": "MINOR", - "description": "
\n

\n DO\n use curly braces for all flow control structures.\n

\n

\n Doing so avoids the \n dangling else\n problem.\n

\n

\n BAD:\n

\n
\nif (overflowChars != other.overflowChars)\n  return overflowChars < other.overflowChars;\n\n  
\n

\n GOOD:\n

\n
\nif (isWeekDay) {\n  print('Bike to work!');\n} else {\n  print('Go dancing or read a book!');\n}\n\n  
\n

\n There is one exception to this: an \n if\n statement with no \n else\n clause where\nthe entire \n if\n statement and the then body all fit in one line. In that case,\nyou may leave off the braces if you prefer:\n

\n

\n GOOD:\n

\n
\nif (arg == null) return defaultValue;\n\n  
\n

If the body wraps to the next line, though, use braces:

\n

\n GOOD:\n

\n
\nif (overflowChars != other.overflowChars) {\n  return overflowChars < other.overflowChars;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "dangling_library_doc_comments", - "name": "Dangling library doc comments", - "severity": "MINOR", - "description": "
\n

\n Attach library doc comments (with \n ///\n ) to library directives, rather than\nleaving them dangling near the top of a library.\n

\n

\n BAD:\n

\n
\n/// This is a great library.\nimport 'package:math';\n\n  
\n
\n/// This is a great library.\n\nclass C {}\n\n  
\n

\n GOOD:\n

\n
\n/// This is a great library.\nlibrary;\n\nimport 'package:math';\n\nclass C {}\n\n  
\n

\n NOTE:\n An unnamed library, like \n library;\n above, is only supported in Dart\n2.19 and later. Code which might run in earlier versions of Dart will need to\nprovide a name in the \n library\n directive.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "deprecated_consistency", - "name": "Deprecated consistency", - "severity": "MINOR", - "description": "
\n

\n DO\n apply \n @Deprecated()\n consistently:\n

\n \n

\n BAD:\n

\n
\n@deprecated\nclass A {\n  A();\n}\n\nclass B {\n  B({this.field});\n  @deprecated\n  Object field;\n}\n\n  
\n

\n GOOD:\n

\n
\n@deprecated\nclass A {\n  @deprecated\n  A();\n}\n\nclass B {\n  B({@deprecated this.field});\n  @deprecated\n  Object field;\n}\n\nclass C extends B {\n  C({@deprecated super.field});\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "directives_ordering", - "name": "Directives ordering", - "severity": "MINOR", - "description": "
\n

\n DO\n follow the directive ordering conventions in\n\n Effective Dart\n :\n

\n

\n DO\n place \n dart:\n imports before other imports.\n

\n

\n BAD:\n

\n
\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n\nimport 'dart:async';  // LINT\nimport 'dart:html';  // LINT\n\n  
\n

\n BAD:\n

\n
\nimport 'dart:html';  // OK\nimport 'package:bar/bar.dart';\n\nimport 'dart:async';  // LINT\nimport 'package:foo/foo.dart';\n\n  
\n

\n GOOD:\n

\n
\nimport 'dart:async';  // OK\nimport 'dart:html';  // OK\n\nimport 'package:bar/bar.dart';\nimport 'package:foo/foo.dart';\n\n  
\n

\n DO\n place \n package:\n imports before relative imports.\n

\n

\n BAD:\n

\n
\nimport 'a.dart';\nimport 'b.dart';\n\nimport 'package:bar/bar.dart';  // LINT\nimport 'package:foo/foo.dart';  // LINT\n\n  
\n

\n BAD:\n

\n
\nimport 'package:bar/bar.dart';  // OK\nimport 'a.dart';\n\nimport 'package:foo/foo.dart';  // LINT\nimport 'b.dart';\n\n  
\n

\n GOOD:\n

\n
\nimport 'package:bar/bar.dart';  // OK\nimport 'package:foo/foo.dart';  // OK\n\nimport 'a.dart';\nimport 'b.dart';\n\n  
\n

\n DO\n specify exports in a separate section after all imports.\n

\n

\n BAD:\n

\n
\nimport 'src/error.dart';\nexport 'src/error.dart'; // LINT\nimport 'src/string_source.dart';\n\n  
\n

\n GOOD:\n

\n
\nimport 'src/error.dart';\nimport 'src/string_source.dart';\n\nexport 'src/error.dart'; // OK\n\n  
\n

\n DO\n sort sections alphabetically.\n

\n

\n BAD:\n

\n
\nimport 'package:foo/bar.dart'; // OK\nimport 'package:bar/bar.dart'; // LINT\n\nimport 'a/b.dart'; // OK\nimport 'a.dart'; // LINT\n\n  
\n

\n GOOD:\n

\n
\nimport 'package:bar/bar.dart'; // OK\nimport 'package:foo/bar.dart'; // OK\n\nimport 'a.dart'; // OK\nimport 'a/b.dart'; // OK\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "do_not_use_environment", - "name": "Do not use environment", - "severity": "MINOR", - "description": "
\n

Using values derived from the environment at compile-time, creates\nhidden global state and makes applications hard to understand and maintain.

\n

\n DON'T\n use \n fromEnvironment\n or \n hasEnvironment\n factory constructors.\n

\n

\n BAD:\n

\n
\nconst loggingLevel =\n  bool.hasEnvironment('logging') ? String.fromEnvironment('logging') : null;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "empty_catches", - "name": "Empty catches", - "severity": "MAJOR", - "description": "
\n

\n AVOID\n empty catch blocks.\n

\n

\n In general, empty catch blocks should be avoided. In cases where they are\nintended, a comment should be provided to explain why exceptions are being\ncaught and suppressed. Alternatively, the exception identifier can be named with\nunderscores (e.g., \n _\n ) to indicate that we intend to skip it.\n

\n

\n BAD:\n

\n
\ntry {\n  ...\n} catch(exception) { }\n\n  
\n

\n GOOD:\n

\n
\ntry {\n  ...\n} catch(e) {\n  // ignored, really.\n}\n\n// Alternatively:\ntry {\n  ...\n} catch(_) { }\n\n// Better still:\ntry {\n  ...\n} catch(e) {\n  doSomething(e);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "empty_constructor_bodies", - "name": "Empty constructor bodies", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n DO\n use \n ;\n instead of \n {}\n for empty constructor bodies.\n

\n

In Dart, a constructor with an empty body can be terminated with just a\nsemicolon. This is required for const constructors. For consistency and\nbrevity, other constructors should also do this.

\n

\n BAD:\n

\n
\nclass Point {\n  int x, y;\n  Point(this.x, this.y) {}\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Point {\n  int x, y;\n  Point(this.x, this.y);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "enable_null_safety", - "name": "Enable null safety", - "severity": "MINOR", - "description": "
\n

\n Unsupported since Dart language version 2.12.0.\n

\n

\n DO\n use sound null safety, by not specifying a dart version lower than \n 2.12\n .\n

\n

\n BAD:\n

\n
\n// @dart=2.8\na() {\n}\n\n  
\n

\n GOOD:\n

\n
\nb() {\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "eol_at_end_of_file", - "name": "Eol at end of file", - "severity": "MINOR", - "description": "
\n

\n DO\n put a single newline at the end of non-empty files.\n

\n

\n BAD:\n

\n
\na {\n}\n\n  
\n

\n GOOD:\n

\n
\nb {\n}\n    <-- newline\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "exhaustive_cases", - "name": "Exhaustive cases", - "severity": "MAJOR", - "description": "
\n

Switching on instances of enum-like classes should be exhaustive.

\n

Enum-like classes are defined as concrete (non-abstract) classes that have:

\n \n

\n DO\n define case clauses for all constants in enum-like classes.\n

\n

\n BAD:\n

\n
\nclass EnumLike {\n  final int i;\n  const EnumLike._(this.i);\n\n  static const e = EnumLike._(1);\n  static const f = EnumLike._(2);\n  static const g = EnumLike._(3);\n}\n\nvoid bad(EnumLike e) {\n  // Missing case.\n  switch(e) { // LINT\n    case EnumLike.e :\n      print('e');\n      break;\n    case EnumLike.f :\n      print('f');\n      break;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass EnumLike {\n  final int i;\n  const EnumLike._(this.i);\n\n  static const e = EnumLike._(1);\n  static const f = EnumLike._(2);\n  static const g = EnumLike._(3);\n}\n\nvoid ok(EnumLike e) {\n  // All cases covered.\n  switch(e) { // OK\n    case EnumLike.e :\n      print('e');\n      break;\n    case EnumLike.f :\n      print('f');\n      break;\n    case EnumLike.g :\n      print('g');\n      break;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "file_names", - "name": "File names", - "severity": "MINOR", - "description": "
\n

\n DO\n name source files using \n lowercase_with_underscores\n .\n

\n

Some file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.

\n

\n BAD:\n

\n \n

\n GOOD:\n

\n \n

\n Files without a strict \n .dart\n extension are ignored. For example:\n

\n

\n OK:\n

\n \n

\n The lint \n library_names\n can be used to enforce the same kind of naming on the\nlibrary.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "flutter_style_todos", - "name": "Flutter style todos", - "severity": "MINOR", - "description": "
\n

\n DO\n use Flutter TODO format.\n

\n

\n From the \n Flutter docs\n :\n

\n
\n

TODOs should include the string TODO in all caps, followed by the GitHub username of the person with the best context about the problem referenced by the TODO in parenthesis. A TODO is not a commitment that the person referenced will fix the problem, it is intended to be the person with enough context to explain the problem. Thus, when you create a TODO, it is almost always your username that is given.

\n
\n

\n GOOD:\n

\n
\n// TODO(username): message.\n// TODO(username): message, https://URL-to-issue.\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "implementation_imports", - "name": "Implementation imports", - "severity": "MAJOR", - "description": "
\n

\n From the the \n pub package layout doc\n :\n

\n

\n DON'T\n import implementation files from another package.\n

\n

\n The libraries inside \n lib\n are publicly visible: other packages are free to\nimport them. But much of a package's code is internal implementation libraries\nthat should only be imported and used by the package itself. Those go inside a\nsubdirectory of \n lib\n called \n src\n . You can create subdirectories in there if\nit helps you organize things.\n

\n

\n You are free to import libraries that live in \n lib/src\n from within other Dart\ncode in the same package (like other libraries in \n lib\n , scripts in \n bin\n ,\nand tests) but you should never import from another package's \n lib/src\n directory. Those files are not part of the package's public API, and they\nmight change in ways that could break your code.\n

\n

\n BAD:\n

\n
\n// In 'road_runner'\nimport 'package:acme/src/internals.dart';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "implicit_call_tearoffs", - "name": "Implicit call tearoffs", - "severity": "MINOR", - "description": "
\n

\n DO\n Explicitly tear off \n .call\n methods from objects when assigning to a Function\ntype. There is less magic with an explicit tear off. Future language versions\nmay remove the implicit call tear off.\n

\n

\n BAD:\n

\n
\nclass Callable {\n  void call() {}\n}\nvoid callIt(void Function() f) {\n  f();\n}\n\ncallIt(Callable());\n\n  
\n

\n GOOD:\n

\n
\nclass Callable {\n  void call() {}\n}\nvoid callIt(void Function() f) {\n  f();\n}\n\ncallIt(Callable().call);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "join_return_with_assignment", - "name": "Join return with assignment", - "severity": "MINOR", - "description": "
\n

\n DO\n join return statement with assignment when possible.\n

\n

\n BAD:\n

\n
\nclass A {\n  B _lazyInstance;\n  static B get instance {\n    _lazyInstance ??= B(); // LINT\n    return _lazyInstance;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  B _lazyInstance;\n  static B get instance => _lazyInstance ??= B();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "leading_newlines_in_multiline_strings", - "name": "Leading newlines in multiline strings", - "severity": "MINOR", - "description": "
\n

Multiline strings are easier to read when they start with a newline (a newline\nstarting a multiline string is ignored).

\n

\n BAD:\n

\n
\nvar s1 = '''{\n  \"a\": 1,\n  \"b\": 2\n}''';\n\n  
\n

\n GOOD:\n

\n
\nvar s1 = '''\n{\n  \"a\": 1,\n  \"b\": 2\n}''';\n\nvar s2 = '''This one-liner multiline string is ok. It usually allows to escape both ' and \" in the string.''';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "library_annotations", - "name": "Library annotations", - "severity": "MINOR", - "description": "
\n

Attach library annotations to library directives, rather than\nsome other library-level element.

\n

\n BAD:\n

\n
\n@TestOn('browser')\n\nimport 'package:test/test.dart';\n\nvoid main() {}\n\n  
\n

\n GOOD:\n

\n
\n@TestOn('browser')\nlibrary;\n\nimport 'package:test/test.dart';\n\nvoid main() {}\n\n  
\n

\n NOTE:\n An unnamed library, like \n library;\n above, is only supported in Dart\n2.19 and later. Code which might run in earlier versions of Dart will need to\nprovide a name in the \n library\n directive.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "library_names", - "name": "Library names", - "severity": "MINOR", - "description": "
\n

\n DO\n name libraries using \n lowercase_with_underscores\n .\n

\n

Some file systems are not case-sensitive, so many projects require filenames to\nbe all lowercase. Using a separating character allows names to still be readable\nin that form. Using underscores as the separator ensures that the name is still\na valid Dart identifier, which may be helpful if the language later supports\nsymbolic imports.

\n

\n BAD:\n

\n
\nlibrary peg-parser;\n\n  
\n

\n GOOD:\n

\n
\nlibrary peg_parser;\n\n  
\n

\n The lint \n file_names\n can be used to enforce the same kind of naming on the\nfile.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "library_prefixes", - "name": "Library prefixes", - "severity": "MINOR", - "description": "
\n

\n DO\n use \n lowercase_with_underscores\n when specifying a library prefix.\n

\n

\n BAD:\n

\n
\nimport 'dart:math' as Math;\nimport 'dart:json' as JSON;\nimport 'package:js/js.dart' as JS;\nimport 'package:javascript_utils/javascript_utils.dart' as jsUtils;\n\n  
\n

\n GOOD:\n

\n
\nimport 'dart:math' as math;\nimport 'dart:json' as json;\nimport 'package:js/js.dart' as js;\nimport 'package:javascript_utils/javascript_utils.dart' as js_utils;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "library_private_types_in_public_api", - "name": "Library private types in public api", - "severity": "CRITICAL", - "description": "
\n

\n AVOID\n using library private types in public APIs.\n

\n

For the purposes of this lint, a public API is considered to be any top-level or\nmember declaration unless the declaration is library private or contained in a\ndeclaration that's library private. The following uses of types are checked:

\n \n

\n BAD:\n

\n
\nf(_Private p) { ... }\nclass _Private {}\n\n  
\n

\n GOOD:\n

\n
\nf(String s) { ... }\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "15min", - "active": true - }, - { - "key": "lines_longer_than_80_chars", - "name": "Lines longer than 80 chars", - "severity": "MINOR", - "description": "
\n

\n AVOID\n lines longer than 80 characters\n

\n

Readability studies show that long lines of text are harder to read because your\neye has to travel farther when moving to the beginning of the next line. This is\nwhy newspapers and magazines use multiple columns of text.

\n

\n If you really find yourself wanting lines longer than 80 characters, our\nexperience is that your code is likely too verbose and could be a little more\ncompact. The main offender is usually \n VeryLongCamelCaseClassNames\n . Ask\nyourself, \u201cDoes each word in that type name tell me something critical or\nprevent a name collision?\u201d If not, consider omitting it.\n

\n

\n Note that \n dart format\n does 99% of this for you, but the last 1% is you. It\ndoes not split long string literals to fit in 80 columns, so you have to do\nthat manually.\n

\n

We make an exception for URIs and file paths. When those occur in comments or\nstrings (usually in imports and exports), they may remain on a single line even\nif they go over the line limit. This makes it easier to search source files for\na given path.

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "matching_super_parameters", - "name": "Matching super parameters", - "severity": "MINOR", - "description": "
\n

\n DO\n use super parameter names that match their corresponding super\nconstructor's parameter names.\n

\n

\n BAD:\n

\n
\nclass Rectangle {\n  final int width;\n  final int height;\n  \n  Rectangle(this.width, this.height);\n}\n\nclass ColoredRectangle extends Rectangle {\n  final Color color;\n  \n  ColoredRectangle(\n    this.color,\n    super.height, // Bad, actually corresponds to the `width` parameter.\n    super.width, // Bad, actually corresponds to the `height` parameter.\n  ); \n}\n\n  
\n

\n GOOD:\n

\n
\nclass Rectangle {\n  final int width;\n  final int height;\n  \n  Rectangle(this.width, this.height);\n}\n\nclass ColoredRectangle extends Rectangle {\n  final Color color;\n  \n  ColoredRectangle(\n    this.color,\n    super.width,\n    super.height, \n  ); \n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "missing_whitespace_between_adjacent_strings", - "name": "Missing whitespace between adjacent strings", - "severity": "MINOR", - "description": "
\n

Add a trailing whitespace to prevent missing whitespace between adjacent\nstrings.

\n

With long text split across adjacent strings it's easy to forget a whitespace\nbetween strings.

\n

\n BAD:\n

\n
\nvar s =\n  'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed'\n  'do eiusmod tempor incididunt ut labore et dolore magna';\n\n  
\n

\n GOOD:\n

\n
\nvar s =\n  'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed '\n  'do eiusmod tempor incididunt ut labore et dolore magna';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "no_default_cases", - "name": "No default cases", - "severity": "MAJOR", - "description": "
\n

\n Switches on enums and enum-like classes should not use a \n default\n clause.\n

\n

Enum-like classes are defined as concrete (non-abstract) classes that have:

\n \n

\n DO\n define default behavior outside switch statements.\n

\n

\n BAD:\n

\n
\n  switch (testEnum) {\n    case TestEnum.A:\n      return '123';\n    case TestEnum.B:\n      return 'abc';\n    default:\n      return null;\n  }\n\n  
\n

\n GOOD:\n

\n
\n  switch (testEnum) {\n    case TestEnum.A:\n      return '123';\n    case TestEnum.B:\n      return 'abc';\n  }\n  // Default here.\n  return null;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "no_leading_underscores_for_library_prefixes", - "name": "No leading underscores for library prefixes", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use a leading underscore for library prefixes.\nThere is no concept of \"private\" for library prefixes. When one of those has a\nname that starts with an underscore, it sends a confusing signal to the reader.\nTo avoid that, don't use leading underscores in those names.\n

\n

\n BAD:\n

\n
\nimport 'dart:core' as _core;\n\n  
\n

\n GOOD:\n

\n
\nimport 'dart:core' as core;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "no_leading_underscores_for_local_identifiers", - "name": "No leading underscores for local identifiers", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use a leading underscore for identifiers that aren't private. Dart\nuses a leading underscore in an identifier to mark members and top-level\ndeclarations as private. This trains users to associate a leading underscore\nwith one of those kinds of declarations. They see \n _\n and think \"private\".\nThere is no concept of \"private\" for local variables or parameters. When one of\nthose has a name that starts with an underscore, it sends a confusing signal to\nthe reader. To avoid that, don't use leading underscores in those names.\n

\n

\n EXCEPTION:\n : An unused parameter can be named \n _\n , \n __\n , \n ___\n , etc. This is\ncommon practice in callbacks where you are passed a value but you don't need\nto use it. Giving it a name that consists solely of underscores is the idiomatic\nway to indicate that the value isn't used.\n

\n

\n BAD:\n

\n
\nvoid print(String _name) {\n  var _size = _name.length;\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid print(String name) {\n  var size = name.length;\n  ...\n}\n\n  
\n

\n OK:\n

\n
\n[1,2,3].map((_) => print('Hello'));\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "no_literal_bool_comparisons", - "name": "No literal bool comparisons", - "severity": "MINOR", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

\n DON'T\n use \n true\n or \n false\n in equality operations.\n

\n

\n This lint applies only if the expression is of a non-nullable \n bool\n type.\n

\n

\n BAD:\n

\n
\nif (someBool == true) {\n}\nwhile (someBool == false) {\n}\n\n  
\n

\n GOOD:\n

\n
\nif (someBool) {\n}\nwhile (!someBool) {\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "no_runtimeType_toString", - "name": "No runtimeType toString", - "severity": "MAJOR", - "description": "
\n

\n Calling \n toString\n on a runtime type is a non-trivial operation that can\nnegatively impact performance. It's better to avoid it.\n

\n

\n BAD:\n

\n
\nclass A {\n  String toString() => '$runtimeType()';\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  String toString() => 'A()';\n}\n\n  
\n

This lint has some exceptions where performance is not a problem or where real\ntype information is more important than performance:

\n \n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "non_constant_identifier_names", - "name": "Non constant identifier names", - "severity": "MINOR", - "description": "
\n

\n DO\n name non-constant identifiers using lowerCamelCase.\n

\n

Class members, top-level definitions, variables, parameters, named parameters\nand named constructors should capitalize the first letter of each word\nexcept the first word, and use no separators.

\n

\n GOOD:\n

\n
\nvar item;\n\nHttpRequest httpRequest;\n\nalign(clearItems) {\n  // ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "noop_primitive_operations", - "name": "Noop primitive operations", - "severity": "MAJOR", - "description": "
\n

Some operations on primitive types are idempotent and can be removed.

\n

\n BAD:\n

\n
\ndoubleValue.toDouble();\n\nintValue.toInt();\nintValue.round();\nintValue.ceil();\nintValue.floor();\nintValue.truncate();\n\nstring.toString();\nstring = 'hello\\n'\n    'world\\n'\n    ''; // useless empty string\n\n'string with ${x.toString()}';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "null_check_on_nullable_type_parameter", - "name": "Null check on nullable type parameter", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n use null check on a potentially nullable type parameter.\n

\n

\n Given a generic type parameter \n T\n which has a nullable bound (e.g. the default\nbound of \n Object?\n ), it is very easy to introduce erroneous null checks when\nworking with a variable of type \n T?\n . Specifically, it is not uncommon to have\n\n T? x;\n and want to assert that \n x\n has been set to a valid value of type \n T\n .\nA common mistake is to do so using \n x!\n . This is almost always incorrect, since\nif \n T\n is a nullable type, \n x\n may validly hold \n null\n as a value of type \n T\n .\n

\n

\n BAD:\n

\n
\nT run<T>(T callback()) {\n  T? result;\n   (() { result = callback(); })();\n  return result!;\n}\n\n  
\n

\n GOOD:\n

\n
\nT run<T>(T callback()) {\n  T? result;\n   (() { result = callback(); })();\n  return result as T;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "null_closures", - "name": "Null closures", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n pass \n null\n as an argument where a closure is expected.\n

\n

\n Often a closure that is passed to a method will only be called conditionally,\nso that tests and \"happy path\" production calls do not reveal that \n null\n will\nresult in an exception being thrown.\n

\n

This rule only catches null literals being passed where closures are expected\nin the following locations:

\n

Constructors

\n \n

Static functions

\n \n

Instance methods

\n \n

\n BAD:\n

\n
\n[1, 3, 5].firstWhere((e) => e.isOdd, orElse: null);\n\n  
\n

\n GOOD:\n

\n
\n[1, 3, 5].firstWhere((e) => e.isOdd, orElse: () => null);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "omit_local_variable_types", - "name": "Omit local variable types", - "severity": "MINOR", - "description": "
\n

\n DON'T\n redundantly type annotate initialized local variables.\n

\n

\n Local variables, especially in modern code where functions tend to be small,\nhave very little scope. Omitting the type focuses the reader's attention on the\nmore important \n name\n of the variable and its initialized value.\n

\n

\n BAD:\n

\n
\nList<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {\n  List<List<Ingredient>> desserts = <List<Ingredient>>[];\n  for (final List<Ingredient> recipe in cookbook) {\n    if (pantry.containsAll(recipe)) {\n      desserts.add(recipe);\n    }\n  }\n\n  return desserts;\n}\n\n  
\n

\n GOOD:\n

\n
\nList<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {\n  var desserts = <List<Ingredient>>[];\n  for (final recipe in cookbook) {\n    if (pantry.containsAll(recipe)) {\n      desserts.add(recipe);\n    }\n  }\n\n  return desserts;\n}\n\n  
\n

Sometimes the inferred type is not the type you want the variable to have. For\nexample, you may intend to assign values of other types later. In that case,\nannotate the variable with the type you want.

\n

\n GOOD:\n

\n
\nWidget build(BuildContext context) {\n  Widget result = Text('You won!');\n  if (applyPadding) {\n    result = Padding(padding: EdgeInsets.all(8.0), child: result);\n  }\n  return result;\n}\n\n  
\n

\n Incompatible with: \n always_specify_types\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "one_member_abstracts", - "name": "One member abstracts", - "severity": "MAJOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n AVOID\n defining a one-member abstract class when a simple function will do.\n

\n

\n Unlike Java, Dart has first-class functions, closures, and a nice light syntax\nfor using them. If all you need is something like a callback, just use a\nfunction. If you're defining a class and it only has a single abstract member\nwith a meaningless name like \n call\n or \n invoke\n , there is a good chance\nyou just want a function.\n

\n

\n BAD:\n

\n
\nabstract class Predicate {\n  bool test(item);\n}\n\n  
\n

\n GOOD:\n

\n
\ntypedef Predicate = bool Function(item);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "only_throw_errors", - "name": "Only throw errors", - "severity": "MAJOR", - "description": "
\n

\n DO\n throw only instances of classes that extend \n dart.core.Error\n or\n\n dart.core.Exception\n .\n

\n

\n Throwing instances that do not extend \n Error\n or \n Exception\n is a bad practice;\ndoing this is usually a hack for something that should be implemented more\nthoroughly.\n

\n

\n BAD:\n

\n
\nvoid throwString() {\n  throw 'hello world!'; // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid throwArgumentError() {\n  Error error = ArgumentError('oh!');\n  throw error; // OK\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "overridden_fields", - "name": "Overridden fields", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n override fields.\n

\n

Overriding fields is almost always done unintentionally. Regardless, it is a\nbad practice to do so.

\n

\n BAD:\n

\n
\nclass Base {\n  Object field = 'lorem';\n\n  Object something = 'change';\n}\n\nclass Bad1 extends Base {\n  @override\n  final field = 'ipsum'; // LINT\n}\n\nclass Bad2 extends Base {\n  @override\n  Object something = 'done'; // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Base {\n  Object field = 'lorem';\n\n  Object something = 'change';\n}\n\nclass Ok extends Base {\n  Object newField; // OK\n\n  final Object newFinal = 'ignore'; // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nabstract class BaseLoggingHandler {\n  Base transformer;\n}\n\nclass LogPrintHandler implements BaseLoggingHandler {\n  @override\n  Derived transformer; // OK\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "package_api_docs", - "name": "Package api docs", - "severity": "INFO", - "description": "
\n

\n DO\n provide doc comments for all public APIs.\n

\n

\n As described in the \n pub package layout doc\n ,\npublic APIs consist in everything in your package's \n lib\n folder, minus\nimplementation files in \n lib/src\n , adding elements explicitly exported with an\n\n export\n directive.\n

\n

\n For example, given \n lib/foo.dart\n :\n

\n
\nexport 'src/bar.dart' show Bar;\nexport 'src/baz.dart';\n\nclass Foo { }\n\nclass _Foo { }\n\n  
\n

its API includes:

\n \n

\n All public API members should be documented with \n ///\n doc-style comments.\n

\n

\n BAD:\n

\n
\nclass Bar {\n  void bar();\n}\n\n  
\n

\n GOOD:\n

\n
\n/// A Foo.\nabstract class Foo {\n  /// Start foo-ing.\n  void start() => _start();\n\n  _start();\n}\n\n  
\n

\n Advice for writing good doc comments can be found in the\n\n Doc Writing Guidelines\n .\n

\n
\n", - "type": "CODE_SMELL", - "debt": "10min", - "active": false - }, - { - "key": "package_prefixed_library_names", - "name": "Package prefixed library names", - "severity": "MAJOR", - "description": "
\n

\n DO\n prefix library names with the package name and a dot-separated path.\n

\n

This guideline helps avoid the warnings you get when two libraries have the same\nname. Here are the rules we recommend:

\n \n

\n For example, say the package name is \n my_package\n . Here are the library names\nfor various files in the package:\n

\n

\n GOOD:\n

\n
\n// In lib/my_package.dart\nlibrary my_package;\n\n// In lib/other.dart\nlibrary my_package.other;\n\n// In lib/foo/bar.dart\nlibrary my_package.foo.bar;\n\n// In example/foo/bar.dart\nlibrary my_package.example.foo.bar;\n\n// In lib/src/private.dart\nlibrary my_package.src.private;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "parameter_assignments", - "name": "Parameter assignments", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n assign new values to parameters of methods or functions.\n

\n

\n Assigning new values to parameters is generally a bad practice unless an\noperator such as \n ??=\n is used. Otherwise, arbitrarily reassigning parameters\nis usually a mistake.\n

\n

\n BAD:\n

\n
\nvoid badFunction(int parameter) { // LINT\n  parameter = 4;\n}\n\n  
\n

\n BAD:\n

\n
\nvoid badFunction(int required, {int optional: 42}) { // LINT\n  optional ??= 8;\n}\n\n  
\n

\n BAD:\n

\n
\nvoid badFunctionPositional(int required, [int optional = 42]) { // LINT\n  optional ??= 8;\n}\n\n  
\n

\n BAD:\n

\n
\nclass A {\n  void badMethod(int parameter) { // LINT\n    parameter = 4;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid ok(String parameter) {\n  print(parameter);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid actuallyGood(int required, {int optional}) { // OK\n  optional ??= ...;\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid actuallyGoodPositional(int required, [int optional]) { // OK\n  optional ??= ...;\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  void ok(String parameter) {\n    print(parameter);\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_adjacent_string_concatenation", - "name": "Prefer adjacent string concatenation", - "severity": "MINOR", - "description": "
\n

\n DO\n use adjacent strings to concatenate string literals.\n

\n

\n BAD:\n

\n
\nraiseAlarm(\n    'ERROR: Parts of the spaceship are on fire. Other ' +\n    'parts are overrun by martians. Unclear which are which.');\n\n  
\n

\n GOOD:\n

\n
\nraiseAlarm(\n    'ERROR: Parts of the spaceship are on fire. Other '\n    'parts are overrun by martians. Unclear which are which.');\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_asserts_in_initializer_lists", - "name": "Prefer asserts in initializer lists", - "severity": "MINOR", - "description": "
\n

\n DO\n put asserts in initializer lists.\n

\n

\n BAD:\n

\n
\nclass A {\n  A(int a) {\n    assert(a != 0);\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  A(int a) : assert(a != 0);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_asserts_with_message", - "name": "Prefer asserts with message", - "severity": "MINOR", - "description": "
\n

\n When assertions fail it's not always simple to understand why. Adding a message\nto the \n assert\n helps the developer to understand why the AssertionError occurs.\n

\n

\n BAD:\n

\n
\nf(a) {\n  assert(a != null);\n}\n\nclass A {\n  A(a) : assert(a != null);\n}\n\n  
\n

\n GOOD:\n

\n
\nf(a) {\n  assert(a != null, 'a must not be null');\n}\n\nclass A {\n  A(a) : assert(a != null, 'a must not be null');\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_bool_in_asserts", - "name": "Prefer bool in asserts", - "severity": "MINOR", - "description": "
\n

\n Unsupported since Dart language version 3.0.0.\n

\n

\n DO\n use a boolean for assert conditions.\n

\n

Not using booleans in assert conditions can lead to code where it isn't clear\nwhat the intention of the assert statement is.

\n

\n BAD:\n

\n
\nassert(() {\n  f();\n  return true;\n});\n\n  
\n

\n GOOD:\n

\n
\nassert(() {\n  f();\n  return true;\n}());\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_collection_literals", - "name": "Prefer collection literals", - "severity": "MINOR", - "description": "
\n

\n DO\n use collection literals when possible.\n

\n

\n BAD:\n

\n
\nvar addresses = Map<String, String>();\nvar uniqueNames = Set<String>();\nvar ids = LinkedHashSet<int>();\nvar coordinates = LinkedHashMap<int, int>();\n\n  
\n

\n GOOD:\n

\n
\nvar addresses = <String, String>{};\nvar uniqueNames = <String>{};\nvar ids = <int>{};\nvar coordinates = <int, int>{};\n\n  
\n

\n EXCEPTIONS:\n

\n

\n There are cases with \n LinkedHashSet\n or \n LinkedHashMap\n where a literal constructor\nwill trigger a type error so those will be excluded from the lint.\n

\n
\nvoid main() {\n  LinkedHashSet<int> linkedHashSet =  LinkedHashSet.from([1, 2, 3]); // OK\n  LinkedHashMap linkedHashMap = LinkedHashMap(); // OK\n  \n  printSet(LinkedHashSet<int>()); // LINT\n  printHashSet(LinkedHashSet<int>()); // OK\n\n  printMap(LinkedHashMap<int, int>()); // LINT\n  printHashMap(LinkedHashMap<int, int>()); // OK\n}\n\nvoid printSet(Set<int> ids) => print('$ids!');\nvoid printHashSet(LinkedHashSet<int> ids) => printSet(ids);\nvoid printMap(Map map) => print('$map!');\nvoid printHashMap(LinkedHashMap map) => printMap(map);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_conditional_assignment", - "name": "Prefer conditional assignment", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using \n ??=\n over testing for null.\n

\n

\n As Dart has the \n ??=\n operator, it is advisable to use it where applicable to\nimprove the brevity of your code.\n

\n

\n BAD:\n

\n
\nString get fullName {\n  if (_fullName == null) {\n    _fullName = getFullUserName(this);\n  }\n  return _fullName;\n}\n\n  
\n

\n GOOD:\n

\n
\nString get fullName {\n  return _fullName ??= getFullUserName(this);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_const_constructors", - "name": "Prefer const constructors", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using \n const\n for instantiating constant constructors.\n

\n

If a constructor can be invoked as const to produce a canonicalized instance,\nit's preferable to do so.

\n

\n BAD:\n

\n
\nclass A {\n  const A();\n}\n\nvoid accessA() {\n  A a = new A();\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  const A();\n}\n\nvoid accessA() {\n  A a = const A();\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  final int x;\n\n  const A(this.x);\n}\n\nA foo(int x) => new A(x);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_const_constructors_in_immutables", - "name": "Prefer const constructors in immutables", - "severity": "MINOR", - "description": "
\n

\n PREFER\n declaring const constructors on \n @immutable\n classes.\n

\n

If a class is immutable, it is usually a good idea to make its constructor a\nconst constructor.

\n

\n BAD:\n

\n
\n@immutable\nclass A {\n  final a;\n  A(this.a);\n}\n\n  
\n

\n GOOD:\n

\n
\n@immutable\nclass A {\n  final a;\n  const A(this.a);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_const_declarations", - "name": "Prefer const declarations", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using \n const\n for const declarations.\n

\n

Const declarations are more hot-reload friendly and allow to use const\nconstructors if an instantiation references this declaration.

\n

\n BAD:\n

\n
\nfinal o = const <int>[];\n\nclass A {\n  static final o = const <int>[];\n}\n\n  
\n

\n GOOD:\n

\n
\nconst o = <int>[];\n\nclass A {\n  static const o = <int>[];\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_const_literals_to_create_immutables", - "name": "Prefer const literals to create immutables", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using \n const\n for instantiating list, map and set literals used as\nparameters in immutable class instantiations.\n

\n

\n BAD:\n

\n
\n@immutable\nclass A {\n  A(this.v);\n  final v;\n}\n\nA a1 = new A([1]);\nA a2 = new A({});\n\n  
\n

\n GOOD:\n

\n
\nA a1 = new A(const [1]);\nA a2 = new A(const {});\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_constructors_over_static_methods", - "name": "Prefer constructors over static methods", - "severity": "MINOR", - "description": "
\n

\n PREFER\n defining constructors instead of static methods to create instances.\n

\n

In most cases, it makes more sense to use a named constructor rather than a\nstatic method because it makes instantiation clearer.

\n

\n BAD:\n

\n
\nclass Point {\n  num x, y;\n  Point(this.x, this.y);\n  static Point polar(num theta, num radius) {\n    return Point(radius * math.cos(theta),\n        radius * math.sin(theta));\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Point {\n  num x, y;\n  Point(this.x, this.y);\n  Point.polar(num theta, num radius)\n      : x = radius * math.cos(theta),\n        y = radius * math.sin(theta);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "prefer_contains", - "name": "Prefer contains", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use \n indexOf\n to see if a collection contains an element.\n

\n

\n Calling \n indexOf\n to see if a collection contains something is difficult to read\nand may have poor performance.\n

\n

\n Instead, prefer \n contains\n .\n

\n

\n BAD:\n

\n
\nif (lunchBox.indexOf('sandwich') == -1) return 'so hungry...';\n\n  
\n

\n GOOD:\n

\n
\nif (!lunchBox.contains('sandwich')) return 'so hungry...';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_double_quotes", - "name": "Prefer double quotes", - "severity": "MINOR", - "description": "
\n

\n DO\n use double quotes where they wouldn't require additional escapes.\n

\n

That means strings with a double quote may use apostrophes so that the double\nquote isn't escaped (note: we don't lint the other way around, ie, a double\nquoted string with an escaped double quote is not flagged).

\n

It's also rare, but possible, to have strings within string interpolations. In\nthis case, its much more readable to use a single quote somewhere. So single\nquotes are allowed either within, or containing, an interpolated string literal.\nArguably strings within string interpolations should be its own type of lint.

\n

\n BAD:\n

\n
\nuseStrings(\n    'should be double quote',\n    r'should be double quote',\n    r'''should be double quotes''')\n\n  
\n

\n GOOD:\n

\n
\nuseStrings(\n    \"should be double quote\",\n    r\"should be double quote\",\n    r\"\"\"should be double quotes\"\"\",\n    'ok with \" inside',\n    'nested ${a ? \"strings\" : \"can\"} be wrapped by a double quote',\n    \"and nested ${a ? 'strings' : 'can be double quoted themselves'}\");\n\n  
\n

\n Incompatible with: \n prefer_single_quotes\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_equal_for_default_values", - "name": "Prefer equal for default values", - "severity": "MINOR", - "description": "
\n

\n Unsupported since Dart language version 3.0.0.\n

\n

\n From the \n style guide\n :\n

\n

\n DO\n use \n =\n to separate a named parameter from its default value.\n

\n

\n BAD:\n

\n
\nm({a: 1})\n\n  
\n

\n GOOD:\n

\n
\nm({a = 1})\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_expression_function_bodies", - "name": "Prefer expression function bodies", - "severity": "MINOR", - "description": "
\n

\n CONSIDER\n using => for short members whose body is a single return statement.\n

\n

\n BAD:\n

\n
\nget width {\n  return right - left;\n}\n\n  
\n

\n BAD:\n

\n
\nbool ready(num time) {\n  return minTime == null || minTime <= time;\n}\n\n  
\n

\n BAD:\n

\n
\ncontainsValue(String value) {\n  return getValues().contains(value);\n}\n\n  
\n

\n GOOD:\n

\n
\nget width => right - left;\n\n  
\n

\n GOOD:\n

\n
\nbool ready(num time) => minTime == null || minTime <= time;\n\n  
\n

\n GOOD:\n

\n
\ncontainsValue(String value) => getValues().contains(value);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_final_fields", - "name": "Prefer final fields", - "severity": "MAJOR", - "description": "
\n

\n DO\n prefer declaring private fields as final if they are not reassigned later\nin the library.\n

\n

Declaring fields as final when possible is a good practice because it helps\navoid accidental reassignments and allows the compiler to do optimizations.

\n

\n BAD:\n

\n
\nclass BadImmutable {\n  var _label = 'hola mundo! BadImmutable'; // LINT\n  var label = 'hola mundo! BadImmutable'; // OK\n}\n\n  
\n

\n BAD:\n

\n
\nclass MultipleMutable {\n  var _label = 'hola mundo! GoodMutable', _offender = 'mumble mumble!'; // LINT\n  var _someOther; // LINT\n\n  MultipleMutable() : _someOther = 5;\n\n  MultipleMutable(this._someOther);\n\n  void changeLabel() {\n    _label= 'hello world! GoodMutable';\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass GoodImmutable {\n  final label = 'hola mundo! BadImmutable', bla = 5; // OK\n  final _label = 'hola mundo! BadImmutable', _bla = 5; // OK\n}\n\n  
\n

\n GOOD:\n

\n
\nclass GoodMutable {\n  var _label = 'hola mundo! GoodMutable';\n\n  void changeLabel() {\n    _label = 'hello world! GoodMutable';\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nclass AssignedInAllConstructors {\n  var _label; // LINT\n  AssignedInAllConstructors(this._label);\n  AssignedInAllConstructors.withDefault() : _label = 'Hello';\n}\n\n  
\n

\n GOOD:\n

\n
\nclass NotAssignedInAllConstructors {\n  var _label; // OK\n  NotAssignedInAllConstructors();\n  NotAssignedInAllConstructors.withDefault() : _label = 'Hello';\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_final_in_for_each", - "name": "Prefer final in for each", - "severity": "MAJOR", - "description": "
\n

\n DO\n prefer declaring for-each loop variables as final if they are not\nreassigned later in the code.\n

\n

Declaring for-each loop variables as final when possible is a good practice\nbecause it helps avoid accidental reassignments and allows the compiler to do\noptimizations.

\n

\n BAD:\n

\n
\nfor (var element in elements) { // LINT\n  print('Element: $element');\n}\n\n  
\n

\n GOOD:\n

\n
\nfor (final element in elements) {\n  print('Element: $element');\n}\n\n  
\n

\n GOOD:\n

\n
\nfor (var element in elements) {\n  element = element + element;\n  print('Element: $element');\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_final_locals", - "name": "Prefer final locals", - "severity": "MAJOR", - "description": "
\n

\n DO\n prefer declaring variables as final if they are not reassigned later in\nthe code.\n

\n

Declaring variables as final when possible is a good practice because it helps\navoid accidental reassignments and allows the compiler to do optimizations.

\n

\n BAD:\n

\n
\nvoid badMethod() {\n  var label = 'hola mundo! badMethod'; // LINT\n  print(label);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid goodMethod() {\n  final label = 'hola mundo! goodMethod';\n  print(label);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid mutableCase() {\n  var label = 'hola mundo! mutableCase';\n  print(label);\n  label = 'hello world';\n  print(label);\n}\n\n  
\n

\n Incompatible with: \n unnecessary_final\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_final_parameters", - "name": "Prefer final parameters", - "severity": "MAJOR", - "description": "
\n

\n DO\n prefer declaring parameters as final if they are not reassigned in\nthe function body.\n

\n

Declaring parameters as final when possible is a good practice because it helps\navoid accidental reassignments.

\n

\n BAD:\n

\n
\nvoid badParameter(String label) { // LINT\n  print(label);\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid goodParameter(final String label) { // OK\n  print(label);\n}\n\n  
\n

\n BAD:\n

\n
\nvoid badExpression(int value) => print(value); // LINT\n\n  
\n

\n GOOD:\n

\n
\nvoid goodExpression(final int value) => print(value); // OK\n\n  
\n

\n BAD:\n

\n
\n[1, 4, 6, 8].forEach((value) => print(value + 2)); // LINT\n\n  
\n

\n GOOD:\n

\n
\n[1, 4, 6, 8].forEach((final value) => print(value + 2)); // OK\n\n  
\n

\n GOOD:\n

\n
\nvoid mutableParameter(String label) { // OK\n  print(label);\n  label = 'Hello Linter!';\n  print(label);\n}\n\n  
\n

\n Incompatible with: \n unnecessary_final\n , \n avoid_final_parameters\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_for_elements_to_map_fromIterable", - "name": "Prefer for elements to map fromIterable", - "severity": "MAJOR", - "description": "
\n

When building maps from iterables, it is preferable to use 'for' elements.

\n

Using 'for' elements brings several benefits including:

\n \n

\n BAD:\n

\n
\nMap<String, WidgetBuilder>.fromIterable(\n  kAllGalleryDemos,\n  key: (demo) => '${demo.routeName}',\n  value: (demo) => demo.buildRoute,\n);\n\n\n  
\n

\n GOOD:\n

\n
\nreturn {\n  for (var demo in kAllGalleryDemos)\n    '${demo.routeName}': demo.buildRoute,\n};\n\n  
\n

\n GOOD:\n

\n
\n// Map<int, Student> is not required, type is inferred automatically.\nfinal pizzaRecipients = {\n  ...studentLeaders,\n  for (var student in classG)\n    if (student.isPassing) student.id: student,\n};\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "prefer_foreach", - "name": "Prefer foreach", - "severity": "MINOR", - "description": "
\n

\n DO\n use \n forEach\n if you are only going to apply a function or a method\nto all the elements of an iterable.\n

\n

\n Using \n forEach\n when you are only going to apply a function or method to all\nelements of an iterable is a good practice because it makes your code more\nterse.\n

\n

\n BAD:\n

\n
\nfor (final key in map.keys.toList()) {\n  map.remove(key);\n}\n\n  
\n

\n GOOD:\n

\n
\nmap.keys.toList().forEach(map.remove);\n\n  
\n

\n NOTE:\n Replacing a for each statement with a forEach call may change the\nbehavior in the case where there are side-effects on the iterable itself.\n

\n
\nfor (final v in myList) {\n  foo().f(v); // This code invokes foo() many times.\n}\n\nmyList.forEach(foo().f); // But this one invokes foo() just once.\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_function_declarations_over_variables", - "name": "Prefer function declarations over variables", - "severity": "MINOR", - "description": "
\n

\n DO\n use a function declaration to bind a function to a name.\n

\n

As Dart allows local function declarations, it is a good practice to use them in\nthe place of function literals.

\n

\n BAD:\n

\n
\nvoid main() {\n  var localFunction = () {\n    ...\n  };\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid main() {\n  localFunction() {\n    ...\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_generic_function_type_aliases", - "name": "Prefer generic function type aliases", - "severity": "MINOR", - "description": "
\n

\n PREFER\n generic function type aliases.\n

\n

\n With the introduction of generic functions, function type aliases\n(\n typedef void F()\n ) couldn't express all of the possible kinds of\nparameterization that users might want to express. Generic function type aliases\n(\n typedef F = void Function()\n ) fixed that issue.\n

\n

For consistency and readability reasons, it's better to only use one syntax and\nthus prefer generic function type aliases.

\n

\n BAD:\n

\n
\ntypedef void F();\n\n  
\n

\n GOOD:\n

\n
\ntypedef F = void Function();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "prefer_if_elements_to_conditional_expressions", - "name": "Prefer if elements to conditional expressions", - "severity": "MINOR", - "description": "
\n

\n When building collections, it is preferable to use \n if\n elements rather than\nconditionals.\n

\n

\n BAD:\n

\n
\nvar list = ['a', 'b', condition ? 'c' : null].where((e) => e != null).toList();\n\n  
\n

\n GOOD:\n

\n
\nvar list = ['a', 'b', if (condition) 'c'];\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_if_null_operators", - "name": "Prefer if null operators", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using if null operators instead of null checks in conditional\nexpressions.\n

\n

\n BAD:\n

\n
\nv = a == null ? b : a;\n\n  
\n

\n GOOD:\n

\n
\nv = a ?? b;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_initializing_formals", - "name": "Prefer initializing formals", - "severity": "MINOR", - "description": "
\n

\n DO\n use initializing formals when possible.\n

\n

Using initializing formals when possible makes your code more terse.

\n

\n BAD:\n

\n
\nclass Point {\n  num x, y;\n  Point(num x, num y) {\n    this.x = x;\n    this.y = y;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Point {\n  num x, y;\n  Point(this.x, this.y);\n}\n\n  
\n

\n BAD:\n

\n
\nclass Point {\n  num x, y;\n  Point({num x, num y}) {\n    this.x = x;\n    this.y = y;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Point {\n  num x, y;\n  Point({this.x, this.y});\n}\n\n  
\n

\n NOTE:\n This rule will not generate a lint for named parameters unless the parameter\nname and the field name are the same. The reason for this is that resolving\nsuch a lint would require either renaming the field or renaming the parameter,\nand both of those actions would potentially be a breaking change. For example,\nthe following will not generate a lint:\n

\n
\nclass Point {\n  bool isEnabled;\n  Point({bool enabled}) {\n    this.isEnabled = enabled; // OK\n  }\n}\n\n  
\n

\n NOTE:\n Also note that it is possible to enforce a type that is stricter than the\ninitialized field with an initializing formal parameter. In the following\nexample the unnamed \n Bid\n constructor requires a non-null \n int\n despite\n\n amount\n being declared nullable (\n int?\n ).\n

\n
\nclass Bid {\n final int? amount;\n Bid(int this.amount);\n Bid.pass() : amount = null;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_inlined_adds", - "name": "Prefer inlined adds", - "severity": "MINOR", - "description": "
\n

\n Declare elements in list literals inline, rather than using \n add\n and\n\n addAll\n methods where possible.\n

\n

\n BAD:\n

\n
\nvar l = ['a']..add('b')..add('c');\nvar l2 = ['a']..addAll(['b', 'c']);\n\n  
\n

\n GOOD:\n

\n
\nvar l = ['a', 'b', 'c'];\nvar l2 = ['a', 'b', 'c'];\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_int_literals", - "name": "Prefer int literals", - "severity": "MINOR", - "description": "
\n

\n DO\n use int literals rather than the corresponding double literal.\n

\n

\n BAD:\n

\n
\nconst double myDouble = 8.0;\nfinal anotherDouble = myDouble + 7.0e2;\nmain() {\n  someMethod(6.0);\n}\n\n  
\n

\n GOOD:\n

\n
\nconst double myDouble = 8;\nfinal anotherDouble = myDouble + 700;\nmain() {\n  someMethod(6);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_interpolation_to_compose_strings", - "name": "Prefer interpolation to compose strings", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using interpolation to compose strings and values.\n

\n

Using interpolation when composing strings and values is usually easier to write\nand read than concatenation.

\n

\n BAD:\n

\n
\n'Hello, ' + person.name + ' from ' + person.city + '.';\n\n  
\n

\n GOOD:\n

\n
\n'Hello, ${person.name} from ${person.city}.'\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_is_empty", - "name": "Prefer is empty", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use \n length\n to see if a collection is empty.\n

\n

\n The \n Iterable\n contract does not require that a collection know its length or be\nable to provide it in constant time. Calling \n length\n just to see if the\ncollection contains anything can be painfully slow.\n

\n

\n Instead, there are faster and more readable getters: \n isEmpty\n and\n\n isNotEmpty\n . Use the one that doesn't require you to negate the result.\n

\n

\n BAD:\n

\n
\nif (lunchBox.length == 0) return 'so hungry...';\nif (words.length != 0) return words.join(' ');\n\n  
\n

\n GOOD:\n

\n
\nif (lunchBox.isEmpty) return 'so hungry...';\nif (words.isNotEmpty) return words.join(' ');\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_is_not_empty", - "name": "Prefer is not empty", - "severity": "MINOR", - "description": "
\n

\n PREFER\n x.isNotEmpty\n to \n !x.isEmpty\n for \n Iterable\n and \n Map\n instances.\n

\n

\n When testing whether an iterable or map is empty, prefer \n isNotEmpty\n over\n\n !isEmpty\n to improve code readability.\n

\n

\n BAD:\n

\n
\nif (!sources.isEmpty) {\n  process(sources);\n}\n\n  
\n

\n GOOD:\n

\n
\nif (todo.isNotEmpty) {\n  sendResults(request, todo.isEmpty);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_is_not_operator", - "name": "Prefer is not operator", - "severity": "MINOR", - "description": "
\n

When checking if an object is not of a specified type, it is preferable to use the 'is!' operator.

\n

\n BAD:\n

\n
\nif (!(foo is Foo)) {\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nif (foo is! Foo) {\n  ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_iterable_whereType", - "name": "Prefer iterable whereType", - "severity": "MINOR", - "description": "
\n

\n PREFER\n iterable.whereType<T>()\n over \n iterable.where((e) => e is T)\n .\n

\n

\n BAD:\n

\n
\niterable.where((e) => e is MyClass);\n\n  
\n

\n GOOD:\n

\n
\niterable.whereType<MyClass>();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_mixin", - "name": "Prefer mixin", - "severity": "MAJOR", - "description": "
\n

\n Dart 2.1 introduced a new syntax for mixins that provides a safe way for a mixin\nto invoke inherited members using \n super\n . The new style of mixins should always\nbe used for types that are to be mixed in. As a result, this lint will flag any\nuses of a class in a \n with\n clause.\n

\n

\n BAD:\n

\n
\nclass A {}\nclass B extends Object with A {}\n\n  
\n

\n OK:\n

\n
\nmixin M {}\nclass C with M {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "prefer_null_aware_method_calls", - "name": "Prefer null aware method calls", - "severity": "MINOR", - "description": "
\n

\n Instead of checking nullability of a function/method \n f\n before calling it you\ncan use \n f?.call()\n .\n

\n

\n BAD:\n

\n
\nif (f != null) f!();\n\n  
\n

\n GOOD:\n

\n
\nf?.call();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_null_aware_operators", - "name": "Prefer null aware operators", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using null aware operators instead of null checks in conditional\nexpressions.\n

\n

\n BAD:\n

\n
\nv = a == null ? null : a.b;\n\n  
\n

\n GOOD:\n

\n
\nv = a?.b;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_single_quotes", - "name": "Prefer single quotes", - "severity": "MINOR", - "description": "
\n

\n DO\n use single quotes where they wouldn't require additional escapes.\n

\n

That means strings with an apostrophe may use double quotes so that the\napostrophe isn't escaped (note: we don't lint the other way around, ie, a single\nquoted string with an escaped apostrophe is not flagged).

\n

It's also rare, but possible, to have strings within string interpolations. In\nthis case, its much more readable to use a double quote somewhere. So double\nquotes are allowed either within, or containing, an interpolated string literal.\nArguably strings within string interpolations should be its own type of lint.

\n

\n BAD:\n

\n
\nuseStrings(\n    \"should be single quote\",\n    r\"should be single quote\",\n    r\"\"\"should be single quotes\"\"\")\n\n  
\n

\n GOOD:\n

\n
\nuseStrings(\n    'should be single quote',\n    r'should be single quote',\n    r'''should be single quotes''',\n    \"here's ok\",\n    \"nested ${a ? 'strings' : 'can'} be wrapped by a double quote\",\n    'and nested ${a ? \"strings\" : \"can be double quoted themselves\"}');\n\n  
\n

\n Incompatible with: \n prefer_double_quotes\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "prefer_spread_collections", - "name": "Prefer spread collections", - "severity": "MINOR", - "description": "
\n

Use spread collections when possible.

\n

Collection literals are excellent when you want to create a new collection out\nof individual items. But, when existing items are already stored in another\ncollection, spread collection syntax leads to simpler code.

\n

\n BAD:\n

\n
\nWidget build(BuildContext context) {\n  return CupertinoPageScaffold(\n    child: ListView(\n      children: [\n        Tab2Header(),\n      ]..addAll(buildTab2Conversation()),\n    ),\n  );\n}\n\n  
\n
\nvar ints = [1, 2, 3];\nprint(['a']..addAll(ints.map((i) => i.toString()))..addAll(['c']));\n\n  
\n
\nvar things;\nvar l = ['a']..addAll(things ?? const []);\n\n  
\n

\n GOOD:\n

\n
\nWidget build(BuildContext context) {\n  return CupertinoPageScaffold(\n    child: ListView(\n      children: [\n        Tab2Header(),\n        ...buildTab2Conversation(),\n      ],\n    ),\n  );\n}\n\n  
\n
\nvar ints = [1, 2, 3];\nprint(['a', ...ints.map((i) => i.toString()), 'c');\n\n  
\n
\nvar things;\nvar l = ['a', ...?things];\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "prefer_typing_uninitialized_variables", - "name": "Prefer typing uninitialized variables", - "severity": "MAJOR", - "description": "
\n

\n PREFER\n specifying a type annotation for uninitialized variables and fields.\n

\n

Forgoing type annotations for uninitialized variables is a bad practice because\nyou may accidentally assign them to a type that you didn't originally intend to.

\n

\n BAD:\n

\n
\nclass BadClass {\n  static var bar; // LINT\n  var foo; // LINT\n\n  void method() {\n    var bar; // LINT\n    bar = 5;\n    print(bar);\n  }\n}\n\n  
\n

\n BAD:\n

\n
\nvoid aFunction() {\n  var bar; // LINT\n  bar = 5;\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nclass GoodClass {\n  static var bar = 7;\n  var foo = 42;\n  int baz; // OK\n\n  void method() {\n    int baz;\n    var bar = 5;\n    ...\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "provide_deprecation_message", - "name": "Provide deprecation message", - "severity": "MAJOR", - "description": "
\n

\n DO\n specify a deprecation message (with migration instructions and/or a\nremoval schedule) in the Deprecation constructor.\n

\n

\n BAD:\n

\n
\n@deprecated\nvoid oldFunction(arg1, arg2) {}\n\n  
\n

\n GOOD:\n

\n
\n@Deprecated(\"\"\"\n[oldFunction] is being deprecated in favor of [newFunction] (with slightly\ndifferent parameters; see [newFunction] for more information). [oldFunction]\nwill be removed on or after the 4.0.0 release.\n\"\"\")\nvoid oldFunction(arg1, arg2) {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "public_member_api_docs", - "name": "Public member api docs", - "severity": "INFO", - "description": "
\n

\n DO\n document all public members.\n

\n

\n All non-overriding public members should be documented with \n ///\n doc-style\ncomments.\n

\n

\n BAD:\n

\n
\nclass Bad {\n  void meh() { }\n}\n\n  
\n

\n GOOD:\n

\n
\n/// A good thing.\nabstract class Good {\n  /// Start doing your thing.\n  void start() => _start();\n\n  _start();\n}\n\n  
\n

\n In case a public member overrides a member it is up to the declaring member\nto provide documentation. For example, in the following, \n Sub\n needn't\ndocument \n init\n (though it certainly may, if there's need).\n

\n

\n GOOD:\n

\n
\n/// Base of all things.\nabstract class Base {\n  /// Initialize the base.\n  void init();\n}\n\n/// A sub base.\nclass Sub extends Base {\n  @override\n  void init() { ... }\n}\n\n  
\n

\n Note that consistent with \n dart doc\n , an exception to the rule is made when\ndocumented getters have corresponding undocumented setters. In this case the\nsetters inherit the docs from the getters.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "10min", - "active": false - }, - { - "key": "recursive_getters", - "name": "Recursive getters", - "severity": "CRITICAL", - "description": "
\n

\n DON'T\n create recursive getters.\n

\n

Recursive getters are getters which return themselves as a value. This is\nusually a typo.

\n

\n BAD:\n

\n
\nint get field => field; // LINT\n\n  
\n

\n BAD:\n

\n
\nint get otherField {\n  return otherField; // LINT\n}\n\n  
\n

\n GOOD:\n

\n
\nint get field => _field;\n\n  
\n
\n", - "type": "BUG", - "debt": "1min", - "active": true - }, - { - "key": "require_trailing_commas", - "name": "Require trailing commas", - "severity": "MINOR", - "description": "
\n

\n DO\n use trailing commas for all function calls and declarations unless the\nfunction call or definition, from the start of the function name up to the\nclosing parenthesis, fits in a single line.\n

\n

\n BAD:\n

\n
\nvoid run() {\n  method('does not fit on one line',\n      'test test test test test test test test test test test');\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid run() {\n  method(\n    'does not fit on one line',\n    'test test test test test test test test test test test',\n  );\n}\n\n  
\n

\n EXCEPTION:\n If the final parameter/argument is positional (vs named) and is\neither a function literal implemented using curly braces, a literal map, a\nliteral set or a literal array. This exception only applies if the final\nparameter does not fit entirely on one line.\n

\n

\n NOTE:\n This lint rule assumes \n dart format\n has been run over the code and\nmay produce false positives until that has happened.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "sized_box_for_whitespace", - "name": "Sized box for whitespace", - "severity": "MAJOR", - "description": "
\n

Use SizedBox to add whitespace to a layout.

\n

\n A \n Container\n is a heavier Widget than a \n SizedBox\n , and as bonus, \n SizedBox\n has a \n const\n constructor.\n

\n

\n BAD:\n

\n
\nWidget buildRow() {\n  return Row(\n    children: <Widget>[\n      const MyLogo(),\n      Container(width: 4),\n      const Expanded(\n        child: Text('...'),\n      ),\n    ],\n  );\n}\n\n  
\n

\n GOOD:\n

\n
\nWidget buildRow() {\n  return Row(\n    children: const <Widget>[\n      MyLogo(),\n      SizedBox(width: 4),\n      Expanded(\n        child: Text('...'),\n      ),\n    ],\n  );\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "sized_box_shrink_expand", - "name": "Sized box shrink expand", - "severity": "MINOR", - "description": "
\n

\n Use \n SizedBox.shrink(...)\n and \n SizedBox.expand(...)\n constructors appropriately.\n

\n

\n The \n SizedBox.shrink(...)\n and \n SizedBox.expand(...)\n constructors should be used\ninstead of the more general \n SizedBox(...)\n constructor when the named constructors\ncapture the intent of the code more succinctly.\n

\n

\n Examples\n

\n

\n BAD:\n

\n
\nWidget buildLogo() {\n  return SizedBox(\n    height: 0,\n    width: 0,\n    child: const MyLogo(),\n  );\n}\n\n  
\n
\nWidget buildLogo() {\n  return SizedBox(\n    height: double.infinity,\n    width: double.infinity,\n    child: const MyLogo(),\n  );\n}\n\n  
\n

\n GOOD:\n

\n
\nWidget buildLogo() {\n  return SizedBox.shrink(\n    child: const MyLogo(),\n  );\n}\n\n  
\n
\nWidget buildLogo() {\n  return SizedBox.expand(\n    child: const MyLogo(),\n  );\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "slash_for_doc_comments", - "name": "Slash for doc comments", - "severity": "INFO", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n PREFER\n using \n ///\n for doc comments.\n

\n

\n Although Dart supports two syntaxes of doc comments (\n ///\n and \n /**\n ), we\nprefer using \n ///\n for doc comments.\n

\n

\n GOOD:\n

\n
\n/// Parses a set of option strings. For each option:\n///\n/// * If it is `null`, then it is ignored.\n/// * If it is a string, then [validate] is called on it.\n/// * If it is any other type, it is *not* validated.\nvoid parse(List options) {\n  // ...\n}\n\n  
\n

Within a doc comment, you can use markdown for formatting.

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "sort_child_properties_last", - "name": "Sort child properties last", - "severity": "MAJOR", - "description": "
\n

Sort child properties last in widget instance creations. This improves\nreadability and plays nicest with UI as Code visualization in IDEs with UI as\nCode Guides in editors (such as IntelliJ) where Properties in the correct order\nappear clearly associated with the constructor call and separated from the\nchildren.

\n

\n BAD:\n

\n
\nreturn Scaffold(\n  appBar: AppBar(\n    title: Text(widget.title),\n  ),\n  body: Center(\n    child: Column(\n      children: <Widget>[\n        Text(\n          'You have pushed the button this many times:',\n         ),\n        Text(\n          '$_counter',\n          style: Theme.of(context).textTheme.display1,\n         ),\n      ],\n      mainAxisAlignment: MainAxisAlignment.center,\n    ),\n    widthFactor: 0.5,\n  ),\n  floatingActionButton: FloatingActionButton(\n    child: Icon(Icons.add),\n    onPressed: _incrementCounter,\n    tooltip: 'Increment',\n  ),\n);\n\n  
\n

\n GOOD:\n

\n
\nreturn Scaffold(\n  appBar: AppBar(\n    title: Text(widget.title),\n  ),\n  body: Center(\n    widthFactor: 0.5,\n    child: Column(\n      mainAxisAlignment: MainAxisAlignment.center,\n      children: <Widget>[\n        Text(\n          'You have pushed the button this many times:',\n         ),\n        Text(\n          '$_counter',\n          style: Theme.of(context).textTheme.display1,\n         ),\n      ],\n    ),\n  ),\n  floatingActionButton: FloatingActionButton(\n    onPressed: _incrementCounter,\n    tooltip: 'Increment',\n    child: Icon(Icons.add),\n  ),\n);\n\n  
\n

\n Exception: It's allowed to have parameter with a function expression after the\n\n child\n property.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "sort_constructors_first", - "name": "Sort constructors first", - "severity": "MAJOR", - "description": "
\n

\n DO\n sort constructor declarations before other members.\n

\n

\n BAD:\n

\n
\nabstract class Visitor {\n  double value;\n  visitSomething(Something s);\n  Visitor();\n}\n\n  
\n

\n GOOD:\n

\n
\nabstract class Animation<T> {\n  const Animation(this.value);\n  double value;\n  void addListener(VoidCallback listener);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "sort_unnamed_constructors_first", - "name": "Sort unnamed constructors first", - "severity": "MAJOR", - "description": "
\n

\n DO\n sort unnamed constructor declarations first, before named ones.\n

\n

\n BAD:\n

\n
\nclass _PriorityItem {\n  factory _PriorityItem.forName(bool isStatic, String name, _MemberKind kind) => ...\n  _PriorityItem(this.isStatic, this.kind, this.isPrivate);\n  ...\n}\n\n  
\n

\n GOOD:\n

\n
\nabstract class CancelableFuture<T> implements Future<T>  {\n  factory CancelableFuture(computation()) => ...\n  factory CancelableFuture.delayed(Duration duration, [computation()]) => ...\n  ...\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "super_goes_last", - "name": "Super goes last", - "severity": "MAJOR", - "description": "
\n

\n Unsupported since Dart language version 3.0.0.\n

\n

\n From the \n style guide\n :\n

\n

\n DO\n place the \n super\n call last in a constructor initialization list.\n

\n

\n Field initializers are evaluated in the order that they appear in the\nconstructor initialization list. If you place a \n super()\n call in the middle of\nan initializer list, the superclass's initializers will be evaluated right then\nbefore evaluating the rest of the subclass's initializers.\n

\n

\n What it doesn't mean is that the superclass's constructor body will be executed\nthen. That always happens after all initializers are run regardless of where\n\n super\n appears. It's vanishingly rare that the order of initializers matters,\nso the placement of \n super\n in the list almost never matters either.\n

\n

Getting in the habit of placing it last improves consistency, visually\nreinforces when the superclass's constructor body is run, and may help\nperformance.

\n

\n BAD:\n

\n
\nView(Style style, List children)\n    : super(style),\n      _children = children {\n\n  
\n

\n GOOD:\n

\n
\nView(Style style, List children)\n    : _children = children,\n      super(style) {\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "tighten_type_of_initializing_formals", - "name": "Tighten type of initializing formals", - "severity": "MAJOR", - "description": "
\n

Tighten the type of an initializing formal if a non-null assert exists. This\nallows the type system to catch problems rather than have them only be caught at\nrun-time.

\n

\n BAD:\n

\n
\nclass A {\n  A.c1(this.p) : assert(p != null);\n  A.c2(this.p);\n  final String? p;\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  A.c1(String this.p);\n  A.c2(this.p);\n  final String? p;\n}\n\nclass B {\n  String? b;\n  B(this.b);\n}\n\nclass C extends B {\n  B(String super.b);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "type_annotate_public_apis", - "name": "Type annotate public apis", - "severity": "INFO", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

\n PREFER\n type annotating public APIs.\n

\n

Type annotations are important documentation for how a library should be used.\nAnnotating the parameter and return types of public methods and functions helps\nusers understand what the API expects and what it provides.

\n

\n Note that if a public API accepts a range of values that Dart's type system\ncannot express, then it is acceptable to leave that untyped. In that case, the\nimplicit \n dynamic\n is the correct type for the API.\n

\n

\n For code internal to a library (either private, or things like nested functions)\nannotate where you feel it helps, but don't feel that you \n must\n provide them.\n

\n

\n BAD:\n

\n
\ninstall(id, destination) {\n  // ...\n}\n\n  
\n

\n Here, it's unclear what \n id\n is. A string? And what is \n destination\n ? A string\nor a \n File\n object? Is this method synchronous or asynchronous?\n

\n

\n GOOD:\n

\n
\nFuture<bool> install(PackageId id, String destination) {\n  // ...\n}\n\n  
\n

With types, all of this is clarified.

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "type_init_formals", - "name": "Type init formals", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n DON'T\n type annotate initializing formals.\n

\n

\n If a constructor parameter is using \n this.x\n to initialize a field, then the\ntype of the parameter is understood to be the same type as the field. If a\na constructor parameter is using \n super.x\n to forward to a super constructor,\nthen the type of the parameter is understood to be the same as the super\nconstructor parameter.\n

\n

Type annotating an initializing formal with a different type than that of the\nfield is OK.

\n

\n BAD:\n

\n
\nclass Point {\n  int x, y;\n  Point(int this.x, int this.y);\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Point {\n  int x, y;\n  Point(this.x, this.y);\n}\n\n  
\n

\n BAD:\n

\n
\nclass A {\n  int a;\n  A(this.a);\n}\n\nclass B extends A {\n  B(int super.a);\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  int a;\n  A(this.a);\n}\n\nclass B extends A {\n  B(super.a);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "type_literal_in_constant_pattern", - "name": "Type literal in constant pattern", - "severity": "MAJOR", - "description": "
\n

\n If you meant to test if the object has type \n Foo\n , instead write \n Foo _\n .\n

\n

\n BAD:\n

\n
\nvoid f(Object? x) {\n  if (x case num) {\n    print('int or double');\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f(Object? x) {\n  if (x case num _) {\n    print('int or double');\n  }\n}\n\n  
\n

\n If you do mean to test that the matched value (which you expect to have the\ntype \n Type\n ) is equal to the type literal \n Foo\n , then this lint can be\nsilenced using \n const (Foo)\n .\n

\n

\n BAD:\n

\n
\nvoid f(Object? x) {\n  if (x case int) {\n    print('int');\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid f(Object? x) {\n  if (x case const (int)) {\n    print('int');\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unawaited_futures", - "name": "Unawaited futures", - "severity": "CRITICAL", - "description": "
\n

\n DO\n await functions that return a \n Future\n inside of an async function body.\n

\n

\n It's easy to forget await in async methods as naming conventions usually don't\ntell us if a method is sync or async (except for some in \n dart:io\n ).\n

\n

\n When you really \n do\n want to start a fire-and-forget \n Future\n , the recommended\nway is to use \n unawaited\n from \n dart:async\n . The \n // ignore\n and\n\n // ignore_for_file\n comments also work.\n

\n

\n BAD:\n

\n
\nvoid main() async {\n  doSomething(); // Likely a bug.\n}\n\n  
\n

\n GOOD:\n

\n
\nFuture doSomething() => ...;\n\nvoid main() async {\n  await doSomething();\n\n  unawaited(doSomething()); // Explicitly-ignored fire-and-forget.\n}\n\n  
\n
\n", - "type": "BUG", - "debt": "5min", - "active": false - }, - { - "key": "unnecessary_await_in_return", - "name": "Unnecessary await in return", - "severity": "MINOR", - "description": "
\n

Avoid returning an awaited expression when the expression type is assignable to\nthe function's return type.

\n

\n BAD:\n

\n
\nFuture<int> future;\nFuture<int> f1() async => await future;\nFuture<int> f2() async {\n  return await future;\n}\n\n  
\n

\n GOOD:\n

\n
\nFuture<int> future;\nFuture<int> f1() => future;\nFuture<int> f2() {\n  return future;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_brace_in_string_interps", - "name": "Unnecessary brace in string interps", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using braces in interpolation when not needed.\n

\n

\n If you're just interpolating a simple identifier, and it's not immediately\nfollowed by more alphanumeric text, the \n {}\n can and should be omitted.\n

\n

\n BAD:\n

\n
\nprint(\"Hi, ${name}!\");\n\n  
\n

\n GOOD:\n

\n
\nprint(\"Hi, $name!\");\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_breaks", - "name": "Unnecessary breaks", - "severity": "MINOR", - "description": "
\n

\n Only use a \n break\n in a non-empty switch case statement if you need to break\nbefore the end of the case body. Dart does not support fallthrough execution\nfor non-empty cases, so \n break\n s at the end of non-empty switch case statements\nare unnecessary.\n

\n

\n BAD:\n

\n
\nswitch (1) {\n  case 1:\n    print(\"one\");\n    break;\n  case 2:\n    print(\"two\");\n    break;\n}\n\n  
\n

\n GOOD:\n

\n
\nswitch (1) {\n  case 1:\n    print(\"one\");\n  case 2:\n    print(\"two\");\n}\n\n  
\n
\nswitch (1) {\n  case 1:\n  case 2:\n    print(\"one or two\");\n}\n\n  
\n
\nswitch (1) {\n  case 1:\n    break;\n  case 2:\n    print(\"just two\");\n}\n\n  
\n

\n NOTE: This lint only reports unnecessary breaks in libraries with a\n\n language version\n of 3.0 or greater. Explicit breaks are still required in Dart 2.19 and below.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_const", - "name": "Unnecessary const", - "severity": "MINOR", - "description": "
\n

\n AVOID\n repeating const keyword in a const context.\n

\n

\n BAD:\n

\n
\nclass A { const A(); }\nm(){\n  const a = const A();\n  final b = const [const A()];\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A { const A(); }\nm(){\n  const a = A();\n  final b = const [A()];\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_constructor_name", - "name": "Unnecessary constructor name", - "severity": "MINOR", - "description": "
\n

\n PREFER\n using the default unnamed Constructor over \n .new\n .\n

\n

\n Given a class \n C\n , the named unnamed constructor \n C.new\n refers to the same\nconstructor as the unnamed \n C\n . As such it adds nothing but visual noise to\ninvocations and should be avoided (unless being used to identify a constructor\ntear-off).\n

\n

\n BAD:\n

\n
\nclass A {\n  A.new(); // LINT\n}\n\nvar a = A.new(); // LINT\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  A.ok();\n}\n\nvar a = A();\nvar aa = A.ok();\nvar makeA = A.new;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_final", - "name": "Unnecessary final", - "severity": "MINOR", - "description": "
\n

\n Use \n var\n , not \n final\n , when declaring local variables.\n

\n

\n Per \n Effective Dart\n ,\nthere are two styles in wide use. This rule enforces the \n var\n style.\nFor the alternative style that prefers \n final\n , enable \n prefer_final_locals\n and \n prefer_final_in_for_each\n instead.\n

\n

\n For fields, \n final\n is always recommended; see the rule \n prefer_final_fields\n .\n

\n

\n BAD:\n

\n
\nvoid badMethod() {\n  final label = 'Final or var?';\n  for (final char in ['v', 'a', 'r']) {\n    print(char);\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nvoid goodMethod() {\n  var label = 'Final or var?';\n  for (var char in ['v', 'a', 'r']) {\n    print(char);\n  }\n}\n\n  
\n

\n Incompatible with: \n prefer_final_locals\n , \n prefer_final_parameters\n .\n\n

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "unnecessary_getters_setters", - "name": "Unnecessary getters setters", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n AVOID\n wrapping fields in getters and setters just to be \"safe\".\n

\n

In Java and C#, it's common to hide all fields behind getters and setters (or\nproperties in C#), even if the implementation just forwards to the field. That\nway, if you ever need to do more work in those members, you can do it without needing\nto touch the callsites. This is because calling a getter method is different\nthan accessing a field in Java, and accessing a property isn't binary-compatible\nwith accessing a raw field in C#.

\n

Dart doesn't have this limitation. Fields and getters/setters are completely\nindistinguishable. You can expose a field in a class and later wrap it in a\ngetter and setter without having to touch any code that uses that field.

\n

\n BAD:\n

\n
\nclass Box {\n  var _contents;\n  get contents => _contents;\n  set contents(value) {\n    _contents = value;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Box {\n  var contents;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_lambdas", - "name": "Unnecessary lambdas", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n create a lambda when a tear-off will do.\n

\n

\n BAD:\n

\n
\nnames.forEach((name) {\n  print(name);\n});\n\n  
\n

\n GOOD:\n

\n
\nnames.forEach(print);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "unnecessary_late", - "name": "Unnecessary late", - "severity": "MINOR", - "description": "
\n

\n DO\n not specify the \n late\n modifier for top-level and static variables\nwhen the declaration contains an initializer.\n

\n

\n Top-level and static variables with initializers are already evaluated lazily\nas if they are marked \n late\n .\n

\n

\n BAD:\n

\n
\nlate String badTopLevel = '';\n\n  
\n

\n GOOD:\n

\n
\nString goodTopLevel = '';\n\n  
\n

\n BAD:\n

\n
\nclass BadExample {\n  static late String badStatic = '';\n}\n\n  
\n

\n GOOD:\n

\n
\nclass GoodExample {\n  late String goodStatic;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_library_directive", - "name": "Unnecessary library directive", - "severity": "MINOR", - "description": "
\n

\n DO\n use library directives if you want to document a library and/or annotate\na library.\n

\n

\n BAD:\n

\n
\nlibrary;\n\n  
\n

\n GOOD:\n

\n
\n/// This library does important things\nlibrary;\n\n  
\n
\n@TestOn('js')\nlibrary;\n\n  
\n

NOTE: Due to limitations with this lint, libraries with parts will not be\nflagged for unnecessary library directives.

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_new", - "name": "Unnecessary new", - "severity": "MINOR", - "description": "
\n

\n AVOID\n new keyword to create instances.\n

\n

\n BAD:\n

\n
\nclass A { A(); }\nm(){\n  final a = new A();\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A { A(); }\nm(){\n  final a = A();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_null_aware_assignments", - "name": "Unnecessary null aware assignments", - "severity": "MINOR", - "description": "
\n

\n AVOID\n null\n in null-aware assignment.\n

\n

\n Using \n null\n on the right-hand side of a null-aware assignment effectively makes\nthe assignment redundant.\n

\n

\n BAD:\n

\n
\nvar x;\nx ??= null;\n\n  
\n

\n GOOD:\n

\n
\nvar x;\nx ??= 1;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_null_aware_operator_on_extension_on_nullable", - "name": "Unnecessary null aware operator on extension on nullable", - "severity": "MINOR", - "description": "
\n

Avoid null aware operators for members defined in an extension on a nullable type.

\n

\n BAD:\n

\n
\nextension E on int? {\n  int m() => 1;\n}\nf(int? i) => i?.m();\n\n  
\n

\n GOOD:\n

\n
\nextension E on int? {\n  int m() => 1;\n}\nf(int? i) => i.m();\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_null_checks", - "name": "Unnecessary null checks", - "severity": "MINOR", - "description": "
\n

\n DON'T\n apply a null check when a nullable value is accepted.\n

\n

\n BAD:\n

\n
\nf(int? i) {}\nm() {\n  int? j;\n  f(j!);\n}\n\n\n  
\n

\n GOOD:\n

\n
\nf(int? i) {}\nm() {\n  int? j;\n  f(j);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_null_in_if_null_operators", - "name": "Unnecessary null in if null operators", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using \n null\n as an operand in \n if null\n operators.\n

\n

\n Using \n null\n in an \n if null\n operator is redundant, regardless of which side\n\n null\n is used on.\n

\n

\n BAD:\n

\n
\nvar x = a ?? null;\nvar y = null ?? 1;\n\n  
\n

\n GOOD:\n

\n
\nvar x = a ?? 1;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_nullable_for_final_variable_declarations", - "name": "Unnecessary nullable for final variable declarations", - "severity": "MINOR", - "description": "
\n

Use a non-nullable type for a final variable initialized with a non-nullable\nvalue.

\n

\n BAD:\n

\n
\nfinal int? i = 1;\n\n  
\n

\n GOOD:\n

\n
\nfinal int i = 1;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_overrides", - "name": "Unnecessary overrides", - "severity": "MAJOR", - "description": "
\n

\n DON'T\n override a method to do a super method invocation with same parameters.\n

\n

\n BAD:\n

\n
\nclass A extends B {\n  @override\n  void foo() {\n    super.foo();\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A extends B {\n  @override\n  void foo() {\n    doSomethingElse();\n  }\n}\n\n  
\n

It's valid to override a member in the following cases:

\n \n

\n noSuchMethod\n is a special method and is not checked by this rule.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": true - }, - { - "key": "unnecessary_parenthesis", - "name": "Unnecessary parenthesis", - "severity": "MINOR", - "description": "
\n

\n AVOID\n using parentheses when not needed.\n

\n

\n BAD:\n

\n
\na = (b);\n\n  
\n

\n GOOD:\n

\n
\na = b;\n\n  
\n

Parentheses are considered unnecessary if they do not change the meaning of the\ncode and they do not improve the readability of the code. The goal is not to\nforce all developers to maintain the expression precedence table in their heads,\nwhich is why the second condition is included. Examples of this condition\ninclude:

\n \n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_raw_strings", - "name": "Unnecessary raw strings", - "severity": "MINOR", - "description": "
\n

Use raw string only when needed.

\n

\n BAD:\n

\n
\nvar s1 = r'a';\n\n  
\n

\n GOOD:\n

\n
\nvar s1 = 'a';\nvar s2 = r'$a';\nvar s3 = r'\\a';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unnecessary_string_escapes", - "name": "Unnecessary string escapes", - "severity": "MINOR", - "description": "
\n

Remove unnecessary backslashes in strings.

\n

\n BAD:\n

\n
\n'this string contains 2 \\\"double quotes\\\" ';\n\"this string contains 2 \\'single quotes\\' \";\n\n  
\n

\n GOOD:\n

\n
\n'this string contains 2 \"double quotes\" ';\n\"this string contains 2 'single quotes' \";\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_string_interpolations", - "name": "Unnecessary string interpolations", - "severity": "MINOR", - "description": "
\n

\n DON'T\n use string interpolation if there's only a string expression in it.\n

\n

\n BAD:\n

\n
\nString message;\nString o = '$message';\n\n  
\n

\n GOOD:\n

\n
\nString message;\nString o = message;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_this", - "name": "Unnecessary this", - "severity": "MINOR", - "description": "
\n

\n From the \n style guide\n :\n

\n

\n DON'T\n use \n this\n when not needed to avoid shadowing.\n

\n

\n BAD:\n

\n
\nclass Box {\n  var value;\n  void update(new_value) {\n    this.value = new_value;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Box {\n  var value;\n  void update(new_value) {\n    value = new_value;\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Box {\n  var value;\n  void update(value) {\n    this.value = value;\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "unnecessary_to_list_in_spreads", - "name": "Unnecessary to list in spreads", - "severity": "MINOR", - "description": "
\n

\n Unnecessary \n toList()\n in spreads.\n

\n

\n BAD:\n

\n
\nchildren: <Widget>[\n  ...['foo', 'bar', 'baz'].map((String s) => Text(s)).toList(),\n]\n\n  
\n

\n GOOD:\n

\n
\nchildren: <Widget>[\n  ...['foo', 'bar', 'baz'].map((String s) => Text(s)),\n]\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "unreachable_from_main", - "name": "Unreachable from main", - "severity": "MAJOR", - "description": "
\n

\n Top-level members in an executable library should be used directly inside this\nlibrary. An executable library is a library that contains a \n main\n top-level\nfunction or that contains a top-level function annotated with\n\n @pragma('vm:entry-point')\n ). Executable libraries are not usually imported\nand it's better to avoid defining unused members.\n

\n

\n This rule assumes that an executable library isn't imported by other files\nexcept to execute its \n main\n function.\n

\n

\n BAD:\n

\n
\nmain() {}\nvoid f() {}\n\n  
\n

\n GOOD:\n

\n
\nmain() {\n  f();\n}\nvoid f() {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_colored_box", - "name": "Use colored box", - "severity": "MAJOR", - "description": "
\n

\n DO\n use \n ColoredBox\n when \n Container\n has only a \n Color\n .\n

\n

\n A \n Container\n is a heavier Widget than a \n ColoredBox\n , and as bonus,\n\n ColoredBox\n has a \n const\n constructor.\n

\n

\n BAD:\n

\n
\nWidget buildArea() {\n  return Container(\n    color: Colors.blue,\n    child: const Text('hello'),\n  );\n}\n\n  
\n

\n GOOD:\n

\n
\nWidget buildArea() {\n  return const ColoredBox(\n    color: Colors.blue,\n    child: Text('hello'),\n  );\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_decorated_box", - "name": "Use decorated box", - "severity": "MAJOR", - "description": "
\n

\n DO\n use \n DecoratedBox\n when \n Container\n has only a \n Decoration\n .\n

\n

\n A \n Container\n is a heavier Widget than a \n DecoratedBox\n , and as bonus,\n\n DecoratedBox\n has a \n const\n constructor.\n

\n

\n BAD:\n

\n
\nWidget buildArea() {\n  return Container(\n    decoration: const BoxDecoration(\n      color: Colors.blue,\n      borderRadius: BorderRadius.all(\n        Radius.circular(5),\n      ),\n    ),\n    child: const Text('...'),\n  );\n}\n\n  
\n

\n GOOD:\n

\n
\nWidget buildArea() {\n  return const DecoratedBox(\n    decoration: BoxDecoration(\n      color: Colors.blue,\n      borderRadius: BorderRadius.all(\n        Radius.circular(5),\n      ),\n    ),\n    child: Text('...'),\n  );\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_enums", - "name": "Use enums", - "severity": "MAJOR", - "description": "
\n

\n Classes that look like enumerations should be declared as \n enum\n s.\n

\n

\n DO\n use enums where appropriate.\n

\n

Candidates for enums are classes that:

\n \n

\n BAD:\n

\n
\nclass LogPriority {\n  static const error = LogPriority._(1, 'Error');\n  static const warning = LogPriority._(2, 'Warning');\n  static const log = LogPriority._unknown('Log');\n\n  final String prefix;\n  final int priority;\n  const LogPriority._(this.priority, this.prefix);\n  const LogPriority._unknown(String prefix) : this._(-1, prefix);\n}\n\n  
\n

\n GOOD:\n

\n
\nenum LogPriority {\n  error(1, 'Error'),\n  warning(2, 'Warning'),\n  log.unknown('Log');\n\n  final String prefix;\n  final int priority;\n  const LogPriority(this.priority, this.prefix);\n  const LogPriority.unknown(String prefix) : this(-1, prefix);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_full_hex_values_for_flutter_colors", - "name": "Use full hex values for flutter colors", - "severity": "MINOR", - "description": "
\n

\n PREFER\n an 8-digit hexadecimal integer(0xFFFFFFFF) to instantiate Color. Colors\nhave four 8-bit channels, which adds up to 32 bits, so Colors are described\nusing a 32 bit integer.\n

\n

\n BAD:\n

\n
\nColor(1);\nColor(0x000001);\n\n  
\n

\n GOOD:\n

\n
\nColor(0x00000001);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_function_type_syntax_for_parameters", - "name": "Use function type syntax for parameters", - "severity": "MINOR", - "description": "
\n

Use generic function type syntax for parameters.

\n

\n BAD:\n

\n
\nIterable<T> where(bool predicate(T element)) {}\n\n  
\n

\n GOOD:\n

\n
\nIterable<T> where(bool Function(T) predicate) {}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "use_if_null_to_convert_nulls_to_bools", - "name": "Use if null to convert nulls to bools", - "severity": "MINOR", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

Use if-null operators to convert nulls to bools.

\n

\n BAD:\n

\n
\nif (nullableBool == true) {\n}\nif (nullableBool != false) {\n}\n\n  
\n

\n GOOD:\n

\n
\nif (nullableBool ?? false) {\n}\nif (nullableBool ?? true) {\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_is_even_rather_than_modulo", - "name": "Use is even rather than modulo", - "severity": "MINOR", - "description": "
\n

\n PREFER\n the use of intValue.isOdd/isEven to check for evenness.\n

\n

\n BAD:\n

\n
\nbool isEven = 1 % 2 == 0;\nbool isOdd = 13 % 2 == 1;\n\n  
\n

\n GOOD:\n

\n
\nbool isEven = 1.isEven;\nbool isOdd = 13.isOdd;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_late_for_private_fields_and_variables", - "name": "Use late for private fields and variables", - "severity": "MINOR", - "description": "
\n

\n Use \n late\n for private members with non-nullable types that are always expected\nto be non-null. Thus it's clear that the field is not expected to be \n null\n and it avoids null checks.\n

\n

\n BAD:\n

\n
\nint? _i;\nm() {\n  _i!.abs();\n}\n\n  
\n

\n GOOD:\n

\n
\nlate int _i;\nm() {\n  _i.abs();\n}\n\n  
\n

\n OK:\n

\n
\nint? _i;\nm() {\n  _i?.abs();\n  _i = null;\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_named_constants", - "name": "Use named constants", - "severity": "MINOR", - "description": "
\n

Where possible, use already defined const values.

\n

\n BAD:\n

\n
\nconst Duration(seconds: 0);\n\n  
\n

\n GOOD:\n

\n
\nDuration.zero;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_raw_strings", - "name": "Use raw strings", - "severity": "MINOR", - "description": "
\n

A raw string can be used to avoid escaping only backslashes and dollars.

\n

\n BAD:\n

\n
\nvar s = 'A string with only \\\\ and \\$';\n\n  
\n

\n GOOD:\n

\n
\nvar s = r'A string with only \\ and $';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_rethrow_when_possible", - "name": "Use rethrow when possible", - "severity": "MINOR", - "description": "
\n

\n DO\n use rethrow to rethrow a caught exception.\n

\n

As Dart provides rethrow as a feature, it should be used to improve terseness\nand readability.

\n

\n BAD:\n

\n
\ntry {\n  somethingRisky();\n} catch(e) {\n  if (!canHandle(e)) throw e;\n  handle(e);\n}\n\n  
\n

\n GOOD:\n

\n
\ntry {\n  somethingRisky();\n} catch(e) {\n  if (!canHandle(e)) rethrow;\n  handle(e);\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "use_setters_to_change_properties", - "name": "Use setters to change properties", - "severity": "MINOR", - "description": "
\n

\n DO\n use a setter for operations that conceptually change a property.\n

\n

\n BAD:\n

\n
\nrectangle.setWidth(3);\nbutton.setVisible(false);\n\n  
\n

\n GOOD:\n

\n
\nrectangle.width = 3;\nbutton.visible = false;\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_string_buffers", - "name": "Use string buffers", - "severity": "MAJOR", - "description": "
\n

\n DO\n use string buffers to compose strings.\n

\n

In most cases, using a string buffer is preferred for composing strings due to\nits improved performance.

\n

\n BAD:\n

\n
\nString foo() {\n  final buffer = '';\n  for (int i = 0; i < 10; i++) {\n    buffer += 'a'; // LINT\n  }\n  return buffer;\n}\n\n  
\n

\n GOOD:\n

\n
\nString foo() {\n  final buffer = StringBuffer();\n  for (int i = 0; i < 10; i++) {\n    buffer.write('a');\n  }\n  return buffer.toString();\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_string_in_part_of_directives", - "name": "Use string in part of directives", - "severity": "MINOR", - "description": "
\n

\n From \n Effective Dart\n :\n

\n

\n DO\n use strings in \n part of\n directives.\n

\n

\n BAD:\n

\n
\npart of my_library;\n\n  
\n

\n GOOD:\n

\n
\npart of '../../my_library.dart';\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "use_super_parameters", - "name": "Use super parameters", - "severity": "MINOR", - "description": "
\n

\"Forwarding constructor\"s, that do nothing except forward parameters to their\nsuperclass constructors should take advantage of super-initializer parameters\nrather than repeating the names of parameters when passing them to the\nsuperclass constructors. This makes the code more concise and easier to read\nand maintain.

\n

\n DO\n use super-initializer parameters where possible.\n

\n

\n BAD:\n

\n
\nclass A {\n  A({int? x, int? y});\n}\nclass B extends A {\n  B({int? x, int? y}) : super(x: x, y: y);\n}\n\n  
\n

\n GOOD:\n

\n
\nclass A {\n  A({int? x, int? y});\n}\nclass B extends A {\n  B({super.x, super.y});\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_test_throws_matchers", - "name": "Use test throws matchers", - "severity": "MINOR", - "description": "
\n

\n Use the \n throwsA\n matcher instead of try-catch with \n fail()\n .\n

\n

\n BAD:\n

\n
\n// sync code\ntry {\n  someSyncFunctionThatThrows();\n  fail('expected Error');\n} on Error catch (error) {\n  expect(error.message, contains('some message'));\n}\n\n// async code\ntry {\n  await someAsyncFunctionThatThrows();\n  fail('expected Error');\n} on Error catch (error) {\n  expect(error.message, contains('some message'));\n}\n\n  
\n

\n GOOD:\n

\n
\n// sync code\nexpect(\n  () => someSyncFunctionThatThrows(),\n  throwsA(isA<Error>().having((Error error) => error.message, 'message', contains('some message'))),\n);\n\n// async code\nawait expectLater(\n  () => someAsyncFunctionThatThrows(),\n  throwsA(isA<Error>().having((Error error) => error.message, 'message', contains('some message'))),\n);\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "5min", - "active": false - }, - { - "key": "use_to_and_as_if_applicable", - "name": "Use to and as if applicable", - "severity": "MINOR", - "description": "
\n

\n From the \n Effective Dart\n :\n

\n

\n PREFER\n naming a method \n to___()\n if it copies the object's state to a new\nobject.\n

\n

\n PREFER\n naming a method \n as___()\n if it returns a different representation\nbacked by the original object.\n

\n

\n BAD:\n

\n
\nclass Bar {\n  Foo myMethod() {\n    return Foo.from(this);\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Bar {\n  Foo toFoo() {\n    return Foo.from(this);\n  }\n}\n\n  
\n

\n GOOD:\n

\n
\nclass Bar {\n  Foo asFoo() {\n    return Foo.from(this);\n  }\n}\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, - { - "key": "depend_on_referenced_packages", - "name": "Depend on referenced packages", - "severity": "MAJOR", - "description": "
\n

\n DO\n depend on referenced packages.\n

\n

When importing a package, add a dependency on it to your pubspec.

\n

Depending explicitly on packages that you reference ensures they will always\nexist and allows you to put a dependency constraint on them to guard you\nagainst breaking changes.

\n

\n Whether this should be a regular dependency or dev_dependency depends on if it\nis referenced from a public file (one under either \n lib\n or \n bin\n ), or some\nother private file.\n

\n

\n BAD:\n

\n
\nimport 'package:a/a.dart';\n\n  
\n
\ndependencies:\n\n  
\n

\n GOOD:\n

\n
\nimport 'package:a/a.dart';\n\n  
\n
\ndependencies:\n  a: ^1.0.0\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "package_names", - "name": "Package names", - "severity": "MINOR", - "description": "
\n

\n From the \n Pubspec format description\n :\n

\n

\n DO\n use \n lowercase_with_underscores\n for package names.\n

\n

\n Package names should be all lowercase, with underscores to separate words,\n\n just_like_this\n . Use only basic Latin letters and Arabic digits: [a-z0-9_].\nAlso, make sure the name is a valid Dart identifier -- that it doesn't start\nwith digits and isn't a reserved word.\n

\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": true - }, - { - "key": "secure_pubspec_urls", - "name": "Secure pubspec urls", - "severity": "MAJOR", - "description": "
\n

\n DO\n Use secure urls in \n pubspec.yaml\n .\n

\n

\n Use \n https\n instead of \n http\n or \n git:\n .\n

\n

\n BAD:\n

\n
\nrepository: http://github.com/dart-lang/example\n\n  
\n
\ngit:\n  url: git://github.com/dart-lang/example/example.git\n\n  
\n

\n GOOD:\n

\n
\nrepository: https://github.com/dart-lang/example\n\n  
\n
\n", - "type": "CODE_SMELL", - "debt": "1min", - "active": false - }, { "key": "abi_specific_integer_invalid", "name": "Abi specific integer invalid", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a class that extends\nAbiSpecificInteger doesn\u2019t meet all of the following requirements:\n @see https://dart.dev/tools/diagnostic-messages#abi_specific_integer_invalid", + "description": "The analyzer produces this diagnostic when a class that extends AbiSpecificInteger doesn't meet all of the following requirements:\n @see https://dart.dev/tools/diagnostic-messages#abi_specific_integer_invalid", "type": "BUG", "debt": "5min", "active": true @@ -1983,7 +12,7 @@ "key": "abstract_field_initializer", "name": "Abstract field initializer", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a field that has the abstract\nmodifier also has an initializer.\n @see https://dart.dev/tools/diagnostic-messages#abstract_field_initializer", + "description": "The analyzer produces this diagnostic when a field that has the abstract modifier also has an initializer.\n @see https://dart.dev/tools/diagnostic-messages#abstract_field_initializer", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -1992,7 +21,7 @@ "key": "argument_type_not_assignable_to_error_handler", "name": "Argument type not assignable to error handler", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an invocation of\nFuture.catchError has an argument that is a function whose parameters\naren\u2019t compatible with the arguments that will be passed to the function\nwhen it\u2019s invoked. The static type of the first argument to catchError\nis just Function, even though the function that is passed in is expected\nto have either a single parameter of type Object or two parameters of\ntype Object and StackTrace.\n @see https://dart.dev/tools/diagnostic-messages#argument_type_not_assignable_to_error_handler", + "description": "The analyzer produces this diagnostic when an invocation of Future.catchError has an argument that is a function whose parameters aren't compatible with the arguments that will be passed to the function when it's invoked. The static type of the first argument to catchError is just Function, even though the function that is passed in is expected to have either a single parameter of type Object or two parameters of type Object and StackTrace.\n @see https://dart.dev/tools/diagnostic-messages#argument_type_not_assignable_to_error_handler", "type": "BUG", "debt": "5min", "active": true @@ -2001,7 +30,7 @@ "key": "body_might_complete_normally", "name": "Body might complete normally", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a method or function has a\nreturn type that\u2019s potentially non-nullable but would implicitly return\nnull if control reached the end of the function.\n @see https://dart.dev/tools/diagnostic-messages#body_might_complete_normally", + "description": "The analyzer produces this diagnostic when a method or function has a return type that's potentially non-nullable but would implicitly return null if control reached the end of the function.\n @see https://dart.dev/tools/diagnostic-messages#body_might_complete_normally", "type": "BUG", "debt": "5min", "active": true @@ -2010,7 +39,7 @@ "key": "conflicting_constructor_and_static_member", "name": "Conflicting constructor and static member", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a named constructor and either a\nstatic method or static field have the same name. Both are accessed using\nthe name of the class, so having the same name makes the reference\nambiguous.\n @see https://dart.dev/tools/diagnostic-messages#conflicting_constructor_and_static_member", + "description": "The analyzer produces this diagnostic when a named constructor and either a static method or static field have the same name. Both are accessed using the name of the class, so having the same name makes the reference ambiguous.\n @see https://dart.dev/tools/diagnostic-messages#conflicting_constructor_and_static_member", "type": "BUG", "debt": "5min", "active": true @@ -2019,7 +48,7 @@ "key": "const_map_key_not_primitive_equality", "name": "Const map key not primitive equality", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when the class of object used as a\nkey in a constant map literal implements either the == operator, the\ngetter hashCode, or both. The implementation of constant maps uses both\nthe == operator and the hashCode getter, so any implementation other\nthan the ones inherited from Object requires executing arbitrary code at\ncompile time, which isn\u2019t supported.\n @see https://dart.dev/tools/diagnostic-messages#const_map_key_not_primitive_equality", + "description": "The analyzer produces this diagnostic when the class of object used as a key in a constant map literal implements either the == operator, the getter hashCode, or both. The implementation of constant maps uses both the == operator and the hashCode getter, so any implementation other than the ones inherited from Object requires executing arbitrary code at compile time, which isn't supported.\n @see https://dart.dev/tools/diagnostic-messages#const_map_key_not_primitive_equality", "type": "BUG", "debt": "5min", "active": true @@ -2028,7 +57,7 @@ "key": "dead_null_aware_expression", "name": "Dead null aware expression", "severity": "MINOR", - "description": "The analyzer produces this diagnostic in two cases.The first is when the left operand of an ?? operator can\u2019t be null.\nThe right operand is only evaluated if the left operand has the value\nnull, and because the left operand can\u2019t be null, the right operand is\nnever evaluated.The second is when the left-hand side of an assignment using the ??=\noperator can\u2019t be null. The right-hand side is only evaluated if the\nleft-hand side has the value null, and because the left-hand side can\u2019t\nbe null, the right-hand side is never evaluated.\n @see https://dart.dev/tools/diagnostic-messages#dead_null_aware_expression", + "description": "The analyzer produces this diagnostic in two cases.The first is when the left operand of an ?? operator can't be null. The right operand is only evaluated if the left operand has the value null, and because the left operand can't be null, the right operand is never evaluated.The second is when the left-hand side of an assignment using the ??= operator can't be null. The right-hand side is only evaluated if the left-hand side has the value null, and because the left-hand side can't be null, the right-hand side is never evaluated.\n @see https://dart.dev/tools/diagnostic-messages#dead_null_aware_expression", "type": "BUG", "debt": "5min", "active": true @@ -2037,7 +66,7 @@ "key": "deprecated_new_in_comment_reference", "name": "Deprecated new in comment reference", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a comment reference (the name\nof a declaration enclosed in square brackets in a documentation comment)\nuses the keyword new to refer to a constructor. This form is deprecated.\n @see https://dart.dev/tools/diagnostic-messages#deprecated_new_in_comment_reference", + "description": "The analyzer produces this diagnostic when a comment reference (the name of a declaration enclosed in square brackets in a documentation comment) uses the keyword new to refer to a constructor. This form is deprecated.\n @see https://dart.dev/tools/diagnostic-messages#deprecated_new_in_comment_reference", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -2046,7 +75,7 @@ "key": "duplicate_constructor", "name": "Duplicate constructor", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a class declares more than one\nunnamed constructor or when it declares more than one constructor with the\nsame name.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_constructor", + "description": "The analyzer produces this diagnostic when a class declares more than one unnamed constructor or when it declares more than one constructor with the same name.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_constructor", "type": "BUG", "debt": "5min", "active": true @@ -2055,7 +84,7 @@ "key": "duplicate_field_name", "name": "Duplicate field name", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when either a record literal or a\nrecord type annotation contains a field whose name is the same as a\npreviously declared field in the same literal or type.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_field_name", + "description": "The analyzer produces this diagnostic when either a record literal or a record type annotation contains a field whose name is the same as a previously declared field in the same literal or type.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_field_name", "type": "BUG", "debt": "5min", "active": true @@ -2064,7 +93,7 @@ "key": "duplicate_ignore", "name": "Duplicate ignore", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a diagnostic name appears in an\nignore comment, but the diagnostic is already being ignored, either\nbecause it\u2019s already included in the same ignore comment or because it\nappears in an ignore-in-file comment.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_ignore", + "description": "The analyzer produces this diagnostic when a diagnostic name appears in an ignore comment, but the diagnostic is already being ignored, either because it's already included in the same ignore comment or because it appears in an ignore-in-file comment.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_ignore", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -2073,7 +102,7 @@ "key": "duplicate_pattern_field", "name": "Duplicate pattern field", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a record pattern matches the\nsame field more than once, or when an object pattern matches the same\ngetter more than once.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_pattern_field", + "description": "The analyzer produces this diagnostic when a record pattern matches the same field more than once, or when an object pattern matches the same getter more than once.\n @see https://dart.dev/tools/diagnostic-messages#duplicate_pattern_field", "type": "BUG", "debt": "5min", "active": true @@ -2082,7 +111,7 @@ "key": "external_with_initializer", "name": "External with initializer", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a field or variable marked with\nthe keyword external has an initializer, or when an external field is\ninitialized in a constructor.\n @see https://dart.dev/tools/diagnostic-messages#external_with_initializer", + "description": "The analyzer produces this diagnostic when a field or variable marked with the keyword external has an initializer, or when an external field is initialized in a constructor.\n @see https://dart.dev/tools/diagnostic-messages#external_with_initializer", "type": "BUG", "debt": "5min", "active": true @@ -2091,7 +120,7 @@ "key": "field_initializer_redirecting_constructor", "name": "Field initializer redirecting constructor", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a redirecting constructor\ninitializes a field in the object. This isn\u2019t allowed because the instance\nthat has the field hasn\u2019t been created at the point at which it should be\ninitialized.\n @see https://dart.dev/tools/diagnostic-messages#field_initializer_redirecting_constructor", + "description": "The analyzer produces this diagnostic when a redirecting constructor initializes a field in the object. This isn't allowed because the instance that has the field hasn't been created at the point at which it should be initialized.\n @see https://dart.dev/tools/diagnostic-messages#field_initializer_redirecting_constructor", "type": "BUG", "debt": "5min", "active": true @@ -2100,7 +129,7 @@ "key": "illegal_concrete_enum_member", "name": "Illegal concrete enum member", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when either an enum declaration, a\nclass that implements Enum, or a mixin with a superclass constraint of\nEnum, declares or inherits a concrete instance member named either\nindex, hashCode, or ==.\n @see https://dart.dev/tools/diagnostic-messages#illegal_concrete_enum_member", + "description": "The analyzer produces this diagnostic when either an enum declaration, a class that implements Enum, or a mixin with a superclass constraint of Enum, declares or inherits a concrete instance member named either index, hashCode, or ==.\n @see https://dart.dev/tools/diagnostic-messages#illegal_concrete_enum_member", "type": "BUG", "debt": "5min", "active": true @@ -2109,7 +138,7 @@ "key": "illegal_enum_values", "name": "Illegal enum values", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when either a class that implements\nEnum or a mixin with a superclass constraint of Enum has an instance\nmember named values.\n @see https://dart.dev/tools/diagnostic-messages#illegal_enum_values", + "description": "The analyzer produces this diagnostic when either a class that implements Enum or a mixin with a superclass constraint of Enum has an instance member named values.\n @see https://dart.dev/tools/diagnostic-messages#illegal_enum_values", "type": "BUG", "debt": "5min", "active": true @@ -2118,7 +147,7 @@ "key": "implicit_super_initializer_missing_arguments", "name": "Implicit super initializer missing arguments", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a constructor implicitly\ninvokes the unnamed constructor from the superclass, the unnamed\nconstructor of the superclass has a required parameter, and there\u2019s no\nsuper parameter corresponding to the required parameter.\n @see https://dart.dev/tools/diagnostic-messages#implicit_super_initializer_missing_arguments", + "description": "The analyzer produces this diagnostic when a constructor implicitly invokes the unnamed constructor from the superclass, the unnamed constructor of the superclass has a required parameter, and there's no super parameter corresponding to the required parameter.\n @see https://dart.dev/tools/diagnostic-messages#implicit_super_initializer_missing_arguments", "type": "BUG", "debt": "5min", "active": true @@ -2127,7 +156,7 @@ "key": "inconsistent_pattern_variable_logical_or", "name": "Inconsistent pattern variable logical or", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a pattern variable that is\ndeclared on all branches of a logical-or pattern doesn\u2019t have the same\ntype on every branch. It is also produced when the variable has a\ndifferent finality on different branches. A pattern variable declared on\nmultiple branches of a logical-or pattern is required to have the same\ntype and finality in each branch, so that the type and finality of the\nvariable can be known in code that\u2019s guarded by the logical-or pattern.\n @see https://dart.dev/tools/diagnostic-messages#inconsistent_pattern_variable_logical_or", + "description": "The analyzer produces this diagnostic when a pattern variable that is declared on all branches of a logical-or pattern doesn't have the same type on every branch. It is also produced when the variable has a different finality on different branches. A pattern variable declared on multiple branches of a logical-or pattern is required to have the same type and finality in each branch, so that the type and finality of the variable can be known in code that's guarded by the logical-or pattern.\n @see https://dart.dev/tools/diagnostic-messages#inconsistent_pattern_variable_logical_or", "type": "BUG", "debt": "5min", "active": true @@ -2136,7 +165,7 @@ "key": "invalid_annotation", "name": "Invalid annotation", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an annotation is found that is\nusing something that is neither a variable marked as const or the\ninvocation of a const constructor.Getters can\u2019t be used as annotations.\n @see https://dart.dev/tools/diagnostic-messages#invalid_annotation", + "description": "The analyzer produces this diagnostic when an annotation is found that is using something that is neither a variable marked as const or the invocation of a const constructor.Getters can't be used as annotations.\n @see https://dart.dev/tools/diagnostic-messages#invalid_annotation", "type": "BUG", "debt": "5min", "active": true @@ -2145,7 +174,7 @@ "key": "invalid_extension_argument_count", "name": "Invalid extension argument count", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an extension override doesn\u2019t\nhave exactly one argument. The argument is the expression used to compute\nthe value of this within the extension method, so there must be one\nargument.\n @see https://dart.dev/tools/diagnostic-messages#invalid_extension_argument_count", + "description": "The analyzer produces this diagnostic when an extension override doesn't have exactly one argument. The argument is the expression used to compute the value of this within the extension method, so there must be one argument.\n @see https://dart.dev/tools/diagnostic-messages#invalid_extension_argument_count", "type": "BUG", "debt": "5min", "active": true @@ -2154,7 +183,7 @@ "key": "invalid_field_name", "name": "Invalid field name", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when either a record literal or a\nrecord type annotation has a field whose name is invalid. The name is\ninvalid if it is:\n @see https://dart.dev/tools/diagnostic-messages#invalid_field_name", + "description": "The analyzer produces this diagnostic when either a record literal or a record type annotation has a field whose name is invalid. The name is invalid if it is:\n @see https://dart.dev/tools/diagnostic-messages#invalid_field_name", "type": "BUG", "debt": "5min", "active": true @@ -2163,7 +192,7 @@ "key": "invalid_literal_annotation", "name": "Invalid literal annotation", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when the [literal][[meta-literal]]\nannotation is applied to anything other than a const constructor.\n @see https://dart.dev/tools/diagnostic-messages#invalid_literal_annotation", + "description": "The analyzer produces this diagnostic when the literal annotation is applied to anything other than a const constructor.\n @see https://dart.dev/tools/diagnostic-messages#invalid_literal_annotation", "type": "BUG", "debt": "5min", "active": true @@ -2172,7 +201,7 @@ "key": "invalid_non_virtual_annotation", "name": "Invalid non virtual annotation", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when the nonVirtual annotation is\nfound on a declaration other than a member of a class, mixin, or enum, or\nif the member isn\u2019t a concrete instance member.\n @see https://dart.dev/tools/diagnostic-messages#invalid_non_virtual_annotation", + "description": "The analyzer produces this diagnostic when the nonVirtual annotation is found on a declaration other than a member of a class, mixin, or enum, or if the member isn't a concrete instance member.\n @see https://dart.dev/tools/diagnostic-messages#invalid_non_virtual_annotation", "type": "BUG", "debt": "5min", "active": true @@ -2181,7 +210,7 @@ "key": "invalid_null_aware_operator", "name": "Invalid null aware operator", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a null-aware operator (?.,\n?.., ?[, ?..[, or ...?) is used on a receiver that\u2019s known to be\nnon-nullable.\n @see https://dart.dev/tools/diagnostic-messages#invalid_null_aware_operator", + "description": "The analyzer produces this diagnostic when a null-aware operator (?., ?.., ?[, ?..[, or ...?) is used on a receiver that's known to be non-nullable.\n @see https://dart.dev/tools/diagnostic-messages#invalid_null_aware_operator", "type": "BUG", "debt": "5min", "active": true @@ -2190,7 +219,7 @@ "key": "invalid_pattern_variable_in_shared_case_scope", "name": "Invalid pattern variable in shared case scope", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when multiple case clauses in a\nswitch statement share a body, and at least one of them declares a\nvariable that is referenced in the shared statements, but the variable is\neither not declared in all of the case clauses or it is declared in\ninconsistent ways.If the variable isn\u2019t declared in all of the case clauses, then it won\u2019t\nhave a value if one of the clauses that doesn\u2019t declare the variable is\nthe one that matches and executes the body. This includes the situation\nwhere one of the case clauses is the default clause.If the variable is declared in inconsistent ways, either being final in\nsome cases and not final in others or having a different type in\ndifferent cases, then the semantics of what the type or finality of the\nvariable should be are not defined.\n @see https://dart.dev/tools/diagnostic-messages#invalid_pattern_variable_in_shared_case_scope", + "description": "The analyzer produces this diagnostic when multiple case clauses in a switch statement share a body, and at least one of them declares a variable that is referenced in the shared statements, but the variable is either not declared in all of the case clauses or it is declared in inconsistent ways.If the variable isn't declared in all of the case clauses, then it won't have a value if one of the clauses that doesn't declare the variable is the one that matches and executes the body. This includes the situation where one of the case clauses is the default clause.If the variable is declared in inconsistent ways, either being final in some cases and not final in others or having a different type in different cases, then the semantics of what the type or finality of the variable should be are not defined.\n @see https://dart.dev/tools/diagnostic-messages#invalid_pattern_variable_in_shared_case_scope", "type": "BUG", "debt": "5min", "active": true @@ -2199,7 +228,7 @@ "key": "invalid_return_type_for_catch_error", "name": "Invalid return type for catch error", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an invocation of\nFuture.catchError has an argument whose return type isn\u2019t compatible with\nthe type returned by the instance of Future. At runtime, the method\ncatchError attempts to return the value from the callback as the result\nof the future, which results in another exception being thrown.\n @see https://dart.dev/tools/diagnostic-messages#invalid_return_type_for_catch_error", + "description": "The analyzer produces this diagnostic when an invocation of Future.catchError has an argument whose return type isn't compatible with the type returned by the instance of Future. At runtime, the method catchError attempts to return the value from the callback as the result of the future, which results in another exception being thrown.\n @see https://dart.dev/tools/diagnostic-messages#invalid_return_type_for_catch_error", "type": "BUG", "debt": "5min", "active": true @@ -2208,7 +237,7 @@ "key": "invalid_super_formal_parameter_location", "name": "Invalid super formal parameter location", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a super parameter is used\nanywhere other than a non-redirecting generative constructor.\n @see https://dart.dev/tools/diagnostic-messages#invalid_super_formal_parameter_location", + "description": "The analyzer produces this diagnostic when a super parameter is used anywhere other than a non-redirecting generative constructor.\n @see https://dart.dev/tools/diagnostic-messages#invalid_super_formal_parameter_location", "type": "BUG", "debt": "5min", "active": true @@ -2217,16 +246,25 @@ "key": "invalid_type_argument_in_const_literal", "name": "Invalid type argument in const literal", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a type parameter is used as a\ntype argument in a list, map, or set literal that is prefixed by const.\nThis isn\u2019t allowed because the value of the type parameter (the actual type\nthat will be used at runtime) can\u2019t be known at compile time.\n @see https://dart.dev/tools/diagnostic-messages#invalid_type_argument_in_const_literal", + "description": "The analyzer produces this diagnostic when a type parameter is used as a type argument in a list, map, or set literal that is prefixed by const. This isn't allowed because the value of the type parameter (the actual type that will be used at runtime) can't be known at compile time.\n @see https://dart.dev/tools/diagnostic-messages#invalid_type_argument_in_const_literal", "type": "BUG", "debt": "5min", "active": true }, + { + "key": "invalid_visible_outside_template_annotation", + "name": "Invalid visible outside template annotation", + "severity": "MINOR", + "description": "The analyzer produces this diagnostic when the @visibleOutsideTemplate annotation is used incorrectly. This annotation is only meant to annotate members of a class, enum, or mixin that has the @visibleForTemplate annotation, to opt those members out of the visibility restrictions that @visibleForTemplate imposes.\n @see https://dart.dev/tools/diagnostic-messages#invalid_visible_outside_template_annotation", + "type": "CODE_SMELL", + "debt": "1min", + "active": true + }, { "key": "invocation_of_non_function_expression", "name": "Invocation of non function expression", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a function invocation is found,\nbut the name being referenced isn\u2019t the name of a function, or when the\nexpression computing the function doesn\u2019t compute a function.\n @see https://dart.dev/tools/diagnostic-messages#invocation_of_non_function_expression", + "description": "The analyzer produces this diagnostic when a function invocation is found, but the name being referenced isn't the name of a function, or when the expression computing the function doesn't compute a function.\n @see https://dart.dev/tools/diagnostic-messages#invocation_of_non_function_expression", "type": "BUG", "debt": "5min", "active": true @@ -2235,7 +273,7 @@ "key": "missing_default_value_for_parameter", "name": "Missing default value for parameter", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an optional parameter, whether\npositional or named, has a potentially non-nullable type and doesn\u2019t\nspecify a default value. Optional parameters that have no explicit default\nvalue have an implicit default value of null. If the type of the\nparameter doesn\u2019t allow the parameter to have a value of null, then the\nimplicit default value isn\u2019t valid.\n @see https://dart.dev/tools/diagnostic-messages#missing_default_value_for_parameter", + "description": "The analyzer produces this diagnostic when an optional parameter, whether positional or named, has a potentially non-nullable type and doesn't specify a default value. Optional parameters that have no explicit default value have an implicit default value of null. If the type of the parameter doesn't allow the parameter to have a value of null, then the implicit default value isn't valid.\n @see https://dart.dev/tools/diagnostic-messages#missing_default_value_for_parameter", "type": "BUG", "debt": "5min", "active": true @@ -2244,7 +282,7 @@ "key": "non_constant_map_element", "name": "Non constant map element", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an if element or a spread\nelement in a constant map isn\u2019t a constant element.\n @see https://dart.dev/tools/diagnostic-messages#non_constant_map_element", + "description": "The analyzer produces this diagnostic when an if element or a spread element in a constant map isn't a constant element.\n @see https://dart.dev/tools/diagnostic-messages#non_constant_map_element", "type": "BUG", "debt": "5min", "active": true @@ -2253,7 +291,7 @@ "key": "not_assigned_potentially_non_nullable_local_variable", "name": "Not assigned potentially non nullable local variable", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a local variable is referenced\nand has all these characteristics:\n @see https://dart.dev/tools/diagnostic-messages#not_assigned_potentially_non_nullable_local_variable", + "description": "The analyzer produces this diagnostic when a local variable is referenced and has all these characteristics:\n @see https://dart.dev/tools/diagnostic-messages#not_assigned_potentially_non_nullable_local_variable", "type": "BUG", "debt": "5min", "active": true @@ -2262,7 +300,7 @@ "key": "not_initialized_non_nullable_instance_field", "name": "Not initialized non nullable instance field", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a field is declared and has all\nthese characteristics:\n @see https://dart.dev/tools/diagnostic-messages#not_initialized_non_nullable_instance_field", + "description": "The analyzer produces this diagnostic when a field is declared and has all these characteristics:\n @see https://dart.dev/tools/diagnostic-messages#not_initialized_non_nullable_instance_field", "type": "BUG", "debt": "5min", "active": true @@ -2271,7 +309,7 @@ "key": "not_initialized_non_nullable_variable", "name": "Not initialized non nullable variable", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a static field or top-level\nvariable has a type that\u2019s non-nullable and doesn\u2019t have an initializer.\nFields and variables that don\u2019t have an initializer are normally\ninitialized to null, but the type of the field or variable doesn\u2019t allow\nit to be set to null, so an explicit initializer must be provided.\n @see https://dart.dev/tools/diagnostic-messages#not_initialized_non_nullable_variable", + "description": "The analyzer produces this diagnostic when a static field or top-level variable has a type that's non-nullable and doesn't have an initializer. Fields and variables that don't have an initializer are normally initialized to null, but the type of the field or variable doesn't allow it to be set to null, so an explicit initializer must be provided.\n @see https://dart.dev/tools/diagnostic-messages#not_initialized_non_nullable_variable", "type": "BUG", "debt": "5min", "active": true @@ -2280,7 +318,7 @@ "key": "recursive_constructor_redirect", "name": "Recursive constructor redirect", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a constructor redirects to\nitself, either directly or indirectly, creating an infinite loop.\n @see https://dart.dev/tools/diagnostic-messages#recursive_constructor_redirect", + "description": "The analyzer produces this diagnostic when a constructor redirects to itself, either directly or indirectly, creating an infinite loop.\n @see https://dart.dev/tools/diagnostic-messages#recursive_constructor_redirect", "type": "BUG", "debt": "5min", "active": true @@ -2289,7 +327,7 @@ "key": "redirect_to_invalid_function_type", "name": "Redirect to invalid function type", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a factory constructor attempts\nto redirect to another constructor, but the two have incompatible\nparameters. The parameters are compatible if all of the parameters of the\nredirecting constructor can be passed to the other constructor and if the\nother constructor doesn\u2019t require any parameters that aren\u2019t declared by\nthe redirecting constructor.\n @see https://dart.dev/tools/diagnostic-messages#redirect_to_invalid_function_type", + "description": "The analyzer produces this diagnostic when a factory constructor attempts to redirect to another constructor, but the two have incompatible parameters. The parameters are compatible if all of the parameters of the redirecting constructor can be passed to the other constructor and if the other constructor doesn't require any parameters that aren't declared by the redirecting constructor.\n @see https://dart.dev/tools/diagnostic-messages#redirect_to_invalid_function_type", "type": "BUG", "debt": "5min", "active": true @@ -2298,7 +336,7 @@ "key": "return_in_generator", "name": "Return in generator", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a generator function (one whose\nbody is marked with either async* or sync*) uses either a return\nstatement to return a value or implicitly returns a value because of using\n=>. In any of these cases, they should use yield instead of return.\n @see https://dart.dev/tools/diagnostic-messages#return_in_generator", + "description": "The analyzer produces this diagnostic when a generator function (one whose body is marked with either async* or sync*) uses either a return statement to return a value or implicitly returns a value because of using =>. In any of these cases, they should use yield instead of return.\n @see https://dart.dev/tools/diagnostic-messages#return_in_generator", "type": "BUG", "debt": "5min", "active": true @@ -2307,7 +345,7 @@ "key": "subtype_of_disallowed_type", "name": "Subtype of disallowed type", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when one of the restricted classes is\nused in either an extends, implements, with, or on clause. The\nclasses bool, double, FutureOr, int, Null, num, and String\nare all restricted in this way, to allow for more efficient\nimplementations.\n @see https://dart.dev/tools/diagnostic-messages#subtype_of_disallowed_type", + "description": "The analyzer produces this diagnostic when one of the restricted classes is used in either an extends, implements, with, or on clause. The classes bool, double, FutureOr, int, Null, num, and String are all restricted in this way, to allow for more efficient implementations.\n @see https://dart.dev/tools/diagnostic-messages#subtype_of_disallowed_type", "type": "BUG", "debt": "5min", "active": true @@ -2316,7 +354,7 @@ "key": "super_formal_parameter_without_associated_positional", "name": "Super formal parameter without associated positional", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when there\u2019s a positional super\nparameter in a constructor and the implicitly or explicitly invoked super\nconstructor doesn\u2019t have a positional parameter at the corresponding\nindex.Positional super parameters are associated with positional parameters in\nthe super constructor by their index. That is, the first super parameter\nis associated with the first positional parameter in the super\nconstructor, the second with the second, and so on.\n @see https://dart.dev/tools/diagnostic-messages#super_formal_parameter_without_associated_positional", + "description": "The analyzer produces this diagnostic when there's a positional super parameter in a constructor and the implicitly or explicitly invoked super constructor doesn't have a positional parameter at the corresponding index.Positional super parameters are associated with positional parameters in the super constructor by their index. That is, the first super parameter is associated with the first positional parameter in the super constructor, the second with the second, and so on.\n @see https://dart.dev/tools/diagnostic-messages#super_formal_parameter_without_associated_positional", "type": "BUG", "debt": "5min", "active": true @@ -2325,7 +363,7 @@ "key": "type_check_with_null", "name": "Type check with null", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when there\u2019s a type check (using the\nas operator) where the type is Null. There\u2019s only one value whose type\nis Null, so the code is both more readable and more performant when it\ntests for null explicitly.\n @see https://dart.dev/tools/diagnostic-messages#type_check_with_null", + "description": "The analyzer produces this diagnostic when there's a type check (using the as operator) where the type is Null. There's only one value whose type is Null, so the code is both more readable and more performant when it tests for null explicitly.\n @see https://dart.dev/tools/diagnostic-messages#type_check_with_null", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -2334,7 +372,7 @@ "key": "type_parameter_supertype_of_its_bound", "name": "Type parameter supertype of its bound", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when the bound of a type parameter\n(the type following the extends keyword) is either directly or indirectly\nthe type parameter itself. Stating that the type parameter must be the same\nas itself or a subtype of itself or a subtype of itself isn\u2019t helpful\nbecause it will always be the same as itself.\n @see https://dart.dev/tools/diagnostic-messages#type_parameter_supertype_of_its_bound", + "description": "The analyzer produces this diagnostic when the bound of a type parameter (the type following the extends keyword) is either directly or indirectly the type parameter itself. Stating that the type parameter must be the same as itself or a subtype of itself or a subtype of itself isn't helpful because it will always be the same as itself.\n @see https://dart.dev/tools/diagnostic-messages#type_parameter_supertype_of_its_bound", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -2343,7 +381,7 @@ "key": "undefined_constructor_in_initializer", "name": "Undefined constructor in initializer", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a superclass constructor is\ninvoked in the initializer list of a constructor, but the superclass\ndoesn\u2019t define the constructor being invoked.\n @see https://dart.dev/tools/diagnostic-messages#undefined_constructor_in_initializer", + "description": "The analyzer produces this diagnostic when a superclass constructor is invoked in the initializer list of a constructor, but the superclass doesn't define the constructor being invoked.\n @see https://dart.dev/tools/diagnostic-messages#undefined_constructor_in_initializer", "type": "BUG", "debt": "5min", "active": true @@ -2352,7 +390,7 @@ "key": "undefined_enum_constructor", "name": "Undefined enum constructor", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when the constructor invoked to\ninitialize an enum constant doesn\u2019t exist.\n @see https://dart.dev/tools/diagnostic-messages#undefined_enum_constructor", + "description": "The analyzer produces this diagnostic when the constructor invoked to initialize an enum value doesn't exist.\n @see https://dart.dev/tools/diagnostic-messages#undefined_enum_constructor", "type": "BUG", "debt": "5min", "active": true @@ -2361,7 +399,7 @@ "key": "undefined_extension_getter", "name": "Undefined extension getter", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an extension override is used to\ninvoke a getter, but the getter isn\u2019t defined by the specified extension.\nThe analyzer also produces this diagnostic when a static getter is\nreferenced but isn\u2019t defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_getter", + "description": "The analyzer produces this diagnostic when an extension override is used to invoke a getter, but the getter isn't defined by the specified extension. The analyzer also produces this diagnostic when a static getter is referenced but isn't defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_getter", "type": "BUG", "debt": "5min", "active": true @@ -2370,7 +408,7 @@ "key": "undefined_extension_method", "name": "Undefined extension method", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an extension override is used to\ninvoke a method, but the method isn\u2019t defined by the specified extension.\nThe analyzer also produces this diagnostic when a static method is\nreferenced but isn\u2019t defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_method", + "description": "The analyzer produces this diagnostic when an extension override is used to invoke a method, but the method isn't defined by the specified extension. The analyzer also produces this diagnostic when a static method is referenced but isn't defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_method", "type": "BUG", "debt": "5min", "active": true @@ -2379,7 +417,7 @@ "key": "undefined_extension_setter", "name": "Undefined extension setter", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an extension override is used to\ninvoke a setter, but the setter isn\u2019t defined by the specified extension.\nThe analyzer also produces this diagnostic when a static setter is\nreferenced but isn\u2019t defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_setter", + "description": "The analyzer produces this diagnostic when an extension override is used to invoke a setter, but the setter isn't defined by the specified extension. The analyzer also produces this diagnostic when a static setter is referenced but isn't defined by the specified extension.\n @see https://dart.dev/tools/diagnostic-messages#undefined_extension_setter", "type": "BUG", "debt": "5min", "active": true @@ -2388,16 +426,25 @@ "key": "undefined_super_member", "name": "Undefined super member", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when an inherited member (method,\ngetter, setter, or operator) is referenced using super, but there\u2019s no\nmember with that name in the superclass chain.\n @see https://dart.dev/tools/diagnostic-messages#undefined_super_member", + "description": "The analyzer produces this diagnostic when an inherited member (method, getter, setter, or operator) is referenced using super, but there's no member with that name in the superclass chain.\n @see https://dart.dev/tools/diagnostic-messages#undefined_super_member", "type": "BUG", "debt": "5min", "active": true }, + { + "key": "unnecessary_final", + "name": "Unnecessary final", + "severity": "MINOR", + "description": "The analyzer produces this diagnostic when either a field initializing parameter or a super parameter in a constructor has the keyword final. In both cases the keyword is unnecessary because the parameter is implicitly final.\n @see https://dart.dev/tools/diagnostic-messages#unnecessary_final", + "type": "CODE_SMELL", + "debt": "5min", + "active": true + }, { "key": "unnecessary_null_comparison", "name": "Unnecessary null comparison", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when it finds an equality comparison\n(either == or !=) with one operand of null and the other operand\ncan\u2019t be null. Such comparisons are always either true or false, so\nthey serve no purpose.\n @see https://dart.dev/tools/diagnostic-messages#unnecessary_null_comparison", + "description": "The analyzer produces this diagnostic when it finds an equality comparison (either == or !=) with one operand of null and the other operand can't be null. Such comparisons are always either true or false, so they serve no purpose.\n @see https://dart.dev/tools/diagnostic-messages#unnecessary_null_comparison", "type": "CODE_SMELL", "debt": "5min", "active": true @@ -2406,7 +453,7 @@ "key": "wrong_number_of_parameters_for_setter", "name": "Wrong number of parameters for setter", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a setter is found that doesn\u2019t\ndeclare exactly one required positional parameter.\n @see https://dart.dev/tools/diagnostic-messages#wrong_number_of_parameters_for_setter", + "description": "The analyzer produces this diagnostic when a setter is found that doesn't declare exactly one required positional parameter.\n @see https://dart.dev/tools/diagnostic-messages#wrong_number_of_parameters_for_setter", "type": "BUG", "debt": "5min", "active": true @@ -2415,7 +462,7 @@ "key": "wrong_number_of_type_arguments", "name": "Wrong number of type arguments", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a type that has type parameters\nis used and type arguments are provided, but the number of type arguments\nisn\u2019t the same as the number of type parameters.The analyzer also produces this diagnostic when a constructor is invoked\nand the number of type arguments doesn\u2019t match the number of type\nparameters declared for the class.\n @see https://dart.dev/tools/diagnostic-messages#wrong_number_of_type_arguments", + "description": "The analyzer produces this diagnostic when a type that has type parameters is used and type arguments are provided, but the number of type arguments isn't the same as the number of type parameters.The analyzer also produces this diagnostic when a constructor is invoked and the number of type arguments doesn't match the number of type parameters declared for the class.\n @see https://dart.dev/tools/diagnostic-messages#wrong_number_of_type_arguments", "type": "BUG", "debt": "5min", "active": true @@ -2424,7 +471,7 @@ "key": "yield_in_non_generator", "name": "Yield in non generator", "severity": "MINOR", - "description": "The analyzer produces this diagnostic when a yield or yield* statement\nappears in a function whose body isn\u2019t marked with one of the async* or\nsync* modifiers.\n @see https://dart.dev/tools/diagnostic-messages#yield_in_non_generator", + "description": "The analyzer produces this diagnostic when a yield or yield* statement appears in a function whose body isn't marked with one of the async* or sync* modifiers.\n @see https://dart.dev/tools/diagnostic-messages#yield_in_non_generator", "type": "BUG", "debt": "5min", "active": true