blob: aa426f639cc62546219f0ce111624f516750c36a [file] [log] [blame] [edit]
# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
# After editing this file to add a new lint rule or code,
# make sure to regenerate supporting classes by running:
#
# dart run pkg/linter/tool/generate_lints.dart
# There is a fixed set of categories:
#
# * binarySize - rules that help to minimize binary size.
# * brevity - rules that encourage brevity in the source code.
# * documentationCommentMaintenance - rules that help to maintain documentation
# comments.
# * effectiveDart - rules that align with the Effective Dart style guide.
# * errorProne - rules that protect against error-prone code.
# * flutter - rules that help to write Flutter code.
# * languageFeatureUsage - rules that promote language feature usage.
# * memoryLeaks - rules that protect against possibly memory-leaking code.
# * nonPerformant - rules that protect against non-performant code.
# * pub - pub-related rules.
# * publicInterface - rules that promote a healthy public interface.
# * style - matters of style, largely derived from Effective Dart.
# * unintentional - rules that protect against code that probably doesn't do
# what you think it does, or that shouldn't be used as it is.
# * unusedCode - rules that protect against unused code.
# * web - rules that help to write code deployed to the web.
LintCode:
always_declare_return_types_of_functions:
sharedName: always_declare_return_types
problemMessage: "The function '{0}' should have a return type but doesn't."
correctionMessage: "Try adding a return type to the function."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a method or function doesn't
have an explicit return type.
#### Example
The following code produces this diagnostic because the function `f`
doesn't have a return type:
```dart
[!f!]() {}
```
#### Common fixes
Add an explicit return type:
```dart
void f() {}
```
deprecatedDetails: |-
**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:**
```dart
main() { }
_bar() => _Foo();
class _Foo {
_foo() => 42;
}
```
**GOOD:**
```dart
void main() { }
_Foo _bar() => _Foo();
class _Foo {
int _foo() => 42;
}
typedef predicate = bool Function(Object o);
```
always_declare_return_types_of_methods:
sharedName: always_declare_return_types
problemMessage: "The method '{0}' should have a return type but doesn't."
correctionMessage: "Try adding a return type to the method."
hasPublishedDocs: true
always_put_control_body_on_new_line:
problemMessage: "Statement should be on a separate line."
correctionMessage: "Try moving the statement to a new line."
state:
stable: "2.0"
categories: [errorProne, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the code being controlled by a
control flow statement (`if`, `for`, `while`, or `do`) is on the same line
as the control flow statement.
#### Example
The following code produces this diagnostic because the `return` statement
is on the same line as the `if` that controls whether the `return` will be
executed:
```dart
void f(bool b) {
if (b) [!return!];
}
```
#### Common fixes
Put the controlled statement onto a separate, indented, line:
```dart
void f(bool b) {
if (b)
return;
}
```
deprecatedDetails: |-
From the [style guide for the flutter repo](https://flutter.dev/style-guide/):
**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:**
```dart
if (notReady) return;
if (notReady)
return;
else print('ok')
while (condition) i += 1;
```
**GOOD:**
```dart
if (notReady)
return;
if (notReady)
return;
else
print('ok')
while (condition)
i += 1;
```
Note that this rule can conflict with the
[Dart formatter](https://dart.dev/tools/dart-format), and should not be enabled
when the Dart formatter is used.
always_put_required_named_parameters_first:
problemMessage: "Required named parameters should be before optional named parameters."
correctionMessage: "Try moving the required named parameter to be before any optional named parameters."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when required named parameters occur
after optional named parameters.
#### Example
The following code produces this diagnostic because the required parameter
`x` is after the optional parameter `y`:
```dart
void f({int? y, required int [!x!]}) {}
```
#### Common fixes
Reorder the parameters so that all required named parameters are before
any optional named parameters:
```dart
void f({required int x, int? y}) {}
```
deprecatedDetails: |-
**DO** specify `required` on named parameter before other named parameters.
**BAD:**
```dart
m({b, c, required a}) ;
```
**GOOD:**
```dart
m({required a, b, c}) ;
```
**BAD:**
```dart
m({b, c, @required a}) ;
```
**GOOD:**
```dart
m({@required a, b, c}) ;
```
always_require_non_null_named_parameters:
state:
stable: "2.0"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
**DO** specify `@required` on named parameters without a default value on which
an `assert(param != null)` is done.
**BAD:**
```dart
m1({a}) {
assert(a != null);
}
```
**GOOD:**
```dart
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_add_type:
sharedName: always_specify_types
problemMessage: "Missing type annotation."
correctionMessage: "Try adding a type annotation."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
From the [style guide for the flutter repo](https://flutter.dev/style-guide/):
**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:**
```dart
var foo = 10;
final bar = Bar();
const quux = 20;
```
**GOOD:**
```dart
int foo = 10;
final Bar bar = Bar();
String baz = 'hello';
const int quux = 20;
```
NOTE: Using the `@optionalTypeArgs` annotation in the `meta` package, API
authors can special-case type parameters whose type needs to be 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:
```dart
import 'package:meta/meta.dart';
@optionalTypeArgs
class Key<T> {
...
}
void main() {
Key s = Key(); // OK!
}
```
always_specify_types_replace_keyword:
sharedName: always_specify_types
problemMessage: "Missing type annotation."
correctionMessage: "Try replacing '{0}' with '{1}'."
hasPublishedDocs: false
always_specify_types_specify_type:
sharedName: always_specify_types
problemMessage: "Missing type annotation."
correctionMessage: "Try specifying the type '{0}'."
hasPublishedDocs: false
always_specify_types_split_to_types:
sharedName: always_specify_types
problemMessage: "Missing type annotation."
correctionMessage: "Try splitting the declaration and specify the different type annotations."
hasPublishedDocs: false
always_use_package_imports:
problemMessage: "Use 'package:' imports for files in the 'lib' directory."
correctionMessage: "Try converting the URI to a 'package:' URI."
state:
stable: "2.10"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an `import` in a library inside
the `lib` directory uses a relative path to import another library inside
the `lib` directory of the same package.
#### Example
Given that a file named `a.dart` and the code below are both inside the
`lib` directory of the same package, the following code produces this
diagnostic because a relative URI is used to import `a.dart`:
```dart
import [!'a.dart'!];
```
#### Common fixes
Use a package import:
```dart
import 'package:p/a.dart';
```
deprecatedDetails: |-
**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:**
```dart
import 'baz.dart';
import 'src/bag.dart'
import '../lib/baz.dart';
...
```
**GOOD:**
```dart
import 'package:foo/bar.dart';
import 'package:foo/baz.dart';
import 'package:foo/src/baz.dart';
...
```
annotate_overrides:
problemMessage: "The member '{0}' overrides an inherited member but isn't annotated with '@override'."
correctionMessage: "Try adding the '@override' annotation."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a member overrides an inherited
member, but isn't annotated with `@override`.
#### Example
The following code produces this diagnostic because the method `m` in the
class `B` overrides the method with the same name in class `A`, but isn't
marked as an intentional override:
```dart
class A {
void m() {}
}
class B extends A {
void [!m!]() {}
}
```
#### Common fixes
If the member in the subclass is intended to override the member in the
superclass, then add an `@override` annotation:
```dart
class A {
void m() {}
}
class B extends A {
@override
void m() {}
}
```
If the member in the subclass is not intended to override the member in
the superclass, then rename one of the members:
```dart
class A {
void m() {}
}
class B extends A {
void m2() {}
}
```
deprecatedDetails: |-
**DO** annotate overridden methods and fields.
This practice improves code readability and helps protect against
unintentionally overriding superclass members.
**BAD:**
```dart
class Cat {
int get lives => 9;
}
class Lucky extends Cat {
final int lives = 14;
}
```
**GOOD:**
```dart
abstract class Dog {
String get breed;
void bark() {}
}
class Husky extends Dog {
@override
final String breed = 'Husky';
@override
void bark() {}
}
```
annotate_redeclares:
problemMessage: "The member '{0}' is redeclaring but isn't annotated with '@redeclare'."
correctionMessage: "Try adding the '@redeclare' annotation."
state:
experimental: "3.2"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** annotate redeclared members.
This practice improves code readability and helps protect against
unintentionally redeclaring members or being surprised when a member ceases to
redeclare (due for example to a rename refactoring).
**BAD:**
```dart
class C {
void f() { }
}
extension type E(C c) implements C {
void f() {
...
}
}
```
**GOOD:**
```dart
import 'package:meta/meta.dart';
class C {
void f() { }
}
extension type E(C c) implements C {
@redeclare
void f() {
...
}
}
```
avoid_annotating_with_dynamic:
problemMessage: "Unnecessary 'dynamic' type annotation."
correctionMessage: "Try removing the type 'dynamic'."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
dynamic lookUpOrDefault(String name, Map map, dynamic defaultValue) {
var value = map[name];
if (value != null) return value;
return defaultValue;
}
```
**GOOD:**
```dart
lookUpOrDefault(String name, Map map, defaultValue) {
var value = map[name];
if (value != null) return value;
return defaultValue;
}
```
avoid_as:
state:
stable: "2.0"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule was removed from the SDK in Dart 3; it is no longer functional.
Its advice is compiler-specific and mostly obsolete with null safety.
**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:**
```dart
(pm as Person).firstName = 'Seth';
```
**GOOD:**
```dart
if (pm is Person)
pm.firstName = 'Seth';
```
but certainly not
**BAD:**
```dart
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:**
```dart
HasScrollDirection scrollable = renderObject as dynamic;
```
avoid_bool_literals_in_conditional_expressions:
problemMessage: "Conditional expressions with a 'bool' literal can be simplified."
correctionMessage: "Try rewriting the expression to use either '&&' or '||'."
state:
stable: "2.0"
categories: [brevity]
hasPublishedDocs: false
deprecatedDetails: |-
**AVOID** `bool` literals in conditional expressions.
**BAD:**
```dart
condition ? true : boolExpression
condition ? false : boolExpression
condition ? boolExpression : true
condition ? boolExpression : false
```
**GOOD:**
```dart
condition || boolExpression
!condition && boolExpression
!condition || boolExpression
condition && boolExpression
```
avoid_catches_without_on_clauses:
problemMessage: "Catch clause should use 'on' to specify the type of exception being caught."
correctionMessage: "Try adding an 'on' clause before the 'catch'."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#avoid-catches-without-on-clauses):
**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:**
```dart
try {
somethingRisky()
} catch(e) {
doSomething(e);
}
```
**GOOD:**
```dart
try {
somethingRisky()
} on Exception catch(e) {
doSomething(e);
}
```
A few exceptional cases are allowed:
* If the body of the catch rethrows the exception.
* If the caught exception is "directly used" in an argument to `Future.error`,
`Completer.completeError`, or `FlutterError.reportError`, or any function with
a return type of `Never`.
* If the caught exception is "directly used" in a new throw-expression.
In these cases, "directly used" means that the exception is referenced within
the relevant code (like within an argument). If the exception variable is
referenced _before_ the relevant code, for example to instantiate a wrapper
exception, the variable is not "directly used."
avoid_catching_errors_class:
sharedName: avoid_catching_errors
problemMessage: "The type 'Error' should not be caught."
correctionMessage: "Try removing the catch or catching an 'Exception' instead."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
try {
somethingRisky();
} on Error catch(e) {
doSomething(e);
}
```
**GOOD:**
```dart
try {
somethingRisky();
} on Exception catch(e) {
doSomething(e);
}
```
avoid_catching_errors_subclass:
sharedName: avoid_catching_errors
problemMessage: "The type '{0}' should not be caught because it is a subclass of 'Error'."
correctionMessage: "Try removing the catch or catching an 'Exception' instead."
hasPublishedDocs: false
avoid_classes_with_only_static_members:
problemMessage: "Classes should define instance members."
correctionMessage: "Try adding instance behavior or moving the members out of the class."
state:
stable: "2.0"
categories: [effectiveDart, languageFeatureUsage, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#avoid-defining-a-class-that-contains-only-static-members):
**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:**
```dart
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:**
```dart
DateTime mostRecent(List<DateTime> dates) {
return dates.reduce((a, b) => a.isAfter(b) ? a : b);
}
const _favoriteMammal = 'weasel';
```
avoid_double_and_int_checks:
problemMessage: "Explicit check for double or int."
correctionMessage: "Try removing the check."
state:
stable: "2.0"
categories: [errorProne, web]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
f(num x) {
if (x is double) {
...
} else if (x is int) {
...
}
}
```
**GOOD:**
```dart
f(dynamic x) {
if (x is num) {
...
} else {
...
}
}
```
avoid_dynamic_calls:
problemMessage: "Method invocation or property access on a 'dynamic' target."
correctionMessage: "Try giving the target a type."
state:
experimental: "2.12"
stable: "2.14"
categories: [binarySize, errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a member of a class is accessed
on an expression whose type is `dynamic`.
#### Example
The following code produces this diagnostic because the getter `length` is
being invoked on `s`, which has the type `dynamic`:
```dart
void f(dynamic s) {
[!s!].length;
}
```
#### Common fixes
Provide enough type information that the expression has a type other than
`dynamic`:
```dart
void f(String s) {
s.length;
}
```
deprecatedDetails: |-
**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 `TypeError` 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.
Dynamic calls are allowed on cast expressions (`as dynamic` or `as Function`).
**BAD:**
```dart
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:**
```dart
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:
problemMessage: "Empty statements are not allowed in an 'else' clause."
correctionMessage: "Try removing the empty statement or removing the else clause."
state:
stable: "2.0"
categories: [brevity, errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the statement after an `else`
is an empty statement (a semicolon).
For more information, see the documentation for
[`avoid_empty_else`](https://dart.dev/diagnostics/avoid_empty_else).
#### Example
The following code produces this diagnostic because the statement
following the `else` is an empty statement:
```dart
void f(int x, int y) {
if (x > y)
print("1");
else [!;!]
print("2");
}
```
#### Common fixes
If the statement after the empty statement is intended to be executed only
when the condition is `false`, then remove the empty statement:
```dart
void f(int x, int y) {
if (x > y)
print("1");
else
print("2");
}
```
If there is no code that is intended to be executed only when the
condition is `false`, then remove the whole `else` clause:
```dart
void f(int x, int y) {
if (x > y)
print("1");
print("2");
}
```
deprecatedDetails: |-
**AVOID** empty statements in the `else` clause of `if` statements.
**BAD:**
```dart
if (x > y)
print('1');
else ;
print('2');
```
If you want a statement that follows the empty clause to _conditionally_ run,
remove the dangling semicolon to include it in the `else` clause.
Optionally, also enclose the else's statement in a block.
**GOOD:**
```dart
if (x > y)
print('1');
else
print('2');
```
**GOOD:**
```dart
if (x > y) {
print('1');
} else {
print('2');
}
```
If you want a statement that follows the empty clause to _unconditionally_ run,
remove the `else` clause.
**GOOD:**
```dart
if (x > y) print('1');
print('2');
```
avoid_equals_and_hash_code_on_mutable_classes:
problemMessage: "The method '{0}' should not be overridden in classes not annotated with '@immutable'."
correctionMessage: "Try removing the override or annotating the class with '@immutable'."
state:
stable: "2.6"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#avoid-defining-custom-equality-for-mutable-classes):
**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.
**BAD:**
```dart
class B {
String key;
const B(this.key);
@override
operator ==(other) => other is B && other.key == key;
@override
int get hashCode => key.hashCode;
}
```
**GOOD:**
```dart
@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:**
```dart
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:
problemMessage: "Unnecessary escape of '{0}'."
correctionMessage: "Try changing the outer quotes to '{1}'."
state:
stable: "2.8"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Avoid escaping inner quotes by converting surrounding quotes.
**BAD:**
```dart
var s = 'It\'s not fun';
```
**GOOD:**
```dart
var s = "It's not fun";
```
avoid_field_initializers_in_const_classes:
problemMessage: "Fields in 'const' classes should not have initializers."
correctionMessage: "Try converting the field to a getter or initialize the field in the constructors."
state:
stable: "2.0"
# TODO(srawlins): This rule has nothing to do with style. It is to reduce
# runtime memory usage. But we don't have a Category for that yet.
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
class A {
final a = const [];
const A();
}
```
**GOOD:**
```dart
class A {
get a => const [];
const A();
}
```
avoid_final_parameters:
problemMessage: "Parameters should not be marked as 'final'."
correctionMessage: "Try removing the keyword 'final'."
state:
stable: "2.16"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**AVOID** declaring parameters as `final`.
Declaring parameters as `final` can lead to unnecessarily verbose code,
especially when using the "parameter_assignments" rule.
**BAD:**
```dart
void goodParameter(final String label) { // LINT
print(label);
}
```
**GOOD:**
```dart
void badParameter(String label) { // OK
print(label);
}
```
**BAD:**
```dart
void goodExpression(final int value) => print(value); // LINT
```
**GOOD:**
```dart
void badExpression(int value) => print(value); // OK
```
**BAD:**
```dart
[1, 4, 6, 8].forEach((final value) => print(value + 2)); // LINT
```
**GOOD:**
```dart
[1, 4, 6, 8].forEach((value) => print(value + 2)); // OK
```
avoid_function_literals_in_foreach_calls:
problemMessage: "Function literals shouldn't be passed to 'forEach'."
correctionMessage: "Try using a 'for' loop."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the argument to
`Iterable.forEach` is a closure.
#### Example
The following code produces this diagnostic because the argument to the
invocation of `forEach` is a closure:
```dart
void f(Iterable<String> s) {
s.[!forEach!]((e) => print(e));
}
```
#### Common fixes
If the closure can be replaced by a tear-off, then replace the closure:
```dart
void f(Iterable<String> s) {
s.forEach(print);
}
```
If the closure can't be replaced by a tear-off, then use a `for` loop to
iterate over the elements:
```dart
void f(Iterable<String> s) {
for (var e in s) {
print(e);
}
}
```
deprecatedDetails: |-
**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:**
```dart
people.forEach((person) {
...
});
```
**GOOD:**
```dart
for (var person in people) {
...
}
```
avoid_futureor_void:
problemMessage: "Don't use the type 'FutureOr<void>'."
correctionMessage: "Try using 'Future<void>?' or 'void'."
state:
experimental: "3.6"
categories: [errorProne, unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the type `FutureOr<void>`
is used as the type of a result (to be precise: it is used in a
position that isn't contravariant). The type `FutureOr<void>` is
problematic because it may appear to encode that a result is either a
`Future<void>`, or the result should be discarded (when it is
`void`). However, there is no safe way to detect whether we have one
or the other case because an expression of type `void` can evaluate
to any object whatsoever, including a future of any type.
It is also conceptually unsound to have a type whose meaning is
something like "ignore this object; also, take a look because it
might be a future".
An exception is made for contravariant occurrences of the type
`FutureOr<void>` (e.g., for the type of a formal parameter), and no
warning is emitted for these occurrences. The reason for this
exception is that the type does not describe a result, it describes a
constraint on a value provided by others. Similarly, an exception is
made for type alias declarations, because they may well be used in a
contravariant position (e.g., as the type of a formal
parameter). Hence, in type alias declarations, only the type
parameter bounds are checked.
#### Example
```dart
import 'dart:async';
[!FutureOr<void>!] m() => null;
```
#### Common fixes
A replacement for the type `FutureOr<void>` which is often useful is
`Future<void>?`. This type encodes that a result is either a
`Future<void>` or it is null, and there is no ambiguity at run time
since no object can have both types.
It may not always be possible to use the type `Future<void>?` as a
replacement for the type `FutureOr<void>`, because the latter is a
supertype of all types, and the former is not. In this case it may be a
useful remedy to replace `FutureOr<void>` by the type `void`.
deprecatedDetails: |-
**AVOID** using `FutureOr<void>` as the type of a result. This type is
problematic because it may appear to encode that a result is either a
`Future<void>`, or the result should be discarded (when it is `void`).
However, there is no safe way to detect whether we have one or the other
case (because an expression of type `void` can evaluate to any object
whatsoever, including a future of any type).
It is also conceptually unsound to have a type whose meaning is something
like "ignore this object; also, take a look because it might be a future".
An exception is made for contravariant occurrences of the type
`FutureOr<void>` (e.g., for the type of a formal parameter), and no
warning is emitted for these occurrences. The reason for this exception
is that the type does not describe a result, it describes a constraint
on a value provided by others. Similarly, an exception is made for type
alias declarations, because they may well be used in a contravariant
position (e.g., as the type of a formal parameter). Hence, in type alias
declarations, only the type parameter bounds are checked.
A replacement for the type `FutureOr<void>` which is often useful is
`Future<void>?`. This type encodes that the result is either a
`Future<void>` or it is null, and there is no ambiguity at run time
since no object can have both types.
It may not always be possible to use the type `Future<void>?` as a
replacement for the type `FutureOr<void>`, because the latter is a
supertype of all types, and the former is not. In this case it may be a
useful remedy to replace `FutureOr<void>` by the type `void`.
**BAD:**
```dart
FutureOr<void> m() {...}
```
**GOOD:**
```dart
Future<void>? m() {...}
```
**This rule is experimental.** It is being evaluated, and it may be changed
or removed. Feedback on its behavior is welcome! The main issue is here:
https://github.com/dart-lang/sdk/issues/59232.
avoid_implementing_value_types:
problemMessage: "Classes that override '==' should not be implemented."
correctionMessage: "Try removing the class from the 'implements' clause."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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`:
```dart
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:**
```dart
class CustomSize implements Size {
final int inBytes;
const CustomSize(this.inBytes);
int get inKilobytes => inBytes ~/ 1000;
}
```
**BAD:**
```dart
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:**
```dart
class ExtendedSize extends Size {
ExtendedSize(int inBytes) : super(inBytes);
int get inKilobytes => inBytes ~/ 1000;
}
```
**GOOD:**
```dart
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:
problemMessage: "Redundant initialization to 'null'."
correctionMessage: "Try removing the initializer."
state:
stable: "2.0"
categories: [brevity, effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a nullable variable is
explicitly initialized to `null`. The variable can be a local variable,
field, or top-level variable.
A variable or field that isn't explicitly initialized automatically gets
initialized to `null`. There's no concept of "uninitialized memory" in
Dart.
#### Example
The following code produces this diagnostic because the variable `f` is
explicitly initialized to `null`:
```dart
class C {
int? [!f = null!];
void m() {
if (f != null) {
print(f);
}
}
}
```
#### Common fixes
Remove the unnecessary initialization:
```dart
class C {
int? f;
void m() {
if (f != null) {
print(f);
}
}
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#dont-explicitly-initialize-variables-to-null):
**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:**
```dart
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:**
```dart
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:
problemMessage: "Integer literal can't be represented exactly when compiled to JavaScript."
correctionMessage: "Try using a 'BigInt' to represent the value."
state:
stable: "2.0"
categories: [errorProne, web]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
int value = 9007199254740995;
```
**GOOD:**
```dart
BigInt value = BigInt.parse('9007199254740995');
```
avoid_multiple_declarations_per_line:
problemMessage: "Multiple variables declared on a single line."
correctionMessage: "Try splitting the variable declarations into multiple lines."
state:
stable: "2.13"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DON'T** declare multiple variables on a single line.
**BAD:**
```dart
String? foo, bar, baz;
```
**GOOD:**
```dart
String? foo;
String? bar;
String? baz;
```
avoid_null_checks_in_equality_operators:
problemMessage: "Unnecessary null comparison in implementation of '=='."
correctionMessage: "Try removing the comparison."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**NOTE:** This lint has been replaced by the
`non_nullable_equals_parameter` warning and is deprecated.
Remove all inclusions of this lint from your analysis options.
**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:**
```dart
class Person {
final String? name;
@override
operator ==(Object? other) =>
other != null && other is Person && name == other.name;
}
```
**GOOD:**
```dart
class Person {
final String? name;
@override
operator ==(Object? other) => other is Person && name == other.name;
}
```
avoid_positional_boolean_parameters:
problemMessage: "'bool' parameters should be named parameters."
correctionMessage: "Try converting the parameter to a named parameter."
state:
experimental: "2.0"
stable: "2.2"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#avoid-positional-boolean-parameters):
**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:**
```dart
Task(true);
Task(false);
ListBox(false, true, true);
Button(false);
```
**GOOD:**
```dart
Task.oneShot();
Task.repeating();
ListBox(scroll: true, showScrollbars: true);
Button(ButtonState.enabled);
```
avoid_print:
problemMessage: "Don't invoke 'print' in production code."
correctionMessage: "Try using a logging framework."
state:
stable: "2.5"
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the function `print` is invoked
in production code.
#### Example
The following code produces this diagnostic because the function `print`
can't be invoked in production:
```dart
void f(int x) {
[!print!]('x = $x');
}
```
#### Common fixes
If you're writing code that uses Flutter, then use the function
[`debugPrint`][debugPrint], guarded by a test
using [`kDebugMode`][kDebugMode]:
```dart
import 'package:flutter/foundation.dart';
void f(int x) {
if (kDebugMode) {
debugPrint('x = $x');
}
}
```
If you're writing code that doesn't use Flutter, then use a logging
service, such as [`package:logging`][package-logging], to write the
information.
deprecatedDetails: |-
**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:**
```dart
void f(int x) {
print('debug: $x');
...
}
```
**GOOD:**
```dart
void f(int x) {
debugPrint('debug: $x');
...
}
```
**GOOD:**
```dart
void f(int x) {
log('log: $x');
...
}
```
**GOOD:**
```dart
void f(int x) {
if (kDebugMode) {
print('debug: $x');
}
...
}
```
avoid_private_typedef_functions:
problemMessage: "The typedef is unnecessary because it is only used in one place."
correctionMessage: "Try inlining the type or using it in other places."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**AVOID** private typedef functions used only once. Prefer inline function
syntax.
**BAD:**
```dart
typedef void _F();
m(_F f);
```
**GOOD:**
```dart
m(void Function() f);
```
avoid_redundant_argument_values:
problemMessage: "The value of the argument is redundant because it matches the default value."
correctionMessage: "Try removing the argument."
state:
stable: "2.8"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
**DON'T** pass an argument that matches the corresponding parameter's default
value.
Note that a method override can change the default value of a parameter, so that
an argument may be equal to one default value, and not the other. Take, for
example, two classes, `A` and `B` where `B` is a subclass of `A`, and `B`
overrides a method declared on `A`, and that method has a parameter with one
default value in `A`'s declaration, and a different default value in `B`'s
declaration. If the static type of the target of the invoked method is `B`, and
`B`'s default value matches the argument, then the argument can be omitted (and
if the argument value is different, then a lint is not reported). If, however,
the static type of the target of the invoked method is `A`, then a lint may be
reported, but we cannot know statically which method is invoked, so the reported
lint may be a false positive. Such cases can be ignored inline with a comment
like `// ignore: avoid_redundant_argument_values`.
**BAD:**
```dart
void f({bool valWithDefault = true, bool? val}) {
...
}
void main() {
f(valWithDefault: true);
}
```
**GOOD:**
```dart
void f({bool valWithDefault = true, bool? val}) {
...
}
void main() {
f(valWithDefault: false);
f();
}
```
avoid_relative_lib_imports:
problemMessage: "Can't use a relative path to import a library in 'lib'."
correctionMessage: "Try fixing the relative path or changing the import to a 'package:' import."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the URI in an `import`
directive has `lib` in the path.
#### Example
Assuming that there is a file named `a.dart` in the `lib` directory:
```dart
%uri="lib/a.dart"
class A {}
```
The following code produces this diagnostic because the import contains a
path that includes `lib`:
```dart
import [!'../lib/a.dart'!];
```
#### Common fixes
Rewrite the import to not include `lib` in the URI:
```dart
import 'a.dart';
```
deprecatedDetails: |-
**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:**
```dart
import 'package:foo/bar.dart';
import '../lib/baz.dart';
...
```
**GOOD:**
```dart
import 'package:foo/bar.dart';
import 'baz.dart';
...
```
avoid_renaming_method_parameters:
problemMessage: "The parameter name '{0}' doesn't match the name '{1}' in the overridden method."
correctionMessage: "Try changing the name to '{1}'."
state:
stable: "2.0"
categories: [documentationCommentMaintenance]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a method that overrides a
method from a superclass changes the names of the parameters.
#### Example
The following code produces this diagnostic because the parameter of the
method `m` in `B` is named `b`, which is different from the name of the
overridden method's parameter in `A`:
```dart
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int [!b!]) {}
}
```
#### Common fixes
Rename one of the parameters so that they are the same:
```dart
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int a) {}
}
```
deprecatedDetails: |-
**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:**
```dart
abstract class A {
m(a);
}
abstract class B extends A {
m(b);
}
```
**GOOD:**
```dart
abstract class A {
m(a);
}
abstract class B extends A {
m(a);
}
```
avoid_return_types_on_setters:
problemMessage: "Unnecessary return type on a setter."
correctionMessage: "Try removing the return type."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a setter has an explicit return
type.
Setters never return a value, so declaring the return type of one is
redundant.
#### Example
The following code produces this diagnostic because the setter `s` has an
explicit return type (`void`):
```dart
[!void!] set s(int p) {}
```
#### Common fixes
Remove the return type:
```dart
set s(int p) {}
```
deprecatedDetails: |-
**AVOID** return types on setters.
As setters do not return a value, declaring the return type of one is redundant.
**BAD:**
```dart
void set speed(int ms);
```
**GOOD:**
```dart
set speed(int ms);
```
avoid_returning_null:
state:
stable: "2.0"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
**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:**
```dart
bool getBool() => null;
num getNum() => null;
int getInt() => null;
double getDouble() => null;
```
**GOOD:**
```dart
bool getBool() => false;
num getNum() => -1;
int getInt() => -1;
double getDouble() => -1.0;
```
avoid_returning_null_for_future:
state:
stable: "2.1"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
**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_returning_null_for_void_from_function:
sharedName: avoid_returning_null_for_void
problemMessage: "Don't return 'null' from a function with a return type of 'void'."
correctionMessage: "Try removing the 'null'."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a function that has a return
type of `void` explicitly returns `null`.
#### Example
The following code produces this diagnostic because there is an explicit
return of `null` in a `void` function:
```dart
void f() {
[!return null;!]
}
```
#### Common fixes
Remove the unnecessary explicit `null`:
```dart
void f() {
return;
}
```
deprecatedDetails: |-
**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:**
```dart
void f1() {
return null;
}
Future<void> f2() async {
return null;
}
```
**GOOD:**
```dart
void f1() {
return;
}
Future<void> f2() async {
return;
}
```
avoid_returning_null_for_void_from_method:
sharedName: avoid_returning_null_for_void
problemMessage: "Don't return 'null' from a method with a return type of 'void'."
correctionMessage: "Try removing the 'null'."
hasPublishedDocs: true
avoid_returning_this:
problemMessage: "Don't return 'this' from a method."
correctionMessage: "Try changing the return type to 'void' and removing the return."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#avoid-returning-this-from-methods-just-to-enable-a-fluent-interface):
**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:**
```dart
var buffer = StringBuffer()
.write('one')
.write('two')
.write('three');
```
**GOOD:**
```dart
var buffer = StringBuffer()
..write('one')
..write('two')
..write('three');
```
avoid_setters_without_getters:
problemMessage: "Setter has no corresponding getter."
correctionMessage: "Try adding a corresponding getter or removing the setter."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
class Bad {
int l, r;
set length(int newLength) {
r = l + newLength;
}
}
```
**GOOD:**
```dart
class Good {
int l, r;
int get length => r - l;
set length(int newLength) {
r = l + newLength;
}
}
```
avoid_shadowing_type_parameters:
problemMessage: "The type parameter '{0}' shadows a type parameter from the enclosing {1}."
correctionMessage: "Try renaming one of the type parameters."
state:
stable: "2.1"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a type parameter shadows a type
parameter from an enclosing declaration.
Shadowing a type parameter with a different type parameter can lead to
subtle bugs that are difficult to debug.
#### Example
The following code produces this diagnostic because the type parameter `T`
defined by the method `m` shadows the type parameter `T` defined by the
class `C`:
```dart
class C<T> {
void m<[!T!]>() {}
}
```
#### Common fixes
Rename one of the type parameters:
```dart
class C<T> {
void m<S>() {}
}
```
deprecatedDetails: |-
**AVOID** shadowing type parameters.
**BAD:**
```dart
class A<T> {
void fn<T>() {}
}
```
**GOOD:**
```dart
class A<T> {
void fn<U>() {}
}
```
avoid_single_cascade_in_expression_statements:
problemMessage: "Unnecessary cascade expression."
correctionMessage: "Try using the operator '{0}'."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a single cascade operator is
used and the value of the expression isn't being used for anything (such
as being assigned to a variable or being passed as an argument).
#### Example
The following code produces this diagnostic because the value of the
cascade expression `s..length` isn't being used:
```dart
void f(String s) {
[!s..length!];
}
```
#### Common fixes
Replace the cascade operator with a simple access operator:
```dart
void f(String s) {
s.length;
}
```
deprecatedDetails: |-
**AVOID** single cascade in expression statements.
**BAD:**
```dart
o..m();
```
**GOOD:**
```dart
o.m();
```
avoid_slow_async_io:
problemMessage: "Use of an async 'dart:io' method."
correctionMessage: "Try using the synchronous version of the method."
state:
stable: "2.0"
categories: [nonPerformant]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an asynchronous file I/O method
with a synchronous equivalent is used.
The following are the specific flagged asynchronous methods:
- `Directory.exists`
- `Directory.stat`
- `File.lastModified`
- `File.exists`
- `File.stat`
- `FileSystemEntity.isDirectory`
- `FileSystemEntity.isFile`
- `FileSystemEntity.isLink`
- `FileSystemEntity.type`
#### Example
The following code produces this diagnostic because the async method
`exists` is invoked:
```dart
import 'dart:io';
Future<void> g(File f) async {
await [!f.exists()!];
}
```
#### Common fixes
Use the synchronous version of the method:
```dart
import 'dart:io';
void g(File f) {
f.existsSync();
}
```
deprecatedDetails: |-
**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:**
```dart
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:**
```dart
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:
problemMessage: "Using 'toString' on a 'Type' is not safe in production code."
correctionMessage: "Try a normal type check or compare the 'runtimeType' directly."
state:
stable: "2.12"
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the method `toString` is
invoked on a value whose static type is `Type`.
#### Example
The following code produces this diagnostic because the method `toString`
is invoked on the `Type` returned by `runtimeType`:
```dart
bool isC(Object o) => o.runtimeType.[!toString!]() == 'C';
class C {}
```
#### Common fixes
If it's essential that the type is exactly the same, then use an explicit
comparison:
```dart
bool isC(Object o) => o.runtimeType == C;
class C {}
```
If it's alright for instances of subtypes of the type to return `true`,
then use a type check:
```dart
bool isC(Object o) => o is C;
class C {}
```
deprecatedDetails: |-
**DO** avoid calls to <Type>.toString() in production code, since it does not
contractually return the user-defined name of the Type (or underlying class).
Development-mode compilers where code size is not a concern use the full name,
but release-mode compilers often choose to minify these symbols.
**BAD:**
```dart
void bar(Object other) {
if (other.runtimeType.toString() == 'Bar') {
doThing();
}
}
Object baz(Thing myThing) {
return getThingFromDatabase(key: myThing.runtimeType.toString());
}
```
**GOOD:**
```dart
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_formal_parameter:
sharedName: avoid_types_as_parameter_names
problemMessage: "The parameter name '{0}' matches a visible type name."
correctionMessage: "Try adding a name for the parameter or changing the parameter name to not match an existing type."
hasPublishedDocs: true
avoid_types_as_parameter_names_type_parameter:
sharedName: avoid_types_as_parameter_names
problemMessage: "The type parameter name '{0}' matches a visible type name."
state:
stable: "2.0"
correctionMessage: "Try changing the type parameter name to not match an existing type."
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a parameter in a
parameter list is the same as a visible type (a type whose name is in
scope).
This often indicates that the intended name of the parameter is missing,
causing the name of the type to be used as the name of the parameter
rather than the type of the parameter. Even when that's not the case (the
name of the parameter is intentional), the name of the parameter will
shadow the existing type, which can lead to bugs that are difficult to
diagnose.
The analyzer also produces this diagnostic when the name of a type
parameter in a type parameter list is the same as a type whose name is
in scope. It is again recommended that the type parameter is renamed
such that the error-prone shadowing is avoided.
#### Example
The following code produces this diagnostic because the function `f` has a
parameter named `int`, which shadows the type `int` from `dart:core`:
```dart
void f([!int!]) {}
```
#### Common fixes
If the parameter name is missing, then add a name for the parameter:
```dart
void f(int x) {}
```
If the parameter is intended to have an implicit type of `dynamic`, then
rename the parameter so that it doesn't shadow the name of any visible type:
```dart
void f(int_) {}
```
deprecatedDetails: |-
**AVOID** using a parameter name that is the same as an existing type.
**BAD:**
```dart
m(f(int));
```
**GOOD:**
```dart
m(f(int v));
```
avoid_types_on_closure_parameters:
problemMessage: "Unnecessary type annotation on a function expression parameter."
correctionMessage: "Try removing the type annotation."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
var names = people.map((Person person) => person.name);
```
**GOOD:**
```dart
var names = people.map((person) => person.name);
```
avoid_unnecessary_containers:
problemMessage: "Unnecessary instance of 'Container'."
correctionMessage: "Try removing the 'Container' (but not its children) from the widget tree."
state:
stable: "2.7"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a widget tree contains an
instance of `Container` and the only argument to the constructor is
`child:`.
#### Example
The following code produces this diagnostic because the invocation of the
`Container` constructor only has a `child:` argument:
```dart
import 'package:flutter/material.dart';
Widget buildRow() {
return [!Container!](
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
```
#### Common fixes
If you intended to provide other arguments to the constructor, then add
them:
```dart
import 'package:flutter/material.dart';
Widget buildRow() {
return Container(
color: Colors.red.shade100,
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
```
If no other arguments are needed, then unwrap the child widget:
```dart
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: [
Text('a'),
Text('b'),
],
);
}
```
deprecatedDetails: |-
**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:**
```dart
Widget buildRow() {
return Container(
child: Row(
children: <Widget>[
const MyLogo(),
const Expanded(
child: Text('...'),
),
],
)
);
}
```
**GOOD:**
```dart
Widget buildRow() {
return Row(
children: <Widget>[
const MyLogo(),
const Expanded(
child: Text('...'),
),
],
);
}
```
avoid_unstable_final_fields:
state:
experimental: "3.3"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
This rule has been removed.
avoid_unused_constructor_parameters:
problemMessage: "The parameter '{0}' is not used in the constructor."
correctionMessage: "Try using the parameter or removing it."
state:
stable: "2.0"
# TODO(srawlins): This isn't even just about unintentional syntax; unused
# parameters can represent code bloat.
categories: [unintentional]
hasPublishedDocs: false
deprecatedDetails: |-
**AVOID** defining unused parameters in constructors.
**BAD:**
```dart
class BadOne {
BadOne(int unusedParameter, [String unusedPositional]);
}
class BadTwo {
int c;
BadTwo(int a, int b, int x) {
c = a + b;
}
}
```
avoid_void_async:
problemMessage: "An 'async' function should have a 'Future' return type when it doesn't return a value."
correctionMessage: "Try changing the return type."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** mark `async` functions as returning `Future<void>`.
When declaring an `async` method or function which does not return a value,
declare that it returns `Future<void>` and not just `void`.
**BAD:**
```dart
void f() async {}
void f2() async => null;
```
**GOOD:**
```dart
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:**
```dart
Future<void> f() async {}
void main() async {
await f();
}
```
avoid_web_libraries_in_flutter:
problemMessage: "Don't use web-only libraries outside Flutter web plugins."
correctionMessage: "Try finding a different library for your needs."
state:
experimental: "2.6"
stable: "2.14"
categories: [errorProne, flutter, web]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a library in a package that
isn't a web plugin contains an import of a web-only library:
- `dart:html`
- `dart:js`
- `dart:js_util`
- `dart:js_interop`
- `dart:js_interop_unsafe`
- `package:js`
- `package:web`
#### Example
When found in a package that isn't a web plugin, the following code
produces this diagnostic because it imports `dart:html`:
```dart
import [!'dart:html'!];
import 'package:flutter/material.dart';
class C {}
```
#### Common fixes
If the package isn't intended to be a web plugin, then remove the import:
```dart
import 'package:flutter/material.dart';
class C {}
```
If the package is intended to be a web plugin, then add the following
lines to the `pubspec.yaml` file of the package:
```yaml
flutter:
plugin:
platforms:
web:
pluginClass: HelloPlugin
fileName: hello_web.dart
```
See [Developing packages & plugins](https://flutter.dev/to/develop-packages)
for more information.
deprecatedDetails: |-
**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 of 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.
await_only_futures:
problemMessage: "Uses 'await' on an instance of '{0}', which is not a subtype of 'Future'."
correctionMessage: "Try removing the 'await' or changing the expression."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the expression after `await`
has any type other than `Future<T>`, `FutureOr<T>`, `Future<T>?`,
`FutureOr<T>?` or `dynamic`.
An exception is made for the expression `await null` because it is a
common way to introduce a microtask delay.
Unless the expression can produce a `Future`, the `await` is unnecessary
and can cause a reader to assume a level of asynchrony that doesn't exist.
#### Example
The following code produces this diagnostic because the expression after
`await` has the type `int`:
```dart
void f() async {
[!await!] 23;
}
```
#### Common fixes
Remove the `await`:
```dart
void f() async {
23;
}
```
deprecatedDetails: |-
**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:**
```dart
main() async {
print(await 23);
}
```
**GOOD:**
```dart
main() async {
await null; // If a delay is really intended.
print(23);
}
```
camel_case_extensions:
problemMessage: "The extension name '{0}' isn't an UpperCamelCase identifier."
correctionMessage: "Try changing the name to follow the UpperCamelCase style."
state:
stable: "2.6"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of an extension
doesn't use the 'UpperCamelCase' naming convention.
#### Example
The following code produces this diagnostic because the name of the
extension doesn't start with an uppercase letter:
```dart
extension [!stringExtension!] on String {}
```
#### Common fixes
If the extension needs to have a name (needs to be visible outside this
library), then rename the extension so that it has a valid name:
```dart
extension StringExtension on String {}
```
If the extension doesn't need to have a name, then remove the name of the
extension:
```dart
extension on String {}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/style#do-name-extensions-using-uppercamelcase):
**DO** name extensions using `UpperCamelCase`.
Extensions should capitalize the first letter of each word (including
the first word), and use no separators.
**GOOD:**
```dart
extension MyFancyList<T> on List<T> {
// ...
}
extension SmartIterable<T> on Iterable<T> {
// ...
}
```
camel_case_types:
problemMessage: "The type name '{0}' isn't an UpperCamelCase identifier."
correctionMessage: "Try changing the name to follow the UpperCamelCase style."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a type (a class,
mixin, enum, or typedef) doesn't use the 'UpperCamelCase' naming
convention.
#### Example
The following code produces this diagnostic because the name of the class
doesn't start with an uppercase letter:
```dart
class [!c!] {}
```
#### Common fixes
Rename the type so that it has a valid name:
```dart
class C {}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/style#do-name-types-using-uppercamelcase):
**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:**
```dart
class SliderMenu {
// ...
}
class HttpRequest {
// ...
}
typedef num Adder(num x, num y);
```
cancel_subscriptions:
problemMessage: "Uncancelled instance of 'StreamSubscription'."
correctionMessage: "Try invoking 'cancel' in the function in which the 'StreamSubscription' was created."
state:
stable: "2.0"
categories: [errorProne, memoryLeaks]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an instance of
`StreamSubscription` is created but the method `cancel` isn't invoked.
#### Example
The following code produces this diagnostic because the `subscription`
isn't canceled:
```dart
import 'dart:async';
void f(Stream stream) {
// ignore: unused_local_variable
var [!subscription = stream.listen((_) {})!];
}
```
#### Common fixes
Cancel the subscription:
```dart
import 'dart:async';
void f(Stream stream) {
var subscription = stream.listen((_) {});
subscription.cancel();
}
```
deprecatedDetails: |-
**DO** invoke `cancel` on instances of `dart:async` `StreamSubscription`.
Cancelling instances of StreamSubscription prevents memory leaks and unexpected
behavior.
**BAD:**
```dart
class A {
StreamSubscription _subscriptionA; // LINT
void init(Stream stream) {
_subscriptionA = stream.listen((_) {});
}
}
```
**BAD:**
```dart
void someFunction() {
StreamSubscription _subscriptionF; // LINT
}
```
**GOOD:**
```dart
class B {
StreamSubscription _subscriptionB; // OK
void init(Stream stream) {
_subscriptionB = stream.listen((_) {});
}
void dispose(filename) {
_subscriptionB.cancel();
}
}
```
**GOOD:**
```dart
void someFunctionOK() {
StreamSubscription _subscriptionB; // OK
_subscriptionB.cancel();
}
```
**Known limitations**
This rule does not track all patterns of StreamSubscription instantiations and
cancellations. See [linter#317](https://github.com/dart-lang/sdk/issues/57387)
for more information.
cascade_invocations:
problemMessage: "Unnecessary duplication of receiver."
correctionMessage: "Try using a cascade to avoid the duplication."
state:
stable: "2.0"
categories: [brevity, languageFeatureUsage, style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** Use the cascading style when successively invoking methods on the same
reference.
**BAD:**
```dart
SomeClass someReference = SomeClass();
someReference.firstMethod();
someReference.secondMethod();
```
**BAD:**
```dart
SomeClass someReference = SomeClass();
...
someReference.firstMethod();
someReference.aProperty = value;
someReference.secondMethod();
```
**GOOD:**
```dart
SomeClass someReference = SomeClass()
..firstMethod()
..aProperty = value
..secondMethod();
```
**GOOD:**
```dart
SomeClass someReference = SomeClass();
...
someReference
..firstMethod()
..aProperty = value
..secondMethod();
```
cast_nullable_to_non_nullable:
problemMessage: "Don't cast a nullable value to a non-nullable type."
correctionMessage: "Try adding a not-null assertion ('!') to make the type non-nullable."
state:
stable: "2.12"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
class A {}
class B extends A {}
A? a;
var v = a as B;
var v = a as A;
```
**GOOD:**
```dart
class A {}
class B extends A {}
A? a;
var v = a! as B;
var v = a!;
```
close_sinks:
problemMessage: "Unclosed instance of 'Sink'."
correctionMessage: "Try invoking 'close' in the function in which the 'Sink' was created."
state:
stable: "2.0"
categories: [errorProne, memoryLeaks]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an instance of `Sink` is
created but the method `close` isn't invoked.
#### Example
The following code produces this diagnostic because the `sink` isn't
closed:
```dart
import 'dart:io';
void g(File f) {
var [!sink = f.openWrite()!];
sink.write('x');
}
```
#### Common fixes
Close the sink:
```dart
import 'dart:io';
void g(File f) {
var sink = f.openWrite();
sink.write('x');
sink.close();
}
```
deprecatedDetails: |-
**DO** invoke `close` on instances of `dart:core` `Sink`.
Closing instances of Sink prevents memory leaks and unexpected behavior.
**BAD:**
```dart
class A {
IOSink _sinkA;
void init(filename) {
_sinkA = File(filename).openWrite(); // LINT
}
}
```
**BAD:**
```dart
void someFunction() {
IOSink _sinkF; // LINT
}
```
**GOOD:**
```dart
class B {
IOSink _sinkB;
void init(filename) {
_sinkB = File(filename).openWrite(); // OK
}
void dispose(filename) {
_sinkB.close();
}
}
```
**GOOD:**
```dart
void someFunctionOK() {
IOSink _sinkFOK; // OK
_sinkFOK.close();
}
```
**Known limitations**
This rule does not track all patterns of Sink instantiations and
closures. See [sdk#57882](https://github.com/dart-lang/sdk/issues/57882)
for more information.
collection_methods_unrelated_type:
problemMessage: "The argument type '{0}' isn't related to '{1}'."
correctionMessage: "Try changing the argument or element type to match."
state:
stable: "2.19"
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when any one of several methods in
the core libraries are invoked with arguments of an inappropriate type.
These methods are ones that don't provide a specific enough type for the
parameter to allow the normal type checking to catch the error.
The arguments that are checked are:
- an argument to `Iterable<E>.contains` should be related to `E`
- an argument to `List<E>.remove` should be related to `E`
- an argument to `Map<K, V>.containsKey` should be related to `K`
- an argument to `Map<K, V>.containsValue` should be related to `V`
- an argument to `Map<K, V>.remove` should be related to `K`
- an argument to `Map<K, V>.[]` should be related to `K`
- an argument to `Queue<E>.remove` should be related to `E`
- an argument to `Set<E>.lookup` should be related to `E`
- an argument to `Set<E>.remove` should be related to `E`
#### Example
The following code produces this diagnostic because the argument to
`contains` is a `String`, which isn't assignable to `int`, the element
type of the list `l`:
```dart
bool f(List<int> l) => l.contains([!'1'!]);
```
#### Common fixes
If the element type is correct, then change the argument to have the same
type:
```dart
bool f(List<int> l) => l.contains(1);
```
If the argument type is correct, then change the element type:
```dart
bool f(List<String> l) => l.contains('1');
```
deprecatedDetails: |-
**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 to `E`
* an argument to `List<E>.remove` should be related to `E`
* an argument to `Map<K, V>.containsKey` should be related to `K`
* an argument to `Map<K, V>.containsValue` should be related to `V`
* an argument to `Map<K, V>.remove` should be related to `K`
* an argument to `Map<K, V>.[]` should be related to `K`
* an argument to `Queue<E>.remove` should be related to `E`
* an argument to `Set<E>.lookup` should be related to `E`
* an argument to `Set<E>.remove` should be related to `E`
**BAD:**
```dart
void someFunction() {
var list = <int>[];
if (list.contains('1')) print('someFunction'); // LINT
}
```
**BAD:**
```dart
void someFunction() {
var set = <int>{};
set.remove('1'); // LINT
}
```
**GOOD:**
```dart
void someFunction() {
var list = <int>[];
if (list.contains(1)) print('someFunction'); // OK
}
```
**GOOD:**
```dart
void someFunction() {
var set = <int>{};
set.remove(1); // OK
}
```
combinators_ordering:
problemMessage: "Sort combinator names alphabetically."
correctionMessage: "Try sorting the combinator names alphabetically."
state:
stable: "2.19"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** sort combinator names alphabetically.
**BAD:**
```dart
import 'a.dart' show B, A hide D, C;
export 'a.dart' show B, A hide D, C;
```
**GOOD:**
```dart
import 'a.dart' show A, B hide C, D;
export 'a.dart' show A, B hide C, D;
```
comment_references:
problemMessage: "The referenced name isn't visible in scope."
correctionMessage: "Try adding an import for the referenced name."
state:
stable: "2.0"
categories: [documentationCommentMaintenance]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** reference only in-scope identifiers in doc comments.
If you surround identifiers like variable, method, or type names in square
brackets, then tools like your IDE and
[`dart doc`](https://dart.dev/tools/dart-doc) can link to them. For this to
work, ensure that all identifiers in docs wrapped in brackets are in scope.
For example, assuming `outOfScopeId` is out of scope:
**BAD:**
```dart
/// Returns whether [value] is larger than [outOfScopeId].
bool isOutOfRange(int value) { ... }
```
**GOOD:**
```dart
/// Returns 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 any of the following:
- A bare identifier which is in-scope for the comment (see the spec for what is
"in-scope" in doc comments). Examples include `[print]` and `[Future]`.
- Two identifiers separated by a period (a "prefixed identifier"), such that the
first identifier acts as a namespacing identifier, such as a class property
name or method name prefixed by the containing class's name, or a top-level
identifier prefixed by an import prefix. Examples include `[Future.new]` (an
unnamed constructor), `[Future.value]` (a constructor), `[Future.wait]` (a
static method), `[Future.then]` (an instance method), `[math.max]` (given that
'dart:async' is imported with a `max` prefix).
- A prefixed identifier followed by a pair of parentheses, used to disambiguate
named constructors from instance members (whose names are allowed to collide).
Examples include `[Future.value()]`.
- Three identifiers separated by two periods, such that the first identifier is
an import prefix name, the second identifier is a top-level element like a
class or an extension, and the third identifier is a member of that top-level
element. Examples include `[async.Future.then]` (given that 'dart:async' is
imported with an `async` prefix).
**Known limitations**
The `comment_references` lint rule aligns with the Dart analyzer's notion of
comment references, which is occasionally distinct from Dartdoc's notion of
comment references. The lint rule may report comment references which Dartdoc
can resolve, even though the analyzer cannot. See
[sdk#57783](https://github.com/dart-lang/sdk/issues/57783) for more
information.
conditional_uri_does_not_exist:
problemMessage: "The target of the conditional URI '{0}' doesn't exist."
correctionMessage: "Try creating the file referenced by the URI, or try using a URI for a file that does exist."
state:
stable: "2.16"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
import 'file_that_does_exist.dart'
if (condition) 'file_that_does_not_exist.dart';
```
**GOOD:**
```dart
import 'file_that_does_exist.dart'
if (condition) 'file_that_also_does_exist.dart';
```
constant_identifier_names:
problemMessage: "The constant name '{0}' isn't a lowerCamelCase identifier."
correctionMessage: "Try changing the name to follow the lowerCamelCase style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a constant doesn't
follow the lowerCamelCase naming convention.
#### Example
The following code produces this diagnostic because the name of the
top-level variable isn't a lowerCamelCase identifier:
```dart
const [!EMPTY_STRING!] = '';
```
#### Common fixes
Rewrite the name to follow the lowerCamelCase naming convention:
```dart
const emptyString = '';
```
deprecatedDetails: |-
**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:**
```dart
const PI = 3.14;
const kDefaultTimeout = 1000;
final URL_SCHEME = RegExp('^([a-z]+):');
class Dice {
static final NUMBER_GENERATOR = Random();
}
```
**GOOD:**
```dart
const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');
class Dice {
static final numberGenerator = Random();
}
```
control_flow_in_finally:
problemMessage: "Use of '{0}' in a 'finally' clause."
correctionMessage: "Try restructuring the code."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `finally` clause contains a
`return`, `break`, or `continue` statement.
#### Example
The following code produces this diagnostic because there is a `return`
statement inside a `finally` block:
```dart
int f() {
try {
return 1;
} catch (e) {
print(e);
} finally {
[!return 0;!]
}
}
```
#### Common fixes
If the statement isn't needed, then remove the statement, and remove the
`finally` clause if the block is empty:
```dart
int f() {
try {
return 1;
} catch (e) {
print(e);
}
}
```
If the statement is needed, then move the statement outside the `finally`
block:
```dart
int f() {
try {
return 1;
} catch (e) {
print(e);
}
return 0;
}
```
deprecatedDetails: |-
**AVOID** control flow leaving `finally` blocks.
Using control flow in `finally` blocks will inevitably cause unexpected behavior
that is hard to debug.
**BAD:**
```dart
class BadReturn {
double nonCompliantMethod() {
try {
return 1 / 0;
} catch (e) {
print(e);
} finally {
return 1.0; // LINT
}
}
}
```
**BAD:**
```dart
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:**
```dart
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:**
```dart
class Ok {
double compliantMethod() {
var i = 5;
try {
i = 1 / 0;
} catch (e) {
print(e); // OK
}
return i;
}
}
```
curly_braces_in_flow_control_structures:
problemMessage: "Statements in {0} should be enclosed in a block."
correctionMessage: "Try wrapping the statement in a block."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a control structure (`if`,
`for`, `while`, or `do` statement) has a statement other than a block.
#### Example
The following code produces this diagnostic because the `then` statement
is not enclosed in a block:
```dart
int f(bool b) {
if (b)
[!return 1;!]
return 0;
}
```
#### Common fixes
Add braces around the statement that should be a block:
```dart
int f(bool b) {
if (b) {
return 1;
}
return 0;
}
```
deprecatedDetails: |-
**DO** use curly braces for all flow control structures.
Doing so avoids the [dangling else](https://en.wikipedia.org/wiki/Dangling_else)
problem.
**BAD:**
```dart
if (overflowChars != other.overflowChars)
return overflowChars < other.overflowChars;
```
**GOOD:**
```dart
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 (including the condition and the body) fits in one
line. In that case, you may leave off the braces if you prefer:
**GOOD:**
```dart
if (arg == null) return defaultValue;
```
If the body wraps to the next line, though, use braces:
**GOOD:**
```dart
if (overflowChars != other.overflowChars) {
return overflowChars < other.overflowChars;
}
```
dangling_library_doc_comments:
problemMessage: "Dangling library doc comment."
correctionMessage: "Add a 'library' directive after the library comment."
state:
stable: "2.19"
categories: [documentationCommentMaintenance]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a documentation comment that
appears to be library documentation isn't followed by a `library`
directive. More specifically, it is produced when a documentation comment
appears before the first directive in the library, assuming that it isn't
a `library` directive, or before the first top-level declaration and is
separated from the declaration by one or more blank lines.
#### Example
The following code produces this diagnostic because there's a
documentation comment before the first `import` directive:
```dart
[!/// This is a great library.!]
import 'dart:core';
```
The following code produces this diagnostic because there's a
documentation comment before the first class declaration, but there's a
blank line between the comment and the declaration.
```dart
[!/// This is a great library.!]
class C {}
```
#### Common fixes
If the comment is library documentation, then add a `library` directive
without a name:
```dart
/// This is a great library.
library;
import 'dart:core';
```
If the comment is documentation for the following declaration, then remove
the blank line:
```dart
/// This is a great library.
class C {}
```
deprecatedDetails: |-
Attach library doc comments (with `///`) to library directives, rather than
leaving them dangling near the top of a library.
**BAD:**
```dart
/// This is a great library.
import 'package:math';
```
```dart
/// This is a great library.
class C {}
```
**GOOD:**
```dart
/// 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.
depend_on_referenced_packages:
problemMessage: "The imported package '{0}' isn't a dependency of the importing package."
correctionMessage: "Try adding a dependency for '{0}' in the 'pubspec.yaml' file."
state:
stable: "2.14"
categories: [pub]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a package import refers to a
package that is not specified in the `pubspec.yaml` file.
Depending explicitly on packages that you reference ensures they will
always exist and allows you to put a dependency constraint on them to
guard against breaking changes.
#### Example
Given a `pubspec.yaml` file containing the following:
```yaml
dependencies:
meta: ^3.0.0
```
The following code produces this diagnostic because there is no dependency
on the package `a`:
```dart
import 'package:a/a.dart';
```
#### Common fixes
Whether the dependency should be a regular dependency or dev dependency
depends on whether the package is referenced from a public library (one
under either `lib` or `bin`), or only private libraries, (such as one
under `test`).
If the package is referenced from at least one public library, then add a
regular dependency on the package to the `pubspec.yaml` file under the
`dependencies` field:
```yaml
dependencies:
a: ^1.0.0
meta: ^3.0.0
```
If the package is referenced only from private libraries, then add a
dev dependency on the package to the `pubspec.yaml` file under the
`dev_dependencies` field:
```yaml
dependencies:
meta: ^3.0.0
dev_dependencies:
a: ^1.0.0
```
deprecatedDetails: |-
**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:**
```dart
import 'package:a/a.dart';
```
```yaml
dependencies:
```
**GOOD:**
```dart
import 'package:a/a.dart';
```
```yaml
dependencies:
a: ^1.0.0
```
deprecated_consistency_constructor:
sharedName: deprecated_consistency
problemMessage: "Constructors in a deprecated class should be deprecated."
correctionMessage: "Try marking the constructor as deprecated."
state:
stable: "2.13"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
@deprecated
class A {
A();
}
class B {
B({this.field});
@deprecated
Object field;
}
```
**GOOD:**
```dart
@deprecated
class A {
@deprecated
A();
}
class B {
B({@deprecated this.field});
@deprecated
Object field;
}
class C extends B {
C({@deprecated super.field});
}
```
deprecated_consistency_field:
sharedName: deprecated_consistency
problemMessage: "Fields that are initialized by a deprecated parameter should be deprecated."
correctionMessage: "Try marking the field as deprecated."
hasPublishedDocs: false
deprecated_consistency_parameter:
sharedName: deprecated_consistency
problemMessage: "Parameters that initialize a deprecated field should be deprecated."
correctionMessage: "Try marking the parameter as deprecated."
hasPublishedDocs: false
deprecated_member_use_from_same_package_with_message:
sharedName: deprecated_member_use_from_same_package
problemMessage: "'{0}' is deprecated and shouldn't be used. {1}"
correctionMessage: "Try replacing the use of the deprecated member with the replacement, if a replacement is specified."
state:
stable: "3.0"
categories: [languageFeatureUsage]
hasPublishedDocs: false
deprecatedDetails: |-
Elements that are annotated with `@Deprecated` should not be referenced from
within the package in which they are declared.
**AVOID** using deprecated elements.
...
**BAD:**
```dart
// 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:**
```dart
// 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;
}
```
deprecated_member_use_from_same_package_without_message:
sharedName: deprecated_member_use_from_same_package
problemMessage: "'{0}' is deprecated and shouldn't be used."
correctionMessage: "Try replacing the use of the deprecated member with the replacement, if a replacement is specified."
hasPublishedDocs: false
diagnostic_describe_all_properties:
problemMessage: "The public property isn't described by either 'debugFillProperties' or 'debugDescribeChildren'."
correctionMessage: "Try describing the property."
state:
stable: "2.3"
categories: [errorProne, flutter]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a class that implements
`Diagnosticable` has a public property that isn't added as a property in
either a `debugFillProperties` or `debugDescribeChildren` method.
#### Example
The following code produces this diagnostic because the property `p2`
isn't added in the `debugFillProperties` method:
```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class C extends Widget {
bool get p1 => true;
bool get [!p2!] => false;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('p1', p1));
}
}
```
#### Common fixes
If there isn't on override of either the `debugFillProperties` or
`debugDescribeChildren` method, then add one.
Add a description of the property in the `debugFillProperties` or
`debugDescribeChildren` method:
```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class C extends Widget {
bool get p1 => true;
bool get p2 => false;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<bool>('p1', p1));
properties.add(DiagnosticsProperty<bool>('p2', p2));
}
}
```
deprecatedDetails: |-
**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 of `Widget`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:**
```dart
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:**
```dart
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));
}
}
```
directives_ordering_alphabetical:
sharedName: directives_ordering
problemMessage: "Sort directive sections alphabetically."
correctionMessage: "Try sorting the directives."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** follow the directive ordering conventions in
[Effective Dart](https://dart.dev/effective-dart/style#ordering):
**DO** place `dart:` imports before other imports.
**BAD:**
```dart
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
import 'dart:async'; // LINT
import 'dart:html'; // LINT
```
**BAD:**
```dart
import 'dart:html'; // OK
import 'package:bar/bar.dart';
import 'dart:async'; // LINT
import 'package:foo/foo.dart';
```
**GOOD:**
```dart
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:**
```dart
import 'a.dart';
import 'b.dart';
import 'package:bar/bar.dart'; // LINT
import 'package:foo/foo.dart'; // LINT
```
**BAD:**
```dart
import 'package:bar/bar.dart'; // OK
import 'a.dart';
import 'package:foo/foo.dart'; // LINT
import 'b.dart';
```
**GOOD:**
```dart
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:**
```dart
import 'src/error.dart';
export 'src/error.dart'; // LINT
import 'src/string_source.dart';
```
**GOOD:**
```dart
import 'src/error.dart';
import 'src/string_source.dart';
export 'src/error.dart'; // OK
```
**DO** sort sections alphabetically.
**BAD:**
```dart
import 'package:foo/bar.dart'; // OK
import 'package:bar/bar.dart'; // LINT
import 'a/b.dart'; // OK
import 'a.dart'; // LINT
```
**GOOD:**
```dart
import 'package:bar/bar.dart'; // OK
import 'package:foo/bar.dart'; // OK
import 'a.dart'; // OK
import 'a/b.dart'; // OK
```
directives_ordering_dart:
sharedName: directives_ordering
problemMessage: "Place 'dart:' {0}s before other {0}s."
correctionMessage: "Try sorting the directives."
hasPublishedDocs: false
directives_ordering_exports:
sharedName: directives_ordering
problemMessage: "Specify exports in a separate section after all imports."
correctionMessage: "Try sorting the directives."
hasPublishedDocs: false
directives_ordering_package_before_relative:
sharedName: directives_ordering
problemMessage: "Place 'package:' {0}s before relative {0}s."
correctionMessage: "Try sorting the directives."
hasPublishedDocs: false
discarded_futures:
problemMessage: "'Future'-returning calls in a non-'async' function."
correctionMessage: "Try converting the enclosing function to be 'async' and then 'await' the future, or wrap the expression in 'unawaited'."
state:
stable: "2.18"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
void recreateDir(String path) {
deleteDir(path);
createDir(path);
}
Future<void> deleteDir(String path) async {}
Future<void> createDir(String path) async {}
```
**GOOD:**
```dart
Future<void> recreateDir(String path) async {
await deleteDir(path);
await createDir(path);
}
Future<void> deleteDir(String path) async {}
Future<void> createDir(String path) async {}
```
do_not_use_environment:
problemMessage: "Invalid use of an environment declaration."
correctionMessage: "Try removing the environment declaration usage."
state:
stable: "2.9"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
const loggingLevel =
bool.hasEnvironment('logging') ? String.fromEnvironment('logging') : null;
```
document_ignores:
problemMessage: "Missing documentation explaining why the diagnostic is ignored."
correctionMessage: "Try adding a comment immediately above the ignore comment."
state:
stable: "3.5"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** document all ignored diagnostic reports.
**BAD:**
```dart
// ignore: unused_element
int _x = 1;
```
**GOOD:**
```dart
// This private field will be used later.
// ignore: unused_element
int _x = 1;
```
empty_catches:
problemMessage: "Empty catch block."
correctionMessage: "Try adding statements to the block, adding a comment to the block, or removing the 'catch' clause."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the block in a `catch` clause
is empty.
#### Example
The following code produces this diagnostic because the catch block is
empty:
```dart
void f() {
try {
print('Hello');
} catch (exception) [!{}!]
}
```
#### Common fixes
If the exception shouldn't be ignored, then add code to handle the
exception:
```dart
void f() {
try {
print('We can print.');
} catch (exception) {
print("We can't print.");
}
}
```
If the exception is intended to be ignored, then add a comment explaining
why:
```dart
void f() {
try {
print('We can print.');
} catch (exception) {
// Nothing to do.
}
}
```
If the exception is intended to be ignored and there isn't any good
explanation for why, then rename the exception parameter:
```dart
void f() {
try {
print('We can print.');
} catch (_) {}
}
```
deprecatedDetails: |-
**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:**
```dart
try {
...
} catch(exception) { }
```
**GOOD:**
```dart
try {
...
} catch(e) {
// ignored, really.
}
// Alternatively:
try {
...
} catch(_) { }
// Better still:
try {
...
} catch(e) {
doSomething(e);
}
```
empty_constructor_bodies:
problemMessage: "Empty constructor bodies should be written using a ';' rather than '{}'."
correctionMessage: "Try replacing the constructor body with ';'."
state:
stable: "2.0"
categories: [brevity, effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constructor has an empty
block body.
#### Example
The following code produces this diagnostic because the constructor for
`C` has a block body that is empty:
```dart
class C {
C() [!{}!]
}
```
#### Common fixes
Replace the block with a semicolon:
```dart
class C {
C();
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#do-use--instead-of--for-empty-constructor-bodies):
**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:**
```dart
class Point {
int x, y;
Point(this.x, this.y) {}
}
```
**GOOD:**
```dart
class Point {
int x, y;
Point(this.x, this.y);
}
```
empty_statements:
problemMessage: "Unnecessary empty statement."
correctionMessage: "Try removing the empty statement or restructuring the code."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an empty statement is found.
#### Example
The following code produces this diagnostic because the statement
controlled by the `while` loop is an empty statement:
```dart
void f(bool condition) {
while (condition)[!;!]
g();
}
void g() {}
```
#### Common fixes
If there are no statements that need to be controlled, then remove both
the empty statement and the control structure it's part of (being careful
that any other code being removed doesn't have a side-effect that needs to
be preserved):
```dart
void f(bool condition) {
g();
}
void g() {}
```
If there are no statements that need to be controlled but the control
structure is still required for other reasons, then replace the empty
statement with a block to make the structure of the code more obvious:
```dart
void f(bool condition) {
while (condition) {}
g();
}
void g() {}
```
If there are statements that need to be controlled, remove the empty
statement and adjust the code so that the appropriate statements are being
controlled, possibly adding a block:
```dart
void f(bool condition) {
while (condition) {
g();
}
}
void g() {}
```
deprecatedDetails: |-
**AVOID** empty statements.
Empty statements almost always indicate a bug.
For example,
**BAD:**
```dart
if (complicated.expression.foo());
bar();
```
Formatted with `dart format` the bug becomes obvious:
```dart
if (complicated.expression.foo()) ;
bar();
```
Better to avoid the empty statement altogether.
**GOOD:**
```dart
if (complicated.expression.foo())
bar();
```
enable_null_safety:
state:
stable: "2.19"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
**DO** use sound null safety, by not specifying a dart version lower than `2.12`.
**BAD:**
```dart
// @dart=2.8
a() {
}
```
**GOOD:**
```dart
b() {
}
```
eol_at_end_of_file:
problemMessage: "Missing a newline at the end of the file."
correctionMessage: "Try adding a newline at the end of the file."
state:
stable: "2.14"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** put a single newline at the end of non-empty files.
**BAD:**
```dart
a {
}
```
**GOOD:**
```dart
b {
}
<-- newline
```
erase_dart_type_extension_types:
problemMessage: "Unsafe use of 'DartType' in an 'is' check."
correctionMessage: "Ensure DartType extension types are erased by using a helper method."
state:
internal: "3.3"
categories: [errorProne]
hasPublishedDocs: false
todo: |-
TODO(nshahan): Update.
deprecatedDetails: |-
Experimental WIP lint to help ensure `DartType` accesses are safe in the dev_compiler.
**For internal use only.**
exhaustive_cases:
problemMessage: "Missing case clauses for some constants in '{0}'."
correctionMessage: "Try adding case clauses for the missing constants."
state:
stable: "2.9"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
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:**
```dart
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:
problemMessage: "The file name '{0}' isn't a lower_case_with_underscores identifier."
correctionMessage: "Try changing the name to follow the lower_case_with_underscores style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a `.dart` file
doesn't use lower_case_with_underscores.
#### Example
A file named `SliderMenu.dart` produces this diagnostic because the file
name uses the UpperCamelCase convention.
#### Common fixes
Rename the file to use the lower_case_with_underscores convention, such as
`slider_menu.dart`.
deprecatedDetails: |-
**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:
problemMessage: "To-do comment doesn't follow the Flutter style."
correctionMessage: "Try following the Flutter style for to-do comments."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** use Flutter TODO format.
From the [Flutter
docs](https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#comments):
> 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:**
```dart
// TODO(username): message.
// TODO(username): message, https://URL-to-issue.
```
hash_and_equals:
problemMessage: "Missing a corresponding override of '{0}'."
correctionMessage: "Try overriding '{0}' or removing '{1}'."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a class or mixin either
overrides the definition of `==` but doesn't override the definition of
`hashCode`, or conversely overrides the definition of `hashCode` but
doesn't override the definition of `==`.
Both the `==` operator and the `hashCode` property of objects must be
consistent for a common hash map implementation to function properly. As a
result, when overriding either method, both should be overridden.
#### Example
The following code produces this diagnostic because the class `C`
overrides the `==` operator but doesn't override the getter `hashCode`:
```dart
class C {
final int value;
C(this.value);
@override
bool operator [!==!](Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
}
```
#### Common fixes
If you need to override one of the members, then add an override of the
other:
```dart
class C {
final int value;
C(this.value);
@override
bool operator ==(Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
@override
int get hashCode => value.hashCode;
}
```
If you don't need to override either of the members, then remove the
unnecessary override:
```dart
class C {
final int value;
C(this.value);
}
```
deprecatedDetails: |-
**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:**
```dart
class Bad {
final int value;
Bad(this.value);
@override
bool operator ==(Object other) => other is Bad && other.value == value;
}
```
**GOOD:**
```dart
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;
}
```
implementation_imports:
problemMessage: "Import of a library in the 'lib/src' directory of another package."
correctionMessage: "Try importing a public library that exports this library, or removing the import."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an import references a library
that's inside the `lib/src` directory of a different package, which
violates [the convention for pub
packages](https://dart.dev/tools/pub/package-layout#implementation-files).
#### Example
The following code, assuming that it isn't part of the `ffi` package,
produces this diagnostic because the library being imported is inside the
top-level `src` directory:
```dart
import [!'package:ffi/src/allocation.dart'!];
```
#### Common fixes
If the library being imported contains code that's part of the public API,
then import the public library that exports the public API:
```dart
import 'package:ffi/ffi.dart';
```
If the library being imported isn't part of the public API of the package,
then either find a different way to accomplish your goal, assuming that
it's possible, or open an issue asking the package authors to make it part
of the public API.
deprecatedDetails: |-
From the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files):
**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:**
```dart
// In 'road_runner'
import 'package:acme/src/internals.dart';
```
implicit_call_tearoffs:
problemMessage: "Implicit tear-off of the 'call' method."
correctionMessage: "Try explicitly tearing off the 'call' method."
state:
stable: "2.19"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an object with a `call` method
is assigned to a function-typed variable, implicitly tearing off the
`call` method.
#### Example
The following code produces this diagnostic because an instance of
`Callable` is passed to a function expecting a `Function`:
```dart
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt([!Callable()!]);
}
```
#### Common fixes
Explicitly tear off the `call` method:
```dart
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt(Callable().call);
}
```
deprecatedDetails: |-
**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:**
```dart
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
callIt(Callable());
```
**GOOD:**
```dart
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
callIt(Callable().call);
```
implicit_reopen:
problemMessage: "The {0} '{1}' reopens '{2}' because it is not marked '{3}'."
correctionMessage: "Try marking '{1}' '{3}' or annotating it with '@reopen'."
state:
experimental: "3.0"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
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`](https://pub.dev/documentation/meta/latest/meta/reopen-constant.html)
annotation in `package:meta`.
**BAD:**
```dart
interface class I {}
class C extends I {} // LINT
```
**GOOD:**
```dart
interface class I {}
final class C extends I {}
```
```dart
import 'package:meta/meta.dart';
interface class I {}
@reopen
class C extends I {}
```
invalid_case_patterns:
problemMessage: "This expression is not valid in a 'case' clause in Dart 3.0."
correctionMessage: "Try refactoring the expression to be valid in 3.0."
state:
experimental: "3.0"
categories: [languageFeatureUsage]
hasPublishedDocs: false
deprecatedDetails: |-
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` and `is!` expressions
Examples of all of them:
```dart
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:
```dart
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:
```dart
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:
```dart
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:
```dart
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 `_`:
```dart
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:
```dart
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:**
```dart
case [1, 2]:
case {'k': 'v'}:
case {1, 2}:
case Point(1, 2):
```
**GOOD:**
```dart
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:**
```dart
switch (n) {
case 1 + 2: ...
}
```
It can be fixed by changing it to:
**GOOD:**
```dart
const three = 1 + 2;
switch (n) {
case three: ...
}
```
invalid_runtime_check_with_js_interop_types_dart_as_js:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Cast from '{0}' to '{1}' casts a Dart value to a JS interop type, which might not be platform-consistent."
correctionMessage: "Try using conversion methods from 'dart:js_interop' to convert between Dart types and JS interop types."
state:
stable: "3.5"
categories: [errorProne, web]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an `is` test has either:
- a JS interop type on the right-hand side, whether directly or as a type
argument to another type, or
- a JS interop value on the left-hand side.
#### Examples
The following code produces this diagnostic because the JS interop type
`JSBoolean` is on the right-hand side of an `is` test:
```dart
import 'dart:js_interop';
bool f(Object b) => [!b is JSBoolean!];
```
The following code produces this diagnostic because the JS interop type
`JSString` is used as a type argument on the right-hand side of an `is`
test:
```dart
import 'dart:js_interop';
bool f(List<Object> l) => [!l is List<JSString>!];
```
The following code produces this diagnostic because the JS interop value
`a` is on the left-hand side of an `is` test:
```dart
import 'dart:js_interop';
bool f(JSAny a) => [!a is String!];
```
#### Common fixes
Use a JS interop helper, such as `isA`, to check the underlying type of
JS interop values:
```dart
import 'dart:js_interop';
void f(Object b) => b.jsify()?.isA<JSBoolean>();
```
deprecatedDetails: |-
**DON'T** use `is` checks where the type is a JS interop type.
**DON'T** use `is` checks where the type is a generic Dart type that has JS
interop type arguments.
**DON'T** use `is` checks with a JS interop value.
`dart:js_interop` types have runtime types that are different based on whether
you are compiling to JS or to Wasm. Therefore, runtime type checks may result in
different behavior. Runtime checks also do not necessarily check that a JS
interop value is a particular JavaScript type.
**BAD:**
```dart
extension type HTMLElement(JSObject o) {}
extension type HTMLDivElement(JSObject o) implements HTMLElement {}
void compute(JSAny a, bool b, List<JSObject> lo, List<String> ls, JSObject o,
HTMLElement e) {
a is String; // LINT, checking that a JS value is a Dart type
b is JSBoolean; // LINT, checking that a Dart value is a JS type
a is JSString; // LINT, checking that a JS value is a different JS interop
// type
o is JSNumber; // LINT, checking that a JS value is a different JS interop
// type
lo is List<String>; // LINT, JS interop type argument and Dart type argument
// are incompatible
ls is List<JSString>; // LINT, Dart type argument and JS interop type argument
// are incompatible
lo is List<JSArray>; // LINT, comparing JS interop type argument with
// different JS interop type argument
lo is List<JSNumber>; // LINT, comparing JS interop type argument with
// different JS interop type argument
o is HTMLElement; // LINT, true because both are JSObjects but doesn't check
// that it's a JS HTMLElement
e is HTMLDivElement; // LINT, true because both are JSObjects but doesn't
// check that it's a JS HTMLDivElement
}
```
Prefer using JS interop helpers like `isA` from `dart:js_interop` to check the
underlying type of JS interop values.
**GOOD:**
```dart
extension type HTMLElement(JSObject o) implements JSObject {}
extension type HTMLDivElement(JSObject o) implements HTMLElement {}
void compute(JSAny a, List<JSAny> l, JSObject o, HTMLElement e) {
a.isA<JSString>; // OK, uses JS interop to check it is a JS string
l[0].isA<JSString>; // OK, uses JS interop to check it is a JS string
o.isA<HTMLElement>(); // OK, uses JS interop to check `o` is an HTMLElement
e.isA<HTMLDivElement>(); // OK, uses JS interop to check `e` is an
// HTMLDivElement
}
```
**DON'T** use `as` to cast a JS interop value to an unrelated Dart type or an
unrelated Dart value to a JS interop type.
**DON'T** use `as` to cast a JS interop value to a JS interop type represented
by an incompatible `dart:js_interop` type.
**BAD:**
```dart
extension type Window(JSObject o) {}
void compute(String s, JSBoolean b, Window w, List<String> l,
List<JSObject> lo) {
s as JSString; // LINT, casting Dart type to JS interop type
b as bool; // LINT, casting JS interop type to Dart type
b as JSNumber; // LINT, JSBoolean and JSNumber are incompatible
b as Window; // LINT, JSBoolean and JSObject are incompatible
w as JSBoolean; // LINT, JSObject and JSBoolean are incompatible
l as List<JSString>; // LINT, casting Dart value with Dart type argument to
// Dart type with JS interop type argument
lo as List<String>; // LINT, casting Dart value with JS interop type argument
// to Dart type with Dart type argument
lo as List<JSBoolean>; // LINT, casting Dart value with JS interop type
// argument to Dart type with incompatible JS interop
// type argument
}
```
Prefer using `dart:js_interop` conversion methods to convert a JS interop value
to a Dart value and vice versa.
**GOOD:**
```dart
extension type Window(JSObject o) {}
extension type Document(JSObject o) {}
void compute(String s, JSBoolean b, Window w, JSArray<JSString> a,
List<String> ls, JSObject o, List<JSAny> la) {
s.toJS; // OK, converts the Dart type to a JS type
b.toDart; // OK, converts the JS type to a Dart type
a.toDart; // OK, converts the JS type to a Dart type
w as Document; // OK, but no runtime check that `w` is a JS Document
ls.map((e) => e.toJS).toList(); // OK, converts the Dart types to JS types
o as JSArray<JSString>; // OK, JSObject and JSArray are compatible
la as List<JSString>; // OK, JSAny and JSString are compatible
(o as Object) as JSObject; // OK, Object is a supertype of JSAny
}
```
invalid_runtime_check_with_js_interop_types_dart_is_js:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Runtime check between '{0}' and '{1}' checks whether a Dart value is a JS interop type, which might not be platform-consistent."
hasPublishedDocs: false
invalid_runtime_check_with_js_interop_types_js_as_dart:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Cast from '{0}' to '{1}' casts a JS interop value to a Dart type, which might not be platform-consistent."
correctionMessage: "Try using conversion methods from 'dart:js_interop' to convert between JS interop types and Dart types."
hasPublishedDocs: false
invalid_runtime_check_with_js_interop_types_js_as_incompatible_js:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Cast from '{0}' to '{1}' casts a JS interop value to an incompatible JS interop type, which might not be platform-consistent."
hasPublishedDocs: false
invalid_runtime_check_with_js_interop_types_js_is_dart:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Runtime check between '{0}' and '{1}' checks whether a JS interop value is a Dart type, which might not be platform-consistent."
hasPublishedDocs: false
invalid_runtime_check_with_js_interop_types_js_is_inconsistent_js:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Runtime check between '{0}' and '{1}' involves a non-trivial runtime check between two JS interop types that might not be platform-consistent."
correctionMessage: "Try using a JS interop member like 'isA' from 'dart:js_interop' to check the underlying type of JS interop values."
hasPublishedDocs: false
invalid_runtime_check_with_js_interop_types_js_is_unrelated_js:
sharedName: invalid_runtime_check_with_js_interop_types
problemMessage: "Runtime check between '{0}' and '{1}' involves a runtime check between a JS interop value and an unrelated JS interop type that will always be true and won't check the underlying type."
correctionMessage: "Try using a JS interop member like 'isA' from 'dart:js_interop' to check the underlying type of JS interop values, or make the JS interop type a supertype using 'implements'."
hasPublishedDocs: false
invariant_booleans:
state:
stable: "2.0"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
**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:**
```dart
// foo can't be both equal and not equal to bar in the same expression
if(foo == bar && something && foo != bar) {...}
```
**BAD:**
```dart
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:**
```dart
void compute(bool foo) {
if (foo) {
return;
}
doSomething();
// foo is always false here
if (foo){...}
...
}
```
**GOOD:**
```dart
void nestedOK() {
if (foo == bar) {
foo = baz;
if (foo != bar) {...}
}
}
```
**GOOD:**
```dart
void nestedOk2() {
if (foo == bar) {
return;
}
foo = baz;
if (foo == bar) {...} // OK
}
```
**GOOD:**
```dart
void nestedOk5() {
if (foo != null) {
if (bar != null) {
return;
}
}
if (bar != null) {...} // OK
}
```
iterable_contains_unrelated_type:
state:
stable: "2.0"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
**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:**
```dart
void someFunction() {
var list = <int>[];
if (list.contains('1')) print('someFunction'); // LINT
}
```
**BAD:**
```dart
void someFunction3() {
List<int> list = <int>[];
if (list.contains('1')) print('someFunction3'); // LINT
}
```
**BAD:**
```dart
void someFunction8() {
List<DerivedClass2> list = <DerivedClass2>[];
DerivedClass3 instance;
if (list.contains(instance)) print('someFunction8'); // LINT
}
```
**BAD:**
```dart
abstract class SomeIterable<E> implements Iterable<E> {}
abstract class MyClass implements SomeIterable<int> {
bool badMethod(String thing) => this.contains(thing); // LINT
}
```
**GOOD:**
```dart
void someFunction10() {
var list = [];
if (list.contains(1)) print('someFunction10'); // OK
}
```
**GOOD:**
```dart
void someFunction1() {
var list = <int>[];
if (list.contains(1)) print('someFunction1'); // OK
}
```
**GOOD:**
```dart
void someFunction4() {
List<int> list = <int>[];
if (list.contains(1)) print('someFunction4'); // OK
}
```
**GOOD:**
```dart
void someFunction5() {
List<ClassBase> list = <ClassBase>[];
DerivedClass1 instance;
if (list.contains(instance)) print('someFunction5'); // OK
}
abstract class ClassBase {}
class DerivedClass1 extends ClassBase {}
```
**GOOD:**
```dart
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:**
```dart
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 {}
```
join_return_with_assignment:
problemMessage: "Assignment could be inlined in 'return' statement."
correctionMessage: "Try inlining the assigned value in the 'return' statement."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** join return statement with assignment when possible.
**BAD:**
```dart
class A {
B _lazyInstance;
static B get instance {
_lazyInstance ??= B(); // LINT
return _lazyInstance;
}
}
```
**GOOD:**
```dart
class A {
B _lazyInstance;
static B get instance => _lazyInstance ??= B();
}
```
leading_newlines_in_multiline_strings:
problemMessage: "Missing a newline at the beginning of a multiline string."
correctionMessage: "Try adding a newline at the beginning of the string."
state:
stable: "2.8"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Multiline strings are easier to read when they start with a newline (a newline
starting a multiline string is ignored).
**BAD:**
```dart
var s1 = '''{
"a": 1,
"b": 2
}''';
```
**GOOD:**
```dart
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:
problemMessage: "This annotation should be attached to a library directive."
correctionMessage: "Try attaching the annotation to a library directive."
state:
stable: "2.19"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an annotation that applies to
a whole library isn't associated with a `library` directive.
#### Example
The following code produces this diagnostic because the `TestOn`
annotation, which applies to the whole library, is associated with an
`import` directive rather than a `library` directive:
```dart
[!@TestOn('browser')!]
import 'package:test/test.dart';
void main() {}
```
#### Common fixes
Associate the annotation with a `library` directive, adding one if
necessary:
```dart
@TestOn('browser')
library;
import 'package:test/test.dart';
void main() {}
```
deprecatedDetails: |-
Attach library annotations to library directives, rather than
some other library-level element.
**BAD:**
```dart
@TestOn('browser')
import 'package:test/test.dart';
void main() {}
```
**GOOD:**
```dart
@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:
problemMessage: "The library name '{0}' isn't a lower_case_with_underscores identifier."
correctionMessage: "Try changing the name to follow the lower_case_with_underscores style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a library doesn't
use the lower_case_with_underscores naming convention.
#### Example
The following code produces this diagnostic because the library name
`libraryName` isn't a lower_case_with_underscores identifier:
```dart
library [!libraryName!];
```
#### Common fixes
If the library name is not required, then remove the library name:
```dart
library;
```
If the library name is required, then convert it to use the
lower_case_with_underscores naming convention:
```dart
library library_name;
```
deprecatedDetails: |-
**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:**
```dart
library peg-parser;
```
**GOOD:**
```dart
library peg_parser;
```
The lint `file_names` can be used to enforce the same kind of naming on the
file.
library_prefixes:
problemMessage: "The prefix '{0}' isn't a lower_case_with_underscores identifier."
correctionMessage: "Try changing the prefix to follow the lower_case_with_underscores style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an import prefix doesn't use
the lower_case_with_underscores naming convention.
#### Example
The following code produces this diagnostic because the prefix
`ffiSupport` isn't a lower_case_with_underscores identifier:
```dart
import 'package:ffi/ffi.dart' as [!ffiSupport!];
```
#### Common fixes
Convert the prefix to use the lower_case_with_underscores naming
convention:
```dart
import 'package:ffi/ffi.dart' as ffi_support;
```
deprecatedDetails: |-
**DO** use `lowercase_with_underscores` when specifying a library prefix.
**BAD:**
```dart
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:**
```dart
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:
problemMessage: "Invalid use of a private type in a public API."
correctionMessage: "Try making the private type public, or making the API that uses the private type also be private."
state:
stable: "2.14"
categories: [publicInterface]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a type that is not part of the
public API of a library is referenced in the public API of that library.
Using a private type in a public API can make the API unusable outside the
defining library.
#### Example
The following code produces this diagnostic because the parameter `c` of
the public function `f` has a type that is library private (`_C`):
```dart
void f([!_C!] c) {}
class _C {}
```
#### Common fixes
If the API doesn't need to be used outside the defining library, then make
it private:
```dart
void _f(_C c) {}
class _C {}
```
If the API needs to be part of the public API of the library, then either
use a different type that's public, or make the referenced type public:
```dart
void f(C c) {}
class C {}
```
deprecatedDetails: |-
**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:**
```dart
f(_Private p) { ... }
class _Private {}
```
**GOOD:**
```dart
f(String s) { ... }
```
lines_longer_than_80_chars:
problemMessage: "The line length exceeds the 80-character limit."
correctionMessage: "Try breaking the line across multiple lines."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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.
list_remove_unrelated_type:
state:
stable: "2.0"
removed: "3.3"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.3.0; it is no longer functional.
**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:**
```dart
void someFunction() {
var list = <int>[];
if (list.remove('1')) print('someFunction'); // LINT
}
```
**BAD:**
```dart
void someFunction3() {
List<int> list = <int>[];
if (list.remove('1')) print('someFunction3'); // LINT
}
```
**BAD:**
```dart
void someFunction8() {
List<DerivedClass2> list = <DerivedClass2>[];
DerivedClass3 instance;
if (list.remove(instance)) print('someFunction8'); // LINT
}
```
**BAD:**
```dart
abstract class SomeList<E> implements List<E> {}
abstract class MyClass implements SomeList<int> {
bool badMethod(String thing) => this.remove(thing); // LINT
}
```
**GOOD:**
```dart
void someFunction10() {
var list = [];
if (list.remove(1)) print('someFunction10'); // OK
}
```
**GOOD:**
```dart
void someFunction1() {
var list = <int>[];
if (list.remove(1)) print('someFunction1'); // OK
}
```
**GOOD:**
```dart
void someFunction4() {
List<int> list = <int>[];
if (list.remove(1)) print('someFunction4'); // OK
}
```
**GOOD:**
```dart
void someFunction5() {
List<ClassBase> list = <ClassBase>[];
DerivedClass1 instance;
if (list.remove(instance)) print('someFunction5'); // OK
}
abstract class ClassBase {}
class DerivedClass1 extends ClassBase {}
```
**GOOD:**
```dart
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:**
```dart
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:
problemMessage: "The Boolean expression has a constant value."
correctionMessage: "Try changing the expression."
state:
experimental: "2.0"
stable: "2.2"
categories: [unusedCode]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the value of the condition in
an `if` or loop statement is known to be either always `true` or always
`false`. An exception is made for a `while` loop whose condition is the
Boolean literal `true`.
#### Examples
The following code produces this diagnostic because the condition will
always evaluate to `true`:
```dart
void f() {
[!if (true) {
print('true');
}!]
}
```
The lint will evaluate a subset of expressions that are composed of
constants, so the following code will also produce this diagnostic because
the condition will always evaluate to `false`:
```dart
void g(int i) {
[!if (1 == 0 || 3 > 4) {
print('false');
}!]
}
```
#### Common fixes
If the condition is wrong, then correct the condition so that it's value
can't be known at compile time:
```dart
void g(int i) {
if (i == 0 || i > 4) {
print('false');
}
}
```
If the condition is correct, then simplify the code to not evaluate the
condition:
```dart
void f() {
print('true');
}
```
deprecatedDetails: |-
**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:**
```dart
void bad() {
if (true) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (true && 1 != 0) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (1 != 0 && true) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (1 < 0 && true) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (true && false) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (1 != 0) {} // LINT
}
```
**BAD:**
```dart
void bad() {
if (true && 1 != 0 || 3 < 4) {} // LINT
}
```
**BAD:**
```dart
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:**
```dart
void good() {
while (true) {
// Do stuff.
}
}
```
matching_super_parameters:
problemMessage: "The super parameter named '{0}'' does not share the same name as the corresponding parameter in the super constructor, '{1}'."
correctionMessage: "Try using the name of the corresponding parameter in the super constructor."
state:
stable: "3.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** use super parameter names that match their corresponding super
constructor's parameter names.
**BAD:**
```dart
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:**
```dart
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_code_block_language_in_doc_comment:
problemMessage: "The code block is missing a specified language."
correctionMessage: "Try adding a language to the code block."
state:
stable: "3.4"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** specify the language used in the code block of a doc comment.
To enable proper syntax highlighting of Markdown code blocks,
[`dart doc`](https://dart.dev/tools/dart-doc) strongly recommends code blocks to
specify the language used after the initial code fence.
See [highlight.js](https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md)
for the list of languages supported by `dart doc`.
To disable syntax highlighting or if no language is suitable,
you can specify `none` as the language.
**BAD:**
```dart
/// ```
/// void main() {}
/// ```
class A {}
```
**GOOD:**
```dart
/// ```dart
/// void main() {}
/// ```
class A {}
```
missing_whitespace_between_adjacent_strings:
problemMessage: "Missing whitespace between adjacent strings."
correctionMessage: "Try adding whitespace between the strings."
state:
stable: "2.8"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic for a pair of adjacent string
literals unless either the left-hand string ends in whitespace or the
right-hand string begins with whitespace.
#### Example
The following code produces this diagnostic because neither the left nor
the right string literal includes a space to separate the words that will
be joined:
```dart
var s =
[!'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed'!]
'do eiusmod tempor incididunt ut labore et dolore magna';
```
#### Common fixes
Add whitespace at the end of the left-hand literal or at the beginning of
the right-hand literal:
```dart
var s =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed '
'do eiusmod tempor incididunt ut labore et dolore magna';
```
deprecatedDetails: |-
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:**
```dart
var s =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed'
'do eiusmod tempor incididunt ut labore et dolore magna';
```
**GOOD:**
```dart
var s =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed '
'do eiusmod tempor incididunt ut labore et dolore magna';
```
no_adjacent_strings_in_list:
problemMessage: "Don't use adjacent strings in a list literal."
correctionMessage: "Try adding a comma between the strings."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when two string literals are
adjacent in a list literal. Adjacent strings in Dart are concatenated
together to form a single string, but the intent might be for each string
to be a separate element in the list.
#### Example
The following code produces this diagnostic because the strings `'a'` and
`'b'` are adjacent:
```dart
List<String> list = [[!'a' 'b'!], 'c'];
```
#### Common fixes
If the two strings are intended to be separate elements of the list, then
add a comma between them:
```dart
List<String> list = ['a', 'b', 'c'];
```
If the two strings are intended to be a single concatenated string, then
either manually merge the strings:
```dart
List<String> list = ['ab', 'c'];
```
Or use the `+` operator to concatenate the strings:
```dart
List<String> list = ['a' + 'b', 'c'];
```
deprecatedDetails: |-
**DON'T** use adjacent strings in a list.
This can indicate a forgotten comma.
**BAD:**
```dart
List<String> list = <String>[
'a'
'b',
'c',
];
```
**GOOD:**
```dart
List<String> list = <String>[
'a' +
'b',
'c',
];
```
no_default_cases:
problemMessage: "Invalid use of 'default' member in a switch."
correctionMessage: "Try enumerating all the possible values of the switch expression."
state:
experimental: "2.9"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
switch (testEnum) {
case TestEnum.A:
return '123';
case TestEnum.B:
return 'abc';
default:
return null;
}
```
**GOOD:**
```dart
switch (testEnum) {
case TestEnum.A:
return '123';
case TestEnum.B:
return 'abc';
}
// Default here.
return null;
```
no_duplicate_case_values:
problemMessage: "The value of the case clause ('{0}') is equal to the value of an earlier case clause ('{1}')."
correctionMessage: "Try removing or changing the value."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when two or more `case` clauses in
the same `switch` statement have the same value.
Any `case` clauses after the first can't be executed, so having duplicate
`case` clauses is misleading.
This diagnostic is often the result of either a typo or a change to the
value of a constant.
#### Example
The following code produces this diagnostic because two case clauses have
the same value (1):
```dart
// @dart = 2.14
void f(int v) {
switch (v) {
case 1:
break;
case [!1!]:
break;
}
}
```
#### Common fixes
If one of the clauses should have a different value, then change the value
of the clause:
```dart
void f(int v) {
switch (v) {
case 1:
break;
case 2:
break;
}
}
```
If the value is correct, then merge the statements into a single clause:
```dart
void f(int v) {
switch (v) {
case 1:
break;
}
}
```
deprecatedDetails: |-
**DON'T** use more than one case with same value.
This is usually a typo or changed value of constant.
**BAD:**
```dart
const int A = 1;
switch (v) {
case 1:
case 2:
case A:
case 2:
}
```
**GOOD:**
```dart
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_leading_underscores_for_library_prefixes:
problemMessage: "The library prefix '{0}' starts with an underscore."
correctionMessage: "Try renaming the prefix to not start with an underscore."
state:
stable: "2.16"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a prefix declared
on an import starts with an underscore.
Library prefixes are inherently not visible outside the declaring library,
so a leading underscore indicating private adds no value.
#### Example
The following code produces this diagnostic because the prefix `_core`
starts with an underscore:
```dart
import 'dart:core' as [!_core!];
```
#### Common fixes
Remove the underscore:
```dart
import 'dart:core' as core;
```
deprecatedDetails: |-
**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:**
```dart
import 'dart:core' as _core;
```
**GOOD:**
```dart
import 'dart:core' as core;
```
no_leading_underscores_for_local_identifiers:
problemMessage: "The local variable '{0}' starts with an underscore."
correctionMessage: "Try renaming the variable to not start with an underscore."
state:
stable: "2.16"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a local variable
starts with an underscore.
Local variables are inherently not visible outside the declaring library,
so a leading underscore indicating private adds no value.
#### Example
The following code produces this diagnostic because the parameter `_s`
starts with an underscore:
```dart
int f(String [!_s!]) => _s.length;
```
#### Common fixes
Remove the underscore:
```dart
int f(String s) => s.length;
```
deprecatedDetails: |-
**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:**
```dart
void print(String _name) {
var _size = _name.length;
...
}
```
**GOOD:**
```dart
void print(String name) {
var size = name.length;
...
}
```
**OK:**
```dart
[1,2,3].map((_) => print('Hello'));
```
no_literal_bool_comparisons:
problemMessage: "Unnecessary comparison to a boolean literal."
correctionMessage: "Remove the comparison and use the negate `!` operator if necessary."
state:
stable: "3.0"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#dont-use-true-or-false-in-equality-operations):
**DON'T** use `true` or `false` in equality operations.
This lint applies only if the expression is of a non-nullable `bool` type.
**BAD:**
```dart
if (someBool == true) {
print('true!');
}
while (someBool == false) {
print('still false!');
}
```
**GOOD:**
```dart
if (someBool) {
print('true!');
}
while (!someBool) {
print('still false!');
}
```
no_logic_in_create_state:
problemMessage: "Don't put any logic in 'createState'."
correctionMessage: "Try moving the logic out of 'createState'."
state:
stable: "2.8"
categories: [errorProne, flutter]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an implementation of
`createState` in a subclass of `StatefulWidget` contains any logic other
than the return of the result of invoking a zero argument constructor.
#### Examples
The following code produces this diagnostic because the constructor
invocation has arguments:
```dart
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => [!MyState(0)!];
}
class MyState extends State {
int x;
MyState(this.x);
}
```
#### Common fixes
Rewrite the code so that `createState` doesn't contain any logic:
```dart
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => MyState();
}
class MyState extends State {
int x = 0;
MyState();
}
```
deprecatedDetails: |-
**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:**
```dart
MyState global;
class MyStateful extends StatefulWidget {
@override
MyState createState() {
global = MyState();
return global;
}
}
```
```dart
class MyStateful extends StatefulWidget {
@override
MyState createState() => MyState()..field = 42;
}
```
```dart
class MyStateful extends StatefulWidget {
@override
MyState createState() => MyState(42);
}
```
**GOOD:**
```dart
class MyStateful extends StatefulWidget {
@override
MyState createState() {
return MyState();
}
}
```
no_runtimeType_toString:
problemMessage: "Using 'toString' on a 'Type' is not safe in production code."
correctionMessage: "Try removing the usage of 'toString' or restructuring the code."
state:
stable: "2.8"
categories: [nonPerformant]
hasPublishedDocs: false
deprecatedDetails: |-
Calling `toString` on a runtime type is a non-trivial operation that can
negatively impact performance. It's better to avoid it.
**BAD:**
```dart
class A {
String toString() => '$runtimeType()';
}
```
**GOOD:**
```dart
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 an assertion
* in a throw expression
* in a catch clause
* in a mixin declaration
* in an abstract class declaration
no_self_assignments:
problemMessage: "The variable or property is being assigned to itself."
correctionMessage: "Try removing the assignment that has no direct effect."
state:
stable: "3.1"
categories: [unintentional]
hasPublishedDocs: false
deprecatedDetails: |-
**DON'T** assign a variable to itself. Usually this is a mistake.
**BAD:**
```dart
class C {
int x;
C(int x) {
x = x;
}
}
```
**GOOD:**
```dart
class C {
int x;
C(int x) : x = x;
}
```
**GOOD:**
```dart
class C {
int x;
C(int x) {
this.x = x;
}
}
```
**BAD:**
```dart
class C {
int _x = 5;
int get x => _x;
set x(int x) {
_x = x;
_customUpdateLogic();
}
void _customUpdateLogic() {
print('updated');
}
void example() {
x = x;
}
}
```
**GOOD:**
```dart
class C {
int _x = 5;
int get x => _x;
set x(int x) {
_x = x;
_customUpdateLogic();
}
void _customUpdateLogic() {
print('updated');
}
void example() {
_customUpdateLogic();
}
}
```
**BAD:**
```dart
class C {
int x = 5;
void update(C other) {
this.x = this.x;
}
}
```
**GOOD:**
```dart
class C {
int x = 5;
void update(C other) {
this.x = other.x;
}
}
```
no_wildcard_variable_uses:
problemMessage: "The referenced identifier is a wildcard."
correctionMessage: "Use an identifier name that is not a wildcard."
state:
stable: "3.1"
categories: [languageFeatureUsage, unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when either a parameter or local
variable whose name consists of only underscores is referenced. Such
names will become non-binding in a future version of the Dart language,
making the reference illegal.
#### Example
The following code produces this diagnostic because the name of the
parameter consists of two underscores:
```dart
// @dart = 3.6
void f(int __) {
print([!__!]);
}
```
The following code produces this diagnostic because the name of the
local variable consists of a single underscore:
```dart
// @dart = 3.6
void f() {
int _ = 0;
print([!_!]);
}
```
#### Common fixes
If the variable or parameter is intended to be referenced, then give it a
name that has at least one non-underscore character:
```dart
void f(int p) {
print(p);
}
```
If the variable or parameter is not intended to be referenced, then
replace the reference with a different expression:
```dart
void f() {
print(0);
}
```
deprecatedDetails: |-
**DON'T** use wildcard parameters or variables.
Wildcard parameters and local variables
(e.g. underscore-only names like `_`, `__`, `___`, etc.) will
become non-binding in a future version of the Dart language.
Any existing code that uses wildcard parameters or variables will
break. In anticipation of this change, and to make adoption easier,
this lint disallows wildcard and variable parameter uses.
**BAD:**
```dart
var _ = 1;
print(_); // LINT
```
```dart
void f(int __) {
print(__); // LINT multiple underscores too
}
```
**GOOD:**
```dart
for (var _ in [1, 2, 3]) count++;
```
```dart
var [a, _, b, _] = [1, 2, 3, 4];
```
non_constant_identifier_names:
problemMessage: "The variable name '{0}' isn't a lowerCamelCase identifier."
correctionMessage: "Try changing the name to follow the lowerCamelCase style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a class member,
top-level declaration, variable, parameter, named parameter, or named
constructor that isn't declared to be `const`, doesn't use the
lowerCamelCase convention.
#### Example
The following code produces this diagnostic because the top-level variable
`Count` doesn't start with a lowercase letter:
```dart
var [!Count!] = 0;
```
#### Common fixes
Change the name in the declaration to follow the lowerCamelCase
convention:
```dart
var count = 0;
```
deprecatedDetails: |-
**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:**
```dart
var item;
HttpRequest httpRequest;
align(clearItems) {
// ...
}
```
noop_primitive_operations:
problemMessage: "The expression has no effect and can be removed."
correctionMessage: "Try removing the expression."
state:
stable: "2.14"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Some operations on primitive types are idempotent and can be removed.
**BAD:**
```dart
doubleValue.toDouble();
intValue.toInt();
intValue.round();
intValue.ceil();
intValue.floor();
intValue.truncate();
string.toString();
string = 'hello\n'
''
'world';
'string with ${x.toString()}';
```
Note that the empty string literals at the beginning or end of a string are
allowed, as they are typically used to format the string literal across multiple
lines:
```dart
// OK
string = ''
'hello\n'
'world\n';
// OK
string = 'hello\n'
'world\n'
'';
```
null_check_on_nullable_type_parameter:
problemMessage: "The null check operator shouldn't be used on a variable whose type is a potentially nullable type parameter."
correctionMessage: "Try explicitly testing for 'null'."
state:
experimental: "2.12"
stable: "2.17"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a null check operator is used
on a variable whose type is `T?`, where `T` is a type parameter that
allows the type argument to be nullable (either has no bound or has a
bound that is nullable).
Given a generic type parameter `T` which has a nullable bound, 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, because
if `T` is a nullable type, `x` may validly hold `null` as a value of type
`T`.
#### Example
The following code produces this diagnostic because `t` has the type `T?`
and `T` allows the type argument to be nullable (because it has no
`extends` clause):
```dart
T f<T>(T? t) => t[!!!];
```
#### Common fixes
Use the type parameter to cast the variable:
```dart
T f<T>(T? t) => t as T;
```
deprecatedDetails: |-
**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:**
```dart
T run<T>(T callback()) {
T? result;
(() { result = callback(); })();
return result!;
}
```
**GOOD:**
```dart
T run<T>(T callback()) {
T? result;
(() { result = callback(); })();
return result as T;
}
```
null_closures:
problemMessage: "Closure can't be 'null' because it might be invoked."
correctionMessage: "Try providing a non-null closure."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
**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 parameter `cleanup`
* `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
parameter `orElse`
* `Iterable.forEach` at the 0th positional parameter
* `Iterable.fold` at the 1st positional parameter
* `Iterable.lastWhere` at the 0th positional parameter, and the named
parameter `orElse`
* `Iterable.map` at the 0th positional parameter
* `Iterable.reduce` at the 0th positional parameter
* `Iterable.singleWhere` at the 0th positional parameter, and the named
parameter `orElse`
* `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 parameters `onMatch` and `onNonMatch`
**BAD:**
```dart
[1, 3, 5].firstWhere((e) => e.isOdd, orElse: null);
```
**GOOD:**
```dart
[1, 3, 5].firstWhere((e) => e.isOdd, orElse: () => null);
```
omit_local_variable_types:
problemMessage: "Unnecessary type annotation on a local variable."
correctionMessage: "Try removing the type annotation."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
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:**
```dart
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:**
```dart
Widget build(BuildContext context) {
Widget result = Text('You won!');
if (applyPadding) {
result = Padding(padding: EdgeInsets.all(8.0), child: result);
}
return result;
}
```
omit_obvious_local_variable_types:
problemMessage: "Omit the type annotation on a local variable when the type is obvious."
correctionMessage: "Try removing the type annotation."
state:
experimental: "3.6"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Don't type annotate initialized local variables when the type is obvious.
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. Hence, local
variable type annotations that are obvious should be omitted.
**BAD:**
```dart
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;
}
const cookbook = <List<Ingredient>>[....];
```
**GOOD:**
```dart
List<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {
var desserts = <List<Ingredient>>[];
for (final List<Ingredient> recipe in cookbook) {
if (pantry.containsAll(recipe)) {
desserts.add(recipe);
}
}
return desserts;
}
const cookbook = <List<Ingredient>>[....];
```
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. You may also
wish to write a type annotation explicitly because the type of the initializing
expression is non-obvious and it will be helpful for future readers of the
code to document this type. Or you may wish to commit to a specific type such
that future updates of dependencies (in nearby code, in imports, anywhere)
will not silently change the type of that variable, thus introducing
compile-time errors or run-time bugs in locations where this variable is used.
In those cases, go ahead and annotate the variable with the type you want.
**GOOD:**
```dart
Widget build(BuildContext context) {
Widget result = someGenericFunction(42) ?? Text('You won!');
if (applyPadding) {
result = Padding(padding: EdgeInsets.all(8.0), child: result);
}
return result;
}
```
**This rule is experimental.** It is being evaluated, and it may be changed
or removed. Feedback on its behavior is welcome! The main issue is here:
https://github.com/dart-lang/sdk/issues/58773.
omit_obvious_property_types:
problemMessage: "The type annotation isn't needed because it is obvious."
correctionMessage: "Try removing the type annotation."
state:
experimental: "3.7"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Don't type annotate initialized top-level or static variables when the type is
obvious.
**BAD:**
```dart
final int myTopLevelVariable = 7;
class A {
static String myStaticVariable = 'Hello';
}
```
**GOOD:**
```dart
final myTopLevelVariable = 7;
class A {
static myStaticVariable = 'Hello';
}
```
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. You may also
wish to write a type annotation explicitly because the type of the initializing
expression is non-obvious and it will be helpful for future readers of the
code to document this type. Or you may wish to commit to a specific type such
that future updates of dependencies (in nearby code, in imports, anywhere)
will not silently change the type of that variable, thus introducing
compile-time errors or run-time bugs in locations where this variable is used.
In those cases, go ahead and annotate the variable with the type you want.
**GOOD:**
```dart
final num myTopLevelVariable = 7;
class A {
static String? myStaticVariable = 'Hello';
}
```
**This rule is experimental.** It is being evaluated, and it may be changed
or removed. Feedback on its behavior is welcome! The main issue is here:
https://github.com/dart-lang/sdk/issues/59550.
one_member_abstracts:
problemMessage: "Unnecessary use of an abstract class."
correctionMessage: "Try making '{0}' a top-level function and removing the class."
state:
stable: "2.0"
categories: [effectiveDart, languageFeatureUsage, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#avoid-defining-a-one-member-abstract-class-when-a-simple-function-will-do):
**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:**
```dart
abstract class Predicate {
bool test(item);
}
```
**GOOD:**
```dart
typedef Predicate = bool Function(item);
```
only_throw_errors:
problemMessage: "Don't throw instances of classes that don't extend either 'Exception' or 'Error'."
correctionMessage: "Try throwing a different class of object."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the value being thrown isn't a
subclass of either `Exception` or `Error`.
#### Example
The following code produces this diagnostic because the string `'f'` is
being thrown:
```dart
void f() => throw [!'f'!];
```
#### Common fixes
Replace the value with an instance of a subclass of either `Exception` or
`Error`:
```dart
void f() => throw ArgumentError('f');
```
deprecatedDetails: |-
**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:**
```dart
void throwString() {
throw 'hello world!'; // LINT
}
```
**GOOD:**
```dart
void throwArgumentError() {
Error error = ArgumentError('oh!');
throw error; // OK
}
```
overridden_fields:
problemMessage: "Field overrides a field inherited from '{0}'."
correctionMessage: "Try removing the field, overriding the getter and setter if necessary."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a class defines a field that
overrides a field from a superclass.
Overriding a field with another field causes the object to have two
distinct fields, but because the fields have the same name only one of the
fields can be referenced in a given scope. That can lead to confusion
where a reference to one of the fields can be mistaken for a reference to
the other.
#### Example
The following code produces this diagnostic because the field `f` in `B`
shadows the field `f` in `A`:
```dart
class A {
int f = 1;
}
class B extends A {
@override
int [!f!] = 2;
}
```
#### Common fixes
If the two fields are representing the same property, then remove the
field from the subclass:
```dart
class A {
int f = 1;
}
class B extends A {}
```
If the two fields should be distinct, then rename one of the fields:
```dart
class A {
int f = 1;
}
class B extends A {
int g = 2;
}
```
If the two fields are related in some way, but can't be the same, then
find a different way to implement the semantics you need.
deprecatedDetails: |-
**DON'T** override fields.
Overriding fields is almost always done unintentionally. Regardless, it is a
bad practice to do so.
**BAD:**
```dart
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:**
```dart
class Base {
Object field = 'lorem';
Object something = 'change';
}
class Ok extends Base {
Object newField; // OK
final Object newFinal = 'ignore'; // OK
}
```
**GOOD:**
```dart
abstract class BaseLoggingHandler {
Base transformer;
}
class LogPrintHandler implements BaseLoggingHandler {
@override
Derived transformer; // OK
}
```
package_api_docs:
problemMessage: "Missing documentation for public API."
correctionMessage: "Try adding a documentation comment."
state:
stable: "2.0"
removed: "3.7"
categories: [effectiveDart, publicInterface]
hasPublishedDocs: false
deprecatedDetails: |-
**NOTE:** This lint has been removed because it is has not
been fully functional since at least Dart 2.0.
Remove all inclusions of this lint from your analysis options.
**DO** provide doc comments for all public APIs.
As described in the [pub package layout doc](https://dart.dev/tools/pub/package-layout#implementation-files),
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`:
```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:**
```dart
class Bar {
void bar();
}
```
**GOOD:**
```dart
/// 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](https://dart.dev/effective-dart/documentation).
package_names:
problemMessage: "The package name '{0}' isn't a lower_case_with_underscores identifier."
correctionMessage: "Try changing the name to follow the lower_case_with_underscores style."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the name of a package doesn't
use the lower_case_with_underscores naming convention.
#### Example
The following code produces this diagnostic because the name of the
package uses the lowerCamelCase naming convention:
```yaml
name: [!somePackage!]
```
#### Common fixes
Rewrite the name of the package using the lower_case_with_underscores
naming convention:
```yaml
name: some_package
```
deprecatedDetails: |-
From the [Pubspec format description](https://dart.dev/tools/pub/pubspec):
**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.
package_prefixed_library_names:
problemMessage: "The library name is not a dot-separated path prefixed by the package name."
correctionMessage: "Try changing the name to '{0}'."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a library has a name that
doesn't follow these guidelines:
- 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, given a package named `my_package`, here are the library
names for various files in the package:
```dart
// 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;
```
#### Example
Assuming that the file containing the following code is not in a file
named `special.dart` in the `lib` directory of a package named `something`
(which would be an exception to the rule), the analyzer produces this
diagnostic because the name of the library doesn't conform to the
guidelines above:
```dart
library [!something.special!];
```
#### Common fixes
Change the name of the library to conform to the guidelines.
deprecatedDetails: |-
**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:**
```dart
// 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:
problemMessage: "Invalid assignment to the parameter '{0}'."
correctionMessage: "Try using a local variable in place of the parameter."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**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:**
```dart
void badFunction(int parameter) { // LINT
parameter = 4;
}
```
**BAD:**
```dart
void badFunction(int required, {int optional: 42}) { // LINT
optional ??= 8;
}
```
**BAD:**
```dart
void badFunctionPositional(int required, [int optional = 42]) { // LINT
optional ??= 8;
}
```
**BAD:**
```dart
class A {
void badMethod(int parameter) { // LINT
parameter = 4;
}
}
```
**GOOD:**
```dart
void ok(String parameter) {
print(parameter);
}
```
**GOOD:**
```dart
void actuallyGood(int required, {int optional}) { // OK
optional ??= ...;
}
```
**GOOD:**
```dart
void actuallyGoodPositional(int required, [int optional]) { // OK
optional ??= ...;
}
```
**GOOD:**
```dart
class A {
void ok(String parameter) {
print(parameter);
}
}
```
prefer_adjacent_string_concatenation:
problemMessage: "String literals shouldn't be concatenated by the '+' operator."
correctionMessage: "Try removing the operator to use adjacent strings."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the `+` operator is used to
concatenate two string literals.
#### Example
The following code produces this diagnostic because two string literals
are being concatenated by using the `+` operator:
```dart
var s = 'a' [!+!] 'b';
```
#### Common fixes
Remove the operator:
```dart
var s = 'a' 'b';
```
deprecatedDetails: |-
**DO** use adjacent strings to concatenate string literals.
**BAD:**
```dart
raiseAlarm(
'ERROR: Parts of the spaceship are on fire. Other ' +
'parts are overrun by martians. Unclear which are which.');
```
**GOOD:**
```dart
raiseAlarm(
'ERROR: Parts of the spaceship are on fire. Other '
'parts are overrun by martians. Unclear which are which.');
```
prefer_asserts_in_initializer_lists:
problemMessage: "Assert should be in the initializer list."
correctionMessage: "Try moving the assert to the initializer list."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the body of a constructor
begins with one or more assert statements.
#### Example
The following code produces this diagnostic because the body of the
constructor begins with an assert statement:
```dart
class C {
C(int i) {
[!assert!](i != 0);
}
}
```
#### Common fixes
Move the assert to the initializer list, removing the body if there are
only assert statements in it:
```dart
class C {
C(int i) : assert(i != 0);
}
```
deprecatedDetails: |-
**DO** put asserts in initializer lists.
**BAD:**
```dart
class A {
A(int a) {
assert(a != 0);
}
}
```
**GOOD:**
```dart
class A {
A(int a) : assert(a != 0);
}
```
prefer_asserts_with_message:
problemMessage: "Missing a message in an assert."
correctionMessage: "Try adding a message to the assert."
state:
stable: "2.3"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an assert statement doesn't
have a message.
#### Example
The following code produces this diagnostic because there's no message
in the assert statement:
```dart
void f(String s) {
[!assert(s.isNotEmpty);!]
}
```
#### Common fixes
Add a message to the assert statement:
```dart
void f(String s) {
assert(s.isNotEmpty, 'The argument must not be empty.');
}
```
deprecatedDetails: |-
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:**
```dart
f(a) {
assert(a != null);
}
class A {
A(a) : assert(a != null);
}
```
**GOOD:**
```dart
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:
state:
stable: "2.0"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
**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:**
```dart
assert(() {
f();
return true;
});
```
**GOOD:**
```dart
assert(() {
f();
return true;
}());
```
prefer_collection_literals:
problemMessage: "Unnecessary constructor invocation."
correctionMessage: "Try using a collection literal."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constructor is used to create
a list, map, or set, but a literal would produce the same result.
#### Example
The following code produces this diagnostic because the constructor for
`Map` is being used to create a map that could also be created using a
literal:
```dart
var m = [!Map<String, String>()!];
```
#### Common fixes
Use the literal representation:
```dart
var m = <String, String>{};
```
deprecatedDetails: |-
**DO** use collection literals when possible.
**BAD:**
```dart
var addresses = Map<String, String>();
var uniqueNames = Set<String>();
var ids = LinkedHashSet<int>();
var coordinates = LinkedHashMap<int, int>();
```
**GOOD:**
```dart
var addresses = <String, String>{};
var uniqueNames = <String>{};
var ids = <int>{};
var coordinates = <int, int>{};
```
**EXCEPTIONS:**
When a `LinkedHashSet` or `LinkedHashMap` is expected, a collection literal is
not preferred (or allowed).
```dart
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:
problemMessage: "The 'if' statement could be replaced by a null-aware assignment."
correctionMessage: "Try using the '??=' operator to conditionally assign a value."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an assignment to a variable is
conditional based on whether the variable has the value `null` and the
`??=` operator could be used instead.
#### Example
The following code produces this diagnostic because the parameter `s` is
being compared to `null` in order to determine whether to assign a
different value:
```dart
int f(String? s) {
[!if (s == null) {
s = '';
}!]
return s.length;
}
```
#### Common fixes
Use the `??=` operator instead of an explicit `if` statement:
```dart
int f(String? s) {
s ??= '';
return s.length;
}
```
deprecatedDetails: |-
**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:**
```dart
String get fullName {
if (_fullName == null) {
_fullName = getFullUserName(this);
}
return _fullName;
}
```
**GOOD:**
```dart
String get fullName {
return _fullName ??= getFullUserName(this);
}
```
prefer_const_constructors:
problemMessage: "Use 'const' with the constructor to improve performance."
correctionMessage: "Try adding the 'const' keyword to the constructor invocation."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an invocation of a const
constructor isn't either preceded by `const` or in a [constant context][].
#### Example
The following code produces this diagnostic because the invocation of the
`const` constructor is neither prefixed by `const` nor in a
[constant context][]:
```dart
class C {
const C();
}
C c = [!C()!];
```
#### Common fixes
If the context can be made a [constant context][], then do so:
```dart
class C {
const C();
}
const C c = C();
```
If the context can't be made a [constant context][], then add `const`
before the constructor invocation:
```dart
class C {
const C();
}
C c = const C();
```
deprecatedDetails: |-
**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:**
```dart
class A {
const A();
}
void accessA() {
A a = new A();
}
```
**GOOD:**
```dart
class A {
const A();
}
void accessA() {
A a = const A();
}
```
**GOOD:**
```dart
class A {
final int x;
const A(this.x);
}
A foo(int x) => new A(x);
```
prefer_const_constructors_in_immutables:
problemMessage: "Constructors in '@immutable' classes should be declared as 'const'."
correctionMessage: "Try adding 'const' to the constructor declaration."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a non-`const` constructor is
found in a class that has the `@immutable` annotation.
#### Example
The following code produces this diagnostic because the constructor in `C`
isn't declared as `const` even though `C` has the `@immutable` annotation:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
[!C!](this.f);
}
```
#### Common fixes
If the class really is intended to be immutable, then add the `const`
modifier to the constructor:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
```
If the class is mutable, then remove the `@immutable` annotation:
```dart
class C {
final f;
C(this.f);
}
```
deprecatedDetails: |-
**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:**
```dart
@immutable
class A {
final a;
A(this.a);
}
```
**GOOD:**
```dart
@immutable
class A {
final a;
const A(this.a);
}
```
prefer_const_declarations:
problemMessage: "Use 'const' for final variables initialized to a constant value."
correctionMessage: "Try replacing 'final' with 'const'."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a top-level variable, static
field, or local variable is marked as `final` and is initialized to a
constant value.
#### Examples
The following code produces this diagnostic because the top-level variable
`v` is both `final` and initialized to a constant value:
```dart
[!final v = const <int>[]!];
```
The following code produces this diagnostic because the static field `f`
is both `final` and initialized to a constant value:
```dart
class C {
static [!final f = const <int>[]!];
}
```
The following code produces this diagnostic because the local variable `v`
is both `final` and initialized to a constant value:
```dart
void f() {
[!final v = const <int>[]!];
print(v);
}
```
#### Common fixes
Replace the keyword `final` with `const` and remove `const` from the
initializer:
```dart
class C {
static const f = <int>[];
}
```
deprecatedDetails: |-
**PREFER** using `const` for constant-valued declarations.
Constant declarations are more hot-reload friendly and allow
values to be used in other constant expressions.
**BAD:**
```dart
final o = const <int>[];
class A {
static final o = const <int>[];
}
```
**GOOD:**
```dart
const o = <int>[];
class A {
static const o = <int>[];
}
```
prefer_const_literals_to_create_immutables:
problemMessage: "Use 'const' literals as arguments to constructors of '@immutable' classes."
correctionMessage: "Try adding 'const' before the literal."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a non-const list, map, or set
literal is passed as an argument to a constructor declared in a class
annotated with `@immutable`.
#### Example
The following code produces this diagnostic because the list literal
(`[1]`) is being passed to a constructor in an immutable class but isn't
a constant list:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C([![1]!]);
```
#### Common fixes
If the context can be made a [constant context][], then do so:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
const C c = C([1]);
```
If the context can't be made a [constant context][] but the constructor
can be invoked using `const`, then add `const` before the constructor
invocation:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = const C([1]);
```
If the context can't be made a [constant context][] and the constructor
can't be invoked using `const`, then add the keyword `const` before the
collection literal:
```dart
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C(const [1]);
```
deprecatedDetails: |-
**PREFER** using `const` for instantiating list, map and set literals used as
parameters in immutable class instantiations.
**BAD:**
```dart
@immutable
class A {
A(this.v);
final v;
}
A a1 = new A([1]);
A a2 = new A({});
```
**GOOD:**
```dart
A a1 = new A(const [1]);
A a2 = new A(const {});
```
prefer_constructors_over_static_methods:
problemMessage: "Static method should be a constructor."
correctionMessage: "Try converting the method into a constructor."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a static method returns a newly
created instance of the class and could, therefore, be a constructor.
#### Example
The following code produces this diagnostic because the static method
`all` could be a constructor:
```dart
class C {
final int a, b, c;
C(this.a, this.b, this.c);
static C [!all!](int i) => C(i, i, i);
}
```
#### Common fixes
Convert the static method to a named constructor:
```dart
class C {
final int a, b, c;
C(this.a, this.b, this.c);
C.all(int i) : a = i, b = i, c = i;
}
```
deprecatedDetails: |-
**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:**
```dart
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:**
```dart
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_always_false:
sharedName: prefer_contains
problemMessage: "Always 'false' because 'indexOf' is always greater than or equal to -1."
categories: [style]
hasPublishedDocs: false
todo: |-
TODO(brianwilkerson): Should be warning rather than lint,
as represents a bug rather than style preference.
prefer_contains_always_true:
sharedName: prefer_contains
problemMessage: "Always 'true' because 'indexOf' is always greater than or equal to -1."
hasPublishedDocs: false
todo: |-
TODO(brianwilkerson): Should be warning rather than lint,
as represents a bug rather than style preference.
prefer_contains_use_contains:
sharedName: prefer_contains
problemMessage: "Unnecessary use of 'indexOf' to test for containment."
correctionMessage: "Try using 'contains'."
state:
stable: "2.0"
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the method `indexOf` is used and
the result is only compared with `-1` or `0` in a way where the semantics
are equivalent to using `contains`.
#### Example
The following code produces this diagnostic because the condition in the
`if` statement is checking to see whether the list contains the string:
```dart
void f(List<String> l, String s) {
if ([!l.indexOf(s) < 0!]) {
// ...
}
}
```
#### Common fixes
Use `contains` instead, negating the condition when necessary:
```dart
void f(List<String> l, String s) {
if (l.contains(s)) {
// ...
}
}
```
deprecatedDetails: |-
**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:**
```dart
if (lunchBox.indexOf('sandwich') == -1) return 'so hungry...';
```
**GOOD:**
```dart
if (!lunchBox.contains('sandwich')) return 'so hungry...';
```
prefer_double_quotes:
problemMessage: "Unnecessary use of single quotes."
correctionMessage: "Try using double quotes unless the string contains double quotes."
state:
stable: "2.4"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string literal uses single
quotes (`'`) when it could use double quotes (`"`) without needing extra
escapes and without hurting readability.
#### Example
The following code produces this diagnostic because the string literal
uses single quotes but doesn't need to:
```dart
void f(String name) {
print([!'Hello $name'!]);
}
```
#### Common fixes
Use double quotes in place of single quotes:
```dart
void f(String name) {
print("Hello $name");
}
```
deprecatedDetails: |-
**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, it's 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:**
```dart
useStrings(
'should be double quote',
r'should be double quote',
r\'''should be double quotes\''')
```
**GOOD:**
```dart
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:
state:
stable: "2.0"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.0; it is no longer functional.
**DO** use `=` to separate a named parameter from its default value.
**BAD:**
```dart
m({a: 1})
```
**GOOD:**
```dart
m({a = 1})
```
prefer_expression_function_bodies:
problemMessage: "Unnecessary use of a block function body."
correctionMessage: "Try using an expression function body."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the body of a function consists
of a single return statement with an expression.
#### Example
The following code produces this diagnostic because the body of `f` has a
single return statement:
```dart
int f() [!{
return 0;
}!]
```
#### Common fixes
If the body is complete, then replace the body with an expression body:
```dart
int f() => 0;
```
If the body isn't complete, then add the missing statements.
deprecatedDetails: |-
**CONSIDER** using => for short members whose body is a single return statement.
**BAD:**
```dart
get width {
return right - left;
}
```
**BAD:**
```dart
bool ready(num time) {
return minTime == null || minTime <= time;
}
```
**BAD:**
```dart
containsValue(String value) {
return getValues().contains(value);
}
```
**GOOD:**
```dart
get width => right - left;
```
**GOOD:**
```dart
bool ready(num time) => minTime == null || minTime <= time;
```
**GOOD:**
```dart
containsValue(String value) => getValues().contains(value);
```
prefer_final_fields:
problemMessage: "The private field {0} could be 'final'."
correctionMessage: "Try making the field 'final'."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a private field is only
assigned one time. The field can be initialized in multiple constructors
and still be flagged because only one of those constructors can ever run.
#### Example
The following code produces this diagnostic because the field `_f` is only
assigned one time, in the field's initializer:
```dart
class C {
int [!_f = 1!];
int get f => _f;
}
```
#### Common fixes
Mark the field `final`:
```dart
class C {
final int _f = 1;
int get f => _f;
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#prefer-making-fields-and-top-level-variables-final):
**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:**
```dart
class BadImmutable {
var _label = 'hola mundo! BadImmutable'; // LINT
var label = 'hola mundo! BadImmutable'; // OK
}
```
**BAD:**
```dart
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:**
```dart
class GoodImmutable {
final label = 'hola mundo! BadImmutable', bla = 5; // OK
final _label = 'hola mundo! BadImmutable', _bla = 5; // OK
}
```
**GOOD:**
```dart
class GoodMutable {
var _label = 'hola mundo! GoodMutable';
void changeLabel() {
_label = 'hello world! GoodMutable';
}
}
```
**BAD:**
```dart
class AssignedInAllConstructors {
var _label; // LINT
AssignedInAllConstructors(this._label);
AssignedInAllConstructors.withDefault() : _label = 'Hello';
}
```
**GOOD:**
```dart
class NotAssignedInAllConstructors {
var _label; // OK
NotAssignedInAllConstructors();
NotAssignedInAllConstructors.withDefault() : _label = 'Hello';
}
```
prefer_final_in_for_each_pattern:
sharedName: prefer_final_in_for_each
problemMessage: "The pattern should be final."
correctionMessage: "Try making the pattern final."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the loop variable in a for-each
statement isn't marked as being `final`.
#### Example
The following code produces this diagnostic because the loop variable `e`
isn't marked as being `final`:
```dart
void f(List<int> l) {
for (var [!e!] in l) {
print(e);
}
}
```
#### Common fixes
Add the modifier `final` to the loop variable, removing the `var` if there
is one:
```dart
void f(List<int> l) {
for (final e in l) {
print(e);
}
}
```
deprecatedDetails: |-
**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:**
```dart
for (var element in elements) { // LINT
print('Element: $element');
}
```
**GOOD:**
```dart
for (final element in elements) {
print('Element: $element');
}
```
**GOOD:**
```dart
for (var element in elements) {
element = element + element;
print('Element: $element');
}
```
prefer_final_in_for_each_variable:
sharedName: prefer_final_in_for_each
problemMessage: "The variable '{0}' should be final."
correctionMessage: "Try making the variable final."
hasPublishedDocs: false
prefer_final_locals:
problemMessage: "Local variables should be final."
correctionMessage: "Try making the variable final."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a local variable isn't marked
as being `final`.
#### Example
The following code produces this diagnostic because the variable `s` isn't
marked as being `final`:
```dart
int f(int i) {
[!var!] s = i + 1;
return s;
}
```
#### Common fixes
Add the modifier `final` to the variable, removing the `var` if there is
one:
```dart
int f(int i) {
final s = i + 1;
return s;
}
```
deprecatedDetails: |-
**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:**
```dart
void badMethod() {
var label = 'hola mundo! badMethod'; // LINT
print(label);
}
```
**GOOD:**
```dart
void goodMethod() {
final label = 'hola mundo! goodMethod';
print(label);
}
```
**GOOD:**
```dart
void mutableCase() {
var label = 'hola mundo! mutableCase';
print(label);
label = 'hello world';
print(label);
}
```
prefer_final_parameters:
problemMessage: "The parameter '{0}' should be final."
correctionMessage: "Try making the parameter final."
state:
stable: "2.14"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a parameter of a constructor,
method, function, or closure isn't marked as being `final`.
#### Example
The following code produces this diagnostic because the parameter `s`
isn't a `final` parameter:
```dart
String f([!String s!]) => s;
```
#### Common fixes
Add the modifier `final` to the parameter:
```dart
String f(final String s) => s;
```
deprecatedDetails: |-
**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:**
```dart
void badParameter(String label) { // LINT
print(label);
}
```
**GOOD:**
```dart
void goodParameter(final String label) { // OK
print(label);
}
```
**BAD:**
```dart
void badExpression(int value) => print(value); // LINT
```
**GOOD:**
```dart
void goodExpression(final int value) => print(value); // OK
```
**BAD:**
```dart
[1, 4, 6, 8].forEach((value) => print(value + 2)); // LINT
```
**GOOD:**
```dart
[1, 4, 6, 8].forEach((final value) => print(value + 2)); // OK
```
**GOOD:**
```dart
void mutableParameter(String label) { // OK
print(label);
label = 'Hello Linter!';
print(label);
}
```
prefer_for_elements_to_map_fromIterable:
problemMessage: "Use 'for' elements when building maps from iterables."
correctionMessage: "Try using a collection literal with a 'for' element."
state:
stable: "2.3"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when `Map.fromIterable` is used to
build a map that could be built using the `for` element.
#### Example
The following code produces this diagnostic because `fromIterable` is
being used to build a map that could be built using a `for` element:
```dart
void f(Iterable<String> data) {
[!Map<String, int>.fromIterable(
data,
key: (element) => element,
value: (element) => element.length,
)!];
}
```
#### Common fixes
Use a `for` element to build the map:
```dart
void f(Iterable<String> data) {
<String, int>{
for (var element in data)
element: element.length
};
}
```
deprecatedDetails: |-
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:**
```dart
Map<String, WidgetBuilder>.fromIterable(
kAllGalleryDemos,
key: (demo) => '${demo.routeName}',
value: (demo) => demo.buildRoute,
);
```
**GOOD:**
```dart
return {
for (var demo in kAllGalleryDemos)
'${demo.routeName}': demo.buildRoute,
};
```
**GOOD:**
```dart
// 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:
problemMessage: "Use 'forEach' and a tear-off rather than a 'for' loop to apply a function to every element."
correctionMessage: "Try using 'forEach' and a tear-off rather than a 'for' loop."
state:
experimental: "2.0"
stable: "2.2"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `for` loop is used to operate
on every member of a collection and the method `forEach` could be used
instead.
#### Example
The following code produces this diagnostic because a `for` loop is being
used to invoke a single function for each key in `m`:
```dart
void f(Map<String, int> m) {
[!for (final key in m.keys) {
print(key);
}!]
}
```
#### Common fixes
Replace the for loop with an invocation of `forEach`:
```dart
void f(Map<String, int> m) {
m.keys.forEach(print);
}
```
deprecatedDetails: |-
**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:**
```dart
for (final key in map.keys.toList()) {
map.remove(key);
}
```
**GOOD:**
```dart
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.
```dart
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:
problemMessage: "Use a function declaration rather than a variable assignment to bind a function to a name."
correctionMessage: "Try rewriting the closure assignment as a function declaration."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a closure is assigned to a
local variable and the local variable is not re-assigned anywhere.
#### Example
The following code produces this diagnostic because the local variable `f`
is initialized to be a closure and isn't assigned any other value:
```dart
void g() {
var [!f = (int i) => i * 2!];
f(1);
}
```
#### Common fixes
Replace the local variable with a local function:
```dart
void g() {
int f(int i) => i * 2;
f(1);
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#do-use-a-function-declaration-to-bind-a-function-to-a-name):
**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:**
```dart
void main() {
var localFunction = () {
...
};
}
```
**GOOD:**
```dart
void main() {
localFunction() {
...
}
}
```
prefer_generic_function_type_aliases:
problemMessage: "Use the generic function type syntax in 'typedef's."
correctionMessage: "Try using the generic function type syntax ('{0}')."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a typedef is written using the
older syntax for function type aliases in which the name being declared is
embedded in the function type.
#### Example
The following code produces this diagnostic because it uses the older
syntax:
```dart
typedef void [!F!]<T>();
```
#### Common fixes
Rewrite the typedef to use the newer syntax:
```dart
typedef F<T> = void Function();
```
deprecatedDetails: |-
**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:**
```dart
typedef void F();
```
**GOOD:**
```dart
typedef F = void Function();
```
prefer_if_elements_to_conditional_expressions:
problemMessage: "Use an 'if' element to conditionally add elements."
correctionMessage: "Try using an 'if' element rather than a conditional expression."
state:
stable: "2.3"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
When building collections, it is preferable to use `if` elements rather than
conditionals.
**BAD:**
```dart
var list = ['a', 'b', condition ? 'c' : null].where((e) => e != null).toList();
```
**GOOD:**
```dart
var list = ['a', 'b', if (condition) 'c'];
```
prefer_if_null_operators:
problemMessage: "Use the '??' operator rather than '?:' when testing for 'null'."
correctionMessage: "Try rewriting the code to use '??'."
state:
stable: "2.4"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a conditional expression (using
the `?:` operator) is used to select a different value when a local
variable is `null`.
#### Example
The following code produces this diagnostic because the variable `s` is
being compared to `null` so that a different value can be returned when
`s` is `null`:
```dart
String f(String? s) => [!s == null ? '' : s!];
```
#### Common fixes
Use the if-null operator instead:
```dart
String f(String? s) => s ?? '';
```
deprecatedDetails: |-
**PREFER** using `??` operators instead of `null` checks and conditional
expressions.
**BAD:**
```dart
v = a == null ? b : a;
```
**GOOD:**
```dart
v = a ?? b;
```
prefer_initializing_formals:
problemMessage: "Use an initializing formal to assign a parameter to a field."
correctionMessage: "Try using an initialing formal ('this.{0}') to initialize the field."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constructor parameter is used
to initialize a field without modification.
#### Example
The following code produces this diagnostic because the parameter `c` is
only used to set the field `c`:
```dart
class C {
int c;
C(int c) : [!this.c = c!];
}
```
#### Common fixes
Use an initializing formal parameter to initialize the field:
```dart
class C {
int c;
C(this.c);
}
```
deprecatedDetails: |-
**DO** use initializing formals when possible.
Using initializing formals when possible makes your code more terse.
**BAD:**
```dart
class Point {
num? x, y;
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
```
**GOOD:**
```dart
class Point {
num? x, y;
Point(num this.x, num this.y);
}
```
**BAD:**
```dart
class Point {
num? x, y;
Point({num? x, num? y}) {
this.x = x;
this.y = y;
}
}
```
**GOOD:**
```dart
class Point {
num? x, y;
Point({required num this.x, required num 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:
```dart
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?`).
```dart
class Bid {
final int? amount;
Bid(int this.amount);
Bid.pass() : amount = null;
}
```
prefer_inlined_adds_multiple:
sharedName: prefer_inlined_adds
problemMessage: "The addition of multiple list items could be inlined."
correctionMessage: "Try adding the items to the list literal directly."
state:
stable: "2.3"
categories: [brevity, style]
hasPublishedDocs: true
deprecatedDetails: |-
Declare elements in list literals inline, rather than using `add` and
`addAll` methods where possible.
**BAD:**
```dart
var l = ['a']..add('b')..add('c');
var l2 = ['a']..addAll(['b', 'c']);
```
**GOOD:**
```dart
var l = ['a', 'b', 'c'];
var l2 = ['a', 'b', 'c'];
```
prefer_inlined_adds_single:
sharedName: prefer_inlined_adds
problemMessage: "The addition of a list item could be inlined."
correctionMessage: "Try adding the item to the list literal directly."
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the methods `add` and `addAll`
are invoked on a list literal where the elements being added could be
included in the list literal.
#### Example
The following code produces this diagnostic because the `add` method is
being used to add `b`, when it could have been included directly in the
list literal:
```dart
List<String> f(String a, String b) {
return [a]..[!add!](b);
}
```
The following code produces this diagnostic because the `addAll` method is
being used to add the elements of `b`, when it could have been included
directly in the list literal:
```dart
List<String> f(String a, List<String> b) {
return [a]..[!addAll!](b);
}
```
#### Common fixes
If the `add` method is being used, then make the argument an element of
the list and remove the invocation:
```dart
List<String> f(String a, String b) {
return [a, b];
}
```
If the `addAll` method is being used, then use the spread operator on the
argument to add its elements to the list and remove the invocation:
```dart
List<String> f(String a, List<String> b) {
return [a, ...b];
}
```
prefer_int_literals:
problemMessage: "Unnecessary use of a 'double' literal."
correctionMessage: "Try using an 'int' literal."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** use int literals rather than the corresponding double literal.
**BAD:**
```dart
const double myDouble = 8.0;
final anotherDouble = myDouble + 7.0e2;
main() {
someMethod(6.0);
}
```
**GOOD:**
```dart
const double myDouble = 8;
final anotherDouble = myDouble + 700;
main() {
someMethod(6);
}
```
prefer_interpolation_to_compose_strings:
problemMessage: "Use interpolation to compose strings and values."
correctionMessage: "Try using string interpolation to build the composite string."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when string literals and computed
strings are being concatenated using the `+` operator, but string
interpolation would achieve the same result.
#### Example
The following code produces this diagnostic because the String `s` is
concatenated with other strings using the `+` operator:
```dart
String f(String s) {
return [!'(' + s!] + ')';
}
```
#### Common fixes
Use string interpolation:
```dart
String f(List<String> l) {
return '(${l[0]}, ${l[1]})';
}
```
deprecatedDetails: |-
**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:**
```dart
'Hello, ' + person.name + ' from ' + person.city + '.';
```
**GOOD:**
```dart
'Hello, ${person.name} from ${person.city}.'
```
prefer_is_empty_always_false:
sharedName: prefer_is_empty
problemMessage: "The comparison is always 'false' because the length is always greater than or equal to 0."
categories: [errorProne]
hasPublishedDocs: false
todo: |-
TODO(brianwilkerson): Should be warning rather than lint,
as represents a bug rather than style preference.
prefer_is_empty_always_true:
sharedName: prefer_is_empty
problemMessage: "The comparison is always 'true' because the length is always greater than or equal to 0."
hasPublishedDocs: false
todo: |-
TODO(brianwilkerson): Should be warning rather than lint,
as represents a bug rather than style preference.
prefer_is_empty_use_is_empty:
sharedName: prefer_is_empty
problemMessage: "Use 'isEmpty' instead of 'length' to test whether the collection is empty."
correctionMessage: "Try rewriting the expression to use 'isEmpty'."
state:
stable: "2.0"
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the result of invoking either
`Iterable.length` or `Map.length` is compared for equality with zero
(`0`).
#### Example
The following code produces this diagnostic because the result of invoking
`length` is checked for equality with zero:
```dart
int f(Iterable<int> p) => [!p.length == 0!] ? 0 : p.first;
```
#### Common fixes
Replace the use of `length` with a use of either `isEmpty` or
`isNotEmpty`:
```dart
void f(Iterable<int> p) => p.isEmpty ? 0 : p.first;
```
deprecatedDetails: |-
**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:**
```dart
if (lunchBox.length == 0) return 'so hungry...';
if (words.length != 0) return words.join(' ');
```
**GOOD:**
```dart
if (lunchBox.isEmpty) return 'so hungry...';
if (words.isNotEmpty) return words.join(' ');
```
prefer_is_empty_use_is_not_empty:
sharedName: prefer_is_empty
problemMessage: "Use 'isNotEmpty' instead of 'length' to test whether the collection is empty."
correctionMessage: "Try rewriting the expression to use 'isNotEmpty'."
hasPublishedDocs: true
prefer_is_not_empty:
problemMessage: "Use 'isNotEmpty' rather than negating the result of 'isEmpty'."
correctionMessage: "Try rewriting the expression to use 'isNotEmpty'."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the result of invoking
`Iterable.isEmpty` or `Map.isEmpty` is negated.
#### Example
The following code produces this diagnostic because the result of invoking
`Iterable.isEmpty` is negated:
```dart
void f(Iterable<int> p) => [!!p.isEmpty!] ? p.first : 0;
```
#### Common fixes
Rewrite the code to use `isNotEmpty`:
```dart
void f(Iterable<int> p) => p.isNotEmpty ? p.first : 0;
```
deprecatedDetails: |-
**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:**
```dart
if (!sources.isEmpty) {
process(sources);
}
```
**GOOD:**
```dart
if (todo.isNotEmpty) {
sendResults(request, todo.isEmpty);
}
```
prefer_is_not_operator:
problemMessage: "Use the 'is!' operator rather than negating the value of the 'is' operator."
correctionMessage: "Try rewriting the condition to use the 'is!' operator."
state:
stable: "2.7"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the prefix `!` operator is used
to negate the result of an `is` test.
#### Example
The following code produces this diagnostic because the result of testing
to see whether `o` is a `String` is negated using the prefix `!` operator:
```dart
String f(Object o) {
if ([!!(o is String)!]) {
return o.toString();
}
return o;
}
```
#### Common fixes
Use the `is!` operator instead:
```dart
String f(Object o) {
if (o is! String) {
return o.toString();
}
return o;
}
```
deprecatedDetails: |-
When checking if an object is not of a specified type, it is preferable to use the 'is!' operator.
**BAD:**
```dart
if (!(foo is Foo)) {
...
}
```
**GOOD:**
```dart
if (foo is! Foo) {
...
}
```
prefer_iterable_whereType:
problemMessage: "Use 'whereType' to select elements of a given type."
correctionMessage: "Try rewriting the expression to use 'whereType'."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the method `Iterable.where` is
being used to filter elements based on their type.
#### Example
The following code produces this diagnostic because the method `where` is
being used to access only the strings within the iterable:
```dart
Iterable<Object> f(Iterable<Object> p) => p.[!where!]((e) => e is String);
```
#### Common fixes
Rewrite the code to use `whereType`:
```dart
Iterable<String> f(Iterable<Object> p) => p.whereType<String>();
```
This might also allow you to tighten the types in your code or remove
other type checks.
deprecatedDetails: |-
**PREFER** `iterable.whereType<T>()` over `iterable.where((e) => e is T)`.
**BAD:**
```dart
iterable.where((e) => e is MyClass);
```
**GOOD:**
```dart
iterable.whereType<MyClass>();
```
prefer_mixin:
problemMessage: "Only mixins should be mixed in."
correctionMessage: "Try converting '{0}' to a mixin."
state:
stable: "2.1"
categories: [languageFeatureUsage, style]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
class A {}
class B extends Object with A {}
```
**OK:**
```dart
mixin M {}
class C with M {}
```
prefer_null_aware_method_calls:
problemMessage: "Use a null-aware invocation of the 'call' method rather than explicitly testing for 'null'."
correctionMessage: "Try using '?.call()' to invoke the function."
state:
stable: "2.14"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
Instead of checking nullability of a function/method `f` before calling it,
you can use `f?.call()`.
**BAD:**
```dart
if (f != null) f!();
```
**GOOD:**
```dart
f?.call();
```
prefer_null_aware_operators:
problemMessage: "Use the null-aware operator '?.' rather than an explicit 'null' comparison."
correctionMessage: "Try using '?.'."
state:
stable: "2.2"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a comparison with `null` is
used to guard a member reference, and `null` is used as a result when the
guarded target is `null`.
#### Example
The following code produces this diagnostic because the invocation of
`length` is guarded by a `null` comparison even though the default value
is `null`:
```dart
int? f(List<int>? p) {
return [!p == null ? null : p.length!];
}
```
#### Common fixes
Use a null-aware access operator instead:
```dart
int? f(List<int>? p) {
return p?.length;
}
```
deprecatedDetails: |-
**PREFER** using `null`-aware operators instead of `null` checks in conditional
expressions.
**BAD:**
```dart
v = a == null ? null : a.b;
```
**GOOD:**
```dart
v = a?.b;
```
prefer_relative_imports:
problemMessage: "Use relative imports for files in the 'lib' directory."
correctionMessage: "Try converting the URI to a relative URI."
state:
stable: "2.6"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an `import` in a library inside
the `lib` directory uses a `package:` URI to refer to another library in
the same package.
#### Example
The following code produces this diagnostic because it uses a `package:`
URI when a relative URI could have been used:
```dart
import 'package:my_package/bar.dart';
```
#### Common fixes
Use a relative URI to import the library:
```dart
import 'bar.dart';
```
deprecatedDetails: |-
**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:**
```dart
import 'package:my_package/bar.dart';
```
**GOOD:**
```dart
import 'bar.dart';
```
prefer_single_quotes:
problemMessage: "Unnecessary use of double quotes."
correctionMessage: "Try using single quotes unless the string contains single quotes."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string literal uses double
quotes (`"`) when it could use single quotes (`'`) without needing extra
escapes and without hurting readability.
#### Example
The following code produces this diagnostic because the string literal
uses double quotes but doesn't need to:
```dart
void f(String name) {
print([!"Hello $name"!]);
}
```
#### Common fixes
Use single quotes in place of double quotes:
```dart
void f(String name) {
print('Hello $name');
}
```
deprecatedDetails: |-
**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, it's 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:**
```dart
useStrings(
"should be single quote",
r"should be single quote",
r"""should be single quotes""")
```
**GOOD:**
```dart
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:
problemMessage: "The addition of multiple elements could be inlined."
correctionMessage: "Try using the spread operator ('...') to inline the addition."
state:
stable: "2.3"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: ListView(
children: [
Tab2Header(),
]..addAll(buildTab2Conversation()),
),
);
}
```
```dart
var ints = [1, 2, 3];
print(['a']..addAll(ints.map((i) => i.toString()))..addAll(['c']));
```
```dart
var things;
var l = ['a']..addAll(things ?? const []);
```
**GOOD:**
```dart
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: ListView(
children: [
Tab2Header(),
...buildTab2Conversation(),
],
),
);
}
```
```dart
var ints = [1, 2, 3];
print(['a', ...ints.map((i) => i.toString()), 'c');
```
```dart
var things;
var l = ['a', ...?things];
```
prefer_typing_uninitialized_variables_for_field:
sharedName: prefer_typing_uninitialized_variables
problemMessage: "An uninitialized field should have an explicit type annotation."
correctionMessage: "Try adding a type annotation."
state:
stable: "2.0"
categories: [errorProne, unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a variable without an
initializer doesn't have an explicit type annotation.
Without either a type annotation or an initializer, a variable has the
type `dynamic`, which allows any value to be assigned to the variable,
often causing hard to identify bugs.
#### Example
The following code produces this diagnostic because the variable `r`
doesn't have either a type annotation or an initializer:
```dart
Object f() {
var [!r!];
r = '';
return r;
}
```
#### Common fixes
If the variable can be initialized, then add an initializer:
```dart
Object f() {
var r = '';
return r;
}
```
If the variable can't be initialized, then add an explicit type
annotation:
```dart
Object f() {
String r;
r = '';
return r;
}
```
deprecatedDetails: |-
**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:**
```dart
class BadClass {
static var bar; // LINT
var foo; // LINT
void method() {
var bar; // LINT
bar = 5;
print(bar);
}
}
```
**BAD:**
```dart
void aFunction() {
var bar; // LINT
bar = 5;
...
}
```
**GOOD:**
```dart
class GoodClass {
static var bar = 7;
var foo = 42;
int baz; // OK
void method() {
int baz;
var bar = 5;
...
}
}
```
prefer_typing_uninitialized_variables_for_local_variable:
sharedName: prefer_typing_uninitialized_variables
problemMessage: "An uninitialized variable should have an explicit type annotation."
correctionMessage: "Try adding a type annotation."
hasPublishedDocs: true
prefer_void_to_null:
problemMessage: "Unnecessary use of the type 'Null'."
correctionMessage: "Try using 'void' instead."
state:
experimental: "2.1"
stable: "2.2"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when `Null` is used in a location
where `void` would be a valid choice.
#### Example
The following code produces this diagnostic because the function `f` is
declared to return `null` (at some future time):
```dart
Future<[!Null!]> f() async {}
```
#### Common fixes
Replace the use of `Null` with a use of `void`:
```dart
Future<void> f() async {}
```
deprecatedDetails: |-
**DON'T** use the type Null where void would work.
**BAD:**
```dart
Null f() {}
Future<Null> f() {}
Stream<Null> f() {}
f(Null x) {}
```
**GOOD:**
```dart
void f() {}
Future<void> f() {}
Stream<void> f() {}
f(void x) {}
```
Some exceptions include formulating special function types:
```dart
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:
```dart
<Null>[];
<int, Null>{};
```
provide_deprecation_message:
problemMessage: "Missing a deprecation message."
correctionMessage: "Try using the constructor to provide a message ('@Deprecated(\"message\")')."
state:
stable: "2.2"
categories: [publicInterface]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `deprecated` annotation is
used instead of the `Deprecated` annotation.
#### Example
The following code produces this diagnostic because the function `f` is
annotated with `deprecated`:
```dart
[!@deprecated!]
void f() {}
```
#### Common fixes
Convert the code to use the longer form:
```dart
@Deprecated('Use g instead. Will be removed in 4.0.0.')
void f() {}
```
deprecatedDetails: |-
**DO** specify a deprecation message (with migration instructions and/or a
removal schedule) in the `Deprecated` constructor.
**BAD:**
```dart
@deprecated
void oldFunction(arg1, arg2) {}
```
**GOOD:**
```dart
@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:
problemMessage: "Missing documentation for a public member."
correctionMessage: "Try adding documentation for the member."
state:
stable: "2.0"
categories: [publicInterface, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the declaration of part of the
public API of a package doesn't have a documentation comment.
#### Example
The following code produces this diagnostic because the class `C` doesn't
have a documentation comment:
```dart
class [!C!] {}
```
#### Common fixes
Add a documentation comment.
```dart
/// Documentation comment.
class C {}
```
deprecatedDetails: |-
**DO** document all public members.
All non-overriding public members should be documented with `///` doc-style
comments.
**BAD:**
```dart
class Bad {
void meh() { }
}
```
**GOOD:**
```dart
/// 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:**
```dart
/// 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:
problemMessage: "The getter '{0}' recursively returns itself."
correctionMessage: "Try changing the value being returned."
state:
stable: "2.0"
categories: [errorProne, unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a getter invokes itself,
resulting in an infinite loop.
#### Example
The following code produces this diagnostic because the getter `count`
invokes itself:
```dart
class C {
int _count = 0;
int get [!count!] => count;
}
```
#### Common fixes
Change the getter to not invoke itself:
```dart
class C {
int _count = 0;
int get count => _count;
}
```
deprecatedDetails: |-
**DON'T** create recursive getters.
Recursive getters are getters which return themselves as a value. This is
usually a typo.
**BAD:**
```dart
int get field => field; // LINT
```
**BAD:**
```dart
int get otherField {
return otherField; // LINT
}
```
**GOOD:**
```dart
int get field => _field;
```
require_trailing_commas:
problemMessage: "Missing a required trailing comma."
correctionMessage: "Try adding a trailing comma."
state:
stable: "2.14"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** use trailing commas for all multi-line parameter lists and argument
lists. A parameter list or argument list that fits on one line, including the
opening parenthesis and closing parenthesis, does not require a trailing comma.
**BAD:**
```dart
void run() {
method('does not fit on one line',
'test test test test test test test test test test test');
}
```
**GOOD:**
```dart
void run() {
method(
'does not fit on one line',
'test test test test test test test test test test test',
);
}
```
**EXCEPTION:** If the final argument in an argument list is positional (vs
named) and is either a function literal with curly braces, a map literal, a set
literal, or a list literal, then a trailing comma is not required.
This exception only applies if the final argument does not fit entirely on one
line.
**NOTE:** This lint rule assumes that code has been formatted with `dart format`
and may produce false positives on unformatted code.
secure_pubspec_urls:
problemMessage: "The '{0}' protocol shouldn't be used because it isn't secure."
correctionMessage: "Try using a secure protocol, such as 'https'."
state:
stable: "2.16"
categories: [pub]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a URL in a `pubspec.yaml` file is
using a non-secure scheme, such as `http`.
#### Example
The following code produces this diagnostic because the `pubspec.yaml` file
contains an `http` URL:
```yaml
dependencies:
example: any
repository: [!http://github.com/dart-lang/example!]
```
#### Common fixes
Change the scheme of the URL to use a secure scheme, such as `https`:
```yaml
dependencies:
example: any
repository: https://github.com/dart-lang/example
```
deprecatedDetails: |-
**DO** Use secure urls in `pubspec.yaml`.
Use `https` instead of `http` or `git:`.
**BAD:**
```yaml
repository: http://github.com/dart-lang/example
```
```yaml
git:
url: git://github.com/dart-lang/example/example.git
```
**GOOD:**
```yaml
repository: https://github.com/dart-lang/example
```
sized_box_for_whitespace:
problemMessage: "Use a 'SizedBox' to add whitespace to a layout."
correctionMessage: "Try using a 'SizedBox' rather than a 'Container'."
state:
stable: "2.9"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `Container` is created using
only the `height` and/or `width` arguments.
#### Example
The following code produces this diagnostic because the `Container` has
only the `width` argument:
```dart
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
const Text('...'),
[!Container!](
width: 4,
child: Text('...'),
),
const Expanded(
child: Text('...'),
),
],
);
}
```
#### Common fixes
Replace the `Container` with a `SizedBox` of the same dimensions:
```dart
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
Text('...'),
SizedBox(
width: 4,
child: Text('...'),
),
Expanded(
child: Text('...'),
),
],
);
}
```
deprecatedDetails: |-
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:**
```dart
Widget buildRow() {
return Row(
children: <Widget>[
const MyLogo(),
Container(width: 4),
const Expanded(
child: Text('...'),
),
],
);
}
```
**GOOD:**
```dart
Widget buildRow() {
return Row(
children: const <Widget>[
MyLogo(),
SizedBox(width: 4),
Expanded(
child: Text('...'),
),
],
);
}
```
sized_box_shrink_expand:
problemMessage: "Use 'SizedBox.{0}' to avoid needing to specify the 'height' and 'width'."
correctionMessage: "Try using 'SizedBox.{0}' and removing the 'height' and 'width' arguments."
state:
stable: "2.16"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `SizedBox` constructor
invocation specifies the values of both `height` and `width` as either
`0.0` or `double.infinity`.
#### Examples
The following code produces this diagnostic because both the `height` and
`width` are `0.0`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return [!SizedBox!](
height: 0.0,
width: 0.0,
child: const Text(''),
);
}
```
The following code produces this diagnostic because both the `height` and
`width` are `double.infinity`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return [!SizedBox!](
height: double.infinity,
width: double.infinity,
child: const Text(''),
);
}
```
#### Common fixes
If both are `0.0`, then use `SizedBox.shrink`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.shrink(
child: const Text(''),
);
}
```
If both are `double.infinity`, then use `SizedBox.expand`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.expand(
child: const Text(''),
);
}
```
deprecatedDetails: |-
Use `SizedBox.shrink(...)` and `SizedBox.expand(...)` constructors
appropriately.
Either the `SizedBox.shrink(...)` or `SizedBox.expand(...)` constructor should
be used instead of the more general `SizedBox(...)` constructor when one of the
named constructors capture the intent of the code more succinctly.
**Examples**
**BAD:**
```dart
Widget buildLogo() {
return SizedBox(
height: 0,
width: 0,
child: const MyLogo(),
);
}
```
```dart
Widget buildLogo() {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: const MyLogo(),
);
}
```
**GOOD:**
```dart
Widget buildLogo() {
return SizedBox.shrink(
child: const MyLogo(),
);
}
```
```dart
Widget buildLogo() {
return SizedBox.expand(
child: const MyLogo(),
);
}
```
slash_for_doc_comments:
problemMessage: "Use the end-of-line form ('///') for doc comments."
correctionMessage: "Try rewriting the comment to use '///'."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a documentation comment uses
the block comment style (delimited by `/**` and `*/`).
#### Example
The following code produces this diagnostic because the documentation
comment for `f` uses a block comment style:
```dart
[!/**
* Example.
*/!]
void f() {}
```
#### Common fixes
Use an end-of-line comment style:
```dart
/// Example.
void f() {}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/documentation#do-use--doc-comments-to-document-members-and-types):
**DO** use `///` for documentation comments.
Although Dart supports two syntaxes of doc comments (`///` and `/**`), we
prefer using `///` for doc comments.
**GOOD:**
```dart
/// 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:
problemMessage: "The '{0}' argument should be last in widget constructor invocations."
correctionMessage: "Try moving the argument to the end of the argument list."
state:
stable: "2.4"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the `child` or `children`
argument isn't the last argument in an invocation of a widget class'
constructor. An exception is made if all of the arguments after the
`child` or `children` argument are function expressions.
#### Example
The following code produces this diagnostic because the `child` argument
isn't the last argument in the invocation of the `Center` constructor:
```dart
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
[!child: Text('...')!],
widthFactor: 0.5,
);
}
```
#### Common fixes
Move the `child` or `children` argument to be last:
```dart
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
widthFactor: 0.5,
child: Text('...'),
);
}
```
deprecatedDetails: |-
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:**
```dart
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:**
```dart
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:
problemMessage: "Constructor declarations should be before non-constructor declarations."
correctionMessage: "Try moving the constructor declaration before all other members."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constructor declaration is
preceded by one or more non-constructor declarations.
#### Example
The following code produces this diagnostic because the constructor for
`C` appears after the method `m`:
```dart
class C {
void m() {}
[!C!]();
}
```
#### Common fixes
Move all of the constructor declarations before any other declarations:
```dart
class C {
C();
void m() {}
}
```
deprecatedDetails: |-
**DO** sort constructor declarations before other members.
**BAD:**
```dart
abstract class Visitor {
double value;
visitSomething(Something s);
Visitor();
}
```
**GOOD:**
```dart
abstract class Animation<T> {
const Animation(this.value);
double value;
void addListener(VoidCallback listener);
}
```
sort_pub_dependencies:
problemMessage: "Dependencies not sorted alphabetically."
correctionMessage: "Try sorting the dependencies alphabetically (A to Z)."
state:
stable: "2.1"
categories: [pub]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the keys in a dependency map in
the `pubspec.yaml` file aren't sorted alphabetically. The dependency maps
that are checked are the `dependencies`, `dev_dependencies`, and
`dependency_overrides` maps.
#### Example
The following code produces this diagnostic because the entries in the
`dependencies` map are not sorted:
```yaml
dependencies:
path: any
collection: any
```
#### Common fixes
Sort the entries:
```yaml
dependencies:
collection: any
path: any
```
deprecatedDetails: |-
**DO** sort pub dependencies alphabetically (A to Z) in `pubspec.yaml`.
Sorting list of pub dependencies makes maintenance easier.
sort_unnamed_constructors_first:
problemMessage: "Invalid location for the unnamed constructor."
correctionMessage: "Try moving the unnamed constructor before all other constructors."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an unnamed constructor appears
after a named constructor.
#### Example
The following code produces this diagnostic because the unnamed
constructor is after the named constructor:
```dart
class C {
C.named();
[!C!]();
}
```
#### Common fixes
Move the unnamed constructor before any other constructors:
```dart
class C {
C();
C.named();
}
```
deprecatedDetails: |-
**DO** sort unnamed constructor declarations first, before named ones.
**BAD:**
```dart
class _PriorityItem {
factory _PriorityItem.forName(bool isStatic, String name, _MemberKind kind) => ...
_PriorityItem(this.isStatic, this.kind, this.isPrivate);
...
}
```
**GOOD:**
```dart
abstract class CancelableFuture<T> implements Future<T> {
factory CancelableFuture(computation()) => ...
factory CancelableFuture.delayed(Duration duration, [computation()]) => ...
...
}
```
specify_nonobvious_local_variable_types:
problemMessage: "Specify the type of a local variable when the type is non-obvious."
correctionMessage: "Try adding a type annotation."
state:
experimental: "3.6"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Do type annotate initialized local variables when the type is non-obvious.
Type annotations on local variables can serve as a request for type inference,
documenting the expected outcome of the type inference step, and declaratively
allowing the compiler and analyzer to solve the possibly complex task of
finding type arguments and annotations in the initializing expression that
yield the desired result.
Type annotations on local variables can also inform readers about the type
of the initializing expression, which will allow them to proceed reading the
subsequent lines of code with known good information about the type of the
given variable (which may not be immediately evident by looking at the
initializing expression).
An expression is considered to have a non-obvious type when it does not
have an obvious type.
An expression e has an obvious type in the following cases:
- e is a non-collection literal. For instance, 1, true, 'Hello, $name!'.
- e is a collection literal with actual type arguments. For instance,
<int, bool>{}.
- e is a list literal or a set literal where at least one element has an
obvious type, and all elements have the same type. For instance, [1, 2] and
{ [true, false], [] }, but not [1, 1.5].
- e is a map literal where all key-value pair have a key with an obvious type
and a value with an obvious type, and all keys have the same type, and all
values have the same type. For instance, { #a: <int>[] }, but not
{1: 1, 2: true}.
- e is an instance creation expression whose class part is not raw. For
instance C(14) if C is a non-generic class, or C<int>(14) if C accepts one
type argument, but not C(14) if C accepts one or more type arguments.
- e is a cascade whose target has an obvious type. For instance,
1..isEven..isEven has an obvious type because 1 has an obvious type.
- e is a type cast. For instance, myComplexExpression as int.
**BAD:**
```dart
List<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {
var desserts = genericFunctionDeclaredFarAway(<num>[42], 'Something');
for (final recipe in cookbook) {
if (pantry.containsAll(recipe)) {
desserts.add(recipe);
}
}
return desserts;
}
const List<List<Ingredient>> cookbook = ...;
```
**GOOD:**
```dart
List<List<Ingredient>> possibleDesserts(Set<Ingredient> pantry) {
List<List<Ingredient>> desserts = genericFunctionDeclaredFarAway(
<num>[42],
'Something',
);
for (final List<Ingredient> recipe in cookbook) {
if (pantry.containsAll(recipe)) {
desserts.add(recipe);
}
}
return desserts;
}
const List<List<Ingredient>> cookbook = ...;
```
**This rule is experimental.** It is being evaluated, and it may be changed
or removed. Feedback on its behavior is welcome! The main issue is here:
https://github.com/dart-lang/sdk/issues/58773.
specify_nonobvious_property_types:
problemMessage: "A type annotation is needed because it isn't obvious."
correctionMessage: "Try adding a type annotation."
state:
experimental: "3.7"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Do type annotate initialized top-level or static variables when the type is
non-obvious.
Type annotations on top-level or static variables can serve as a request for
type inference, documenting the expected outcome of the type inference step,
and declaratively allowing the compiler and analyzer to solve the possibly
complex task of finding type arguments and annotations in the initializing
expression that yield the desired result.
Type annotations on top-level or static variables can also inform readers about
the type of the initializing expression, which will allow them to proceed
reading the locations in code where this variable is used with known good
information about the type of the given variable (which may not be immediately
evident by looking at the initializing expression).
An expression is considered to have a non-obvious type when it does not
have an obvious type.
An expression e has an obvious type in the following cases:
- e is a non-collection literal. For instance, 1, true, 'Hello, $name!'.
- e is a collection literal with actual type arguments. For instance,
<int, bool>{}.
- e is a list literal or a set literal where at least one element has an
obvious type, and all elements have the same type. For instance, [1, 2] and
{ [true, false], [] }, but not [1, 1.5].
- e is a map literal where all key-value pair have a key with an obvious type
and a value with an obvious type, and all keys have the same type, and all
values have the same type. For instance, { #a: <int>[] }, but not
{1: 1, 2: true}.
- e is an instance creation expression whose class part is not raw. For
instance C(14) if C is a non-generic class, or C<int>(14) if C accepts one
type argument, but not C(14) if C accepts one or more type arguments.
- e is a cascade whose target has an obvious type. For instance,
1..isEven..isEven has an obvious type because 1 has an obvious type.
- e is a type cast. For instance, `myComplexExpression as int`.
**BAD:**
```dart
final myTopLevelVariable =
genericFunctionWrittenByOtherFolks(with, args);
class A {
static var myStaticVariable =
myTopLevelVariable.update('foo', null);
}
```
**GOOD:**
```dart
final Map<String, Widget?> myTopLevelVariable =
genericFunctionWrittenByOtherFolks(with, args);
class A {
static Map<String, Widget?> myStaticVariable =
myTopLevelVariable.update('foo', null);
}
```
**This rule is experimental.** It is being evaluated, and it may be changed
or removed. Feedback on its behavior is welcome! The main issue is here:
https://github.com/dart-lang/sdk/issues/59550.
strict_top_level_inference_add_type:
sharedName: strict_top_level_inference
problemMessage: "Missing type annotation."
correctionMessage: "Try adding a type annotation."
state:
stable: "3.7"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Do type annotate top-level and class-like member declarations, where types
are not inferred from super-interfaces or initializers.
The lint warns about every omitted return type, parameter type, and
variable type of a top-level declaration or class-like-namespace-level
declaration (static or instance member or constructor declaration), which
is not given a type by inference, and which therefore defaults to dynamic.
The only omitted types that can be given a type by top-level inference,
are those of variable declarations with initializer expressions, and
return and parameter types of instance members that override a consistent
combined super-interface signature.
Setters do not need a return type, as it is always assumed to be `void`.
**BAD:**
```dart
var _zeroPointCache;
class Point {
get zero => ...;
final x, y;
Point(x, y) {}
closest(b, c) => distance(b) <= distance(c) ? b : c;
distance(other) => ...;
}
_sq(v) => v * v;
```
**GOOD:**
```dart
Point? _zeroPointCache;
class Point {
Point get zero => ...;
final int x, y;
Point(int x, int y) {}
closest(Point b, Point c) =>
distance(b) <= distance(c) ? b : c;
distance(Point other) => ...;
}
int _sq(int v) => v * v;
```
strict_top_level_inference_replace_keyword:
sharedName: strict_top_level_inference
problemMessage: "Missing type annotation."
correctionMessage: "Try replacing '{0}' with a type annotation."
hasPublishedDocs: false
strict_top_level_inference_split_to_types:
sharedName: strict_top_level_inference
problemMessage: "Missing type annotation."
correctionMessage: "Try splitting the declaration and specify the different type annotations."
hasPublishedDocs: false
super_goes_last:
state:
stable: "2.0"
removed: "3.0"
hasPublishedDocs: false
deprecatedDetails: |-
NOTE: This rule is removed in Dart 3.0.0; it is no longer functional.
**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:**
```dart
View(Style style, List children)
: super(style),
_children = children {
```
**GOOD:**
```dart
View(Style style, List children)
: _children = children,
super(style) {
```
switch_on_type:
problemMessage: "Avoid switch statements on a 'Type'."
correctionMessage: "Try using pattern matching on a variable instead."
state:
stable: "3.9"
categories: [unintentional, style, languageFeatureUsage, errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a switch statement or switch
expression is used on either the value of a `Type` or a `toString` call
on a `Type`.
#### Example
The following code produces this diagnostic because the switch statement
is used on a `Type`:
```dart
void f(Object o) {
switch ([!o.runtimeType!]) {
case const (int):
print('int');
case const (String):
print('String');
}
}
```
#### Common fixes
Use pattern matching on the variable instead:
```dart
void f(Object o) {
switch (o) {
case int():
print('int');
case String():
print('String');
}
}
```
deprecatedDetails: |-
**AVOID** using switch on `Type`.
Switching on `Type` is not type-safe and can lead to bugs if the
class hierarchy changes. Prefer to use pattern matching on the variable
instead.
**BAD:**
```dart
void f(Object o) {
switch (o.runtimeType) {
case int:
print('int');
case String:
print('String');
}
}
```
**GOOD:**
```dart
void f(Object o) {
switch(o) {
case int():
print('int');
case String _:
print('String');
default:
print('other');
}
}
```
test_types_in_equals:
problemMessage: "Missing type test for '{0}' in '=='."
correctionMessage: "Try testing the type of '{0}'."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an override of the `==`
operator doesn't include a type test on the value of the parameter.
#### Example
The following code produces this diagnostic because `other` is not type
tested:
```dart
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return ([!other as C!]).f == f;
}
}
```
#### Common fixes
Perform an `is` test as part of computing the return value:
```dart
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return other is C && other.f == f;
}
}
```
deprecatedDetails: |-
**DO** test type of argument in `operator ==(Object other)`.
Not testing the type might result in runtime type errors which will be
unexpected for consumers of your class.
**BAD:**
```dart
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:**
```dart
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:
problemMessage: "Use of '{0}' in 'finally' block."
correctionMessage: "Try moving the '{0}' outside the 'finally' block."
state:
stable: "2.0"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `throw` statement is found
inside a `finally` block.
#### Example
The following code produces this diagnostic because there is a `throw`
statement inside a `finally` block:
```dart
void f() {
try {
// ...
} catch (e) {
// ...
} finally {
[!throw 'error'!];
}
}
```
#### Common fixes
Rewrite the code so that the `throw` statement isn't inside a `finally`
block:
```dart
void f() {
try {
// ...
} catch (e) {
// ...
}
throw 'error';
}
```
deprecatedDetails: |-
**AVOID** throwing exceptions in `finally` blocks.
Throwing exceptions in `finally` blocks will inevitably cause unexpected
behavior that is hard to debug.
**BAD:**
```dart
class BadThrow {
double nonCompliantMethod() {
try {
print('hello world! ${1 / 0}');
} catch (e) {
print(e);
} finally {
throw 'Find the hidden error :P'; // LINT
}
}
}
```
**GOOD:**
```dart
class Ok {
double compliantMethod() {
var i = 5;
try {
i = 1 / 0;
} catch (e) {
print(e); // OK
}
return i;
}
}
```
tighten_type_of_initializing_formals:
problemMessage: "Use a type annotation rather than 'assert' to enforce non-nullability."
correctionMessage: "Try adding a type annotation and removing the 'assert'."
state:
stable: "2.12"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an `assert` is being used in
the initializer list of a constructor to ensure that only a non-`null`
value is being used to initialize a field.
#### Example
The following code produces this diagnostic because an `assert` is being
used to catch an error that could be caught by the type system:
```dart
class C {
final String? s;
C([!this.s!]) : assert(s != null);
}
```
#### Common fixes
Remove the `assert` and add the non-nullable type before the initializing
formal:
```dart
class C {
final String? s;
C(String this.s);
}
```
deprecatedDetails: |-
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:**
```dart
class A {
A.c1(this.p) : assert(p != null);
A.c2(this.p);
final String? p;
}
```
**GOOD:**
```dart
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:
problemMessage: "Missing type annotation on a public API."
correctionMessage: "Try adding a type annotation."
state:
stable: "2.0"
categories: [effectiveDart, publicInterface]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the declaration of part of the
public API of a package doesn't have explicit type annotations.
#### Example
The following code produces this diagnostic because the function `f`
doesn't have an explicit return type and the parameters `x` and `y` don't
have explicit types:
```dart
[!f!](x, y) => '';
```
#### Common fixes
Add type annotations to the API:
```dart
String f(int x, int y) => '';
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#do-type-annotate-fields-and-top-level-variables-if-the-type-isnt-obvious):
**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:**
```dart
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:**
```dart
Future<bool> install(PackageId id, String destination) {
// ...
}
```
With types, all of this is clarified.
type_init_formals:
problemMessage: "Don't needlessly type annotate initializing formals."
correctionMessage: "Try removing the type."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an initializing formal
parameter (`this.x`) or a super parameter (`super.x`) has an explicit type
annotation that is the same as the field or overridden parameter.
If a constructor parameter is using `this.x` to initialize a field, then
the type of the parameter is implicitly the same type as the field. If a
constructor parameter is using `super.x` to forward to a super
constructor, then the type of the parameter is implicitly the same as the
super constructor parameter.
#### Example
The following code produces this diagnostic because the parameter `this.c`
has an explicit type that is the same as the field `c`:
```dart
class C {
int c;
C([!int!] this.c);
}
```
The following code produces this diagnostic because the parameter
`super.a` has an explicit type that is the same as the parameter `a` from
the superclass:
```dart
class A {
A(int a);
}
class B extends A {
B([!int!] super.a);
}
```
#### Common fixes
Remove the type annotation from the parameter:
```dart
class C {
int c;
C(this.c);
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#dont-type-annotate-initializing-formals):
**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:**
```dart
class Point {
int x, y;
Point(int this.x, int this.y);
}
```
**GOOD:**
```dart
class Point {
int x, y;
Point(this.x, this.y);
}
```
**BAD:**
```dart
class A {
int a;
A(this.a);
}
class B extends A {
B(int super.a);
}
```
**GOOD:**
```dart
class A {
int a;
A(this.a);
}
class B extends A {
B(super.a);
}
```
type_literal_in_constant_pattern:
problemMessage: "Use 'TypeName _' instead of a type literal."
correctionMessage: "Replace with 'TypeName _'."
state:
stable: "3.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a type literal appears as a
pattern.
#### Example
The following code produces this diagnostic because a type literal is used
as a constant pattern:
```dart
void f(Object? x) {
if (x case [!num!]) {
// ...
}
}
```
#### Common fixes
If the type literal is intended to match an object of the given type, then
use either a variable pattern:
```dart
void f(Object? x) {
if (x case num _) {
// ...
}
}
```
Or an object pattern:
```dart
void f(Object? x) {
if (x case num()) {
// ...
}
}
```
If the type literal is intended to match the type literal, then write it
as a constant pattern:
```dart
void f(Object? x) {
if (x case const (num)) {
// ...
}
}
```
deprecatedDetails: |-
If you meant to test if the object has type `Foo`, instead write `Foo _`.
**BAD:**
```dart
void f(Object? x) {
if (x case num) {
print('int or double');
}
}
```
**GOOD:**
```dart
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:**
```dart
void f(Object? x) {
if (x case int) {
print('int');
}
}
```
**GOOD:**
```dart
void f(Object? x) {
if (x case const (int)) {
print('int');
}
}
```
unawaited_futures:
problemMessage: "Missing an 'await' for the 'Future' computed by this expression."
correctionMessage: "Try adding an 'await' or wrapping the expression with 'unawaited'."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic on an expression with a `Future`
type, only in a few specific cases:
* when the expression is itself a statement (like `f();`),
* when the expression is part of a cascade (like `C()..f()`),
* when the expression is a String interpolation (like `'${f()}'`).
The analyzer only produces this diagnostic on expressions inside an
`async` or `async*` function.
The two common corrections are to 'await' the expression, or to wrap the
expression in a call to `unawaited()`.
#### Example
The following code produces this diagnostic because the function `g`
returns a future, but the future isn't awaited:
```dart
Future<void> f() async {
[!g!]();
}
Future<int> g() => Future.value(0);
```
#### Common fixes
If the future needs to complete before the following code is executed,
then add an `await` before the invocation:
```dart
Future<void> f() async {
await g();
}
Future<int> g() => Future.value(0);
```
If the future doesn't need to complete before the following code is
executed, then wrap the `Future`-returning invocation in an invocation of
the `unawaited` function:
```dart
import 'dart:async';
Future<void> f() async {
unawaited(g());
}
Future<int> g() => Future.value(0);
```
deprecatedDetails: |-
**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:**
```dart
void main() async {
doSomething(); // Likely a bug.
}
```
**GOOD:**
```dart
Future doSomething() => ...;
void main() async {
await doSomething();
unawaited(doSomething()); // Explicitly-ignored fire-and-forget.
}
```
unintended_html_in_doc_comment:
problemMessage: "Angle brackets will be interpreted as HTML."
correctionMessage: "Try using backticks around the content with angle brackets, or try replacing `<` with `&lt;` and `>` with `&gt;`."
state:
stable: "3.5"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a documentation comment
contains angle bracketed text (`<...>`) that isn't one of the allowed
exceptions.
Such text is interpreted by markdown to be an HTML tag, which is rarely
what was intended.
See the [lint rule description](https://dart.dev/tools/linter-rules/unintended_html_in_doc_comment)
for the list of allowed exceptions.
#### Example
The following code produces this diagnostic because the documentation
comment contains the text `<int>`, which isn't one of the allowed
exceptions:
```dart
/// Converts a List[!<int>!] to a comma-separated String.
String f(List<int> l) => '';
```
#### Common fixes
If the text was intended to be part of a code span, then add backticks
around the code:
```dart
/// Converts a `List<int>` to a comma-separated String.
String f(List<int> l) => '';
```
If the text was intended to be part of a link, then add square brackets
around the code:
```dart
/// Converts a [List<int>] to a comma-separated String.
String f(List<int> l) => '';
```
If the text was intended to be printed as-is, including the angle
brackets, then add backslash escapes before the angle brackets:
```dart
/// Converts a List\<int\> to a comma-separated String.
String f(List<int> l) => '';
```
deprecatedDetails: |-
**DON'T** use angle-bracketed text, `<…>`, in a doc comment unless you want to
write an HTML tag or link.
Markdown allows HTML tags as part of the Markdown code, so you can write, for
example, `T<sub>1</sub>`. Markdown does not restrict the allowed tags, it just
includes the tags verbatim in the output.
Dartdoc only allows some known and valid HTML tags, and will omit any disallowed
HTML tag from the output. See the list of allowed tags and directives below.
Your doc comment should not contain any HTML tags that are not on this list.
Markdown also allows you to write an "auto-link" to an URL as for example
`<https://example.com/page.html>`, delimited only by `<...>`. Such a link is
allowed by Dartdoc as well.
A `<...>` delimited text is an auto-link if it is a valid absolute URL, starting
with a scheme of at least two characters followed by a colon, like
`<mailto:mr_example@example.com>`.
Any other other occurrence of `<word...>` or `</word...>` is likely a mistake
and this lint will warn about it.
If something looks like an HTML tag, meaning it starts with `<` or `</`
and then a letter, and it has a later matching `>`, then it's considered an
invalid HTML tag unless it is an auto-link, or it starts with an *allowed*
HTML tag.
Such a mistake can, for example, happen if writing Dart code with type arguments
outside of a code span, for example `The type List<int> is ...`, where `<int>`
looks like an HTML tag. Missing the end quote of a code span can have the same
effect: ``The type `List<int> is ...`` will also treat `<int>` as an HTML tag.
Allows the following HTML directives: HTML comments, `<!-- text -->`, processing
instructions, `<?...?>`, CDATA-sections, and `<[CDATA...]>`.
Allows DartDoc links like `[List<int>]` which are not after a `]` or before a
`[` or `(`, and allows the following recognized HTML tags:
`a`, `abbr`, `address`, `area`, `article`, `aside`, `audio`, `b`,
`bdi`, `bdo`, `blockquote`, `br`, `button`, `canvas`, `caption`,
`cite`, `code`, `col`, `colgroup`, `data`, `datalist`, `dd`, `del`,
`dfn`, `div`, `dl`, `dt`, `em`, `fieldset`, `figcaption`, `figure`,
`footer`, `form`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `header`, `hr`,
`i`, `iframe`, `img`, `input`, `ins`, `kbd`, `keygen`, `label`,
`legend`, `li`, `link`, `main`, `map`, `mark`, `meta`, `meter`, `nav`,
`noscript`, `object`, `ol`, `optgroup`, `option`, `output`, `p`,
`param`, `pre`, `progress`, `q`, `s`, `samp`, `script`, `section`,
`select`, `small`, `source`, `span`, `strong`, `style`, `sub`, `sup`,
`table`, `tbody`, `td`, `template`, `textarea`, `tfoot`, `th`, `thead`,
`time`, `title`, `tr`, `track`, `u`, `ul`, `var`, `video` and `wbr`.
**BAD:**
```dart
/// The type List<int>.
/// <assignment> -> <variable> = <expression>
```
**GOOD:**
```dart
/// The type `List<int>`.
/// The type [List<int>]
/// `<assignment> -> <variable> = <expression>`
/// \<assignment\> -> \<variable\> = \<expression\>`
/// <https://example.com/example>
```
unnecessary_async:
problemMessage: "Don't make a function 'async' if it doesn't use 'await'."
correctionMessage: "Try removing the 'async' modifier."
state:
experimental: "3.7"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Functions that don't do `await` don't have to be `async`.
Usually such functions also don't have to return a `Future`, which allows
an invoker to avoid `await` in its code, etc. Synchronous code in
general runs faster, and is easier to reason about.
**BAD:**
```dart
void f() async {
// await Future.delayed(const Duration(seconds: 2));
print(0);
}
```
**GOOD:**
```dart
void f() {
// await Future.delayed(const Duration(seconds: 2));
print(0);
}
```
unnecessary_await_in_return:
problemMessage: "Unnecessary 'await'."
correctionMessage: "Try removing the 'await'."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Avoid returning an awaited expression when the expression type is assignable to
the function's return type.
**BAD:**
```dart
Future<int> future;
Future<int> f1() async => await future;
Future<int> f2() async {
return await future;
}
```
**GOOD:**
```dart
Future<int> future;
Future<int> f1() => future;
Future<int> f2() {
return future;
}
```
unnecessary_brace_in_string_interps:
problemMessage: "Unnecessary braces in a string interpolation."
correctionMessage: "Try removing the braces."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string interpolation with
braces is used to interpolate a simple identifier and isn't followed by
alphanumeric text.
#### Example
The following code produces this diagnostic because the interpolation
element `${s}` uses braces when they are not necessary:
```dart
String f(String s) {
return '"[!${s}!]"';
}
```
#### Common fixes
Remove the unnecessary braces:
```dart
String f(String s) {
return '"$s"';
}
```
deprecatedDetails: |-
**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:**
```dart
print("Hi, ${name}!");
```
**GOOD:**
```dart
print("Hi, $name!");
```
unnecessary_breaks:
problemMessage: "Unnecessary 'break' statement."
correctionMessage: "Try removing the 'break'."
state:
stable: "3.0"
categories: [brevity, style]
hasPublishedDocs: false
deprecatedDetails: |-
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:**
```dart
switch (1) {
case 1:
print("one");
break;
case 2:
print("two");
break;
}
```
**GOOD:**
```dart
switch (1) {
case 1:
print("one");
case 2:
print("two");
}
```
```dart
switch (1) {
case 1:
case 2:
print("one or two");
}
```
```dart
switch (1) {
case 1:
break;
case 2:
print("just two");
}
```
NOTE: This lint only reports unnecessary breaks in libraries with a
[language version](https://dart.dev/resources/language/evolution#language-versioning)
of 3.0 or greater. Explicit breaks are still required in Dart 2.19 and below.
unnecessary_const:
problemMessage: "Unnecessary 'const' keyword."
correctionMessage: "Try removing the keyword."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the keyword `const` is used in
a [constant context][]. The keyword isn't required because it's implied.
#### Example
The following code produces this diagnostic because the keyword `const` in
the list literal isn't needed:
```dart
const l = [!const!] <int>[];
```
The list is implicitly `const` because of the keyword `const` on the
variable declaration.
#### Common fixes
Remove the unnecessary keyword:
```dart
const l = <int>[];
```
deprecatedDetails: |-
**AVOID** repeating `const` keyword in a `const` context.
**BAD:**
```dart
class A { const A(); }
m(){
const a = const A();
final b = const [const A()];
}
```
**GOOD:**
```dart
class A { const A(); }
m(){
const a = A();
final b = const [A()];
}
```
unnecessary_constructor_name:
problemMessage: "Unnecessary '.new' constructor name."
correctionMessage: "Try removing the '.new'."
state:
stable: "2.15"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a reference to an unnamed
constructor uses `.new`. The only place where `.new` is required is in a
constructor tear-off.
#### Example
The following code produces this diagnostic because `.new` is being used
to refer to the unnamed constructor where it isn't required:
```dart
var o = Object.[!new!]();
```
#### Common fixes
Remove the unnecessary `.new`:
```dart
var o = Object();
```
deprecatedDetails: |-
**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:**
```dart
class A {
A.new(); // LINT
}
var a = A.new(); // LINT
```
**GOOD:**
```dart
class A {
A.ok();
}
var a = A();
var aa = A.ok();
var makeA = A.new;
```
unnecessary_final_with_type:
sharedName: unnecessary_final
problemMessage: "Local variables should not be marked as 'final'."
correctionMessage: "Remove the 'final'."
state:
stable: "2.7"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a local variable is marked as
being `final`.
#### Example
The following code produces this diagnostic because the local variable `c`
is marked as being `final`:
```dart
void f(int a, int b) {
[!final!] c = a + b;
print(c);
}
```
#### Common fixes
If the variable doesn't have a type annotation, then replace the `final`
with `var`:
```dart
void f(int a, int b) {
var c = a + b;
print(c);
}
```
If the variable has a type annotation, then remove the `final`
modifier:
```dart
void f(int a, int b) {
int c = a + b;
print(c);
}
```
deprecatedDetails: |-
Use `var`, not `final`, when declaring local variables.
Per [Effective Dart](https://dart.dev/effective-dart/usage#do-follow-a-consistent-rule-for-var-and-final-on-local-variables),
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:**
```dart
void badMethod() {
final label = 'Final or var?';
for (final char in ['v', 'a', 'r']) {
print(char);
}
}
```
**GOOD:**
```dart
void goodMethod() {
var label = 'Final or var?';
for (var char in ['v', 'a', 'r']) {
print(char);
}
}
```
unnecessary_final_without_type:
sharedName: unnecessary_final
problemMessage: "Local variables should not be marked as 'final'."
correctionMessage: "Replace 'final' with 'var'."
hasPublishedDocs: false
unnecessary_getters_setters:
problemMessage: "Unnecessary use of getter and setter to wrap a field."
correctionMessage: "Try removing the getter and setter and renaming the field."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a getter and setter pair
returns and sets the value of a field without any additional processing.
#### Example
The following code produces this diagnostic because the getter/setter pair
named `c` only expose the field named `_c`:
```dart
class C {
int? _c;
int? get [!c!] => _c;
set c(int? v) => _c = v;
}
```
#### Common fixes
Make the field public and remove the getter and setter:
```dart
class C {
int? c;
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#dont-wrap-a-field-in-a-getter-and-setter-unnecessarily):
**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:**
```dart
class Box {
var _contents;
get contents => _contents;
set contents(value) {
_contents = value;
}
}
```
**GOOD:**
```dart
class Box {
var contents;
}
```
unnecessary_ignore:
sharedName: unnecessary_ignore
problemMessage: "The diagnostic '{0}' isn't produced at this location so it doesn't need to be ignored."
correctionMessage: "Try removing the ignore comment."
state:
experimental: "3.8"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an ignore is specified to
ignore a diagnostic that isn't produced.
#### Example
The following code produces this diagnostic because the
`unused_local_variable` diagnostic isn't reported at the ignored location:
```dart
// ignore: [!unused_local_variable!]
void f() {}
```
#### Common fixes
Remove the ignore comment:
```dart
void f() {}
```
deprecatedDetails: |-
**DON'T** specify an ignore for a diagnostic that is not produced.
unnecessary_ignore_file:
sharedName: unnecessary_ignore
problemMessage: "The diagnostic '{0}' isn't produced in this file so it doesn't need to be ignored."
correctionMessage: "Try removing the ignore comment."
hasPublishedDocs: false
unnecessary_ignore_name:
sharedName: unnecessary_ignore
problemMessage: "The diagnostic '{0}' isn't produced at this location so it doesn't need to be ignored."
correctionMessage: "Try removing the name from the list."
hasPublishedDocs: false
unnecessary_ignore_name_file:
sharedName: unnecessary_ignore
problemMessage: "The diagnostic '{0}' isn't produced in this file so it doesn't need to be ignored."
correctionMessage: "Try removing the name from the list."
hasPublishedDocs: false
unnecessary_lambdas:
problemMessage: "Closure should be a tearoff."
correctionMessage: "Try using a tearoff rather than a closure."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a closure (lambda) could be
replaced by a tear-off.
#### Example
The following code produces this diagnostic because the closure passed to
`forEach` contains only an invocation of the function `print` with the
parameter of the closure:
```dart
void f(List<String> strings) {
strings.forEach([!(string) {
print(string);
}!]);
}
```
#### Common fixes
Replace the closure with a tear-off of the function or method being
invoked with the closure:
```dart
void f(List<String> strings) {
strings.forEach(print);
}
```
deprecatedDetails: |-
**DON'T** create a lambda when a tear-off will do.
**BAD:**
```dart
names.forEach((name) {
print(name);
});
```
**GOOD:**
```dart
names.forEach(print);
```
unnecessary_late:
problemMessage: "Unnecessary 'late' modifier."
correctionMessage: "Try removing the 'late'."
state:
stable: "2.16"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a top-level variable or static
field with an initializer is marked as `late`. Top-level variables and
static fields are implicitly late, so they don't need to be explicitly
marked.
#### Example
The following code produces this diagnostic because the static field `c`
has the modifier `late` even though it has an initializer:
```dart
class C {
static [!late!] String c = '';
}
```
#### Common fixes
Remove the keyword `late`:
```dart
class C {
static String c = '';
}
```
deprecatedDetails: |-
**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:**
```dart
late String badTopLevel = '';
```
**GOOD:**
```dart
String goodTopLevel = '';
```
**BAD:**
```dart
class BadExample {
static late String badStatic = '';
}
```
**GOOD:**
```dart
class GoodExample {
late String goodStatic;
}
```
unnecessary_library_directive:
problemMessage: "Library directives without comments or annotations should be avoided."
correctionMessage: "Try deleting the library directive."
state:
stable: "2.19"
categories: [brevity]
hasPublishedDocs: false
deprecatedDetails: |-
**DO** use library directives if you want to document a library and/or annotate
a library.
**BAD:**
```dart
library;
```
**GOOD:**
```dart
/// This library does important things
library;
```
```dart
@TestOn('js')
library;
```
NOTE: Due to limitations with this lint, libraries with parts will not be
flagged for unnecessary library directives.
unnecessary_library_name:
problemMessage: "Library names are not necessary."
correctionMessage: "Remove the library name."
state:
stable: "3.4"
categories: [brevity, languageFeatureUsage, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `library` directive specifies
a name.
#### Example
The following code produces this diagnostic because the `library`
directive includes a name:
```dart
library [!some.name!];
class C {}
```
#### Common fixes
Remove the name from the `library` directive:
```dart
library;
class C {}
```
If the library has any parts, then any `part of` declarations that use
the library name should be updated to use the URI of the library instead.
deprecatedDetails: |-
**DON'T** have a library name in a `library` declaration.
Library names are not necessary.
A library does not need a library declaration, but one can be added to attach
library documentation and library metadata to. A declaration of `library;` is
sufficient for those uses.
The only *use* of a library name is for a `part` file to refer back to its
owning library, but part files should prefer to use a string URI to refer back
to the library file, not a library name.
If a library name is added to a library declaration, it introduces the risk of
name *conflicts*. It's a compile-time error if two libraries in the same program
have the same library name. To avoid that, library names tend to be long,
including the package name and path, just to avoid accidental name clashes. That
makes such library names hard to read, and not even useful as documentation.
**BAD:**
```dart
/// This library has a long name.
library magnificator.src.helper.bananas;
```
```dart
library utils; // Not as verbose, but risks conflicts.
```
**GOOD:**
```dart
/// This library is awesome.
library;
part "apart.dart"; // contains: `part of "good_library.dart";`
```
unnecessary_new:
problemMessage: "Unnecessary 'new' keyword."
correctionMessage: "Try removing the 'new' keyword."
state:
stable: "2.0"
categories: [brevity, languageFeatureUsage, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the keyword `new` is used to
invoke a constructor.
#### Example
The following code produces this diagnostic because the keyword `new` is
used to invoke the unnamed constructor from `Object`:
```dart
var o = [!new!] Object();
```
#### Common fixes
Remove the keyword `new`:
```dart
var o = Object();
```
deprecatedDetails: |-
**AVOID** new keyword to create instances.
**BAD:**
```dart
class A { A(); }
m(){
final a = new A();
}
```
**GOOD:**
```dart
class A { A(); }
m(){
final a = A();
}
```
unnecessary_null_aware_assignments:
problemMessage: "Unnecessary assignment of 'null'."
correctionMessage: "Try removing the assignment."
state:
stable: "2.0"
categories: [brevity, effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the right-hand side of a
null-aware assignment is the `null` literal.
#### Example
The following code produces this diagnostic because the null aware
operator is being used to assign `null` to `s` when `s` is already `null`:
```dart
void f(String? s) {
[!s ??= null!];
}
```
#### Common fixes
If a non-null value should be assigned to the left-hand operand, then
change the right-hand side:
```dart
void f(String? s) {
s ??= '';
}
```
If there is no non-null value to assign to the left-hand operand, then
remove the assignment:
```dart
void f(String? s) {
}
```
deprecatedDetails: |-
**AVOID** `null` in `null`-aware assignment.
Using `null` on the right-hand side of a `null`-aware assignment effectively
makes the assignment redundant.
**BAD:**
```dart
var x;
x ??= null;
```
**GOOD:**
```dart
var x;
x ??= 1;
```
unnecessary_null_aware_operator_on_extension_on_nullable:
problemMessage: "Unnecessary use of a null-aware operator to invoke an extension method on a nullable type."
correctionMessage: "Try removing the '?'."
state:
stable: "2.18"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a null-aware operator is used
to invoke an extension method on an extension whose type is nullable.
#### Example
The following code produces this diagnostic because the extension method
`m` is invoked using `?.` when it doesn't need to be:
```dart
extension E on int? {
int m() => 1;
}
int? f(int? i) => i[!?.!]m();
```
#### Common fixes
If it isn't a requirement not invoke the method when the receiver is
`null`, then remove the question mark from the invocation:
```dart
extension E on int? {
int m() => 1;
}
int? f(int? i) => i.m();
```
deprecatedDetails: |-
Avoid null aware operators for members defined in an extension on a nullable
type.
**BAD:**
```dart
extension E on int? {
int m() => 1;
}
f(int? i) => i?.m();
```
**GOOD:**
```dart
extension E on int? {
int m() => 1;
}
f(int? i) => i.m();
```
unnecessary_null_checks:
problemMessage: "Unnecessary use of a null check ('!')."
correctionMessage: "Try removing the null check."
state:
experimental: "2.12"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a null check operator (`!`) is
used in a context where a nullable value is acceptable.
#### Example
The following code produces this diagnostic because a null check is being
used even though `null` is a valid value to return:
```dart
int? f(int? i) {
return i[!!!];
}
```
#### Common fixes
Remove the null check operator:
```dart
int? f(int? i) {
return i;
}
```
deprecatedDetails: |-
**DON'T** apply a `null` check where a nullable value is accepted.
**BAD:**
```dart
f(int? i) {}
m() {
int? j;
f(j!);
}
```
**GOOD:**
```dart
f(int? i) {}
m() {
int? j;
f(j);
}
```
unnecessary_null_in_if_null_operators:
problemMessage: "Unnecessary use of '??' with 'null'."
correctionMessage: "Try removing the '??' operator and the 'null' operand."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the right operand of the `??`
operator is the literal `null`.
#### Example
The following code produces this diagnostic because the right-hand operand
of the `??` operator is `null`:
```dart
String? f(String? s) => s ?? [!null!];
```
#### Common fixes
If a non-null value should be used for the right-hand operand, then
change the right-hand side:
```dart
String f(String? s) => s ?? '';
```
If there is no non-null value to use for the right-hand operand, then
remove the operator and the right-hand operand:
```dart
String? f(String? s) => s;
```
deprecatedDetails: |-
**AVOID** using `null` as an operand in `??` operators.
Using `null` in an `if null` operator is redundant, regardless of which side
`null` is used on.
**BAD:**
```dart
var x = a ?? null;
var y = null ?? 1;
```
**GOOD:**
```dart
var x = a ?? 1;
```
unnecessary_nullable_for_final_variable_declarations:
problemMessage: "Type could be non-nullable."
correctionMessage: "Try changing the type to be non-nullable."
state:
stable: "2.10"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a final field or variable has a
nullable type but is initialized to a non-nullable value.
#### Example
The following code produces this diagnostic because the final variable `i`
has a nullable type (`int?`), but can never be `null`:
```dart
final int? [!i!] = 1;
```
#### Common fixes
Make the type non-nullable:
```dart
final int i = 1;
```
deprecatedDetails: |-
Use a non-nullable type for a final variable initialized with a non-nullable
value.
**BAD:**
```dart
final int? i = 1;
```
**GOOD:**
```dart
final int i = 1;
```
unnecessary_overrides:
problemMessage: "Unnecessary override."
correctionMessage: "Try adding behavior in the overriding member or removing the override."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an instance member overrides an
inherited member but only invokes the overridden member with exactly the
same arguments.
#### Example
The following code produces this diagnostic because the method `D.m`
doesn't do anything other than invoke the overridden method:
```dart
class C {
int m(int x) => x;
}
class D extends C {
@override
int [!m!](int x) => super.m(x);
}
```
#### Common fixes
If the method should do something more than what the overridden method
does, then implement the missing functionality:
```dart
class C {
int m(int x) => x;
}
class D extends C {
@override
int m(int x) => super.m(x) + 1;
}
```
If the overridden method should be modified by changing the return type or
one or more of the parameter types, making one of the parameters
`covariant`, having a documentation comment, or by having additional
annotations, then update the code:
```dart
import 'package:meta/meta.dart';
class C {
int m(int x) => x;
}
class D extends C {
@mustCallSuper
@override
int m(int x) => super.m(x);
}
```
If the overriding method doesn't change or enhance the semantics of the
code, then remove it:
```dart
class C {
int m(int x) => x;
}
class D extends C {}
```
deprecatedDetails: |-
**DON'T** override a method to do a super method invocation with same parameters.
**BAD:**
```dart
class A extends B {
@override
void foo() {
super.foo();
}
}
```
**GOOD:**
```dart
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:
problemMessage: "Unnecessary use of parentheses."
correctionMessage: "Try removing the parentheses."
state:
stable: "2.0"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when parentheses are used where they
do not affect the semantics of the code.
#### Example
The following code produces this diagnostic because the parentheses around
the binary expression are not necessary:
```dart
int f(int a, int b) => [!(a + b)!];
```
#### Common fixes
Remove the unnecessary parentheses:
```dart
int f(int a, int b) => a + b;
```
deprecatedDetails: |-
**AVOID** using parentheses when not needed.
**BAD:**
```dart
a = (b);
```
**GOOD:**
```dart
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:
problemMessage: "Unnecessary use of a raw string."
correctionMessage: "Try using a normal string."
state:
stable: "2.8"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string literal is marked as
being raw (is prefixed with an `r`), but making the string raw doesn't
change the value of the string.
#### Example
The following code produces this diagnostic because the string literal
will have the same value without the `r` as it does with the `r`:
```dart
var s = [!r'abc'!];
```
#### Common fixes
Remove the `r` in front of the string literal:
```dart
var s = 'abc';
```
deprecatedDetails: |-
Use raw string only when needed.
**BAD:**
```dart
var s1 = r'a';
```
**GOOD:**
```dart
var s1 = 'a';
var s2 = r'$a';
var s3 = r'\a';
```
unnecessary_statements:
problemMessage: "Unnecessary statement."
correctionMessage: "Try completing the statement or breaking it up."
state:
stable: "2.0"
categories: [brevity, unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an expression statement has no
clear effect.
#### Example
The following code produces this diagnostic because the addition of the
returned values from the two invocations has no clear effect:
```dart
void f(int Function() first, int Function() second) {
[!first() + second()!];
}
```
#### Common fixes
If the expression doesn't need to be computed, then remove it:
```dart
void f(int Function() first, int Function() second) {
}
```
If the value of the expression is needed, then make use of it, possibly
assigning it to a local variable first:
```dart
void f(int Function() first, int Function() second) {
print(first() + second());
}
```
If portions of the expression need to be executed, then remove the
unnecessary portions:
```dart
void f(int Function() first, int Function() second) {
first();
second();
}
```
deprecatedDetails: |-
**AVOID** using unnecessary statements.
Statements which have no clear effect are usually unnecessary, or should be
broken up.
For example,
**BAD:**
```dart
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:**
```dart
some.method();
const SomeClass();
methodOne();
methodTwo();
foo ? bar() : baz();
return myvar;
```
unnecessary_string_escapes:
problemMessage: "Unnecessary escape in string literal."
correctionMessage: "Remove the '\\' escape."
state:
stable: "2.8"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when characters in a string are
escaped when escaping them is unnecessary.
#### Example
The following code produces this diagnostic because single quotes don't
need to be escaped inside strings delimited by double quotes:
```dart
var s = "Don[!\!]'t use a backslash here.";
```
#### Common fixes
Remove the unnecessary backslashes:
```dart
var s = "Don't use a backslash here.";
```
deprecatedDetails: |-
Remove unnecessary backslashes in strings.
**BAD:**
```dart
'this string contains 2 \"double quotes\" ';
"this string contains 2 \'single quotes\' ";
```
**GOOD:**
```dart
'this string contains 2 "double quotes" ';
"this string contains 2 'single quotes' ";
```
unnecessary_string_interpolations:
problemMessage: "Unnecessary use of string interpolation."
correctionMessage: "Try replacing the string literal with the variable name."
state:
stable: "2.8"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string literal contains a
single interpolation of a `String`-valued variable and no other
characters.
#### Example
The following code produces this diagnostic because the string literal
contains a single interpolation and doesn't contain any character outside
the interpolation:
```dart
String f(String s) => [!'$s'!];
```
#### Common fixes
Replace the string literal with the content of the interpolation:
```dart
String f(String s) => s;
```
deprecatedDetails: |-
**DON'T** use string interpolation if there's only a string expression in it.
**BAD:**
```dart
String message;
String o = '$message';
```
**GOOD:**
```dart
String message;
String o = message;
```
unnecessary_this:
problemMessage: "Unnecessary 'this.' qualifier."
correctionMessage: "Try removing 'this.'."
state:
stable: "2.0"
categories: [brevity, effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the keyword `this` is used to
access a member that isn't shadowed.
#### Example
The following code produces this diagnostic because the use of `this` to
access the field `_f` isn't necessary:
```dart
class C {
int _f = 2;
int get f => [!this!]._f;
}
```
#### Common fixes
Remove the `this.`:
```dart
class C {
int _f = 2;
int get f => _f;
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#dont-use-this-when-not-needed-to-avoid-shadowing):
**DON'T** use `this` when not needed to avoid shadowing.
**BAD:**
```dart
class Box {
int value;
void update(int newValue) {
this.value = newValue;
}
}
```
**GOOD:**
```dart
class Box {
int value;
void update(int newValue) {
value = newValue;
}
}
```
**GOOD:**
```dart
class Box {
int value;
void update(int value) {
this.value = value;
}
}
```
unnecessary_to_list_in_spreads:
problemMessage: "Unnecessary use of 'toList' in a spread."
correctionMessage: "Try removing the invocation of 'toList'."
state:
stable: "2.18"
categories: [brevity]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when `toList` is used to convert an
`Iterable` to a `List` just before a spread operator is applied to the
list. The spread operator can be applied to any `Iterable`, so the
conversion isn't necessary.
#### Example
The following code produces this diagnostic because `toList` is invoked on
the result of `map`, which is an `Iterable` that the spread operator could
be applied to directly:
```dart
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()).[!toList!](),
];
}
```
#### Common fixes
Remove the invocation of `toList`:
```dart
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()),
];
}
```
deprecatedDetails: |-
Unnecessary `toList()` in spreads.
**BAD:**
```dart
children: <Widget>[
...['foo', 'bar', 'baz'].map((String s) => Text(s)).toList(),
]
```
**GOOD:**
```dart
children: <Widget>[
...['foo', 'bar', 'baz'].map((String s) => Text(s)),
]
```
unnecessary_unawaited:
problemMessage: "Unnecessary use of 'unawaited'."
correctionMessage: "Try removing the use of 'unawaited', as the unawaited element is annotated with '@awaitNotRequired'."
state:
stable: "3.9"
categories: [brevity, unintentional, unusedCode]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when `unawaited` is used to mark a
call to a function, method, or operator, or a reference to a field,
getter, or top-level variable as safely not being awaited, but the called
member is also annotated with `@awaitNotRequired`. This annotation itself
signals that wrapping with `unawaited` is unnecessary at any call site.
#### Example
The following code produces this diagnostic because `unawaited` is invoked
on a call to a function that's annotated with `@awaitNotRequired`:
```dart
import 'dart:async';
import 'package:meta/meta.dart';
@awaitNotRequired
Future<bool> log(String message) async => true;
void f() {
[!unawaited!](log('Message.'));
}
```
#### Common fixes
Remove the invocation of `unawaited`:
```dart
import 'package:meta/meta.dart';
@awaitNotRequired
Future<bool> log(String message) async => true;
void f() {
log('Message.');
}
```
deprecatedDetails: |-
A call to a function, method, or operator, or a reference to a field,
getter, or top-level variable which is annotated with `@awaitNotRequired`
does not need to be wrapped in a call to `unawaited()`.
**BAD:**
```dart
@awaitNotRequired
Future<LogMessage> log(String message) { ... }
void f() {
unawaited(log('Message.'));
}
```
**GOOD:**
```dart
@awaitNotRequired
Future<LogMessage> log(String message) { ... }
void f() {
log('Message.');
}
```
unnecessary_underscores:
problemMessage: "Unnecessary use of multiple underscores."
correctionMessage: "Try using '_'."
state:
experimental: "3.7"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an unused variable is named
with multiple underscores (for example `__`). A single `_` wildcard variable
can be used instead.
#### Example
The following code produces this diagnostic because the `__` parameter is unused:
```dart
void function(int [!__!]) { }
```
#### Common fixes
Replace the name with a single underscore:
```dart
void function(int _) { }
```
deprecatedDetails: |-
**AVOID** using multiple underscores when a single wildcard will do.
**BAD:**
```dart
void function(int __) { }
```
**GOOD:**
```dart
void function(int _) { }
```
unreachable_from_main:
problemMessage: "Unreachable member '{0}' in an executable library."
correctionMessage: "Try referencing the member or removing it."
state:
stable: "2.19"
categories: [unusedCode]
hasPublishedDocs: false
deprecatedDetails: |-
Any member declared in an executable library should be used directly inside that
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 libraries
except to execute its `main` function.
**BAD:**
```dart
main() {}
void f() {}
```
**GOOD:**
```dart
main() {
f();
}
void f() {}
```
unrelated_type_equality_checks_in_expression:
sharedName: unrelated_type_equality_checks
problemMessage: "The type of the right operand ('{0}') isn't a subtype or a supertype of the left operand ('{1}')."
correctionMessage: "Try changing one or both of the operands."
state:
stable: "2.0"
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when two objects are being compared
and neither of the static types of the two objects is a subtype of the
other.
Such a comparison will usually return `false` and might not reflect the
programmer's intent.
There can be false positives. For example, a class named `Point` might
have subclasses named `CartesianPoint` and `PolarPoint`, neither of which
is a subtype of the other, but it might still be appropriate to test the
equality of instances.
As a concrete case, the classes `Int64` and `Int32` from `package:fixnum`
allow comparing instances to an `int` provided the `int` is on the
right-hand side. This case is specifically allowed by the diagnostic, but
other such cases are not.
#### Example
The following code produces this diagnostic because the string `s` is
being compared to the integer `1`:
```dart
bool f(String s) {
return s [!==!] 1;
}
```
#### Common fixes
Replace one of the operands with something compatible with the other
operand:
```dart
bool f(String s) {
return s.length == 1;
}
```
deprecatedDetails: |-
**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:**
```dart
void someFunction() {
var x = '1';
if (x == 1) print('someFunction'); // LINT
}
```
**BAD:**
```dart
void someFunction1() {
String x = '1';
if (x == 1) print('someFunction1'); // LINT
}
```
**BAD:**
```dart
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:**
```dart
void someFunction2() {
var x = '1';
var y = '2';
if (x == y) print(someFunction2); // OK
}
```
**GOOD:**
```dart
void someFunction3() {
for (var i = 0; i < 10; i++) {
if (i == 0) print(someFunction3); // OK
}
}
```
**GOOD:**
```dart
void someFunction4() {
var x = '1';
if (x == null) print(someFunction4); // OK
}
```
**GOOD:**
```dart
void someFunction7() {
List someList;
if (someList.length == 0) print('someFunction7'); // OK
}
```
**GOOD:**
```dart
void someFunction8(ClassBase instance) {
DerivedClass1 other;
if (other == instance) print('someFunction8'); // OK
}
```
**GOOD:**
```dart
void someFunction10(unknown) {
var what = unknown - 1;
for (var index = 0; index < unknown; index++) {
if (what == index) print('someFunction10'); // OK
}
}
```
**GOOD:**
```dart
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 {}
```
unrelated_type_equality_checks_in_pattern:
sharedName: unrelated_type_equality_checks
problemMessage: "The type of the operand ('{0}') isn't a subtype or a supertype of the value being matched ('{1}')."
correctionMessage: "Try changing one or both of the operands."
hasPublishedDocs: true
unsafe_html_attribute:
sharedName: unsafe_html
problemMessage: "Assigning to the attribute '{0}' is unsafe."
correctionMessage: "Try finding a different way to implement the page."
state:
stable: "2.4"
removed: "3.7"
categories: [errorProne]
hasPublishedDocs: false
deprecatedDetails: |-
**NOTE:** This lint is deprecated and will be removed in a future release.
Remove all inclusions of this lint from your analysis options.
**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:**
```dart
var script = ScriptElement()..src = 'foo.js';
```
This rule has been removed.
unsafe_html_constructor:
sharedName: unsafe_html
problemMessage: "Invoking the constructor '{0}' is unsafe."
correctionMessage: "Try finding a different way to implement the page."
hasPublishedDocs: false
unsafe_html_method:
sharedName: unsafe_html
problemMessage: "Invoking the method '{0}' is unsafe."
correctionMessage: "Try finding a different way to implement the page."
hasPublishedDocs: false
unsafe_variance:
problemMessage: "This type is unsafe: a type parameter occurs in a non-covariant position."
correctionMessage: "Try using a more general type that doesn't contain any type parameters in such a position."
state:
experimental: "3.7"
categories: [errorProne]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when an instance member has a result
type which is [contravariant or invariant](https://dart.dev/resources/glossary#variance)
in a type parameter of the enclosing declaration. The result type of a
variable is its type, and the result type of a getter or method is its
return type. This lint warns against such members because they are likely
to cause a failing type check at run time, with no static warning or error
at the call site.
#### Example
The following code produces this diagnostic because `X` occurs
as a parameter type in the type of `f`, which is a
contravariant occurrence of this type parameter:
```dart
class C<X> {
bool Function([!X!]) f;
C(this.f);
}
```
This is unsafe: If `c` has static type `C<num>` and run-time type `C<int>`
then `c.f` will throw. Hence, every invocation `c.f(a)` will also throw,
even in the case where `a` has a correct type as an argument to `c.f`.
#### Common fixes
If the linted member is or can be private then you may be able
to enforce that it is never accessed on any other receiver than `this`.
This is sufficient to ensure that that the run-time type error does not
occur. For example:
```dart
class C<X> {
// NB: Ensure manually that `_f` is only accessed on `this`.
// ignore: unsafe_variance
bool Function(X) _f;
C(this._f);
// We can write a forwarding method to allow clients to call `_f`.
bool f(X x) => _f(x);
}
```
You can eliminate the unsafe variance by using a more general type for
the linted member. In this case you may need to check the run-time type
and perform a downcast at call sites.
```dart
class C<X> {
bool Function(Never) f;
C(this.f);
}
```
If `c` has static type `C<num>` then you may test the type. For example,
`c.f is bool Function(num)`. You may safely call it with an argument of
type `num` if it has that type.
You can also eliminate the unsafe variance by using a much more general
type like `Function`, which is essentially the type `dynamic` for
functions.
```dart
class C<X> {
Function f;
C(this.f);
}
```
This will make `c.f(a)` dynamically safe: It will throw if and only if the
argument `a` does not have the type required by the function. This is
better than the original version because it will not throw because of a
mismatched static type. It only throws when it _must_ throw for soundness
reasons.
deprecatedDetails: |-
An instance variable whose type contains a type parameter of the
enclosing class, mixin, or enum in a non-covariant position is
likely to cause run-time failures due to failing type
checks. For example, in `class C<X> {...}`, an instance variable
of the form `void Function(X) myVariable;` may cause this kind
of run-time failure.
The same is true for a getter or method whose return type has a
non-covariant occurrence of a type parameter of the enclosing
declaration.
This lint flags this kind of member declaration.
**BAD:**
```dart
class C<X> {
final bool Function([!X!]) fun; // LINT
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Throws.
}
```
The problem is that `X` occurs as a parameter type in the type
of `fun`.
One way to reduce the potential for run-time type errors is to
ensure that the non-covariant member `fun` is _only_ used on
`this`. We cannot strictly enforce this, but we can make it
private and add a forwarding method `fun` such that we can check
locally in the same library that this constraint is satisfied:
**BETTER:**
```dart
class C<X> {
// ignore: unsafe_variance
final bool Function(X) _fun;
bool fun(X x) => _fun(x);
C(this._fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
```
A fully safe approach requires a feature that Dart does not yet
have, namely statically checked variance. With that, we could
specify that the type parameter `X` is invariant (`inout X`).
It is possible to emulate invariance without support for statically
checked variance. This puts some restrictions on the creation of
subtypes, but faithfully provides the typing that `inout` would
give:
**GOOD:**
```dart
typedef Inv<X> = X Function(X);
typedef C<X> = _C<X, Inv<X>>;
class _C<X, Invariance extends Inv<X>> {
// ignore: unsafe_variance
final bool Function(X) fun; // Safe!
_C(this.fun);
}
void main() {
C<int> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
```
With this approach, `C<int>` is not a subtype of `C<num>`, so
`c` must have a different declared type.
Another possibility is to declare the variable to have a safe
but more general type. It is then safe to use the variable
itself, but every invocation will have to be checked at run
time:
**HONEST:**
```dart
class C<X> {
final bool Function(Never) fun;
C(this.fun);
}
void main() {
C<num> c = C<int>((int i) => i.isEven);
var cfun = c.fun; // Local variable, enables promotion.
if (cfun is bool Function(int)) cfun(10); // Succeeds.
if (cfun is bool Function(bool)) cfun(true); // Not called.
}
```
use_build_context_synchronously_async_use:
sharedName: use_build_context_synchronously
problemMessage: "Don't use 'BuildContext's across async gaps."
correctionMessage: "Try rewriting the code to not use the 'BuildContext', or guard the use with a 'mounted' check."
state:
experimental: "2.13"
stable: "3.2"
categories: [errorProne, flutter]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `BuildContext` is referenced
by a `StatefulWidget` after an asynchronous gap without first checking the
`mounted` property.
Storing a `BuildContext` for later use can lead to difficult-to-diagnose
crashes. Asynchronous gaps implicitly store a `BuildContext`, making them
easy to overlook for diagnosis.
#### Example
The following code produces this diagnostic because the `context` is
passed to a constructor after the `await`:
```dart
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of([!context!]).pop();
}
}
```
#### Common fixes
If you can remove the asynchronous gap, do so:
```dart
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
}
```
If you can't remove the asynchronous gap, then use `mounted` to guard the
use of the `context`:
```dart
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
if (context.mounted) {
Navigator.of(context).pop();
}
}
}
```
deprecatedDetails: |-
**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, a `mounted` property must be checked after an
asynchronous gap, depending on how the `BuildContext` is accessed:
* When using a `State`'s `context` property, the `State`'s `mounted` property
must be checked.
* For other `BuildContext` instances (like a local variable or function
argument), the `BuildContext`'s `mounted` property must be checked.
**BAD:**
```dart
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
}
```
**GOOD:**
```dart
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
```
**GOOD:**
```dart
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
if (!context.mounted) return;
Navigator.of(context).pop();
}
```
**GOOD:**
```dart
abstract class MyState extends State<MyWidget> {
void foo() async {
await Future.delayed(const Duration(seconds: 1));
if (!mounted) return; // Checks `this.mounted`, not `context.mounted`.
Navigator.of(context).pop();
}
}
```
use_build_context_synchronously_wrong_mounted:
sharedName: use_build_context_synchronously
problemMessage: "Don't use 'BuildContext's across async gaps, guarded by an unrelated 'mounted' check."
correctionMessage: "Guard a 'State.context' use with a 'mounted' check on the State, and other BuildContext use with a 'mounted' check on the BuildContext."
hasPublishedDocs: true
use_colored_box:
problemMessage: "Use a 'ColoredBox' rather than a 'Container' with only a 'Color'."
correctionMessage: "Try replacing the 'Container' with a 'ColoredBox'."
state:
stable: "2.17"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `Container` is created that
only sets the color.
#### Example
The following code produces this diagnostic because the only attribute of
the container that is set is the `color`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return [!Container!](
color: Colors.red,
child: const Text('hello'),
);
}
```
#### Common fixes
Replace the `Container` with a `ColoredBox`:
```dart
import 'package:flutter/material.dart';
Widget build() {
return ColoredBox(
color: Colors.red,
child: const Text('hello'),
);
}
```
deprecatedDetails: |-
**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:**
```dart
Widget buildArea() {
return Container(
color: Colors.blue,
child: const Text('hello'),
);
}
```
**GOOD:**
```dart
Widget buildArea() {
return const ColoredBox(
color: Colors.blue,
child: Text('hello'),
);
}
```
use_decorated_box:
problemMessage: "Use 'DecoratedBox' rather than a 'Container' with only a 'Decoration'."
correctionMessage: "Try replacing the 'Container' with a 'DecoratedBox'."
state:
stable: "2.16"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `Container` is created that
only sets the decoration.
#### Example
The following code produces this diagnostic because the only attribute of
the container that is set is the `decoration`:
```dart
import 'package:flutter/material.dart';
Widget buildArea() {
return [!Container!](
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
```
#### Common fixes
Replace the `Container` with a `DecoratedBox`:
```dart
import 'package:flutter/material.dart';
Widget buildArea() {
return DecoratedBox(
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
```
deprecatedDetails: |-
**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:**
```dart
Widget buildArea() {
return Container(
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
```
**GOOD:**
```dart
Widget buildArea() {
return const DecoratedBox(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: Text('...'),
);
}
```
use_enums:
problemMessage: "Class should be an enum."
correctionMessage: "Try using an enum rather than a class."
state:
stable: "2.17"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
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` or `index`,
* do not extend any class other than `Object`, and
* have no subclasses declared in the defining library.
To learn more about creating and using these enums, check out
[Declaring enhanced enums](https://dart.dev/language/enums#declaring-enhanced-enums).
**BAD:**
```dart
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:**
```dart
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:
problemMessage: "Instances of 'Color' should be created using an 8-digit hexadecimal integer (such as '0xFFFFFFFF')."
state:
stable: "2.2"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the argument to the constructor
of the `Color` class is a literal integer that isn't represented as an
8-digit hexadecimal integer.
#### Example
The following code produces this diagnostic because the argument (`1`)
isn't represented as an 8-digit hexadecimal integer:
```dart
import 'package:flutter/material.dart';
Color c = Color([!1!]);
```
#### Common fixes
Convert the representation to be an 8-digit hexadecimal integer:
```dart
import 'package:flutter/material.dart';
Color c = Color(0x00000001);
```
deprecatedDetails: |-
**PREFER** an 8-digit hexadecimal integer (for example, 0xFFFFFFFF) to
instantiate a Color. Colors have four 8-bit channels, which adds up to 32 bits,
so Colors are described using a 32-bit integer.
**BAD:**
```dart
Color(1);
Color(0x000001);
```
**GOOD:**
```dart
Color(0x00000001);
```
use_function_type_syntax_for_parameters:
problemMessage: "Use the generic function type syntax to declare the parameter '{0}'."
correctionMessage: "Try using the generic function type syntax."
state:
stable: "2.1"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the older style function-valued
parameter syntax is used.
#### Example
The following code produces this diagnostic because the function-valued
parameter `f` is declared using an older style syntax:
```dart
void g([!bool f(String s)!]) {}
```
#### Common fixes
Use the generic function type syntax to declare the parameter:
```dart
void g(bool Function(String) f) {}
```
deprecatedDetails: |-
Use generic function type syntax for parameters.
**BAD:**
```dart
Iterable<T> where(bool predicate(T element)) {}
```
**GOOD:**
```dart
Iterable<T> where(bool Function(T) predicate) {}
```
use_if_null_to_convert_nulls_to_bools:
problemMessage: "Use an if-null operator to convert a 'null' to a 'bool'."
correctionMessage: "Try using an if-null operator."
state:
stable: "2.13"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a nullable `bool`-valued
expression is compared (using `==` or `!=`) to a boolean literal.
#### Example
The following code produces this diagnostic because the nullable boolean
variable `b` is compared to `true`:
```dart
void f(bool? b) {
if ([!b == true!]) {
// Treats `null` as `false`.
}
}
```
#### Common fixes
Rewrite the condition to use `??` instead:
```dart
void f(bool? b) {
if (b ?? false) {
// Treats `null` as `false`.
}
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#prefer-using--to-convert-null-to-a-boolean-value):
Use `??` operators to convert `null`s to `bool`s.
**BAD:**
```dart
if (nullableBool == true) {
}
if (nullableBool != false) {
}
```
**GOOD:**
```dart
if (nullableBool ?? false) {
}
if (nullableBool ?? true) {
}
```
use_is_even_rather_than_modulo:
problemMessage: "Use '{0}' rather than '% 2'."
correctionMessage: "Try using '{0}'."
state:
stable: "2.9"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
**PREFER** the use of intValue.isOdd/isEven to check for evenness.
**BAD:**
```dart
bool isEven = 1 % 2 == 0;
bool isOdd = 13 % 2 == 1;
```
**GOOD:**
```dart
bool isEven = 1.isEven;
bool isOdd = 13.isOdd;
```
use_key_in_widget_constructors:
problemMessage: "Constructors for public widgets should have a named 'key' parameter."
correctionMessage: "Try adding a named parameter to the constructor."
state:
stable: "2.8"
categories: [flutter, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constructor in a subclass of
`Widget` that isn't private to its library doesn't have a parameter named
`key`.
#### Example
The following code produces this diagnostic because the constructor for
the class `MyWidget` doesn't have a parameter named `key`:
```dart
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
[!MyWidget!]({required int height});
}
```
The following code produces this diagnostic because the default
constructor for the class `MyWidget` doesn't have a parameter named `key`:
```dart
import 'package:flutter/material.dart';
class [!MyWidget!] extends StatelessWidget {}
```
#### Common fixes
Add a parameter named `key` to the constructor, explicitly declaring the
constructor if necessary:
```dart
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget({super.key, required int height});
}
```
deprecatedDetails: |-
**DO** use key in widget constructors.
It's a good practice to expose the ability to provide a key when creating public
widgets.
**BAD:**
```dart
class MyPublicWidget extends StatelessWidget {
}
```
**GOOD:**
```dart
class MyPublicWidget extends StatelessWidget {
MyPublicWidget({super.key});
}
```
use_late_for_private_fields_and_variables:
problemMessage: "Use 'late' for private members with a non-nullable type."
correctionMessage: "Try making adding the modifier 'late'."
state:
experimental: "2.10"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a private field or variable is
marked as being nullable, but every reference assumes that the variable is
never `null`.
#### Example
The following code produces this diagnostic because the private top-level
variable `_i` is nullable, but every reference assumes that it will not be
`null`:
```dart
void f() {
_i!.abs();
}
int? [!_i!];
```
#### Common fixes
Mark the variable or field as being both non-nullable and `late` to
indicate that it will always be assigned a non-null:
```dart
void f() {
_i.abs();
}
late int _i;
```
deprecatedDetails: |-
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:**
```dart
int? _i;
m() {
_i!.abs();
}
```
**GOOD:**
```dart
late int _i;
m() {
_i.abs();
}
```
**OK:**
```dart
int? _i;
m() {
_i?.abs();
_i = null;
}
```
use_named_constants:
problemMessage: "Use the constant '{0}' rather than a constructor returning the same object."
correctionMessage: "Try using '{0}'."
state:
stable: "2.13"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a constant is created with the
same value as a known `const` variable.
#### Example
The following code produces this diagnostic because there is a known
`const` field (`Duration.zero`) whose value is the same as what the
constructor invocation will evaluate to:
```dart
Duration d = [!const Duration(seconds: 0)!];
```
#### Common fixes
Replace the constructor invocation with a reference to the known `const`
variable:
```dart
Duration d = Duration.zero;
```
deprecatedDetails: |-
Where possible, use already defined const values.
**BAD:**
```dart
const Duration(seconds: 0);
```
**GOOD:**
```dart
Duration.zero;
```
use_null_aware_elements:
problemMessage: "Use the null-aware marker '?' rather than a null check via an 'if'."
correctionMessage: "Try using '?'."
state:
stable: "3.8"
categories: [brevity, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a null check is used instead
of a null-aware marker inside of a collection literal.
#### Example
The following code produces this diagnostic because a null check is used
to decide whether `x` should be inserted into the list, while the
null-aware marker '?' would be less brittle and less verbose.
```dart
f(int? x) => [[!if!] (x != null) x];
```
#### Common fixes
Replace the null-check with the null-aware marker '?':
```dart
f(int? x) => [?x];
```
deprecatedDetails: |-
Where possible, use null-aware elements in collection literals.
**BAD:**
```dart
f(String? key) => {if (key != null) key: "value"};
```
**GOOD:**
```dart
f(String? key) => {?key: "value"};
```
use_raw_strings:
problemMessage: "Use a raw string to avoid using escapes."
correctionMessage: "Try making the string a raw string and removing the escapes."
state:
stable: "2.8"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a string literal containing
escapes, and no interpolations, could be marked as being raw in order to
avoid the need for the escapes.
#### Example
The following code produces this diagnostic because the string contains
escaped characters that wouldn't need to be escaped if the string is
made a raw string:
```dart
var s = [!'A string with only \\ and \$'!];
```
#### Common fixes
Mark the string as being raw and remove the unnecessary backslashes:
```dart
var s = r'A string with only \ and $';
```
deprecatedDetails: |-
A raw string can be used to avoid escaping only backslashes and dollars.
**BAD:**
```dart
var s = 'A string with only \\ and \$';
```
**GOOD:**
```dart
var s = r'A string with only \ and $';
```
use_rethrow_when_possible:
problemMessage: "Use 'rethrow' to rethrow a caught exception."
correctionMessage: "Try replacing the 'throw' with a 'rethrow'."
state:
stable: "2.0"
categories: [brevity, effectiveDart]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a caught exception is thrown
using a `throw` expression rather than a `rethrow` statement.
#### Example
The following code produces this diagnostic because the caught exception
`e` is thrown using a `throw` expression:
```dart
void f() {
try {
// ...
} catch (e) {
[!throw e!];
}
}
```
#### Common fixes
Use `rethrow` instead of `throw`:
```dart
void f() {
try {
// ...
} catch (e) {
rethrow;
}
}
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#do-use-rethrow-to-rethrow-a-caught-exception):
**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:**
```dart
try {
somethingRisky();
} catch(e) {
if (!canHandle(e)) throw e;
handle(e);
}
```
**GOOD:**
```dart
try {
somethingRisky();
} catch(e) {
if (!canHandle(e)) rethrow;
handle(e);
}
```
use_setters_to_change_properties:
problemMessage: "The method is used to change a property."
correctionMessage: "Try converting the method to a setter."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a method is used to set the
value of a field, or a function is used to set the value of a top-level
variable, and nothing else.
#### Example
The following code produces this diagnostic because the method `setF` is
used to set the value of the field `_f` and does no other work:
```dart
class C {
int _f = 0;
void [!setF!](int value) => _f = value;
}
```
#### Common fixes
Convert the method to a setter:
```dart
class C {
int _f = 0;
set f(int value) => _f = value;
}
```
deprecatedDetails: |-
**DO** use a setter for operations that conceptually change a property.
**BAD:**
```dart
rectangle.setWidth(3);
button.setVisible(false);
```
**GOOD:**
```dart
rectangle.width = 3;
button.visible = false;
```
use_string_buffers:
problemMessage: "Use a string buffer rather than '+' to compose strings."
correctionMessage: "Try writing the parts of a string to a string buffer."
state:
stable: "2.0"
categories: [nonPerformant]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when values are concatenated to a
string inside a loop without using a `StringBuffer` to do the
concatenation.
#### Example
The following code produces this diagnostic because the string `result` is
computed by repeated concatenation within the `for` loop:
```dart
String f() {
var result = '';
for (int i = 0; i < 10; i++) {
[!result += 'a'!];
}
return result;
}
```
#### Common fixes
Use a `StringBuffer` to compute the result:
```dart
String f() {
var buffer = StringBuffer();
for (int i = 0; i < 10; i++) {
buffer.write('a');
}
return buffer.toString();
}
```
deprecatedDetails: |-
**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:**
```dart
String foo() {
final buffer = '';
for (int i = 0; i < 10; i++) {
buffer += 'a'; // LINT
}
return buffer;
}
```
**GOOD:**
```dart
String foo() {
final buffer = StringBuffer();
for (int i = 0; i < 10; i++) {
buffer.write('a');
}
return buffer.toString();
}
```
use_string_in_part_of_directives:
problemMessage: "The part-of directive uses a library name."
correctionMessage: "Try converting the directive to use the URI of the library."
state:
stable: "2.19"
categories: [effectiveDart, style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a `part of` directive uses a
library name to refer to the library that the part is a part of.
#### Example
Given a file named `lib.dart` that contains the following:
```dart
%uri="lib/lib.dart"
library lib;
part 'test.dart';
```
The following code produces this diagnostic because the `part of`
directive uses the name of the library rather than the URI of the library
it's part of:
```dart
[!part of lib;!]
```
#### Common fixes
Use a URI to reference the library:
```dart
part of 'lib.dart';
```
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/usage#do-use-strings-in-part-of-directives):
**DO** use strings in `part of` directives.
**BAD:**
```dart
part of my_library;
```
**GOOD:**
```dart
part of '../../my_library.dart';
```
use_super_parameters_multiple:
sharedName: use_super_parameters
problemMessage: "Parameters '{0}' could be super parameters."
correctionMessage: "Trying converting '{0}' to super parameters."
state:
experimental: "2.17"
categories: [brevity]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a parameter to a constructor is
passed to a super constructor without being referenced or modified and a
`super` parameter isn't used.
#### Example
The following code produces this diagnostic because the parameters of the
constructor for `B` are only used as arguments to the super constructor:
```dart
class A {
A({int? x, int? y});
}
class B extends A {
[!B!]({int? x, int? y}) : super(x: x, y: y);
}
```
#### Common fixes
Use a `super` parameter to pass the arguments:
```dart
class A {
A({int? x, int? y});
}
class B extends A {
B({super.x, super.y});
}
```
deprecatedDetails: |-
"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:**
```dart
class A {
A({int? x, int? y});
}
class B extends A {
B({int? x, int? y}) : super(x: x, y: y);
}
```
**GOOD:**
```dart
class A {
A({int? x, int? y});
}
class B extends A {
B({super.x, super.y});
}
```
use_super_parameters_single:
sharedName: use_super_parameters
problemMessage: "Parameter '{0}' could be a super parameter."
correctionMessage: "Trying converting '{0}' to a super parameter."
hasPublishedDocs: true
use_test_throws_matchers:
problemMessage: "Use the 'throwsA' matcher instead of using 'fail' when there is no exception thrown."
correctionMessage: "Try removing the try-catch and using 'throwsA' to expect an exception."
state:
stable: "2.14"
categories: [style]
hasPublishedDocs: false
deprecatedDetails: |-
Use the `throwsA` matcher instead of try-catch with `fail()`.
**BAD:**
```dart
// 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:**
```dart
// 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:
problemMessage: "Start the name of the method with 'to' or 'as'."
correctionMessage: "Try renaming the method to use either 'to' or 'as'."
state:
stable: "2.0"
categories: [effectiveDart, style]
hasPublishedDocs: false
deprecatedDetails: |-
From [Effective Dart](https://dart.dev/effective-dart/design#prefer-naming-a-method-to___-if-it-copies-the-objects-state-to-a-new-object):
**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:**
```dart
class Bar {
Foo myMethod() {
return Foo.from(this);
}
}
```
**GOOD:**
```dart
class Bar {
Foo toFoo() {
return Foo.from(this);
}
}
```
**GOOD:**
```dart
class Bar {
Foo asFoo() {
return Foo.from(this);
}
}
```
use_truncating_division:
problemMessage: "Use truncating division."
correctionMessage: "Try using truncating division, '~/', instead of regular division ('/') followed by 'toInt()'."
state:
stable: "3.6"
categories: [languageFeatureUsage]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the result of dividing two
numbers is converted to an integer using `toInt`.
Dart has a built-in integer division operator that is both more efficient
and more concise.
#### Example
The following code produces this diagnostic because the result of dividing
`x` and `y` is converted to an integer using `toInt`:
```dart
int divide(int x, int y) => [!(x / y).toInt()!];
```
#### Common fixes
Use the integer division operator (`~/`):
```dart
int divide(int x, int y) => x ~/ y;
```
deprecatedDetails: |-
**DO** use truncating division, '~/', instead of regular division ('/') followed
by 'toInt()'.
Dart features a "truncating division" operator which is the same operation as
division followed by truncation, but which is more concise and expressive, and
may be more performant on some platforms, for certain inputs.
**BAD:**
```dart
var x = (2 / 3).toInt();
```
**GOOD:**
```dart
var x = 2 ~/ 3;
```
valid_regexps:
problemMessage: "Invalid regular expression syntax."
correctionMessage: "Try correcting the regular expression."
state:
stable: "2.0"
categories: [unintentional]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when the string passed to the
default constructor of the class `RegExp` doesn't contain a valid regular
expression.
A regular expression created with invalid syntax will throw a
`FormatException` at runtime.
#### Example
The following code produces this diagnostic because the regular expression
isn't valid:
```dart
var r = RegExp([!r'('!]);
```
#### Common fixes
Fix the regular expression:
```dart
var r = RegExp(r'\(');
```
deprecatedDetails: |-
**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:**
```dart
print(RegExp(r'(').hasMatch('foo()'));
```
**GOOD:**
```dart
print(RegExp(r'\(').hasMatch('foo()'));
```
void_checks:
problemMessage: "Assignment to a variable of type 'void'."
correctionMessage: "Try removing the assignment or changing the type of the variable."
state:
stable: "2.0"
categories: [style]
hasPublishedDocs: true
documentation: |-
#### Description
The analyzer produces this diagnostic when a value is assigned to a
variable of type `void`.
It isn't possible to access the value of such a variable, so the
assignment has no value.
#### Example
The following code produces this diagnostic because the field `value` has
the type `void`, but a value is being assigned to it:
```dart
class A<T> {
T? value;
}
void f(A<void> a) {
[!a.value = 1!];
}
```
The following code produces this diagnostic because the type of the
parameter `p` in the method `m` is `void`, but a value is being assigned
to it in the invocation:
```dart
class A<T> {
void m(T p) { }
}
void f(A<void> a) {
a.m([!1!]);
}
```
#### Common fixes
If the type of the variable is incorrect, then change the type of the
variable:
```dart
class A<T> {
T? value;
}
void f(A<int> a) {
a.value = 1;
}
```
If the type of the variable is correct, then remove the assignment:
```dart
class A<T> {
T? value;
}
void f(A<void> a) {}
```
deprecatedDetails: |-
**DON'T** assign to `void`.
**BAD:**
```dart
class A<T> {
T value;
void test(T arg) { }
}
void main() {
A<void> a = A<void>();
a.value = 1; // LINT
a.test(1); // LINT
}
```