- Predefined rule sets
- Rule types
- Maturity levels
- Quick fixes
- Error rules
- always_use_package_imports
- avoid_dynamic_calls
- avoid_empty_else
- avoid_print
- avoid_relative_lib_imports
- avoid_returning_null_for_future
- 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
- valid_regexps
- Style rules
- always_declare_return_types
- always_put_control_body_on_new_line
- always_put_required_named_parameters_first
- always_require_non_null_named_parameters
- 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
- 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
- void_checks
- Pub rules
Use the Dart linter to identify possible problems in your Dart code.
You can use the linter through your IDE
or with the dart analyze
command.
For information on how to enable and disable individual linter rules, see
individual rules sections of the analyzer documentation.
This page lists all the linter rules, with details such as when you might want to use each rule, what code patterns trigger it, and how you might fix your code.
Predefined rule sets
To avoid the need to individually select compatible linter rules, consider starting with a linter rule set, which the following packages provide:
- lints
- Contains two rule sets curated by the Dart team.
We recommend using at least the
core
rule set, which is used when scoring packages uploaded to pub.dev. Or, better yet, use therecommended
rule set, a superset ofcore
that identifies additional issues and enforces style and format. If you’re writing Flutter code, use the rule set in theflutter_lints
package, which builds onlints
. - flutter_lints
- Contains the
flutter
rule set, which the Flutter team encourages you to use in Flutter apps, packages, and plugins. This rule set is a superset of therecommended
set, which is itself a superset of thecore
set that partially determines the score of packages uploaded to pub.dev.
To learn how to use a specific rule set, see the documentation for enabling and disabling linter rules.
Rule types
Each rule is in one of the following groups:
- Errors
- Possible errors or mistakes in your code.
- Style
- Matters of style, largely derived from the Dart style guide.
- Pub
- Possible issues with pub package setup.
Maturity levels
Each rule also has a maturity level:
- Stable
- These rules are safe to use and are verified as functional with the latest versions of the Dart language. All rules are considered stable unless they’re marked as experimental or deprecated.
- Experimental
- These rules are still under evaluation and might never be stabilized. Use these with caution and report any issues you come across.
- Deprecated
- These rules are no longer suggested for use and might be removed in a future linter release.
Quick fixes
Some rules can be fixed automatically using quick fixes. A quick fix is an automated edit targeted at fixing the issue reported by the linter rule.
If the rule has a quick fix,
it can be applied using dart fix
or using your editor with Dart support.
To learn more, see Quick fixes for analysis issues.
Error rules
These rules identify possible errors and other mistakes in your code.
always_use_package_imports
Avoid relative imports for files in lib/
.
This rule is available as of Dart 2.10.0.
This rule has a quick fix available.
Incompatible rules: prefer_relative_imports
Details
DO avoid relative imports for files in lib/
.
When mixing relative and absolute imports it’s possible to create confusion
where the same member gets imported in two different ways. One way to avoid
that is to ensure you consistently use absolute imports for files within the
lib/
directory.
This is the opposite of ‘prefer_relative_imports’.
You can also use ‘avoid_relative_lib_imports’ to disallow relative imports of
files within lib/
directory outside of it (for example test/
).
BAD:
import 'baz.dart';
import 'src/bag.dart'
import '../lib/baz.dart';
...
GOOD:
import 'package:foo/bar.dart';
import 'package:foo/baz.dart';
import 'package:foo/src/baz.dart';
...
avoid_dynamic_calls
Avoid method calls or property accesses on a “dynamic” target.
This rule is available as of Dart 2.12.0.
Details
DO avoid method calls or accessing properties on an object that is either explicitly or implicitly statically typed “dynamic”. Dynamic calls are treated slightly different in every runtime environment and compiler, but most production modes (and even some development modes) have both compile size and runtime performance penalties associated with dynamic calls.
Additionally, targets typed “dynamic” disables most static analysis, meaning it is easier to lead to a runtime “NoSuchMethodError” or “NullError” than properly statically typed Dart code.
There is an exception to methods and properties that exist on “Object?”:
- a.hashCode
- a.runtimeType
- a.noSuchMethod(someInvocation)
- a.toString()
… these members are dynamically dispatched in the web-based runtimes, but not
in the VM-based ones. Additionally, they are so common that it would be very
punishing to disallow any.toString()
or any == true
, for example.
Note that despite “Function” being a type, the semantics are close to identical to “dynamic”, and calls to an object that is typed “Function” will also trigger this lint.
BAD:
void explicitDynamicType(dynamic object) {
print(object.foo());
}
void implicitDynamicType(object) {
print(object.foo());
}
abstract class SomeWrapper {
T doSomething<T>();
}
void inferredDynamicType(SomeWrapper wrapper) {
var object = wrapper.doSomething();
print(object.foo());
}
void callDynamic(dynamic function) {
function();
}
void functionType(Function function) {
function();
}
GOOD:
void explicitType(Fooable object) {
object.foo();
}
void castedType(dynamic object) {
(object as Fooable).foo();
}
abstract class SomeWrapper {
T doSomething<T>();
}
void inferredType(SomeWrapper wrapper) {
var object = wrapper.doSomething<Fooable>();
object.foo();
}
void functionTypeWithParameters(Function() function) {
function();
}
avoid_empty_else
Avoid empty else statements.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
AVOID empty else statements.
BAD:
if (x > y)
print("1");
else ;
print("2");
avoid_print
Avoid print
calls in production code.
This rule is available as of Dart 2.5.0.
Rule sets: flutter
This rule has a quick fix available.
Details
DO avoid print
calls in production code.
For production code, consider using a logging framework.
If you are using Flutter, you can use debugPrint
or surround print
calls with a check for kDebugMode
BAD:
void f(int x) {
print('debug: $x');
...
}
GOOD:
void f(int x) {
debugPrint('debug: $x');
...
}
GOOD:
void f(int x) {
log('log: $x');
...
}
GOOD:
void f(int x) {
if (kDebugMode) {
print('debug: $x');
}
...
}
avoid_relative_lib_imports
Avoid relative imports for files in lib/
.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DO avoid relative imports for files in lib/
.
When mixing relative and absolute imports it’s possible to create confusion
where the same member gets imported in two different ways. An easy way to avoid
that is to ensure you have no relative imports that include lib/
in their
paths.
You can also use ‘always_use_package_imports’ to disallow relative imports
between files within lib/
.
BAD:
import 'package:foo/bar.dart';
import '../lib/baz.dart';
...
GOOD:
import 'package:foo/bar.dart';
import 'baz.dart';
...
avoid_returning_null_for_future
Avoid returning null for Future.
This rule is currently deprecated and available as of Dart 2.1.1.
This rule has a quick fix available.
Details
AVOID returning null for Future.
It is almost always wrong to return null
for a Future
. Most of the time the
developer simply forgot to put an async
keyword on the function.
avoid_slow_async_io
Avoid slow async dart:io
methods.
This rule is available as of Dart 2.0.0.
Details
AVOID using the following asynchronous file I/O methods because they are much slower than their synchronous counterparts.
Directory.exists
Directory.stat
File.lastModified
File.exists
File.stat
FileSystemEntity.isDirectory
FileSystemEntity.isFile
FileSystemEntity.isLink
FileSystemEntity.type
BAD:
import 'dart:io';
Future<Null> someFunction() async {
var file = File('/path/to/my/file');
var now = DateTime.now();
if ((await file.lastModified()).isBefore(now)) print('before'); // LINT
}
GOOD:
import 'dart:io';
Future<Null> someFunction() async {
var file = File('/path/to/my/file');
var now = DateTime.now();
if (file.lastModifiedSync().isBefore(now)) print('before'); // OK
}
avoid_type_to_string
Avoid
This rule is available as of Dart 2.12.0.
Details
DO avoid calls to
BAD:
void bar(Object other) {
if (other.runtimeType.toString() == 'Bar') {
doThing();
}
}
Object baz(Thing myThing) {
return getThingFromDatabase(key: myThing.runtimeType.toString());
}
GOOD:
void bar(Object other) {
if (other is Bar) {
doThing();
}
}
class Thing {
String get thingTypeKey => ...
}
Object baz(Thing myThing) {
return getThingFromDatabase(key: myThing.thingTypeKey);
}
avoid_types_as_parameter_names
Avoid types as parameter names.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
AVOID using a parameter name that is the same as an existing type.
BAD:
m(f(int));
GOOD:
m(f(int v));
avoid_web_libraries_in_flutter
Avoid using web-only libraries outside Flutter web plugin packages.
This rule is available as of Dart 2.6.0.
Rule sets: flutter
Details
AVOID using web libraries, dart:html
, dart:js
and
dart:js_util
in Flutter packages that are not web plugins. These libraries are
not supported outside a web context; functionality that depends on them will
fail at runtime in Flutter mobile, and their use is generally discouraged in
Flutter web.
Web library access is allowed in:
- plugin packages that declare
web
as a supported context
otherwise, imports of dart:html
, dart:js
and dart:js_util
are disallowed.
cancel_subscriptions
Cancel instances of dart.async.StreamSubscription.
This rule is available as of Dart 2.0.0.
Details
DO invoke cancel
on instances of dart.async.StreamSubscription
.
Cancelling instances of StreamSubscription prevents memory leaks and unexpected behavior.
BAD:
class A {
StreamSubscription _subscriptionA; // LINT
void init(Stream stream) {
_subscriptionA = stream.listen((_) {});
}
}
BAD:
void someFunction() {
StreamSubscription _subscriptionF; // LINT
}
GOOD:
class B {
StreamSubscription _subscriptionB; // OK
void init(Stream stream) {
_subscriptionB = stream.listen((_) {});
}
void dispose(filename) {
_subscriptionB.cancel();
}
}
GOOD:
void someFunctionOK() {
StreamSubscription _subscriptionB; // OK
_subscriptionB.cancel();
}
close_sinks
Close instances of dart.core.Sink
.
This rule is available as of Dart 2.0.0.
Details
DO invoke close
on instances of dart.core.Sink
.
Closing instances of Sink prevents memory leaks and unexpected behavior.
BAD:
class A {
IOSink _sinkA;
void init(filename) {
_sinkA = File(filename).openWrite(); // LINT
}
}
BAD:
void someFunction() {
IOSink _sinkF; // LINT
}
GOOD:
class B {
IOSink _sinkB;
void init(filename) {
_sinkB = File(filename).openWrite(); // OK
}
void dispose(filename) {
_sinkB.close();
}
}
GOOD:
void someFunctionOK() {
IOSink _sinkFOK; // OK
_sinkFOK.close();
}
collection_methods_unrelated_type
Invocation of various collection methods with arguments of unrelated types.
This rule is available as of Dart 2.19.0.
Details
DON’T invoke certain collection method with an argument with an unrelated type.
Doing this will invoke ==
on the collection’s elements and most likely will
return false
.
An argument passed to a collection method should relate to the collection type as follows:
- an argument to
Iterable<E>.contains
should be related toE
- an argument to
List<E>.remove
should be related toE
- an argument to
Map<K, V>.containsKey
should be related toK
- an argument to
Map<K, V>.containsValue
should be related toV
- an argument to
Map<K, V>.remove
should be related toK
- an argument to
Map<K, V>.[]
should be related toK
- an argument to
Queue<E>.remove
should be related toE
- an argument to
Set<E>.lookup
should be related toE
- an argument to
Set<E>.remove
should be related toE
BAD:
void someFunction() {
var list = <int>[];
if (list.contains('1')) print('someFunction'); // LINT
}
BAD:
void someFunction() {
var set = <int>{};
set.remove('1'); // LINT
}
GOOD:
void someFunction() {
var list = <int>[];
if (list.contains(1)) print('someFunction'); // OK
}
GOOD:
void someFunction() {
var set = <int>{};
set.remove(1); // OK
}
comment_references
Only reference in scope identifiers in doc comments.
This rule is available as of Dart 2.0.0.
Details
DO reference only in scope identifiers in doc comments.
If you surround things like variable, method, or type names in square brackets,
then dart doc
will look
up the name and link to its docs. For this all to work, ensure that all
identifiers in docs wrapped in brackets are in scope.
For example, assuming outOfScopeId
is out of scope:
BAD:
/// Return true if [value] is larger than [outOfScopeId].
bool isOutOfRange(int value) { ... }
GOOD:
/// Return the larger of [a] or [b].
int max_int(int a, int b) { ... }
Note that the square bracket comment format is designed to allow comments to refer to declarations using a fairly natural format but does not allow arbitrary expressions. In particular, code references within square brackets can consist of either
- a single identifier where the identifier is any identifier in scope for the comment (see the spec for what is in scope in doc comments),
- two identifiers separated by a period where the first identifier is the name of a class that is in scope and the second is the name of a member declared in the class,
- a single identifier followed by a pair of parentheses where the identifier is the name of a class that is in scope (used to refer to the unnamed constructor for the class), or
- two identifiers separated by a period and followed by a pair of parentheses where the first identifier is the name of a class that is in scope and the second is the name of a named constructor (not strictly necessary, but allowed for consistency).
control_flow_in_finally
Avoid control flow in finally blocks.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
AVOID control flow leaving finally blocks.
Using control flow in finally blocks will inevitably cause unexpected behavior that is hard to debug.
BAD:
class BadReturn {
double nonCompliantMethod() {
try {
return 1 / 0;
} catch (e) {
print(e);
} finally {
return 1.0; // LINT
}
}
}
BAD:
class BadContinue {
double nonCompliantMethod() {
for (var o in [1, 2]) {
try {
print(o / 0);
} catch (e) {
print(e);
} finally {
continue; // LINT
}
}
return 1.0;
}
}
BAD:
class BadBreak {
double nonCompliantMethod() {
for (var o in [1, 2]) {
try {
print(o / 0);
} catch (e) {
print(e);
} finally {
break; // LINT
}
}
return 1.0;
}
}
GOOD:
class Ok {
double compliantMethod() {
var i = 5;
try {
i = 1 / 0;
} catch (e) {
print(e); // OK
}
return i;
}
}
deprecated_member_use_from_same_package
Avoid using deprecated elements from within the package in which they are declared.
This rule is available as of Dart 3.0.0.
Details
Elements which are annotated with @deprecated
should not be referenced from
within the package in which they are declared.
AVOID using deprecated elements.
…
BAD:
// Declared in one library:
class Foo {
@Deprecated("Use 'm2' instead")
void m1() {}
void m2({
@Deprecated('This is an old parameter') int? p,
})
}
@Deprecated('Do not use')
int x = 0;
// In the same or another library, but within the same package:
void m(Foo foo) {
foo.m1();
foo.m2(p: 7);
x = 1;
}
Deprecated elements can be used from within other deprecated elements, in order to allow for the deprecation of a collection of APIs together as one unit.
GOOD:
// Declared in one library:
class Foo {
@Deprecated("Use 'm2' instead")
void m1() {}
void m2({
@Deprecated('This is an old parameter') int? p,
})
}
@Deprecated('Do not use')
int x = 0;
// In the same or another library, but within the same package:
@Deprecated('Do not use')
void m(Foo foo) {
foo.m1();
foo.m2(p: 7);
x = 1;
}
diagnostic_describe_all_properties
DO reference all public properties in debug methods.
This rule is available as of Dart 2.3.0.
This rule has a quick fix available.
Details
DO reference all public properties in debug
method implementations.
Implementers of Diagnosticable
should reference all public properties in
a debugFillProperties(...)
or debugDescribeChildren(...)
method
implementation to improve debuggability at runtime.
Public properties are defined as fields and getters that are
- not package-private (e.g., prefixed with
_
) - not
static
or overriding - not themselves
Widget
s or collections ofWidget
s
In addition, the “debug” prefix is treated specially for properties in Flutter.
For the purposes of diagnostics, a property foo
and a prefixed property
debugFoo
are treated as effectively describing the same property and it is
sufficient to refer to one or the other.
BAD:
class Absorber extends Widget {
bool get absorbing => _absorbing;
bool _absorbing;
bool get ignoringSemantics => _ignoringSemantics;
bool _ignoringSemantics;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
// Missing reference to ignoringSemantics
}
}
GOOD:
class Absorber extends Widget {
bool get absorbing => _absorbing;
bool _absorbing;
bool get ignoringSemantics => _ignoringSemantics;
bool _ignoringSemantics;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
properties.add(DiagnosticsProperty<bool>('ignoringSemantics', ignoringSemantics));
}
}
discarded_futures
Don’t invoke asynchronous functions in non-async blocks.
This rule is available as of Dart 2.18.0.
This rule has a quick fix available.
Details
Making asynchronous calls in non-async
functions is usually the sign of a
programming error. In general these functions should be marked async
and such
futures should likely be awaited (as enforced by unawaited_futures
).
DON’T invoke asynchronous functions in non-async
blocks.
BAD:
void recreateDir(String path) {
deleteDir(path);
createDir(path);
}
Future<void> deleteDir(String path) async {}
Future<void> createDir(String path) async {}
GOOD:
Future<void> recreateDir(String path) async {
await deleteDir(path);
await createDir(path);
}
Future<void> deleteDir(String path) async {}
Future<void> createDir(String path) async {}
empty_statements
Avoid empty statements.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID empty statements.
Empty statements almost always indicate a bug.
For example,
BAD:
if (complicated.expression.foo());
bar();
Formatted with dart format
the bug becomes obvious:
if (complicated.expression.foo()) ;
bar();
Better to avoid the empty statement altogether.
GOOD:
if (complicated.expression.foo())
bar();
hash_and_equals
Always override hashCode
if overriding ==
.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DO override hashCode
if overriding ==
and prefer overriding ==
if
overriding hashCode
.
Every object in Dart has a hashCode
. Both the ==
operator and the
hashCode
property of objects must be consistent in order for a common hash
map implementation to function properly. Thus, when overriding ==
, the
hashCode
should also be overridden to maintain consistency. Similarly, if
hashCode
is overridden, ==
should be also.
BAD:
class Bad {
final int value;
Bad(this.value);
@override
bool operator ==(Object other) => other is Bad && other.value == value;
}
GOOD:
class Better {
final int value;
Better(this.value);
@override
bool operator ==(Object other) =>
other is Better &&
other.runtimeType == runtimeType &&
other.value == value;
@override
int get hashCode => value.hashCode;
}
implicit_reopen
Don’t implicitly reopen classes.
This rule is currently experimental and available as of Dart 3.0.0.
This rule has a quick fix available.
Details
Using an interface
, base
, final
, or sealed
modifier on a class,
or a base
modifier on a mixin,
authors can control whether classes and mixins allow being implemented,
extended, and/or mixed in from outside of the library where they’re defined.
In some cases, it’s possible for an author to inadvertently relax these controls
and implicitly “reopen” a class. (A similar reopening cannot occur with a mixin.)
This lint guards against unintentionally reopening a class by requiring such
cases to be made explicit with the
@reopen
annotation in package:meta
.
BAD:
interface class I {}
class C extends I {} // LINT
GOOD:
interface class I {}
final class C extends I {}
interface class I {}
final class C extends I {}
import 'package:meta/meta.dart';
interface class I {}
@reopen
class C extends I {}
invalid_case_patterns
Use case expressions that are valid in Dart 3.0.
This rule is currently experimental and available as of Dart 3.0.0.
This rule has a quick fix available.
Details
Some case expressions that are valid in Dart 2.19 and below will become an error or have changed semantics when a library is upgraded to 3.0. This lint flags those expressions in order to ease migration to Dart 3.0.
Some valid switch cases in 2.19 will become compile errors in Dart 3.0:
- Set literals
- Parenthesized expressions
- Calls to
identical()
. - Unary operator expressions
!
,-
, or~
(except for-
before an integer literal, which is a valid pattern and is fine) - Binary operator expressions
!=
,==
,&
,|
,^
,~/
,>>
,>>>
,<<
,+
,-
,*
,/
,%
,<
,<=
,>
,>=
,??
. - Conditional operator
?:
-
.length
calls on strings -
is
andis!
expressions
Examples of all of them:
switch (obj) {
case {1}: // Set literal.
case (1): // Parenthesized expression.
case identical(1, 2): // `identical()` call.
case -pi: // Unary operator.
case 1 + 2: // Binary operator.
case true ? 1 : 2: // Conditional operator.
case 'hi'.length: // .length call.
case i is int: // is expression.
}
Some valid switch cases in 2.19 are also syntactically valid patterns, but the pattern matching behavior may be different from the current constant equality behavior. They are:
List and map literals. A list or map literal can appear as a constant in a case:
switch (obj) {
case [1, 2]: ...
case {'k': 'v'}: ...
}
Currently, the case will only match if the incoming value has the same identity as the constant. So:
test(List<int> list) {
switch (list) {
case [1, 2]: print('Matched'); break;
default: print('Did not match'); break;
}
}
main() {
test(const [1, 2]); // Prints "Matched".
test([1, 2]); // Prints "Did not match".
}
With patterns, a list or map literal becomes a list or map pattern. The pattern destructures the incoming object and matches if the subpatterns all match. In other words, list and map pattern match using something more like deep equality.
With Dart 3.0, the above program prints “Matched” twice.
Constant constructor calls. Similar to collections, you can construct a constant instance of a class in a case:
class Point {
final int x;
final int y;
const Point({this.x, this.y});
}
test(Point p) {
switch (p) {
case Point(x: 1, y: 2): print('Matched'); break;
default: print('Did not match'); break;
}
}
main() {
test(const Point(1, 2)); // Prints "Matched".
test(Point(1, 2)); // Prints "Did not match".
}
Again, like collections, the case currently only matches if the incoming value
has the same identity. With patterns, the Point(...)
syntax becomes an object
pattern that destructures the incoming point, calls the x
and y
getters on
it and then matches the results of those against the corresponding subpatterns.
In this example, it will print “Matched” twice.
Note that object patterns only support named fields. So any constant constructor in a case today that has positional arguments will become a compile-time error when parsed as a pattern. A constant constructor call with no arguments is a valid object pattern and only does a type test:
class Thing {
const Thing();
}
test(Thing t) {
switch (t) {
case Thing(): print('Matched'); break;
default: print('Did not match'); break;
}
}
main() {
test(const Thing()); // Prints "Matched".
test(Thing()); // Prints "Did not match".
}
When interpreted as a pattern, this prints “Matched” twice.
Wildcards. Today, you can have a constant named _
:
test(int n) {
const _ = 3;
switch (n) {
case _: print('Matched'); break;
default: print('Did not match'); break;
}
}
main() {
test(3); // Prints "Matched".
test(5); // Prints "Did not match".
}
With patterns, the identifier _
is treated as a pattern that matches all
values, so this prints “Matched” twice.
Logic operators. The logic operators &&
and ||
are valid constant
expressions and also valid patterns. As a constant expression, they simply
evaluate the expression to a boolean and match if the incoming value is equal to
that boolean value. So:
test(bool b) {
switch (b) {
case true && false: print('Matched'); break;
default: print('Did not match'); break;
}
}
main() {
test(false); // Prints "Matched".
test(true); // Prints "Did not match".
}
With Dart 3.0, these become patterns. The above example prints “Did not match” twice because no boolean value can be both true and false.
Many of invalid cases can be mechanically changed to something that is valid both in Dart today and valid and means the same in Dart 3.0.
Parenthesized expressions: Provided the inner expression is one that’s not broken in Dart 3.0, just discard the parentheses.
List literals, map literals, set literals, and constant constructor calls:
Put const
before the literal or call. This turns it into a constant pattern
which preserves the current behavior:
BAD:
case [1, 2]:
case {'k': 'v'}:
case {1, 2}:
case Point(1, 2):
GOOD:
case const [1, 2]:
case const {'k': 'v'}:
case const {1, 2}:
case const Point(1, 2):
-
Wildcards: Rename the constant from
_
to something else. Since the name is private, this can be done locally in the library without affecting other code. -
Everything else: For any other invalid expression, you have to hoist the expression out into a new named constant. For example, if you have code like this:
BAD:
switch (n) {
case 1 + 2: ...
}
It can be fixed by changing it to:
GOOD:
const three = 1 + 2;
switch (n) {
case three: ...
}
invariant_booleans
Conditions should not unconditionally evaluate to true
or to false
.
This rule has been removed as of the latest Dart releases.
Details
DON’T test for conditions that can be inferred at compile time or test the same condition twice.
Conditional statements using a condition which cannot be anything but false
have the effect of making blocks of code non-functional. If the condition
cannot evaluate to anything but true
, the conditional statement is completely
redundant, and makes the code less readable.
It is quite likely that the code does not match the programmer’s intent.
Either the condition should be removed or it should be updated so that it does
not always evaluate to true
or false
and does not perform redundant tests.
This rule will hint to the test conflicting with the linted one.
BAD:
// foo can't be both equal and not equal to bar in the same expression
if(foo == bar && something && foo != bar) {...}
BAD:
void compute(int foo) {
if (foo == 4) {
doSomething();
// we know foo is equal to 4 at this point, so the next condition is always false
if (foo > 4) {...}
...
}
...
}
BAD:
void compute(bool foo) {
if (foo) {
return;
}
doSomething();
// foo is always false here
if (foo){...}
...
}
GOOD:
void nestedOK() {
if (foo == bar) {
foo = baz;
if (foo != bar) {...}
}
}
GOOD:
void nestedOk2() {
if (foo == bar) {
return;
}
foo = baz;
if (foo == bar) {...} // OK
}
GOOD:
void nestedOk5() {
if (foo != null) {
if (bar != null) {
return;
}
}
if (bar != null) {...} // OK
}
iterable_contains_unrelated_type
Invocation of Iterable
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DON’T invoke contains
on Iterable
with an instance of different type
than the parameter type.
Doing this will invoke ==
on its elements and most likely will return false
.
BAD:
void someFunction() {
var list = <int>[];
if (list.contains('1')) print('someFunction'); // LINT
}
BAD:
void someFunction3() {
List<int> list = <int>[];
if (list.contains('1')) print('someFunction3'); // LINT
}
BAD:
void someFunction8() {
List<DerivedClass2> list = <DerivedClass2>[];
DerivedClass3 instance;
if (list.contains(instance)) print('someFunction8'); // LINT
}
BAD:
abstract class SomeIterable<E> implements Iterable<E> {}
abstract class MyClass implements SomeIterable<int> {
bool badMethod(String thing) => this.contains(thing); // LINT
}
GOOD:
void someFunction10() {
var list = [];
if (list.contains(1)) print('someFunction10'); // OK
}
GOOD:
void someFunction1() {
var list = <int>[];
if (list.contains(1)) print('someFunction1'); // OK
}
GOOD:
void someFunction4() {
List<int> list = <int>[];
if (list.contains(1)) print('someFunction4'); // OK
}
GOOD:
void someFunction5() {
List<ClassBase> list = <ClassBase>[];
DerivedClass1 instance;
if (list.contains(instance)) print('someFunction5'); // OK
}
abstract class ClassBase {}
class DerivedClass1 extends ClassBase {}
GOOD:
void someFunction6() {
List<Mixin> list = <Mixin>[];
DerivedClass2 instance;
if (list.contains(instance)) print('someFunction6'); // OK
}
abstract class ClassBase {}
abstract class Mixin {}
class DerivedClass2 extends ClassBase with Mixin {}
GOOD:
void someFunction7() {
List<Mixin> list = <Mixin>[];
DerivedClass3 instance;
if (list.contains(instance)) print('someFunction7'); // OK
}
abstract class ClassBase {}
abstract class Mixin {}
class DerivedClass3 extends ClassBase implements Mixin {}
list_remove_unrelated_type
Invocation of remove
with references of unrelated types.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DON’T invoke remove
on List
with an instance of different type than
the parameter type.
Doing this will invoke ==
on its elements and most likely will
return false
.
BAD:
void someFunction() {
var list = <int>[];
if (list.remove('1')) print('someFunction'); // LINT
}
BAD:
void someFunction3() {
List<int> list = <int>[];
if (list.remove('1')) print('someFunction3'); // LINT
}
BAD:
void someFunction8() {
List<DerivedClass2> list = <DerivedClass2>[];
DerivedClass3 instance;
if (list.remove(instance)) print('someFunction8'); // LINT
}
BAD:
abstract class SomeList<E> implements List<E> {}
abstract class MyClass implements SomeList<int> {
bool badMethod(String thing) => this.remove(thing); // LINT
}
GOOD:
void someFunction10() {
var list = [];
if (list.remove(1)) print('someFunction10'); // OK
}
GOOD:
void someFunction1() {
var list = <int>[];
if (list.remove(1)) print('someFunction1'); // OK
}
GOOD:
void someFunction4() {
List<int> list = <int>[];
if (list.remove(1)) print('someFunction4'); // OK
}
GOOD:
void someFunction5() {
List<ClassBase> list = <ClassBase>[];
DerivedClass1 instance;
if (list.remove(instance)) print('someFunction5'); // OK
}
abstract class ClassBase {}
class DerivedClass1 extends ClassBase {}
GOOD:
void someFunction6() {
List<Mixin> list = <Mixin>[];
DerivedClass2 instance;
if (list.remove(instance)) print('someFunction6'); // OK
}
abstract class ClassBase {}
abstract class Mixin {}
class DerivedClass2 extends ClassBase with Mixin {}
GOOD:
void someFunction7() {
List<Mixin> list = <Mixin>[];
DerivedClass3 instance;
if (list.remove(instance)) print('someFunction7'); // OK
}
abstract class ClassBase {}
abstract class Mixin {}
class DerivedClass3 extends ClassBase implements Mixin {}
literal_only_boolean_expressions
Boolean expression composed only with literals.
This rule is available as of Dart 2.0.0.
Details
DON’T test for conditions composed only by literals, since the value can be inferred at compile time.
Conditional statements using a condition which cannot be anything but FALSE have
the effect of making blocks of code non-functional. If the condition cannot
evaluate to anything but true
, the conditional statement is completely
redundant, and makes the code less readable.
It is quite likely that the code does not match the programmer’s intent.
Either the condition should be removed or it should be updated so that it does
not always evaluate to true
or false
.
BAD:
void bad() {
if (true) {} // LINT
}
BAD:
void bad() {
if (true && 1 != 0) {} // LINT
}
BAD:
void bad() {
if (1 != 0 && true) {} // LINT
}
BAD:
void bad() {
if (1 < 0 && true) {} // LINT
}
BAD:
void bad() {
if (true && false) {} // LINT
}
BAD:
void bad() {
if (1 != 0) {} // LINT
}
BAD:
void bad() {
if (true && 1 != 0 || 3 < 4) {} // LINT
}
BAD:
void bad() {
if (1 != 0 || 3 < 4 && true) {} // LINT
}
NOTE: that an exception is made for the common while (true) { }
idiom,
which is often reasonably preferred to the equivalent for (;;)
.
GOOD:
void good() {
while (true) {
// Do stuff.
}
}
no_adjacent_strings_in_list
Don’t use adjacent strings in list.
This rule is available as of Dart 2.0.0.
Details
DON’T use adjacent strings in a list.
This can indicate a forgotten comma.
BAD:
List<String> list = <String>[
'a'
'b',
'c',
];
GOOD:
List<String> list = <String>[
'a' +
'b',
'c',
];
no_duplicate_case_values
Don’t use more than one case with same value.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DON’T use more than one case with same value.
This is usually a typo or changed value of constant.
BAD:
const int A = 1;
switch (v) {
case 1:
case 2:
case A:
case 2:
}
GOOD:
const int A = 1;
switch (v) {
case A:
case 2:
}
NOTE: this lint only reports duplicate cases in libraries opted in to Dart 2.19 and below. In Dart 3.0 and after, duplicate cases are reported as dead code by the analyzer.
no_logic_in_create_state
Don’t put any logic in createState.
This rule is available as of Dart 2.8.1.
Rule sets: flutter
Details
DON’T put any logic in createState()
.
Implementations of createState()
should return a new instance
of a State object and do nothing more. Since state access is preferred
via the widget
field, passing data to State
objects using custom
constructor parameters should also be avoided and so further, the State
constructor is required to be passed no arguments.
BAD:
MyState global;
class MyStateful extends StatefulWidget {
@override
MyState createState() {
global = MyState();
return global;
}
}
class MyStateful extends StatefulWidget {
@override
MyState createState() => MyState()..field = 42;
}
class MyStateful extends StatefulWidget {
@override
MyState createState() => MyState(42);
}
GOOD:
class MyStateful extends StatefulWidget {
@override
MyState createState() {
return MyState();
}
}
prefer_relative_imports
Prefer relative imports for files in lib/
.
This rule is available as of Dart 2.6.0.
This rule has a quick fix available.
Incompatible rules: always_use_package_imports
Details
PREFER relative imports for files in lib/
.
When mixing relative and absolute imports it’s possible to create confusion
where the same member gets imported in two different ways. One way to avoid
that is to ensure you consistently use relative imports for files within the
lib/
directory.
BAD:
import 'package:my_package/bar.dart';
GOOD:
import 'bar.dart';
prefer_void_to_null
Don’t use the Null type, unless you are positive that you don’t want void.
This rule is available as of Dart 2.1.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T use the type Null where void would work.
BAD:
Null f() {}
Future<Null> f() {}
Stream<Null> f() {}
f(Null x) {}
GOOD:
void f() {}
Future<void> f() {}
Stream<void> f() {}
f(void x) {}
Some exceptions include formulating special function types:
Null Function(Null, Null);
and for making empty literals which are safe to pass into read-only locations for any type of map or list:
<Null>[];
<int, Null>{};
test_types_in_equals
Test type arguments in operator ==(Object other).
This rule is available as of Dart 2.0.0.
Details
DO test type arguments in operator ==(Object other).
Not testing types might result in null pointer exceptions which will be unexpected for consumers of your class.
BAD:
class Field {
}
class Bad {
final Field someField;
Bad(this.someField);
@override
bool operator ==(Object other) {
Bad otherBad = other as Bad; // LINT
bool areEqual = otherBad != null && otherBad.someField == someField;
return areEqual;
}
@override
int get hashCode {
return someField.hashCode;
}
}
GOOD:
class Field {
}
class Good {
final Field someField;
Good(this.someField);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
return other is Good &&
this.someField == other.someField;
}
@override
int get hashCode {
return someField.hashCode;
}
}
throw_in_finally
Avoid throw
in finally block.
This rule is available as of Dart 2.0.0.
Details
AVOID throwing exceptions in finally blocks.
Throwing exceptions in finally blocks will inevitably cause unexpected behavior that is hard to debug.
BAD:
class BadThrow {
double nonCompliantMethod() {
try {
print('hello world! ${1 / 0}');
} catch (e) {
print(e);
} finally {
throw 'Find the hidden error :P'; // LINT
}
}
}
GOOD:
class Ok {
double compliantMethod() {
var i = 5;
try {
i = 1 / 0;
} catch (e) {
print(e); // OK
}
return i;
}
}
unnecessary_statements
Avoid using unnecessary statements.
This rule is available as of Dart 2.0.0.
Details
AVOID using unnecessary statements.
Statements which have no clear effect are usually unnecessary, or should be broken up.
For example,
BAD:
myvar;
list.clear;
1 + 2;
methodOne() + methodTwo();
foo ? bar : baz;
Though the added methods have a clear effect, the addition itself does not unless there is some magical overload of the + operator.
Usually code like this indicates an incomplete thought, and is a bug.
GOOD:
some.method();
const SomeClass();
methodOne();
methodTwo();
foo ? bar() : baz();
return myvar;
unrelated_type_equality_checks
Equality operator ==
invocation with references of unrelated types.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DON’T Compare references of unrelated types for equality.
Comparing references of a type where neither is a subtype of the other most
likely will return false
and might not reflect programmer’s intent.
Int64
and Int32
from package:fixnum
allow comparing to int
provided
the int
is on the right hand side. The lint allows this as a special case.
BAD:
void someFunction() {
var x = '1';
if (x == 1) print('someFunction'); // LINT
}
BAD:
void someFunction1() {
String x = '1';
if (x == 1) print('someFunction1'); // LINT
}
BAD:
void someFunction13(DerivedClass2 instance) {
var other = DerivedClass3();
if (other == instance) print('someFunction13'); // LINT
}
class ClassBase {}
class DerivedClass1 extends ClassBase {}
abstract class Mixin {}
class DerivedClass2 extends ClassBase with Mixin {}
class DerivedClass3 extends ClassBase implements Mixin {}
GOOD:
void someFunction2() {
var x = '1';
var y = '2';
if (x == y) print(someFunction2); // OK
}
GOOD:
void someFunction3() {
for (var i = 0; i < 10; i++) {
if (i == 0) print(someFunction3); // OK
}
}
GOOD:
void someFunction4() {
var x = '1';
if (x == null) print(someFunction4); // OK
}
GOOD:
void someFunction7() {
List someList;
if (someList.length == 0) print('someFunction7'); // OK
}
GOOD:
void someFunction8(ClassBase instance) {
DerivedClass1 other;
if (other == instance) print('someFunction8'); // OK
}
GOOD:
void someFunction10(unknown) {
var what = unknown - 1;
for (var index = 0; index < unknown; index++) {
if (what == index) print('someFunction10'); // OK
}
}
GOOD:
void someFunction11(Mixin instance) {
var other = DerivedClass2();
if (other == instance) print('someFunction11'); // OK
if (other != instance) print('!someFunction11'); // OK
}
class ClassBase {}
abstract class Mixin {}
class DerivedClass2 extends ClassBase with Mixin {}
unsafe_html
Avoid unsafe HTML APIs.
This rule is available as of Dart 2.4.0.
Details
AVOID
- assigning directly to the
href
field of an AnchorElement - assigning directly to the
src
field of an EmbedElement, IFrameElement, or ScriptElement - assigning directly to the
srcdoc
field of an IFrameElement - calling the
createFragment
method of Element - calling the
open
method of Window - calling the
setInnerHtml
method of Element - calling the
Element.html
constructor - calling the
DocumentFragment.html
constructor
BAD:
var script = ScriptElement()..src = 'foo.js';
use_build_context_synchronously
Do not use BuildContexts across async gaps.
This rule is currently experimental and available as of Dart 2.13.0.
Rule sets: flutter
Details
DON’T use BuildContext across asynchronous gaps.
Storing BuildContext
for later usage can easily lead to difficult to diagnose
crashes. Asynchronous gaps are implicitly storing BuildContext
and are some of
the easiest to overlook when writing code.
When a BuildContext
is used, its mounted
property must be checked after an
asynchronous gap.
BAD:
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
}
GOOD:
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
GOOD:
void onButtonTapped() async {
await Future.delayed(const Duration(seconds: 1));
if (!context.mounted) return;
Navigator.of(context).pop();
}
use_key_in_widget_constructors
Use key in widget constructors.
This rule is available as of Dart 2.8.1.
Rule sets: flutter
This rule has a quick fix available.
Details
DO use key in widget constructors.
It’s a good practice to expose the ability to provide a key when creating public widgets.
BAD:
class MyPublicWidget extends StatelessWidget {
}
GOOD:
class MyPublicWidget extends StatelessWidget {
MyPublicWidget({super.key});
}
valid_regexps
Use valid regular expression syntax.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DO use valid regular expression syntax when creating regular expression instances.
Regular expressions created with invalid syntax will throw a FormatException
at runtime so should be avoided.
BAD:
print(RegExp(r'(').hasMatch('foo()'));
GOOD:
print(RegExp(r'\(').hasMatch('foo()'));
Style rules
These rules identify opportunities for style improvements, largely derived from the Dart style guide.
always_declare_return_types
Declare method return types.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO declare method return types.
When declaring a method or function always specify a return type. Declaring return types for functions helps improve your codebase by allowing the analyzer to more adequately check your code for errors that could occur during runtime.
BAD:
main() { }
_bar() => _Foo();
class _Foo {
_foo() => 42;
}
GOOD:
void main() { }
_Foo _bar() => _Foo();
class _Foo {
int _foo() => 42;
}
typedef predicate = bool Function(Object o);
always_put_control_body_on_new_line
Separate the control structure expression from its statement.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
From the style guide for the flutter repo:
DO separate the control structure expression from its statement.
Don’t put the statement part of an if
, for
, while
, do
on the same line
as the expression, even if it is short. Doing so makes it unclear that there
is relevant code there. This is especially important for early returns.
BAD:
if (notReady) return;
if (notReady)
return;
else print('ok')
while (condition) i += 1;
GOOD:
if (notReady)
return;
if (notReady)
return;
else
print('ok')
while (condition)
i += 1;
Note that this rule can conflict with the Dart formatter, and should not be enabled when the Dart formatter is used.
always_put_required_named_parameters_first
Put required named parameters first.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO specify required
on named parameter before other named parameters.
BAD:
m({b, c, required a}) ;
GOOD:
m({required a, b, c}) ;
BAD:
m({b, c, @required a}) ;
GOOD:
m({@required a, b, c}) ;
always_require_non_null_named_parameters
Specify @required
on named parameters without defaults.
This rule is currently deprecated and available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO specify @required
on named parameters without a default value on which
an assert(param != null)
is done.
BAD:
m1({a}) {
assert(a != null);
}
GOOD:
m1({@required a}) {
assert(a != null);
}
m2({a: 1}) {
assert(a != null);
}
NOTE: Only asserts at the start of the bodies will be taken into account.
always_specify_types
Specify type annotations.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Incompatible rules: avoid_types_on_closure_parameters, omit_local_variable_types
Details
From the style guide for the flutter repo:
DO specify type annotations.
Avoid var
when specifying that a type is unknown and short-hands that elide
type annotations. Use dynamic
if you are being explicit that the type is
unknown. Use Object
if you are being explicit that you want an object that
implements ==
and hashCode
.
BAD:
var foo = 10;
final bar = Bar();
const quux = 20;
GOOD:
int foo = 10;
final Bar bar = Bar();
String baz = 'hello';
const int quux = 20;
NOTE: Using the the @optionalTypeArgs
annotation in the meta
package, API
authors can special-case type variables whose type needs to by dynamic but whose
declaration should be treated as optional. For example, suppose you have a
Key
object whose type parameter you’d like to treat as optional. Using the
@optionalTypeArgs
would look like this:
import 'package:meta/meta.dart';
@optionalTypeArgs
class Key<T> {
...
}
main() {
Key s = Key(); // OK!
}
annotate_overrides
Annotate overridden members.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO annotate overridden methods and fields.
This practice improves code readability and helps protect against unintentionally overriding superclass members.
BAD:
class Cat {
int get lives => 9;
}
class Lucky extends Cat {
final int lives = 14;
}
GOOD:
abstract class Dog {
String get breed;
void bark() {}
}
class Husky extends Dog {
@override
final String breed = 'Husky';
@override
void bark() {}
}
avoid_annotating_with_dynamic
Avoid annotating with dynamic when not required.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
AVOID annotating with dynamic when not required.
As dynamic
is the assumed return value of a function or method, it is usually
not necessary to annotate it.
BAD:
dynamic lookUpOrDefault(String name, Map map, dynamic defaultValue) {
var value = map[name];
if (value != null) return value;
return defaultValue;
}
GOOD:
lookUpOrDefault(String name, Map map, defaultValue) {
var value = map[name];
if (value != null) return value;
return defaultValue;
}
avoid_as
Avoid using as
.
This rule has been removed as of the latest Dart releases.
Details
AVOID using as
.
If you know the type is correct, use an assertion or assign to a more
narrowly-typed variable (this avoids the type check in release mode; as
is not
compiled out in release mode). If you don’t know whether the type is
correct, check using is
(this avoids the exception that as
raises).
BAD:
(pm as Person).firstName = 'Seth';
GOOD:
if (pm is Person)
pm.firstName = 'Seth';
but certainly not
BAD:
try {
(pm as Person).firstName = 'Seth';
} on CastError { }
Note that an exception is made in the case of dynamic
since the cast has no
performance impact.
OK:
HasScrollDirection scrollable = renderObject as dynamic;
avoid_bool_literals_in_conditional_expressions
Avoid bool literals in conditional expressions.
This rule is available as of Dart 2.0.0.
Details
AVOID bool literals in conditional expressions.
BAD:
condition ? true : boolExpression
condition ? false : boolExpression
condition ? boolExpression : true
condition ? boolExpression : false
GOOD:
condition || boolExpression
!condition && boolExpression
!condition || boolExpression
condition && boolExpression
avoid_catches_without_on_clauses
Avoid catches without on clauses.
This rule is available as of Dart 2.0.0.
Details
AVOID catches without on clauses.
Using catch clauses without on clauses make your code prone to encountering unexpected errors that won’t be thrown (and thus will go unnoticed).
BAD:
try {
somethingRisky()
}
catch(e) {
doSomething(e);
}
GOOD:
try {
somethingRisky()
}
on Exception catch(e) {
doSomething(e);
}
avoid_catching_errors
Don’t explicitly catch Error or types that implement it.
This rule is available as of Dart 2.0.0.
Details
DON’T explicitly catch Error or types that implement it.
Errors differ from Exceptions in that Errors can be analyzed and prevented prior to runtime. It should almost never be necessary to catch an error at runtime.
BAD:
try {
somethingRisky();
} on Error catch(e) {
doSomething(e);
}
GOOD:
try {
somethingRisky();
} on Exception catch(e) {
doSomething(e);
}
avoid_classes_with_only_static_members
Avoid defining a class that contains only static members.
This rule is available as of Dart 2.0.0.
Details
From Effective Dart:
AVOID defining a class that contains only static members.
Creating classes with the sole purpose of providing utility or otherwise static methods is discouraged. Dart allows functions to exist outside of classes for this very reason.
BAD:
class DateUtils {
static DateTime mostRecent(List<DateTime> dates) {
return dates.reduce((a, b) => a.isAfter(b) ? a : b);
}
}
class _Favorites {
static const mammal = 'weasel';
}
GOOD:
DateTime mostRecent(List<DateTime> dates) {
return dates.reduce((a, b) => a.isAfter(b) ? a : b);
}
const _favoriteMammal = 'weasel';
avoid_double_and_int_checks
Avoid double and int checks.
This rule is available as of Dart 2.0.0.
Details
AVOID to check if type is double or int.
When compiled to JS, integer values are represented as floats. That can lead to
some unexpected behavior when using either is
or is!
where the type is
either int
or double
.
BAD:
f(num x) {
if (x is double) {
...
} else if (x is int) {
...
}
}
GOOD:
f(dynamic x) {
if (x is num) {
...
} else {
...
}
}
avoid_equals_and_hash_code_on_mutable_classes
Avoid overloading operator == and hashCode on classes not marked @immutable
.
This rule is available as of Dart 2.6.0.
Details
AVOID overloading operator == and hashCode on classes not marked @immutable
.
If a class is not immutable, overloading operator == and hashCode can lead to unpredictable and undesirable behavior when used in collections. See https://dart.dev/guides/language/effective-dart/design#avoid-defining-custom-equality-for-mutable-classes for more information.
BAD:
class B {
String key;
const B(this.key);
@override
operator ==(other) => other is B && other.key == key;
@override
int get hashCode => key.hashCode;
}
GOOD:
@immutable
class A {
final String key;
const A(this.key);
@override
operator ==(other) => other is A && other.key == key;
@override
int get hashCode => key.hashCode;
}
NOTE: The lint checks the use of the @immutable
annotation, and will trigger
even if the class is otherwise not mutable. Thus:
BAD:
class C {
final String key;
const C(this.key);
@override
operator ==(other) => other is C && other.key == key;
@override
int get hashCode => key.hashCode;
}
avoid_escaping_inner_quotes
Avoid escaping inner quotes by converting surrounding quotes.
This rule is available as of Dart 2.8.1.
This rule has a quick fix available.
Details
Avoid escaping inner quotes by converting surrounding quotes.
BAD:
var s = 'It\'s not fun';
GOOD:
var s = "It's not fun";
avoid_field_initializers_in_const_classes
Avoid field initializers in const classes.
This rule is available as of Dart 2.0.0.
Details
AVOID field initializers in const classes.
Instead of final x = const expr;
, you should write get x => const expr;
and
not allocate a useless field. As of April 2018 this is true for the VM, but not
for code that will be compiled to JS.
BAD:
class A {
final a = const [];
const A();
}
GOOD:
class A {
get a => const [];
const A();
}
avoid_final_parameters
Avoid final for parameter declarations.
This rule is available as of Dart 2.16.0.
Incompatible rules: prefer_final_parameters
Details
AVOID declaring parameters as final.
Declaring parameters as final can lead to unnecessarily verbose code, especially when using the “parameter_assignments” rule.
BAD:
void goodParameter(final String label) { // LINT
print(label);
}
GOOD:
void badParameter(String label) { // OK
print(label);
}
BAD:
void goodExpression(final int value) => print(value); // LINT
GOOD:
void badExpression(int value) => print(value); // OK
BAD:
[1, 4, 6, 8].forEach((final value) => print(value + 2)); // LINT
GOOD:
[1, 4, 6, 8].forEach((value) => print(value + 2)); // OK
avoid_function_literals_in_foreach_calls
Avoid using forEach
with a function literal.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID using forEach
with a function literal.
The for
loop enables a developer to be clear and explicit as to their intent.
A return in the body of the for
loop returns from the body of the function,
where as a return in the body of the forEach
closure only returns a value
for that iteration of the forEach
. The body of a for
loop can contain
await
s, while the closure body of a forEach
cannot.
BAD:
people.forEach((person) {
...
});
GOOD:
for (var person in people) {
...
}
avoid_implementing_value_types
Don’t implement classes that override ==
.
This rule is available as of Dart 2.1.0.
Details
DON’T implement classes that override ==
.
The ==
operator is contractually required to be an equivalence relation;
that is, symmetrically for all objects o1
and o2
, o1 == o2
and o2 == o1
must either both be true, or both be false.
NOTE: Dart does not have true value types, so instead we consider a class that implements
==
as a proxy for identifying value types.
When using implements
, you do not inherit the method body of ==
, making it
nearly impossible to follow the contract of ==
. Classes that override ==
typically are usable directly in tests without creating mocks or fakes as
well. For example, for a given class Size
:
class Size {
final int inBytes;
const Size(this.inBytes);
@override
bool operator ==(Object other) => other is Size && other.inBytes == inBytes;
@override
int get hashCode => inBytes.hashCode;
}
BAD:
class CustomSize implements Size {
final int inBytes;
const CustomSize(this.inBytes);
int get inKilobytes => inBytes ~/ 1000;
}
BAD:
import 'package:test/test.dart';
import 'size.dart';
class FakeSize implements Size {
int inBytes = 0;
}
void main() {
test('should not throw on a size >1Kb', () {
expect(() => someFunction(FakeSize()..inBytes = 1001), returnsNormally);
});
}
GOOD:
class ExtendedSize extends Size {
ExtendedSize(int inBytes) : super(inBytes);
int get inKilobytes => inBytes ~/ 1000;
}
GOOD::
import 'package:test/test.dart';
import 'size.dart';
void main() {
test('should not throw on a size >1Kb', () {
expect(() => someFunction(Size(1001)), returnsNormally);
});
}
avoid_init_to_null
Don’t explicitly initialize variables to null.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From Effective Dart:
DON’T explicitly initialize variables to null
.
If a variable has a non-nullable type or is final
,
Dart reports a compile error if you try to use it
before it has been definitely initialized.
If the variable is nullable and not const
or final
,
then it is implicitly initialized to null
for you.
There’s no concept of “uninitialized memory” in Dart
and no need to explicitly initialize a variable to null
to be “safe”.
Adding = null
is redundant and unneeded.
BAD:
Item? bestDeal(List<Item> cart) {
Item? bestItem = null;
for (final item in cart) {
if (bestItem == null || item.price < bestItem.price) {
bestItem = item;
}
}
return bestItem;
}
GOOD:
Item? bestDeal(List<Item> cart) {
Item? bestItem;
for (final item in cart) {
if (bestItem == null || item.price < bestItem.price) {
bestItem = item;
}
}
return bestItem;
}
avoid_js_rounded_ints
Avoid JavaScript rounded ints.
This rule is available as of Dart 2.0.0.
Details
AVOID integer literals that cannot be represented exactly when compiled to JavaScript.
When a program is compiled to JavaScript int
and double
become JavaScript
Numbers. Too large integers (value < Number.MIN_SAFE_INTEGER
or
value > Number.MAX_SAFE_INTEGER
) may be rounded to the closest Number value.
For instance 1000000000000000001
cannot be represented exactly as a JavaScript
Number, so 1000000000000000000
will be used instead.
BAD:
int value = 9007199254740995;
GOOD:
BigInt value = BigInt.parse('9007199254740995');
avoid_multiple_declarations_per_line
Don’t declare multiple variables on a single line.
This rule is available as of Dart 2.13.0.
Details
DON’T declare multiple variables on a single line.
BAD:
String? foo, bar, baz;
GOOD:
String? foo;
String? bar;
String? baz;
avoid_null_checks_in_equality_operators
Don’t check for null in custom == operators.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T check for null in custom == operators.
As null is a special value, no instance of any class (other than Null
) can be
equivalent to it. Thus, it is redundant to check whether the other instance is
null.
BAD:
class Person {
final String? name;
@override
operator ==(Object? other) =>
other != null && other is Person && name == other.name;
}
GOOD:
class Person {
final String? name;
@override
operator ==(Object? other) => other is Person && name == other.name;
}
avoid_positional_boolean_parameters
Avoid positional boolean parameters.
This rule is available as of Dart 2.0.0.
Details
AVOID positional boolean parameters.
Positional boolean parameters are a bad practice because they are very ambiguous. Using named boolean parameters is much more readable because it inherently describes what the boolean value represents.
BAD:
Task(true);
Task(false);
ListBox(false, true, true);
Button(false);
GOOD:
Task.oneShot();
Task.repeating();
ListBox(scroll: true, showScrollbars: true);
Button(ButtonState.enabled);
avoid_private_typedef_functions
Avoid private typedef functions.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
AVOID private typedef functions used only once. Prefer inline function syntax.
BAD:
typedef void _F();
m(_F f);
GOOD:
m(void Function() f);
avoid_redundant_argument_values
Avoid redundant argument values.
This rule is available as of Dart 2.8.1.
This rule has a quick fix available.
Details
DON’T pass an argument that matches the corresponding parameter’s default value.
BAD:
void f({bool valWithDefault = true, bool? val}) {
...
}
void main() {
f(valWithDefault: true);
}
GOOD:
void f({bool valWithDefault = true, bool? val}) {
...
}
void main() {
f(valWithDefault: false);
f();
}
avoid_renaming_method_parameters
Don’t rename parameters of overridden methods.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T rename parameters of overridden methods.
Methods that override another method, but do not have their own documentation
comment, will inherit the overridden method’s comment when dart doc
produces
documentation. If the inherited method contains the name of the parameter (in
square brackets), then dart doc
cannot link it correctly.
BAD:
abstract class A {
m(a);
}
abstract class B extends A {
m(b);
}
GOOD:
abstract class A {
m(a);
}
abstract class B extends A {
m(a);
}
avoid_return_types_on_setters
Avoid return types on setters.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID return types on setters.
As setters do not return a value, declaring the return type of one is redundant.
BAD:
void set speed(int ms);
GOOD:
set speed(int ms);
avoid_returning_null
Avoid returning null from members whose return type is bool, double, int, or num.
This rule is currently deprecated and available as of Dart 2.0.0.
Details
AVOID returning null from members whose return type is bool, double, int, or num.
Functions that return primitive types such as bool, double, int, and num are generally expected to return non-nullable values. Thus, returning null where a primitive type was expected can lead to runtime exceptions.
BAD:
bool getBool() => null;
num getNum() => null;
int getInt() => null;
double getDouble() => null;
GOOD:
bool getBool() => false;
num getNum() => -1;
int getInt() => -1;
double getDouble() => -1.0;
avoid_returning_null_for_void
Avoid returning null for void.
This rule is available as of Dart 2.1.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID returning null for void.
In a large variety of languages void
as return type is used to indicate that
a function doesn’t return anything. Dart allows returning null
in functions
with void
return type but it also allow using return;
without specifying any
value. To have a consistent way you should not return null
and only use an
empty return.
BAD:
void f1() {
return null;
}
Future<void> f2() async {
return null;
}
GOOD:
void f1() {
return;
}
Future<void> f2() async {
return;
}
avoid_returning_this
Avoid returning this from methods just to enable a fluent interface.
This rule is available as of Dart 2.0.0.
Details
AVOID returning this from methods just to enable a fluent interface.
Returning this
from a method is redundant; Dart has a cascade operator which
allows method chaining universally.
Returning this
is allowed for:
- operators
- methods with a return type different of the current class
- methods defined in parent classes / mixins or interfaces
- methods defined in extensions
BAD:
var buffer = StringBuffer()
.write('one')
.write('two')
.write('three');
GOOD:
var buffer = StringBuffer()
..write('one')
..write('two')
..write('three');
avoid_setters_without_getters
Avoid setters without getters.
This rule is available as of Dart 2.0.0.
Details
DON’T define a setter without a corresponding getter.
Defining a setter without defining a corresponding getter can lead to logical inconsistencies. Doing this could allow you to set a property to some value, but then upon observing the property’s value, it could easily be different.
BAD:
class Bad {
int l, r;
set length(int newLength) {
r = l + newLength;
}
}
GOOD:
class Good {
int l, r;
int get length => r - l;
set length(int newLength) {
r = l + newLength;
}
}
avoid_shadowing_type_parameters
Avoid shadowing type parameters.
This rule is available as of Dart 2.1.1.
Rule sets: core, recommended, flutter
Details
AVOID shadowing type parameters.
BAD:
class A<T> {
void fn<T>() {}
}
GOOD:
class A<T> {
void fn<U>() {}
}
avoid_single_cascade_in_expression_statements
Avoid single cascade in expression statements.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID single cascade in expression statements.
BAD:
o..m();
GOOD:
o.m();
avoid_types_on_closure_parameters
Avoid annotating types for function expression parameters.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Incompatible rules: always_specify_types
Details
AVOID annotating types for function expression parameters.
Annotating types for function expression parameters is usually unnecessary because the parameter types can almost always be inferred from the context, thus making the practice redundant.
BAD:
var names = people.map((Person person) => person.name);
GOOD:
var names = people.map((person) => person.name);
avoid_unnecessary_containers
Avoid unnecessary containers.
This rule is available as of Dart 2.7.0.
Rule sets: flutter
This rule has a quick fix available.
Details
AVOID wrapping widgets in unnecessary containers.
Wrapping a widget in Container
with no other parameters set has no effect
and makes code needlessly more complex.
BAD:
Widget buildRow() {
return Container(
child: Row(
children: <Widget>[
const MyLogo(),
const Expanded(
child: Text('...'),
),
],
)
);
}
GOOD:
Widget buildRow() {
return Row(
children: <Widget>[
const MyLogo(),
const Expanded(
child: Text('...'),
),
],
);
}
avoid_unused_constructor_parameters
Avoid defining unused parameters in constructors.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
AVOID defining unused parameters in constructors.
BAD:
class BadOne {
BadOne(int unusedParameter, [String unusedPositional]);
}
class BadTwo {
int c;
BadTwo(int a, int b, int x) {
c = a + b;
}
}
avoid_void_async
Avoid async functions that return void.
This rule is available as of Dart 2.1.0.
This rule has a quick fix available.
Details
DO mark async functions as returning Future
When declaring an async method or function which does not return a value,
declare that it returns Future<void>
and not just void
.
BAD:
void f() async {}
void f2() async => null;
GOOD:
Future<void> f() async {}
Future<void> f2() async => null;
EXCEPTION:
An exception is made for top-level main
functions, where the Future
annotation can (and generally should) be dropped in favor of void
.
GOOD:
Future<void> f() async {}
void main() async {
await f();
}
await_only_futures
Await only futures.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
AVOID using await on anything which is not a future.
Await is allowed on the types: Future<X>
, FutureOr<X>
, Future<X>?
,
FutureOr<X>?
and dynamic
.
Further, using await null
is specifically allowed as a way to introduce a
microtask delay.
BAD:
main() async {
print(await 23);
}
GOOD:
main() async {
await null; // If a delay is really intended.
print(23);
}
camel_case_extensions
Name extensions using UpperCamelCase.
This rule is available as of Dart 2.6.0.
Rule sets: core, recommended, flutter
Details
From the style guide:
DO name extensions using UpperCamelCase
.
Extensions should capitalize the first letter of each word (including the first word), and use no separators.
GOOD:
extension MyFancyList<T> on List<T> {
// ...
}
extension SmartIterable<T> on Iterable<T> {
// ...
}
camel_case_types
Name types using UpperCamelCase.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
From the style guide:
DO name types using UpperCamelCase.
Classes and typedefs should capitalize the first letter of each word (including the first word), and use no separators.
GOOD:
class SliderMenu {
// ...
}
class HttpRequest {
// ...
}
typedef num Adder(num x, num y);
cascade_invocations
Cascade consecutive method invocations on the same reference.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO Use the cascading style when successively invoking methods on the same reference.
BAD:
SomeClass someReference = SomeClass();
someReference.firstMethod();
someReference.secondMethod();
BAD:
SomeClass someReference = SomeClass();
...
someReference.firstMethod();
someReference.aProperty = value;
someReference.secondMethod();
GOOD:
SomeClass someReference = SomeClass()
..firstMethod()
..aProperty = value
..secondMethod();
GOOD:
SomeClass someReference = SomeClass();
...
someReference
..firstMethod()
..aProperty = value
..secondMethod();
cast_nullable_to_non_nullable
Don’t cast a nullable value to a non nullable type.
This rule is available as of Dart 2.12.0.
Details
DON’T cast a nullable value to a non nullable type. This hides a null check and most of the time it is not what is expected.
BAD:
class A {}
class B extends A {}
A? a;
var v = a as B;
var v = a as A;
GOOD:
class A {}
class B extends A {}
A? a;
var v = a! as B;
var v = a!;
combinators_ordering
Sort combinator names alphabetically.
This rule is available as of Dart 2.19.0.
This rule has a quick fix available.
Details
DO sort combinator names alphabetically.
BAD:
import 'a.dart' show B, A hide D, C;
export 'a.dart' show B, A hide D, C;
GOOD:
import 'a.dart' show A, B hide C, D;
export 'a.dart' show A, B hide C, D;
conditional_uri_does_not_exist
Missing conditional import.
This rule is available as of Dart 2.16.0.
Details
DON’T reference files that do not exist in conditional imports.
Code may fail at runtime if the condition evaluates such that the missing file needs to be imported.
BAD:
import 'file_that_does_exist.dart'
if (condition) 'file_that_does_not_exist.dart';
GOOD:
import 'file_that_does_exist.dart'
if (condition) 'file_that_also_does_exist.dart';
constant_identifier_names
Prefer using lowerCamelCase for constant names.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
PREFER using lowerCamelCase for constant names.
In new code, use lowerCamelCase
for constant variables, including enum values.
In existing code that uses ALL_CAPS_WITH_UNDERSCORES
for constants, you may
continue to use all caps to stay consistent.
BAD:
const PI = 3.14;
const kDefaultTimeout = 1000;
final URL_SCHEME = RegExp('^([a-z]+):');
class Dice {
static final NUMBER_GENERATOR = Random();
}
GOOD:
const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');
class Dice {
static final numberGenerator = Random();
}
curly_braces_in_flow_control_structures
DO use curly braces for all flow control structures.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DO use curly braces for all flow control structures.
Doing so avoids the dangling else problem.
BAD:
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;
GOOD:
if (isWeekDay) {
print('Bike to work!');
} else {
print('Go dancing or read a book!');
}
There is one exception to this: an if
statement with no else
clause where
the entire if
statement and the then body all fit in one line. In that case,
you may leave off the braces if you prefer:
GOOD:
if (arg == null) return defaultValue;
If the body wraps to the next line, though, use braces:
GOOD:
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}
dangling_library_doc_comments
Attach library doc comments to library directives.
This rule is available as of Dart 2.19.0.
This rule has a quick fix available.
Details
Attach library doc comments (with ///
) to library directives, rather than
leaving them dangling near the top of a library.
BAD:
/// This is a great library.
import 'package:math';
/// This is a great library.
class C {}
GOOD:
/// This is a great library.
library;
import 'package:math';
class C {}
NOTE: An unnamed library, like library;
above, is only supported in Dart
2.19 and later. Code which might run in earlier versions of Dart will need to
provide a name in the library
directive.
deprecated_consistency
Missing deprecated annotation.
This rule is available as of Dart 2.13.0.
Details
DO apply @Deprecated()
consistently:
- if a class is deprecated, its constructors should also be deprecated.
- if a field is deprecated, the constructor parameter pointing to it should also be deprecated.
- if a constructor parameter pointing to a field is deprecated, the field should also be deprecated.
BAD:
@deprecated
class A {
A();
}
class B {
B({this.field});
@deprecated
Object field;
}
GOOD:
@deprecated
class A {
@deprecated
A();
}
class B {
B({@deprecated this.field});
@deprecated
Object field;
}
class C extends B {
C({@deprecated super.field});
}
directives_ordering
Adhere to Effective Dart Guide directives sorting conventions.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO follow the directive ordering conventions in Effective Dart:
DO place dart:
imports before other imports.
BAD:
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'dart:async'; // LINT
import 'dart:html'; // LINT
BAD:
import 'dart:html'; // OK
import 'package:bar/bar.dart';
import 'dart:async'; // LINT
import 'package:foo/foo.dart';
GOOD:
import 'dart:async'; // OK
import 'dart:html'; // OK
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
DO place package:
imports before relative imports.
BAD:
import 'a.dart';
import 'b.dart';
import 'package:bar/bar.dart'; // LINT
import 'package:foo/foo.dart'; // LINT
BAD:
import 'package:bar/bar.dart'; // OK
import 'a.dart';
import 'package:foo/foo.dart'; // LINT
import 'b.dart';
GOOD:
import 'package:bar/bar.dart'; // OK
import 'package:foo/foo.dart'; // OK
import 'a.dart';
import 'b.dart';
DO specify exports in a separate section after all imports.
BAD:
import 'src/error.dart';
export 'src/error.dart'; // LINT
import 'src/string_source.dart';
GOOD:
import 'src/error.dart';
import 'src/string_source.dart';
export 'src/error.dart'; // OK
DO sort sections alphabetically.
BAD:
import 'package:foo/bar.dart'; // OK
import 'package:bar/bar.dart'; // LINT
import 'a/b.dart'; // OK
import 'a.dart'; // LINT
GOOD:
import 'package:bar/bar.dart'; // OK
import 'package:foo/bar.dart'; // OK
import 'a.dart'; // OK
import 'a/b.dart'; // OK
do_not_use_environment
Do not use environment declared variables.
This rule is available as of Dart 2.9.0.
Details
Using values derived from the environment at compile-time, creates hidden global state and makes applications hard to understand and maintain.
DON’T use fromEnvironment
or hasEnvironment
factory constructors.
BAD:
const loggingLevel =
bool.hasEnvironment('logging') ? String.fromEnvironment('logging') : null;
empty_catches
Avoid empty catch blocks.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
AVOID empty catch blocks.
In general, empty catch blocks should be avoided. In cases where they are
intended, a comment should be provided to explain why exceptions are being
caught and suppressed. Alternatively, the exception identifier can be named with
underscores (e.g., _
) to indicate that we intend to skip it.
BAD:
try {
...
} catch(exception) { }
GOOD:
try {
...
} catch(e) {
// ignored, really.
}
// Alternatively:
try {
...
} catch(_) { }
// Better still:
try {
...
} catch(e) {
doSomething(e);
}
empty_constructor_bodies
Use ;
instead of {}
for empty constructor bodies.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From the style guide:
DO use ;
instead of {}
for empty constructor bodies.
In Dart, a constructor with an empty body can be terminated with just a semicolon. This is required for const constructors. For consistency and brevity, other constructors should also do this.
BAD:
class Point {
int x, y;
Point(this.x, this.y) {}
}
GOOD:
class Point {
int x, y;
Point(this.x, this.y);
}
enable_null_safety
Do use sound null safety.
This rule has been removed as of the latest Dart releases.
Details
DO use sound null safety, by not specifying a dart version lower than 2.12
.
BAD:
// @dart=2.8
a() {
}
GOOD:
b() {
}
eol_at_end_of_file
Put a single newline at end of file.
This rule is available as of Dart 2.14.0.
This rule has a quick fix available.
Details
DO put a single newline at the end of non-empty files.
BAD:
a {
}
GOOD:
b {
}
<-- newline
exhaustive_cases
Define case clauses for all constants in enum-like classes.
This rule is available as of Dart 2.9.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Switching on instances of enum-like classes should be exhaustive.
Enum-like classes are defined as concrete (non-abstract) classes that have:
- only private non-factory constructors
- two or more static const fields whose type is the enclosing class and
- no subclasses of the class in the defining library
DO define case clauses for all constants in enum-like classes.
BAD:
class EnumLike {
final int i;
const EnumLike._(this.i);
static const e = EnumLike._(1);
static const f = EnumLike._(2);
static const g = EnumLike._(3);
}
void bad(EnumLike e) {
// Missing case.
switch(e) { // LINT
case EnumLike.e :
print('e');
break;
case EnumLike.f :
print('f');
break;
}
}
GOOD:
class EnumLike {
final int i;
const EnumLike._(this.i);
static const e = EnumLike._(1);
static const f = EnumLike._(2);
static const g = EnumLike._(3);
}
void ok(EnumLike e) {
// All cases covered.
switch(e) { // OK
case EnumLike.e :
print('e');
break;
case EnumLike.f :
print('f');
break;
case EnumLike.g :
print('g');
break;
}
}
file_names
Name source files using lowercase_with_underscores
.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DO name source files using lowercase_with_underscores
.
Some file systems are not case-sensitive, so many projects require filenames to be all lowercase. Using a separating character allows names to still be readable in that form. Using underscores as the separator ensures that the name is still a valid Dart identifier, which may be helpful if the language later supports symbolic imports.
BAD:
SliderMenu.dart
filesystem.dart
file-system.dart
GOOD:
slider_menu.dart
file_system.dart
Files without a strict .dart
extension are ignored. For example:
OK:
file-system.g.dart
SliderMenu.css.dart
The lint library_names
can be used to enforce the same kind of naming on the
library.
flutter_style_todos
Use Flutter TODO format: // TODO(username): message, https://URL-to-issue.
This rule is available as of Dart 2.1.0.
Details
DO use Flutter TODO format.
From the Flutter docs:
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.
GOOD:
// TODO(username): message.
// TODO(username): message, https://URL-to-issue.
implementation_imports
Don’t import implementation files from another package.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
From the the pub package layout doc:
DON’T import implementation files from another package.
The libraries inside lib
are publicly visible: other packages are free to
import them. But much of a package’s code is internal implementation libraries
that should only be imported and used by the package itself. Those go inside a
subdirectory of lib
called src
. You can create subdirectories in there if
it helps you organize things.
You are free to import libraries that live in lib/src
from within other Dart
code in the same package (like other libraries in lib
, scripts in bin
,
and tests) but you should never import from another package’s lib/src
directory. Those files are not part of the package’s public API, and they
might change in ways that could break your code.
BAD:
// In 'road_runner'
import 'package:acme/src/internals.dart';
implicit_call_tearoffs
Explicitly tear-off call
methods when using an object as a Function.
This rule is available as of Dart 2.19.0.
This rule has a quick fix available.
Details
DO
Explicitly tear off .call
methods from objects when assigning to a Function
type. There is less magic with an explicit tear off. Future language versions
may remove the implicit call tear off.
BAD:
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
callIt(Callable());
GOOD:
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
callIt(Callable().call);
join_return_with_assignment
Join return statement with assignment when possible.
This rule is available as of Dart 2.0.0.
Details
DO join return statement with assignment when possible.
BAD:
class A {
B _lazyInstance;
static B get instance {
_lazyInstance ??= B(); // LINT
return _lazyInstance;
}
}
GOOD:
class A {
B _lazyInstance;
static B get instance => _lazyInstance ??= B();
}
leading_newlines_in_multiline_strings
Start multiline strings with a newline.
This rule is available as of Dart 2.8.1.
This rule has a quick fix available.
Details
Multiline strings are easier to read when they start with a newline (a newline starting a multiline string is ignored).
BAD:
var s1 = '''{
"a": 1,
"b": 2
}''';
GOOD:
var s1 = '''
{
"a": 1,
"b": 2
}''';
var s2 = '''This one-liner multiline string is ok. It usually allows to escape both ' and " in the string.''';
library_annotations
Attach library annotations to library directives.
This rule is available as of Dart 2.19.0.
This rule has a quick fix available.
Details
Attach library annotations to library directives, rather than some other library-level element.
BAD:
@TestOn('browser')
import 'package:test/test.dart';
void main() {}
GOOD:
@TestOn('browser')
library;
import 'package:test/test.dart';
void main() {}
NOTE: An unnamed library, like library;
above, is only supported in Dart
2.19 and later. Code which might run in earlier versions of Dart will need to
provide a name in the library
directive.
library_names
Name libraries using lowercase_with_underscores
.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
DO name libraries using lowercase_with_underscores
.
Some file systems are not case-sensitive, so many projects require filenames to be all lowercase. Using a separating character allows names to still be readable in that form. Using underscores as the separator ensures that the name is still a valid Dart identifier, which may be helpful if the language later supports symbolic imports.
BAD:
library peg-parser;
GOOD:
library peg_parser;
The lint file_names
can be used to enforce the same kind of naming on the
file.
library_prefixes
Use lowercase_with_underscores
when specifying a library prefix.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
DO use lowercase_with_underscores
when specifying a library prefix.
BAD:
import 'dart:math' as Math;
import 'dart:json' as JSON;
import 'package:js/js.dart' as JS;
import 'package:javascript_utils/javascript_utils.dart' as jsUtils;
GOOD:
import 'dart:math' as math;
import 'dart:json' as json;
import 'package:js/js.dart' as js;
import 'package:javascript_utils/javascript_utils.dart' as js_utils;
library_private_types_in_public_api
Avoid using private types in public APIs.
This rule is available as of Dart 2.14.0.
Rule sets: recommended, flutter
Details
AVOID using library private types in public APIs.
For the purposes of this lint, a public API is considered to be any top-level or member declaration unless the declaration is library private or contained in a declaration that’s library private. The following uses of types are checked:
- the return type of a function or method,
- the type of any parameter of a function or method,
- the bound of a type parameter to any function, method, class, mixin, extension’s extended type, or type alias,
- the type of any top level variable or field,
- any type used in the declaration of a type alias (for example
typedef F = _Private Function();
), or - any type used in the
on
clause of an extension or a mixin
BAD:
f(_Private p) { ... }
class _Private {}
GOOD:
f(String s) { ... }
lines_longer_than_80_chars
Avoid lines longer than 80 characters.
This rule is available as of Dart 2.0.0.
Details
AVOID lines longer than 80 characters
Readability studies show that long lines of text are harder to read because your eye has to travel farther when moving to the beginning of the next line. This is why newspapers and magazines use multiple columns of text.
If you really find yourself wanting lines longer than 80 characters, our
experience is that your code is likely too verbose and could be a little more
compact. The main offender is usually VeryLongCamelCaseClassNames
. Ask
yourself, “Does each word in that type name tell me something critical or
prevent a name collision?” If not, consider omitting it.
Note that dart format
does 99% of this for you, but the last 1% is you. It
does not split long string literals to fit in 80 columns, so you have to do
that manually.
We make an exception for URIs and file paths. When those occur in comments or strings (usually in imports and exports), they may remain on a single line even if they go over the line limit. This makes it easier to search source files for a given path.
matching_super_parameters
Use matching super parameter names.
This rule is currently experimental and not yet available in a stable SDK.
Details
DO use super parameter names that match their corresponding super constructor’s parameter names.
BAD:
class Rectangle {
final int width;
final int height;
Rectangle(this.width, this.height);
}
class ColoredRectangle extends Rectangle {
final Color color;
ColoredRectangle(
this.color,
super.height, // Bad, actually corresponds to the `width` parameter.
super.width, // Bad, actually corresponds to the `height` parameter.
);
}
GOOD:
class Rectangle {
final int width;
final int height;
Rectangle(this.width, this.height);
}
class ColoredRectangle extends Rectangle {
final Color color;
ColoredRectangle(
this.color,
super.width,
super.height,
);
}
missing_whitespace_between_adjacent_strings
Missing whitespace between adjacent strings.
This rule is available as of Dart 2.8.1.
Details
Add a trailing whitespace to prevent missing whitespace between adjacent strings.
With long text split across adjacent strings it’s easy to forget a whitespace between strings.
BAD:
var s =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed'
'do eiusmod tempor incididunt ut labore et dolore magna';
GOOD:
var s =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed '
'do eiusmod tempor incididunt ut labore et dolore magna';
no_default_cases
No default cases.
This rule is currently experimental and available as of Dart 2.9.0.
Details
Switches on enums and enum-like classes should not use a default
clause.
Enum-like classes are defined as concrete (non-abstract) classes that have:
- only private non-factory constructors
- two or more static const fields whose type is the enclosing class and
- no subclasses of the class in the defining library
DO define default behavior outside switch statements.
BAD:
switch (testEnum) {
case TestEnum.A:
return '123';
case TestEnum.B:
return 'abc';
default:
return null;
}
GOOD:
switch (testEnum) {
case TestEnum.A:
return '123';
case TestEnum.B:
return 'abc';
}
// Default here.
return null;
no_leading_underscores_for_library_prefixes
Avoid leading underscores for library prefixes.
This rule is available as of Dart 2.16.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T use a leading underscore for library prefixes. There is no concept of “private” for library prefixes. When one of those has a name that starts with an underscore, it sends a confusing signal to the reader. To avoid that, don’t use leading underscores in those names.
BAD:
import 'dart:core' as _core;
GOOD:
import 'dart:core' as core;
no_leading_underscores_for_local_identifiers
Avoid leading underscores for local identifiers.
This rule is available as of Dart 2.16.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T use a leading underscore for identifiers that aren’t private. Dart
uses a leading underscore in an identifier to mark members and top-level
declarations as private. This trains users to associate a leading underscore
with one of those kinds of declarations. They see _
and think “private”.
There is no concept of “private” for local variables or parameters. When one of
those has a name that starts with an underscore, it sends a confusing signal to
the reader. To avoid that, don’t use leading underscores in those names.
EXCEPTION:: An unused parameter can be named _
, __
, ___
, etc. This is
common practice in callbacks where you are passed a value but you don’t need
to use it. Giving it a name that consists solely of underscores is the idiomatic
way to indicate that the value isn’t used.
BAD:
void print(String _name) {
var _size = _name.length;
...
}
GOOD:
void print(String name) {
var size = name.length;
...
}
OK:
[1,2,3].map((_) => print('Hello'));
no_literal_bool_comparisons
Don’t compare booleans to boolean literals.
This rule is currently experimental and not yet available in a stable SDK.
This rule has a quick fix available.
Details
From Effective Dart:
DON’T use true
or false
in equality operations.
This lint applies only if the expression is of a non-nullable bool
type.
BAD:
if (someBool == true) {
}
while (someBool == false) {
}
GOOD:
if (someBool) {
}
while (!someBool) {
}
no_runtimeType_toString
Avoid calling toString() on runtimeType.
This rule is available as of Dart 2.8.1.
Details
Calling toString
on a runtime type is a non-trivial operation that can
negatively impact performance. It’s better to avoid it.
BAD:
class A {
String toString() => '$runtimeType()';
}
GOOD:
class A {
String toString() => 'A()';
}
This lint has some exceptions where performance is not a problem or where real type information is more important than performance:
- in assertion
- in throw expressions
- in catch clauses
- in mixin declaration
- in abstract class
non_constant_identifier_names
Name non-constant identifiers using lowerCamelCase.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DO name non-constant identifiers using lowerCamelCase.
Class members, top-level definitions, variables, parameters, named parameters and named constructors should capitalize the first letter of each word except the first word, and use no separators.
GOOD:
var item;
HttpRequest httpRequest;
align(clearItems) {
// ...
}
noop_primitive_operations
Noop primitive operations.
This rule is available as of Dart 2.14.0.
This rule has a quick fix available.
Details
Some operations on primitive types are idempotent and can be removed.
BAD:
doubleValue.toDouble();
intValue.toInt();
intValue.round();
intValue.ceil();
intValue.floor();
intValue.truncate();
string.toString();
string = 'hello\n'
'world\n'
''; // useless empty string
'string with ${x.toString()}';
null_check_on_nullable_type_parameter
Don’t use null check on a potentially nullable type parameter.
This rule is available as of Dart 2.12.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DON’T use null check on a potentially nullable type parameter.
Given a generic type parameter T
which has a nullable bound (e.g. the default
bound of Object?
), it is very easy to introduce erroneous null checks when
working with a variable of type T?
. Specifically, it is not uncommon to have
T? x;
and want to assert that x
has been set to a valid value of type T
.
A common mistake is to do so using x!
. This is almost always incorrect, since
if T
is a nullable type, x
may validly hold null
as a value of type T
.
BAD:
T run<T>(T callback()) {
T? result;
(() { result = callback(); })();
return result!;
}
GOOD:
T run<T>(T callback()) {
T? result;
(() { result = callback(); })();
return result as T;
}
null_closures
Do not pass null
as an argument where a closure is expected.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T pass null
as an argument where a closure is expected.
Often a closure that is passed to a method will only be called conditionally,
so that tests and “happy path” production calls do not reveal that null
will
result in an exception being thrown.
This rule only catches null literals being passed where closures are expected in the following locations:
Constructors
- From
dart:async
-
Future
at the 0th positional parameter -
Future.microtask
at the 0th positional parameter -
Future.sync
at the 0th positional parameter -
Timer
at the 0th positional parameter -
Timer.periodic
at the 1st positional parameter
-
- From
dart:core
-
List.generate
at the 1st positional parameter
-
Static functions
- From
dart:async
-
scheduleMicrotask
at the 0th positional parameter -
Future.doWhile
at the 0th positional parameter -
Future.forEach
at the 0th positional parameter -
Future.wait
at the named parametercleanup
-
Timer.run
at the 0th positional parameter
-
Instance methods
- From
dart:async
-
Future.then
at the 0th positional parameter -
Future.complete
at the 0th positional parameter
-
- From
dart:collection
-
Queue.removeWhere
at the 0th positional parameter - `Queue.retain
-
Iterable.firstWhere
at the 0th positional parameter, and the named parameterorElse
-
Iterable.forEach
at the 0th positional parameter -
Iterable.fold
at the 1st positional parameter -
Iterable.lastWhere
at the 0th positional parameter, and the named parameterorElse
-
Iterable.map
at the 0th positional parameter -
Iterable.reduce
at the 0th positional parameter -
Iterable.singleWhere
at the 0th positional parameter, and the named parameterorElse
-
Iterable.skipWhile
at the 0th positional parameter -
Iterable.takeWhile
at the 0th positional parameter -
Iterable.where
at the 0th positional parameter -
List.removeWhere
at the 0th positional parameter -
List.retainWhere
at the 0th positional parameter -
String.replaceAllMapped
at the 1st positional parameter -
String.replaceFirstMapped
at the 1st positional parameter -
String.splitMapJoin
at the named parametersonMatch
andonNonMatch
-
BAD:
[1, 3, 5].firstWhere((e) => e.isOdd, orElse: null);
GOOD:
[1, 3, 5].firstWhere((e) => e.isOdd, orElse: () => null);
omit_local_variable_types
Omit type annotations for local variables.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Incompatible rules: always_specify_types
Details
DON’T redundantly type annotate initialized local variables.
Local variables, especially in modern code where functions tend to be small, have very little scope. Omitting the type focuses the reader’s attention on the more important name of the variable and its initialized value.
BAD:
List<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {
List<List<Ingredient>> desserts = <List<Ingredient>>[];
for (final List<Ingredient> recipe in cookbook) {
if (pantry.containsAll(recipe)) {
desserts.add(recipe);
}
}
return desserts;
}
GOOD:
List<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {
var desserts = <List<Ingredient>>[];
for (final recipe in cookbook) {
if (pantry.containsAll(recipe)) {
desserts.add(recipe);
}
}
return desserts;
}
Sometimes the inferred type is not the type you want the variable to have. For example, you may intend to assign values of other types later. In that case, annotate the variable with the type you want.
GOOD:
Widget build(BuildContext context) {
Widget result = Text('You won!');
if (applyPadding) {
result = Padding(padding: EdgeInsets.all(8.0), child: result);
}
return result;
}
one_member_abstracts
Avoid defining a one-member abstract class when a simple function will do.
This rule is available as of Dart 2.0.0.
Details
From the style guide:
AVOID defining a one-member abstract class when a simple function will do.
Unlike Java, Dart has first-class functions, closures, and a nice light syntax
for using them. If all you need is something like a callback, just use a
function. If you’re defining a class and it only has a single abstract member
with a meaningless name like call
or invoke
, there is a good chance
you just want a function.
BAD:
abstract class Predicate {
bool test(item);
}
GOOD:
typedef Predicate = bool Function(item);
only_throw_errors
Only throw instances of classes extending either Exception or Error.
This rule is available as of Dart 2.0.0.
Details
DO throw only instances of classes that extend dart.core.Error
or
dart.core.Exception
.
Throwing instances that do not extend Error
or Exception
is a bad practice;
doing this is usually a hack for something that should be implemented more
thoroughly.
BAD:
void throwString() {
throw 'hello world!'; // LINT
}
GOOD:
void throwArgumentError() {
Error error = ArgumentError('oh!');
throw error; // OK
}
overridden_fields
Don’t override fields.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
DON’T override fields.
Overriding fields is almost always done unintentionally. Regardless, it is a bad practice to do so.
BAD:
class Base {
Object field = 'lorem';
Object something = 'change';
}
class Bad1 extends Base {
@override
final field = 'ipsum'; // LINT
}
class Bad2 extends Base {
@override
Object something = 'done'; // LINT
}
GOOD:
class Base {
Object field = 'lorem';
Object something = 'change';
}
class Ok extends Base {
Object newField; // OK
final Object newFinal = 'ignore'; // OK
}
GOOD:
abstract class BaseLoggingHandler {
Base transformer;
}
class LogPrintHandler implements BaseLoggingHandler {
@override
Derived transformer; // OK
}
package_api_docs
Provide doc comments for all public APIs.
This rule is available as of Dart 2.0.0.
Details
DO provide doc comments for all public APIs.
As described in the pub package layout doc,
public APIs consist in everything in your package’s lib
folder, minus
implementation files in lib/src
, adding elements explicitly exported with an
export
directive.
For example, given lib/foo.dart
:
export 'src/bar.dart' show Bar;
export 'src/baz.dart';
class Foo { }
class _Foo { }
its API includes:
-
Foo
(but not_Foo
) -
Bar
(exported) and - all public elements in
src/baz.dart
All public API members should be documented with ///
doc-style comments.
BAD:
class Bar {
void bar();
}
GOOD:
/// A Foo.
abstract class Foo {
/// Start foo-ing.
void start() => _start();
_start();
}
Advice for writing good doc comments can be found in the Doc Writing Guidelines.
package_prefixed_library_names
Prefix library names with the package name and a dot-separated path.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DO prefix library names with the package name and a dot-separated path.
This guideline helps avoid the warnings you get when two libraries have the same name. Here are the rules we recommend:
- Prefix all library names with the package name.
- Make the entry library have the same name as the package.
- For all other libraries in a package, after the package name add the dot-separated path to the library’s Dart file.
- For libraries under
lib
, omit the top directory name.
For example, say the package name is my_package
. Here are the library names
for various files in the package:
GOOD:
// In lib/my_package.dart
library my_package;
// In lib/other.dart
library my_package.other;
// In lib/foo/bar.dart
library my_package.foo.bar;
// In example/foo/bar.dart
library my_package.example.foo.bar;
// In lib/src/private.dart
library my_package.src.private;
parameter_assignments
Don’t reassign references to parameters of functions or methods.
This rule is available as of Dart 2.0.0.
Details
DON’T assign new values to parameters of methods or functions.
Assigning new values to parameters is generally a bad practice unless an
operator such as ??=
is used. Otherwise, arbitrarily reassigning parameters
is usually a mistake.
BAD:
void badFunction(int parameter) { // LINT
parameter = 4;
}
BAD:
void badFunction(int required, {int optional: 42}) { // LINT
optional ??= 8;
}
BAD:
void badFunctionPositional(int required, [int optional = 42]) { // LINT
optional ??= 8;
}
BAD:
class A {
void badMethod(int parameter) { // LINT
parameter = 4;
}
}
GOOD:
void ok(String parameter) {
print(parameter);
}
GOOD:
void actuallyGood(int required, {int optional}) { // OK
optional ??= ...;
}
GOOD:
void actuallyGoodPositional(int required, [int optional]) { // OK
optional ??= ...;
}
GOOD:
class A {
void ok(String parameter) {
print(parameter);
}
}
prefer_adjacent_string_concatenation
Use adjacent strings to concatenate string literals.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO use adjacent strings to concatenate string literals.
BAD:
raiseAlarm(
'ERROR: Parts of the spaceship are on fire. Other ' +
'parts are overrun by martians. Unclear which are which.');
GOOD:
raiseAlarm(
'ERROR: Parts of the spaceship are on fire. Other '
'parts are overrun by martians. Unclear which are which.');
prefer_asserts_in_initializer_lists
Prefer putting asserts in initializer lists.
This rule is available as of Dart 2.0.0.
Details
DO put asserts in initializer lists.
BAD:
class A {
A(int a) {
assert(a != 0);
}
}
GOOD:
class A {
A(int a) : assert(a != 0);
}
prefer_asserts_with_message
Prefer asserts with message.
This rule is available as of Dart 2.3.0.
Details
When assertions fail it’s not always simple to understand why. Adding a message
to the assert
helps the developer to understand why the AssertionError occurs.
BAD:
f(a) {
assert(a != null);
}
class A {
A(a) : assert(a != null);
}
GOOD:
f(a) {
assert(a != null, 'a must not be null');
}
class A {
A(a) : assert(a != null, 'a must not be null');
}
prefer_bool_in_asserts
Prefer using a boolean as the assert condition.
This rule has been removed as of the latest Dart releases.
Details
DO use a boolean for assert conditions.
Not using booleans in assert conditions can lead to code where it isn’t clear what the intention of the assert statement is.
BAD:
assert(() {
f();
return true;
});
GOOD:
assert(() {
f();
return true;
}());
prefer_collection_literals
Use collection literals when possible.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO use collection literals when possible.
BAD:
var addresses = Map<String, String>();
var uniqueNames = Set<String>();
var ids = LinkedHashSet<int>();
var coordinates = LinkedHashMap<int, int>();
GOOD:
var addresses = <String, String>{};
var uniqueNames = <String>{};
var ids = <int>{};
var coordinates = <int, int>{};
EXCEPTIONS:
There are cases with LinkedHashSet
or LinkedHashMap
where a literal constructor
will trigger a type error so those will be excluded from the lint.
void main() {
LinkedHashSet<int> linkedHashSet = LinkedHashSet.from([1, 2, 3]); // OK
LinkedHashMap linkedHashMap = LinkedHashMap(); // OK
printSet(LinkedHashSet<int>()); // LINT
printHashSet(LinkedHashSet<int>()); // OK
printMap(LinkedHashMap<int, int>()); // LINT
printHashMap(LinkedHashMap<int, int>()); // OK
}
void printSet(Set<int> ids) => print('$ids!');
void printHashSet(LinkedHashSet<int> ids) => printSet(ids);
void printMap(Map map) => print('$map!');
void printHashMap(LinkedHashMap map) => printMap(map);
prefer_conditional_assignment
Prefer using ??=
over testing for null.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
PREFER using ??=
over testing for null.
As Dart has the ??=
operator, it is advisable to use it where applicable to
improve the brevity of your code.
BAD:
String get fullName {
if (_fullName == null) {
_fullName = getFullUserName(this);
}
return _fullName;
}
GOOD:
String get fullName {
return _fullName ??= getFullUserName(this);
}
prefer_const_constructors
Prefer const with constant constructors.
This rule is available as of Dart 2.0.0.
Rule sets: flutter
This rule has a quick fix available.
Details
PREFER using const
for instantiating constant constructors.
If a constructor can be invoked as const to produce a canonicalized instance, it’s preferable to do so.
BAD:
class A {
const A();
}
void accessA() {
A a = new A();
}
GOOD:
class A {
const A();
}
void accessA() {
A a = const A();
}
GOOD:
class A {
final int x;
const A(this.x);
}
A foo(int x) => new A(x);
prefer_const_constructors_in_immutables
Prefer declaring const constructors on @immutable
classes.
This rule is available as of Dart 2.0.0.
Rule sets: flutter
This rule has a quick fix available.
Details
PREFER declaring const constructors on @immutable
classes.
If a class is immutable, it is usually a good idea to make its constructor a const constructor.
BAD:
@immutable
class A {
final a;
A(this.a);
}
GOOD:
@immutable
class A {
final a;
const A(this.a);
}
prefer_const_declarations
Prefer const over final for declarations.
This rule is available as of Dart 2.0.0.
Rule sets: flutter
This rule has a quick fix available.
Details
PREFER using const
for const declarations.
Const declarations are more hot-reload friendly and allow to use const constructors if an instantiation references this declaration.
BAD:
final o = const <int>[];
class A {
static final o = const <int>[];
}
GOOD:
const o = <int>[];
class A {
static const o = <int>[];
}
prefer_const_literals_to_create_immutables
Prefer const literals as parameters of constructors on @immutable classes.
This rule is available as of Dart 2.0.0.
Rule sets: flutter
This rule has a quick fix available.
Details
PREFER using const
for instantiating list, map and set literals used as
parameters in immutable class instantiations.
BAD:
@immutable
class A {
A(this.v);
final v;
}
A a1 = new A([1]);
A a2 = new A({});
GOOD:
A a1 = new A(const [1]);
A a2 = new A(const {});
prefer_constructors_over_static_methods
Prefer defining constructors instead of static methods to create instances.
This rule is available as of Dart 2.0.0.
Details
PREFER defining constructors instead of static methods to create instances.
In most cases, it makes more sense to use a named constructor rather than a static method because it makes instantiation clearer.
BAD:
class Point {
num x, y;
Point(this.x, this.y);
static Point polar(num theta, num radius) {
return Point(radius * math.cos(theta),
radius * math.sin(theta));
}
}
GOOD:
class Point {
num x, y;
Point(this.x, this.y);
Point.polar(num theta, num radius)
: x = radius * math.cos(theta),
y = radius * math.sin(theta);
}
prefer_contains
Use contains for List
and String
instances.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T use indexOf
to see if a collection contains an element.
Calling indexOf
to see if a collection contains something is difficult to read
and may have poor performance.
Instead, prefer contains
.
BAD:
if (lunchBox.indexOf('sandwich') == -1) return 'so hungry...';
GOOD:
if (!lunchBox.contains('sandwich')) return 'so hungry...';
prefer_double_quotes
Prefer double quotes where they won’t require escape sequences.
This rule is available as of Dart 2.4.0.
This rule has a quick fix available.
Incompatible rules: prefer_single_quotes
Details
DO use double quotes where they wouldn’t require additional escapes.
That means strings with a double quote may use apostrophes so that the double quote isn’t escaped (note: we don’t lint the other way around, ie, a double quoted string with an escaped double quote is not flagged).
It’s also rare, but possible, to have strings within string interpolations. In this case, its much more readable to use a single quote somewhere. So single quotes are allowed either within, or containing, an interpolated string literal. Arguably strings within string interpolations should be its own type of lint.
BAD:
useStrings(
'should be double quote',
r'should be double quote',
r'''should be double quotes''')
GOOD:
useStrings(
"should be double quote",
r"should be double quote",
r"""should be double quotes""",
'ok with " inside',
'nested ${a ? "strings" : "can"} be wrapped by a double quote',
"and nested ${a ? 'strings' : 'can be double quoted themselves'}");
prefer_equal_for_default_values
Use =
to separate a named parameter from its default value.
This rule has been removed as of the latest Dart releases.
Rule sets: recommended, flutter
Details
From the style guide:
DO use =
to separate a named parameter from its default value.
BAD:
m({a: 1})
GOOD:
m({a = 1})
prefer_expression_function_bodies
Use => for short members whose body is a single return statement.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
CONSIDER using => for short members whose body is a single return statement.
BAD:
get width {
return right - left;
}
BAD:
bool ready(num time) {
return minTime == null || minTime <= time;
}
BAD:
containsValue(String value) {
return getValues().contains(value);
}
GOOD:
get width => right - left;
GOOD:
bool ready(num time) => minTime == null || minTime <= time;
GOOD:
containsValue(String value) => getValues().contains(value);
prefer_final_fields
Private field could be final.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO prefer declaring private fields as final if they are not reassigned later in the library.
Declaring fields as final when possible is a good practice because it helps avoid accidental reassignments and allows the compiler to do optimizations.
BAD:
class BadImmutable {
var _label = 'hola mundo! BadImmutable'; // LINT
var label = 'hola mundo! BadImmutable'; // OK
}
BAD:
class MultipleMutable {
var _label = 'hola mundo! GoodMutable', _offender = 'mumble mumble!'; // LINT
var _someOther; // LINT
MultipleMutable() : _someOther = 5;
MultipleMutable(this._someOther);
void changeLabel() {
_label= 'hello world! GoodMutable';
}
}
GOOD:
class GoodImmutable {
final label = 'hola mundo! BadImmutable', bla = 5; // OK
final _label = 'hola mundo! BadImmutable', _bla = 5; // OK
}
GOOD:
class GoodMutable {
var _label = 'hola mundo! GoodMutable';
void changeLabel() {
_label = 'hello world! GoodMutable';
}
}
BAD:
class AssignedInAllConstructors {
var _label; // LINT
AssignedInAllConstructors(this._label);
AssignedInAllConstructors.withDefault() : _label = 'Hello';
}
GOOD:
class NotAssignedInAllConstructors {
var _label; // OK
NotAssignedInAllConstructors();
NotAssignedInAllConstructors.withDefault() : _label = 'Hello';
}
prefer_final_in_for_each
Prefer final in for-each loop variable if reference is not reassigned.
This rule is available as of Dart 2.1.1.
This rule has a quick fix available.
Details
DO prefer declaring for-each loop variables as final if they are not reassigned later in the code.
Declaring for-each loop variables as final when possible is a good practice because it helps avoid accidental reassignments and allows the compiler to do optimizations.
BAD:
for (var element in elements) { // LINT
print('Element: $element');
}
GOOD:
for (final element in elements) {
print('Element: $element');
}
GOOD:
for (var element in elements) {
element = element + element;
print('Element: $element');
}
prefer_final_locals
Prefer final for variable declarations if they are not reassigned.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Incompatible rules: unnecessary_final
Details
DO prefer declaring variables as final if they are not reassigned later in the code.
Declaring variables as final when possible is a good practice because it helps avoid accidental reassignments and allows the compiler to do optimizations.
BAD:
void badMethod() {
var label = 'hola mundo! badMethod'; // LINT
print(label);
}
GOOD:
void goodMethod() {
final label = 'hola mundo! goodMethod';
print(label);
}
GOOD:
void mutableCase() {
var label = 'hola mundo! mutableCase';
print(label);
label = 'hello world';
print(label);
}
prefer_final_parameters
Prefer final for parameter declarations if they are not reassigned.
This rule is available as of Dart 2.14.0.
This rule has a quick fix available.
Incompatible rules: unnecessary_final, avoid_final_parameters
Details
DO prefer declaring parameters as final if they are not reassigned in the function body.
Declaring parameters as final when possible is a good practice because it helps avoid accidental reassignments.
BAD:
void badParameter(String label) { // LINT
print(label);
}
GOOD:
void goodParameter(final String label) { // OK
print(label);
}
BAD:
void badExpression(int value) => print(value); // LINT
GOOD:
void goodExpression(final int value) => print(value); // OK
BAD:
[1, 4, 6, 8].forEach((value) => print(value + 2)); // LINT
GOOD:
[1, 4, 6, 8].forEach((final value) => print(value + 2)); // OK
GOOD:
void mutableParameter(String label) { // OK
print(label);
label = 'Hello Linter!';
print(label);
}
prefer_for_elements_to_map_fromIterable
Prefer ‘for’ elements when building maps from iterables.
This rule is available as of Dart 2.3.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
When building maps from iterables, it is preferable to use ‘for’ elements.
Using ‘for’ elements brings several benefits including:
- Performance
- Flexibility
- Readability
- Improved type inference
- Improved interaction with null safety
BAD:
Map<String, WidgetBuilder>.fromIterable(
kAllGalleryDemos,
key: (demo) => '${demo.routeName}',
value: (demo) => demo.buildRoute,
);
GOOD:
return {
for (var demo in kAllGalleryDemos)
'${demo.routeName}': demo.buildRoute,
};
GOOD:
// Map<int, Student> is not required, type is inferred automatically.
final pizzaRecipients = {
...studentLeaders,
for (var student in classG)
if (student.isPassing) student.id: student,
};
prefer_foreach
Use forEach
to only apply a function to all the elements.
This rule is available as of Dart 2.0.0.
Details
DO use forEach
if you are only going to apply a function or a method
to all the elements of an iterable.
Using forEach
when you are only going to apply a function or method to all
elements of an iterable is a good practice because it makes your code more
terse.
BAD:
for (final key in map.keys.toList()) {
map.remove(key);
}
GOOD:
map.keys.toList().forEach(map.remove);
NOTE: Replacing a for each statement with a forEach call may change the behavior in the case where there are side-effects on the iterable itself.
for (final v in myList) {
foo().f(v); // This code invokes foo() many times.
}
myList.forEach(foo().f); // But this one invokes foo() just once.
prefer_function_declarations_over_variables
Use a function declaration to bind a function to a name.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO use a function declaration to bind a function to a name.
As Dart allows local function declarations, it is a good practice to use them in the place of function literals.
BAD:
void main() {
var localFunction = () {
...
};
}
GOOD:
void main() {
localFunction() {
...
}
}
prefer_generic_function_type_aliases
Prefer generic function type aliases.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
PREFER generic function type aliases.
With the introduction of generic functions, function type aliases
(typedef void F()
) couldn’t express all of the possible kinds of
parameterization that users might want to express. Generic function type aliases
(typedef F = void Function()
) fixed that issue.
For consistency and readability reasons, it’s better to only use one syntax and thus prefer generic function type aliases.
BAD:
typedef void F();
GOOD:
typedef F = void Function();
prefer_if_elements_to_conditional_expressions
Prefer if elements to conditional expressions where possible.
This rule is available as of Dart 2.3.0.
This rule has a quick fix available.
Details
When building collections, it is preferable to use if
elements rather than
conditionals.
BAD:
var list = ['a', 'b', condition ? 'c' : null].where((e) => e != null).toList();
GOOD:
var list = ['a', 'b', if (condition) 'c'];
prefer_if_null_operators
Prefer using if null operators.
This rule is available as of Dart 2.4.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
PREFER using if null operators instead of null checks in conditional expressions.
BAD:
v = a == null ? b : a;
GOOD:
v = a ?? b;
prefer_initializing_formals
Use initializing formals when possible.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO use initializing formals when possible.
Using initializing formals when possible makes your code more terse.
BAD:
class Point {
num x, y;
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
GOOD:
class Point {
num x, y;
Point(this.x, this.y);
}
BAD:
class Point {
num x, y;
Point({num x, num y}) {
this.x = x;
this.y = y;
}
}
GOOD:
class Point {
num x, y;
Point({this.x, this.y});
}
NOTE: This rule will not generate a lint for named parameters unless the parameter name and the field name are the same. The reason for this is that resolving such a lint would require either renaming the field or renaming the parameter, and both of those actions would potentially be a breaking change. For example, the following will not generate a lint:
class Point {
bool isEnabled;
Point({bool enabled}) {
this.isEnabled = enabled; // OK
}
}
NOTE:
Also note that it is possible to enforce a type that is stricter than the
initialized field with an initializing formal parameter. In the following
example the unnamed Bid
constructor requires a non-null int
despite
amount
being declared nullable (int?
).
class Bid {
final int? amount;
Bid(int this.amount);
Bid.pass() : amount = null;
}
prefer_inlined_adds
Inline list item declarations where possible.
This rule is available as of Dart 2.3.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Declare elements in list literals inline, rather than using add
and
addAll
methods where possible.
BAD:
var l = ['a']..add('b')..add('c');
var l2 = ['a']..addAll(['b', 'c']);
GOOD:
var l = ['a', 'b', 'c'];
var l2 = ['a', 'b', 'c'];
prefer_int_literals
Prefer int literals over double literals.
This rule is available as of Dart 2.1.0.
This rule has a quick fix available.
Details
DO use int literals rather than the corresponding double literal.
BAD:
const double myDouble = 8.0;
final anotherDouble = myDouble + 7.0e2;
main() {
someMethod(6.0);
}
GOOD:
const double myDouble = 8;
final anotherDouble = myDouble + 700;
main() {
someMethod(6);
}
prefer_interpolation_to_compose_strings
Use interpolation to compose strings and values.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
PREFER using interpolation to compose strings and values.
Using interpolation when composing strings and values is usually easier to write and read than concatenation.
BAD:
'Hello, ' + person.name + ' from ' + person.city + '.';
GOOD:
'Hello, ${person.name} from ${person.city}.'
prefer_is_empty
Use isEmpty
for Iterables and Maps.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DON’T use length
to see if a collection is empty.
The Iterable
contract does not require that a collection know its length or be
able to provide it in constant time. Calling length
just to see if the
collection contains anything can be painfully slow.
Instead, there are faster and more readable getters: isEmpty
and
isNotEmpty
. Use the one that doesn’t require you to negate the result.
BAD:
if (lunchBox.length == 0) return 'so hungry...';
if (words.length != 0) return words.join(' ');
GOOD:
if (lunchBox.isEmpty) return 'so hungry...';
if (words.isNotEmpty) return words.join(' ');
prefer_is_not_empty
Use isNotEmpty
for Iterables and Maps.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
PREFER x.isNotEmpty
to !x.isEmpty
for Iterable
and Map
instances.
When testing whether an iterable or map is empty, prefer isNotEmpty
over
!isEmpty
to improve code readability.
BAD:
if (!sources.isEmpty) {
process(sources);
}
GOOD:
if (todo.isNotEmpty) {
sendResults(request, todo.isEmpty);
}
prefer_is_not_operator
Prefer is! operator.
This rule is available as of Dart 2.7.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
When checking if an object is not of a specified type, it is preferable to use the ‘is!’ operator.
BAD:
if (!(foo is Foo)) {
...
}
GOOD:
if (foo is! Foo) {
...
}
prefer_iterable_whereType
Prefer to use whereType on iterable.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
PREFER iterable.whereType<T>()
over iterable.where((e) => e is T)
.
BAD:
iterable.where((e) => e is MyClass);
GOOD:
iterable.whereType<MyClass>();
prefer_mixin
Prefer using mixins.
This rule is available as of Dart 2.1.0.
Details
Dart 2.1 introduced a new syntax for mixins that provides a safe way for a mixin
to invoke inherited members using super
. The new style of mixins should always
be used for types that are to be mixed in. As a result, this lint will flag any
uses of a class in a with
clause.
BAD:
class A {}
class B extends Object with A {}
OK:
mixin M {}
class C with M {}
prefer_null_aware_method_calls
Prefer null aware method calls.
This rule is available as of Dart 2.14.0.
Details
Instead of checking nullability of a function/method f
before calling it you
can use f?.call()
.
BAD:
if (f != null) f!();
GOOD:
f?.call();
prefer_null_aware_operators
Prefer using null aware operators.
This rule is available as of Dart 2.2.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
PREFER using null aware operators instead of null checks in conditional expressions.
BAD:
v = a == null ? null : a.b;
GOOD:
v = a?.b;
prefer_single_quotes
Only use double quotes for strings containing single quotes.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Incompatible rules: prefer_double_quotes
Details
DO use single quotes where they wouldn’t require additional escapes.
That means strings with an apostrophe may use double quotes so that the apostrophe isn’t escaped (note: we don’t lint the other way around, ie, a single quoted string with an escaped apostrophe is not flagged).
It’s also rare, but possible, to have strings within string interpolations. In this case, its much more readable to use a double quote somewhere. So double quotes are allowed either within, or containing, an interpolated string literal. Arguably strings within string interpolations should be its own type of lint.
BAD:
useStrings(
"should be single quote",
r"should be single quote",
r"""should be single quotes""")
GOOD:
useStrings(
'should be single quote',
r'should be single quote',
r'''should be single quotes''',
"here's ok",
"nested ${a ? 'strings' : 'can'} be wrapped by a double quote",
'and nested ${a ? "strings" : "can be double quoted themselves"}');
prefer_spread_collections
Use spread collections when possible.
This rule is available as of Dart 2.3.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Use spread collections when possible.
Collection literals are excellent when you want to create a new collection out of individual items. But, when existing items are already stored in another collection, spread collection syntax leads to simpler code.
BAD:
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: ListView(
children: [
Tab2Header(),
]..addAll(buildTab2Conversation()),
),
);
}
var ints = [1, 2, 3];
print(['a']..addAll(ints.map((i) => i.toString()))..addAll(['c']));
var things;
var l = ['a']..addAll(things ?? const []);
GOOD:
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: ListView(
children: [
Tab2Header(),
...buildTab2Conversation(),
],
),
);
}
var ints = [1, 2, 3];
print(['a', ...ints.map((i) => i.toString()), 'c');
var things;
var l = ['a', ...?things];
prefer_typing_uninitialized_variables
Prefer typing uninitialized variables and fields.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
PREFER specifying a type annotation for uninitialized variables and fields.
Forgoing type annotations for uninitialized variables is a bad practice because you may accidentally assign them to a type that you didn’t originally intend to.
BAD:
class BadClass {
static var bar; // LINT
var foo; // LINT
void method() {
var bar; // LINT
bar = 5;
print(bar);
}
}
BAD:
void aFunction() {
var bar; // LINT
bar = 5;
...
}
GOOD:
class GoodClass {
static var bar = 7;
var foo = 42;
int baz; // OK
void method() {
int baz;
var bar = 5;
...
}
}
provide_deprecation_message
Provide a deprecation message, via @Deprecated(“message”).
This rule is available as of Dart 2.2.0.
Rule sets: core, recommended, flutter
Details
DO specify a deprecation message (with migration instructions and/or a removal schedule) in the Deprecation constructor.
BAD:
@deprecated
void oldFunction(arg1, arg2) {}
GOOD:
@Deprecated("""
[oldFunction] is being deprecated in favor of [newFunction] (with slightly
different parameters; see [newFunction] for more information). [oldFunction]
will be removed on or after the 4.0.0 release.
""")
void oldFunction(arg1, arg2) {}
public_member_api_docs
Document all public members.
This rule is available as of Dart 2.0.0.
Details
DO document all public members.
All non-overriding public members should be documented with ///
doc-style
comments.
BAD:
class Bad {
void meh() { }
}
GOOD:
/// A good thing.
abstract class Good {
/// Start doing your thing.
void start() => _start();
_start();
}
In case a public member overrides a member it is up to the declaring member
to provide documentation. For example, in the following, Sub
needn’t
document init
(though it certainly may, if there’s need).
GOOD:
/// Base of all things.
abstract class Base {
/// Initialize the base.
void init();
}
/// A sub base.
class Sub extends Base {
@override
void init() { ... }
}
Note that consistent with dart doc
, an exception to the rule is made when
documented getters have corresponding undocumented setters. In this case the
setters inherit the docs from the getters.
recursive_getters
Property getter recursively returns itself.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
DON’T create recursive getters.
Recursive getters are getters which return themselves as a value. This is usually a typo.
BAD:
int get field => field; // LINT
BAD:
int get otherField {
return otherField; // LINT
}
GOOD:
int get field => _field;
require_trailing_commas
Use trailing commas for all function calls and declarations.
This rule is available as of Dart 2.14.0.
This rule has a quick fix available.
Details
DO use trailing commas for all function calls and declarations unless the function call or definition, from the start of the function name up to the closing parenthesis, fits in a single line.
BAD:
void run() {
method('does not fit on one line',
'test test test test test test test test test test test');
}
GOOD:
void run() {
method(
'does not fit on one line',
'test test test test test test test test test test test',
);
}
EXCEPTION: If the final parameter/argument is positional (vs named) and is either a function literal implemented using curly braces, a literal map, a literal set or a literal array. This exception only applies if the final parameter does not fit entirely on one line.
NOTE: This lint rule assumes dart format
has been run over the code and
may produce false positives until that has happened.
sized_box_for_whitespace
SizedBox for whitespace.
This rule is available as of Dart 2.9.0.
Rule sets: flutter
This rule has a quick fix available.
Details
Use SizedBox to add whitespace to a layout.
A Container
is a heavier Widget than a SizedBox
, and as bonus, SizedBox
has a const
constructor.
BAD:
Widget buildRow() {
return Row(
children: <Widget>[
const MyLogo(),
Container(width: 4),
const Expanded(
child: Text('...'),
),
],
);
}
GOOD:
Widget buildRow() {
return Row(
children: const <Widget>[
MyLogo(),
SizedBox(width: 4),
Expanded(
child: Text('...'),
),
],
);
}
sized_box_shrink_expand
Use SizedBox shrink and expand named constructors.
This rule is available as of Dart 2.16.0.
Details
Use SizedBox.shrink(...)
and SizedBox.expand(...)
constructors appropriately.
The SizedBox.shrink(...)
and SizedBox.expand(...)
constructors should be used
instead of the more general SizedBox(...)
constructor when the named constructors
capture the intent of the code more succinctly.
Examples
BAD:
Widget buildLogo() {
return SizedBox(
height: 0,
width: 0,
child: const MyLogo(),
);
}
Widget buildLogo() {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: const MyLogo(),
);
}
GOOD:
Widget buildLogo() {
return SizedBox.shrink(
child: const MyLogo(),
);
}
Widget buildLogo() {
return SizedBox.expand(
child: const MyLogo(),
);
}
slash_for_doc_comments
Prefer using /// for doc comments.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From the style guide:
PREFER using ///
for doc comments.
Although Dart supports two syntaxes of doc comments (///
and /**
), we
prefer using ///
for doc comments.
GOOD:
/// Parses a set of option strings. For each option:
///
/// * If it is `null`, then it is ignored.
/// * If it is a string, then [validate] is called on it.
/// * If it is any other type, it is *not* validated.
void parse(List options) {
// ...
}
Within a doc comment, you can use markdown for formatting.
sort_child_properties_last
Sort child properties last in widget instance creations.
This rule is available as of Dart 2.4.0.
Rule sets: flutter
This rule has a quick fix available.
Details
Sort child properties last in widget instance creations. This improves readability and plays nicest with UI as Code visualization in IDEs with UI as Code Guides in editors (such as IntelliJ) where Properties in the correct order appear clearly associated with the constructor call and separated from the children.
BAD:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
mainAxisAlignment: MainAxisAlignment.center,
),
widthFactor: 0.5,
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _incrementCounter,
tooltip: 'Increment',
),
);
GOOD:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
widthFactor: 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
Exception: It’s allowed to have parameter with a function expression after the
child
property.
sort_constructors_first
Sort constructor declarations before other members.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO sort constructor declarations before other members.
BAD:
abstract class Visitor {
double value;
visitSomething(Something s);
Visitor();
}
GOOD:
abstract class Animation<T> {
const Animation(this.value);
double value;
void addListener(VoidCallback listener);
}
sort_unnamed_constructors_first
Sort unnamed constructor declarations first.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO sort unnamed constructor declarations first, before named ones.
BAD:
class _PriorityItem {
factory _PriorityItem.forName(bool isStatic, String name, _MemberKind kind) => ...
_PriorityItem(this.isStatic, this.kind, this.isPrivate);
...
}
GOOD:
abstract class CancelableFuture<T> implements Future<T> {
factory CancelableFuture(computation()) => ...
factory CancelableFuture.delayed(Duration duration, [computation()]) => ...
...
}
super_goes_last
Place the super
call last in a constructor initialization list.
This rule has been removed as of the latest Dart releases.
Details
From the style guide:
DO place the super
call last in a constructor initialization list.
Field initializers are evaluated in the order that they appear in the
constructor initialization list. If you place a super()
call in the middle of
an initializer list, the superclass’s initializers will be evaluated right then
before evaluating the rest of the subclass’s initializers.
What it doesn’t mean is that the superclass’s constructor body will be executed
then. That always happens after all initializers are run regardless of where
super
appears. It’s vanishingly rare that the order of initializers matters,
so the placement of super
in the list almost never matters either.
Getting in the habit of placing it last improves consistency, visually reinforces when the superclass’s constructor body is run, and may help performance.
BAD:
View(Style style, List children)
: super(style),
_children = children {
GOOD:
View(Style style, List children)
: _children = children,
super(style) {
tighten_type_of_initializing_formals
Tighten type of initializing formal.
This rule is available as of Dart 2.12.0.
Details
Tighten the type of an initializing formal if a non-null assert exists. This allows the type system to catch problems rather than have them only be caught at run-time.
BAD:
class A {
A.c1(this.p) : assert(p != null);
A.c2(this.p);
final String? p;
}
GOOD:
class A {
A.c1(String this.p);
A.c2(this.p);
final String? p;
}
class B {
String? b;
B(this.b);
}
class C extends B {
B(String super.b);
}
type_annotate_public_apis
Type annotate public APIs.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
From Effective Dart:
PREFER type annotating public APIs.
Type annotations are important documentation for how a library should be used. Annotating the parameter and return types of public methods and functions helps users understand what the API expects and what it provides.
Note that if a public API accepts a range of values that Dart’s type system
cannot express, then it is acceptable to leave that untyped. In that case, the
implicit dynamic
is the correct type for the API.
For code internal to a library (either private, or things like nested functions) annotate where you feel it helps, but don’t feel that you must provide them.
BAD:
install(id, destination) {
// ...
}
Here, it’s unclear what id
is. A string? And what is destination
? A string
or a File
object? Is this method synchronous or asynchronous?
GOOD:
Future<bool> install(PackageId id, String destination) {
// ...
}
With types, all of this is clarified.
type_init_formals
Don’t type annotate initializing formals.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From the style guide:
DON’T type annotate initializing formals.
If a constructor parameter is using this.x
to initialize a field, then the
type of the parameter is understood to be the same type as the field. If a
a constructor parameter is using super.x
to forward to a super constructor,
then the type of the parameter is understood to be the same as the super
constructor parameter.
Type annotating an initializing formal with a different type than that of the field is OK.
BAD:
class Point {
int x, y;
Point(int this.x, int this.y);
}
GOOD:
class Point {
int x, y;
Point(this.x, this.y);
}
BAD:
class A {
int a;
A(this.a);
}
class B extends A {
B(int super.a);
}
GOOD:
class A {
int a;
A(this.a);
}
class B extends A {
B(super.a);
}
type_literal_in_constant_pattern
Don’t use constant patterns with type literals.
This rule is available as of Dart 3.0.0.
This rule has a quick fix available.
Details
If you meant to test if the object has type Foo
, instead write Foo _
.
BAD:
void f(Object? x) {
if (x case num) {
print('int or double');
}
}
GOOD:
void f(Object? x) {
if (x case num _) {
print('int or double');
}
}
If you do mean to test that the matched value (which you expect to have the
type Type
) is equal to the type literal Foo
, then this lint can be
silenced using const (Foo)
.
BAD:
void f(Object? x) {
if (x case int) {
print('int');
}
}
GOOD:
void f(Object? x) {
if (x case const (int)) {
print('int');
}
}
unawaited_futures
Future
results in async
function bodies must be await
ed or marked unawaited
using dart:async
.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DO await functions that return a Future
inside of an async function body.
It’s easy to forget await in async methods as naming conventions usually don’t
tell us if a method is sync or async (except for some in dart:io
).
When you really do want to start a fire-and-forget Future
, the recommended
way is to use unawaited
from dart:async
. The // ignore
and
// ignore_for_file
comments also work.
BAD:
void main() async {
doSomething(); // Likely a bug.
}
GOOD:
Future doSomething() => ...;
void main() async {
await doSomething();
unawaited(doSomething()); // Explicitly-ignored fire-and-forget.
}
unnecessary_await_in_return
Unnecessary await keyword in return.
This rule is available as of Dart 2.1.1.
Details
Avoid returning an awaited expression when the expression type is assignable to the function’s return type.
BAD:
Future<int> future;
Future<int> f1() async => await future;
Future<int> f2() async {
return await future;
}
GOOD:
Future<int> future;
Future<int> f1() => future;
Future<int> f2() {
return future;
}
unnecessary_brace_in_string_interps
Avoid using braces in interpolation when not needed.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID using braces in interpolation when not needed.
If you’re just interpolating a simple identifier, and it’s not immediately
followed by more alphanumeric text, the {}
can and should be omitted.
BAD:
print("Hi, ${name}!");
GOOD:
print("Hi, $name!");
unnecessary_breaks
Don’t use explicit break
s when a break is implied.
This rule is available as of Dart 3.0.0.
This rule has a quick fix available.
Details
Only use a break
in a non-empty switch case statement if you need to break
before the end of the case body. Dart does not support fallthrough execution
for non-empty cases, so break
s at the end of non-empty switch case statements
are unnecessary.
BAD:
switch (1) {
case 1:
print("one");
break;
case 2:
print("two");
break;
}
GOOD:
switch (1) {
case 1:
print("one");
case 2:
print("two");
}
switch (1) {
case 1:
case 2:
print("one or two");
}
switch (1) {
case 1:
break;
case 2:
print("just two");
}
NOTE: This lint only reports unnecessary breaks in libraries with a language version of 3.0 or greater. Explicit breaks are still required in Dart 2.19 and below.
unnecessary_const
Avoid const keyword.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID repeating const keyword in a const context.
BAD:
class A { const A(); }
m(){
const a = const A();
final b = const [const A()];
}
GOOD:
class A { const A(); }
m(){
const a = A();
final b = const [A()];
}
unnecessary_constructor_name
Unnecessary .new
constructor name.
This rule is available as of Dart 2.15.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
PREFER using the default unnamed Constructor over .new
.
Given a class C
, the named unnamed constructor C.new
refers to the same
constructor as the unnamed C
. As such it adds nothing but visual noise to
invocations and should be avoided (unless being used to identify a constructor
tear-off).
BAD:
class A {
A.new(); // LINT
}
var a = A.new(); // LINT
GOOD:
class A {
A.ok();
}
var a = A();
var aa = A.ok();
var makeA = A.new;
unnecessary_final
Don’t use final
for local variables.
This rule is available as of Dart 2.7.0.
This rule has a quick fix available.
Incompatible rules: prefer_final_locals, prefer_final_parameters
Details
Use var
, not final
, when declaring local variables.
Per Effective Dart,
there are two styles in wide use. This rule enforces the var
style.
For the alternative style that prefers final
, enable prefer_final_locals
and prefer_final_in_for_each
instead.
For fields, final
is always recommended; see the rule prefer_final_fields
.
BAD:
void badMethod() {
final label = 'Final or var?';
for (final char in ['v', 'a', 'r']) {
print(char);
}
}
GOOD:
void goodMethod() {
var label = 'Final or var?';
for (var char in ['v', 'a', 'r']) {
print(char);
}
}
unnecessary_getters_setters
Avoid wrapping fields in getters and setters just to be “safe”.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From the style guide:
AVOID wrapping fields in getters and setters just to be “safe”.
In Java and C#, it’s common to hide all fields behind getters and setters (or properties in C#), even if the implementation just forwards to the field. That way, if you ever need to do more work in those members, you can do it without needing to touch the callsites. This is because calling a getter method is different than accessing a field in Java, and accessing a property isn’t binary-compatible with accessing a raw field in C#.
Dart doesn’t have this limitation. Fields and getters/setters are completely indistinguishable. You can expose a field in a class and later wrap it in a getter and setter without having to touch any code that uses that field.
BAD:
class Box {
var _contents;
get contents => _contents;
set contents(value) {
_contents = value;
}
}
GOOD:
class Box {
var contents;
}
unnecessary_lambdas
Don’t create a lambda when a tear-off will do.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
DON’T create a lambda when a tear-off will do.
BAD:
names.forEach((name) {
print(name);
});
GOOD:
names.forEach(print);
unnecessary_late
Don’t specify the late
modifier when it is not needed.
This rule is available as of Dart 2.16.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO not specify the late
modifier for top-level and static variables
when the declaration contains an initializer.
Top-level and static variables with initializers are already evaluated lazily
as if they are marked late
.
BAD:
late String badTopLevel = '';
GOOD:
String goodTopLevel = '';
BAD:
class BadExample {
static late String badStatic = '';
}
GOOD:
class GoodExample {
late String goodStatic;
}
unnecessary_library_directive
Avoid library directives unless they have documentation comments or annotations.
This rule is available as of Dart 2.19.0.
This rule has a quick fix available.
Details
DO use library directives if you want to document a library and/or annotate a library.
BAD:
library;
GOOD:
/// This library does important things
library;
@TestOn('js')
library;
NOTE: Due to limitations with this lint, libraries with parts will not be flagged for unnecessary library directives.
unnecessary_new
Unnecessary new keyword.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID new keyword to create instances.
BAD:
class A { A(); }
m(){
final a = new A();
}
GOOD:
class A { A(); }
m(){
final a = A();
}
unnecessary_null_aware_assignments
Avoid null in null-aware assignment.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID null
in null-aware assignment.
Using null
on the right-hand side of a null-aware assignment effectively makes
the assignment redundant.
BAD:
var x;
x ??= null;
GOOD:
var x;
x ??= 1;
unnecessary_null_aware_operator_on_extension_on_nullable
Unnecessary null aware operator on extension on a nullable type.
This rule is available as of Dart 2.18.0.
Details
Avoid null aware operators for members defined in an extension on a nullable type.
BAD:
extension E on int? {
int m() => 1;
}
f(int? i) => i?.m();
GOOD:
extension E on int? {
int m() => 1;
}
f(int? i) => i.m();
unnecessary_null_checks
Unnecessary null checks.
This rule is currently experimental and available as of Dart 2.12.0.
This rule has a quick fix available.
Details
DON’T apply a null check when a nullable value is accepted.
BAD:
f(int? i) {}
m() {
int? j;
f(j!);
}
GOOD:
f(int? i) {}
m() {
int? j;
f(j);
}
unnecessary_null_in_if_null_operators
Avoid using null
in if null
operators.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
AVOID using null
as an operand in if null
operators.
Using null
in an if null
operator is redundant, regardless of which side
null
is used on.
BAD:
var x = a ?? null;
var y = null ?? 1;
GOOD:
var x = a ?? 1;
unnecessary_nullable_for_final_variable_declarations
Use a non-nullable type for a final variable initialized with a non-nullable value.
This rule is available as of Dart 2.10.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Use a non-nullable type for a final variable initialized with a non-nullable value.
BAD:
final int? i = 1;
GOOD:
final int i = 1;
unnecessary_overrides
Don’t override a method to do a super method invocation with the same parameters.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
This rule has a quick fix available.
Details
DON’T override a method to do a super method invocation with same parameters.
BAD:
class A extends B {
@override
void foo() {
super.foo();
}
}
GOOD:
class A extends B {
@override
void foo() {
doSomethingElse();
}
}
It’s valid to override a member in the following cases:
- if a type (return type or a parameter type) is not the exactly the same as the super member,
- if the
covariant
keyword is added to one of the parameters, - if documentation comments are present on the member,
- if the member has annotations other than
@override
, - if the member is not annotated with
@protected
, and the super member is.
noSuchMethod
is a special method and is not checked by this rule.
unnecessary_parenthesis
Unnecessary parentheses can be removed.
This rule is available as of Dart 2.0.0.
This rule has a quick fix available.
Details
AVOID using parentheses when not needed.
BAD:
a = (b);
GOOD:
a = b;
Parentheses are considered unnecessary if they do not change the meaning of the code and they do not improve the readability of the code. The goal is not to force all developers to maintain the expression precedence table in their heads, which is why the second condition is included. Examples of this condition include:
- cascade expressions - it is sometimes not clear what the target of a cascade
expression is, especially with assignments, or nested cascades. For example,
the expression
a.b = (c..d)
. - expressions with whitespace between tokens - it can look very strange to see
an expression like
!await foo
which is valid and equivalent to!(await foo)
. - logical expressions - parentheses can improve the readability of the implicit
grouping defined by precedence. For example, the expression
(a && b) || c && d
.
unnecessary_raw_strings
Unnecessary raw string.
This rule is available as of Dart 2.8.1.
This rule has a quick fix available.
Details
Use raw string only when needed.
BAD:
var s1 = r'a';
GOOD:
var s1 = 'a';
var s2 = r'$a';
var s3 = r'\a';
unnecessary_string_escapes
Remove unnecessary backslashes in strings.
This rule is available as of Dart 2.8.1.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Remove unnecessary backslashes in strings.
BAD:
'this string contains 2 \"double quotes\" ';
"this string contains 2 \'single quotes\' ";
GOOD:
'this string contains 2 "double quotes" ';
"this string contains 2 'single quotes' ";
unnecessary_string_interpolations
Unnecessary string interpolation.
This rule is available as of Dart 2.8.1.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DON’T use string interpolation if there’s only a string expression in it.
BAD:
String message;
String o = '$message';
GOOD:
String message;
String o = message;
unnecessary_this
Don’t access members with this
unless avoiding shadowing.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
From the style guide:
DON’T use this
when not needed to avoid shadowing.
BAD:
class Box {
var value;
void update(new_value) {
this.value = new_value;
}
}
GOOD:
class Box {
var value;
void update(new_value) {
value = new_value;
}
}
GOOD:
class Box {
var value;
void update(value) {
this.value = value;
}
}
unnecessary_to_list_in_spreads
Unnecessary toList() in spreads.
This rule is available as of Dart 2.18.0.
Details
Unnecessary toList()
in spreads.
BAD:
children: <Widget>[
...['foo', 'bar', 'baz'].map((String s) => Text(s)).toList(),
]
GOOD:
children: <Widget>[
...['foo', 'bar', 'baz'].map((String s) => Text(s)),
]
unreachable_from_main
Unreachable top-level members in executable libraries.
This rule is currently experimental and available as of Dart 2.19.0.
Details
Top-level members in an executable library should be used directly inside this
library. An executable library is a library that contains a main
top-level
function or that contains a top-level function annotated with
@pragma('vm:entry-point')
). Executable libraries are not usually imported
and it’s better to avoid defining unused members.
This rule assumes that an executable library isn’t imported by other files
except to execute its main
function.
BAD:
main() {}
void f() {}
GOOD:
main() {
f();
}
void f() {}
use_colored_box
Use ColoredBox
.
This rule is available as of Dart 2.17.0.
Details
DO use ColoredBox
when Container
has only a Color
.
A Container
is a heavier Widget than a ColoredBox
, and as bonus,
ColoredBox
has a const
constructor.
BAD:
Widget buildArea() {
return Container(
color: Colors.blue,
child: const Text('hello'),
);
}
GOOD:
Widget buildArea() {
return const ColoredBox(
color: Colors.blue,
child: Text('hello'),
);
}
use_decorated_box
Use DecoratedBox
.
This rule is available as of Dart 2.16.0.
This rule has a quick fix available.
Details
DO use DecoratedBox
when Container
has only a Decoration
.
A Container
is a heavier Widget than a DecoratedBox
, and as bonus,
DecoratedBox
has a const
constructor.
BAD:
Widget buildArea() {
return Container(
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
GOOD:
Widget buildArea() {
return const DecoratedBox(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: Text('...'),
);
}
use_enums
Use enums rather than classes that behave like enums.
This rule is available as of Dart 2.17.0.
This rule has a quick fix available.
Details
Classes that look like enumerations should be declared as enum
s.
DO use enums where appropriate.
Candidates for enums are classes that:
- are concrete,
- are private or have only private generative constructors,
- have two or more static const fields with the same type as the class,
- have generative constructors that are only invoked at the top-level of the initialization expression of these static fields,
- do not define
hashCode
,==
,values
orindex
, - do not extend any class other than Object, and
- have no subclasses declared in the defining library.
BAD:
class LogPriority {
static const error = LogPriority._(1, 'Error');
static const warning = LogPriority._(2, 'Warning');
static const log = LogPriority._unknown('Log');
final String prefix;
final int priority;
const LogPriority._(this.priority, this.prefix);
const LogPriority._unknown(String prefix) : this._(-1, prefix);
}
GOOD:
enum LogPriority {
error(1, 'Error'),
warning(2, 'Warning'),
log.unknown('Log');
final String prefix;
final int priority;
const LogPriority(this.priority, this.prefix);
const LogPriority.unknown(String prefix) : this(-1, prefix);
}
use_full_hex_values_for_flutter_colors
Prefer an 8-digit hexadecimal integer(0xFFFFFFFF) to instantiate Color.
This rule is available as of Dart 2.2.0.
Rule sets: flutter
This rule has a quick fix available.
Details
PREFER an 8-digit hexadecimal integer(0xFFFFFFFF) to instantiate Color. Colors have four 8-bit channels, which adds up to 32 bits, so Colors are described using a 32 bit integer.
BAD:
Color(1);
Color(0x000001);
GOOD:
Color(0x00000001);
use_function_type_syntax_for_parameters
Use generic function type syntax for parameters.
This rule is available as of Dart 2.1.1.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
Use generic function type syntax for parameters.
BAD:
Iterable<T> where(bool predicate(T element)) {}
GOOD:
Iterable<T> where(bool Function(T) predicate) {}
use_if_null_to_convert_nulls_to_bools
Use if-null operators to convert nulls to bools.
This rule is available as of Dart 2.13.0.
Details
From Effective Dart:
Use if-null operators to convert nulls to bools.
BAD:
if (nullableBool == true) {
}
if (nullableBool != false) {
}
GOOD:
if (nullableBool ?? false) {
}
if (nullableBool ?? true) {
}
use_is_even_rather_than_modulo
Prefer intValue.isOdd/isEven instead of checking the result of % 2.
This rule is available as of Dart 2.9.0.
Details
PREFER the use of intValue.isOdd/isEven to check for evenness.
BAD:
bool isEven = 1 % 2 == 0;
bool isOdd = 13 % 2 == 1;
GOOD:
bool isEven = 1.isEven;
bool isOdd = 13.isOdd;
use_late_for_private_fields_and_variables
Use late for private members with a non-nullable type.
This rule is currently experimental and available as of Dart 2.10.0.
Details
Use late
for private members with non-nullable types that are always expected
to be non-null. Thus it’s clear that the field is not expected to be null
and it avoids null checks.
BAD:
int? _i;
m() {
_i!.abs();
}
GOOD:
late int _i;
m() {
_i.abs();
}
OK:
int? _i;
m() {
_i?.abs();
_i = null;
}
use_named_constants
Use predefined named constants.
This rule is available as of Dart 2.13.0.
Details
Where possible, use already defined const values.
BAD:
const Duration(seconds: 0);
GOOD:
Duration.zero;
use_raw_strings
Use raw string to avoid escapes.
This rule is available as of Dart 2.8.1.
This rule has a quick fix available.
Details
A raw string can be used to avoid escaping only backslashes and dollars.
BAD:
var s = 'A string with only \\ and \$';
GOOD:
var s = r'A string with only \ and $';
use_rethrow_when_possible
Use rethrow to rethrow a caught exception.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
This rule has a quick fix available.
Details
DO use rethrow to rethrow a caught exception.
As Dart provides rethrow as a feature, it should be used to improve terseness and readability.
BAD:
try {
somethingRisky();
} catch(e) {
if (!canHandle(e)) throw e;
handle(e);
}
GOOD:
try {
somethingRisky();
} catch(e) {
if (!canHandle(e)) rethrow;
handle(e);
}
use_setters_to_change_properties
Use a setter for operations that conceptually change a property.
This rule is available as of Dart 2.0.0.
Details
DO use a setter for operations that conceptually change a property.
BAD:
rectangle.setWidth(3);
button.setVisible(false);
GOOD:
rectangle.width = 3;
button.visible = false;
use_string_buffers
Use string buffers to compose strings.
This rule is available as of Dart 2.0.0.
Details
DO use string buffers to compose strings.
In most cases, using a string buffer is preferred for composing strings due to its improved performance.
BAD:
String foo() {
final buffer = '';
for (int i = 0; i < 10; i++) {
buffer += 'a'; // LINT
}
return buffer;
}
GOOD:
String foo() {
final buffer = StringBuffer();
for (int i = 0; i < 10; i++) {
buffer.write('a');
}
return buffer.toString();
}
use_string_in_part_of_directives
Use string in part of directives.
This rule is available as of Dart 2.19.0.
Details
From Effective Dart:
DO use strings in part of
directives.
BAD:
part of my_library;
GOOD:
part of '../../my_library.dart';
use_super_parameters
Use super-initializer parameters where possible.
This rule is currently experimental and available as of Dart 2.17.0.
This rule has a quick fix available.
Details
“Forwarding constructor”s, that do nothing except forward parameters to their superclass constructors should take advantage of super-initializer parameters rather than repeating the names of parameters when passing them to the superclass constructors. This makes the code more concise and easier to read and maintain.
DO use super-initializer parameters where possible.
BAD:
class A {
A({int? x, int? y});
}
class B extends A {
B({int? x, int? y}) : super(x: x, y: y);
}
GOOD:
class A {
A({int? x, int? y});
}
class B extends A {
B({super.x, super.y});
}
use_test_throws_matchers
Use throwsA matcher instead of fail().
This rule is available as of Dart 2.14.0.
Details
Use the throwsA
matcher instead of try-catch with fail()
.
BAD:
// sync code
try {
someSyncFunctionThatThrows();
fail('expected Error');
} on Error catch (error) {
expect(error.message, contains('some message'));
}
// async code
try {
await someAsyncFunctionThatThrows();
fail('expected Error');
} on Error catch (error) {
expect(error.message, contains('some message'));
}
GOOD:
// sync code
expect(
() => someSyncFunctionThatThrows(),
throwsA(isA<Error>().having((Error error) => error.message, 'message', contains('some message'))),
);
// async code
await expectLater(
() => someAsyncFunctionThatThrows(),
throwsA(isA<Error>().having((Error error) => error.message, 'message', contains('some message'))),
);
use_to_and_as_if_applicable
Start the name of the method with to/_to or as/_as if applicable.
This rule is available as of Dart 2.0.0.
Details
From the Effective Dart:
PREFER naming a method to___()
if it copies the object’s state to a new
object.
PREFER naming a method as___()
if it returns a different representation
backed by the original object.
BAD:
class Bar {
Foo myMethod() {
return Foo.from(this);
}
}
GOOD:
class Bar {
Foo toFoo() {
return Foo.from(this);
}
}
GOOD:
class Bar {
Foo asFoo() {
return Foo.from(this);
}
}
void_checks
Don’t assign to void.
This rule is available as of Dart 2.0.0.
Rule sets: core, recommended, flutter
Details
DON’T assign to void.
BAD:
class A<T> {
T value;
void test(T arg) { }
}
void main() {
A<void> a = A<void>();
a.value = 1; // LINT
a.test(1); // LINT
}
Pub rules
These rules identify possible issues around pub package setup.
depend_on_referenced_packages
Depend on referenced packages.
This rule is available as of Dart 2.14.0.
Rule sets: core, recommended, flutter
Details
DO depend on referenced packages.
When importing a package, add a dependency on it to your pubspec.
Depending explicitly on packages that you reference ensures they will always exist and allows you to put a dependency constraint on them to guard you against breaking changes.
Whether this should be a regular dependency or dev_dependency depends on if it
is referenced from a public file (one under either lib
or bin
), or some
other private file.
BAD:
import 'package:a/a.dart';
dependencies:
GOOD:
import 'package:a/a.dart';
dependencies:
a: ^1.0.0
package_names
Use lowercase_with_underscores
for package names.
This rule is available as of Dart 2.0.0.
Rule sets: recommended, flutter
Details
From the Pubspec format description:
DO use lowercase_with_underscores
for package names.
Package names should be all lowercase, with underscores to separate words,
just_like_this
. Use only basic Latin letters and Arabic digits: [a-z0-9_].
Also, make sure the name is a valid Dart identifier – that it doesn’t start
with digits and isn’t a reserved word.
secure_pubspec_urls
Use secure urls in pubspec.yaml
.
This rule is available as of Dart 2.16.0.
Details
DO Use secure urls in pubspec.yaml
.
Use https
instead of http
or git:
.
BAD:
repository: http://github.com/dart-lang/example
git:
url: git://github.com/dart-lang/example/example.git
GOOD:
repository: https://github.com/dart-lang/example
sort_pub_dependencies
Sort pub dependencies alphabetically.
This rule is available as of Dart 2.1.0.
Details
DO sort pub dependencies alphabetically (A to Z) in pubspec.yaml
.
Sorting list of pub dependencies makes maintenance easier.