# 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 # dart run pkg/analyzer/tool/messages/generate.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. LinterLintCode: alwaysDeclareReturnTypesOfFunctions: type: lint parameters: Object p0: undocumented sharedName: alwaysDeclareReturnTypes problemMessage: "The function '#p0' 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); ``` alwaysDeclareReturnTypesOfMethods: type: lint parameters: Object p0: undocumented sharedName: alwaysDeclareReturnTypes problemMessage: "The method '#p0' should have a return type but doesn't." correctionMessage: "Try adding a return type to the method." hasPublishedDocs: true alwaysPutControlBodyOnNewLine: type: lint parameters: none 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. alwaysPutRequiredNamedParametersFirst: type: lint parameters: none 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}) ; ``` alwaysRequireNonNullNamedParameters: type: lint parameters: none 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. alwaysSpecifyTypesAddType: type: lint parameters: none sharedName: alwaysSpecifyTypes problemMessage: "Missing type annotation." correctionMessage: "Try adding a type annotation." state: stable: "2.0" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when an explicit type annotation is missing. This includes in the following cases: - A variable declaration that uses `var`, `final`, or `const` without a specific type. - A function parameter lacks a type annotation. - A collection literal lacks explicit type arguments. - A reference to a generic class, mixin, or enum lacks type arguments. Types annotated with `@optionalTypeArgs` from `package:meta` are exempt from requiring type arguments. #### Examples The following code produces this diagnostic because the top-level variable uses `var` without an explicit type: ```dart [!var!] x = 1; ``` The following code produces this diagnostic because the parameter `p` lacks a type annotation: ```dart void f([!p!]) {} ``` The following code produces this diagnostic because the set literal lacks an explicit type argument: ```dart Set items = [!{!]1, 2}; ``` The following code produces this diagnostic because the generic type `C` is used without specifying its type argument: ```dart class C {} [!C!] c = C(); ``` #### Common fixes Add an explicit type annotation to variable declarations: ```dart int x = 1; ``` Add a type annotation to parameters: ```dart void f(int p) {} ``` Add explicit type arguments to collection literals: ```dart Set items = {1, 2}; ``` Add type arguments to generic type references: ```dart class C {} C c = C(); ``` If a type argument is meant to be optional, annotate the declaration with `@optionalTypeArgs` from `package:meta` to exempt it from this lint: ```dart import 'package:meta/meta.dart'; @optionalTypeArgs class C {} C c = C(); ``` 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 { ... } void main() { Key s = Key(); // OK! } ``` alwaysSpecifyTypesReplaceKeyword: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: alwaysSpecifyTypes problemMessage: "Missing type annotation." correctionMessage: "Try replacing '#p0' with '#p1'." hasPublishedDocs: false alwaysSpecifyTypesSpecifyType: type: lint parameters: Object p0: undocumented sharedName: alwaysSpecifyTypes problemMessage: "Missing type annotation." correctionMessage: "Try specifying the type '#p0'." hasPublishedDocs: false alwaysSpecifyTypesSplitToTypes: type: lint parameters: none sharedName: alwaysSpecifyTypes problemMessage: "Missing type annotation." correctionMessage: "Try splitting the declaration and specify the different type annotations." hasPublishedDocs: false alwaysUsePackageImports: type: lint parameters: none 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 %ignore=uri_does_not_exist import [!'a.dart'!]; ``` #### Common fixes Use a package import: ```dart %ignore=uri_does_not_exist 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'; ... ``` analyzerElementModelTrackingBad: type: lint parameters: none problemMessage: "Bad tracking annotation for this member." state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." hasPublishedDocs: false analyzerElementModelTrackingMoreThanOne: type: lint parameters: none problemMessage: "There can be only one tracking annotation." state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." hasPublishedDocs: false analyzerElementModelTrackingZero: type: lint parameters: none problemMessage: "No required tracking annotation." state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." hasPublishedDocs: false analyzerPublicApiBadPartDirective: type: lint parameters: none problemMessage: "Part directives in the analyzer public API should point to files in the analyzer public API." hasPublishedDocs: false state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." comment: |- Lint issued if a file in the analyzer public API contains a `part` directive that points to a file that's not in the analyzer public API. The rationale for this lint is that if such a `part` directive were to exist, it would cause all the members of the part file to become part of the analyzer's public API, even though they don't appear to be public API. Note that the analyzer doesn't make very much use of `part` directives, but it may do so in the future once augmentations and enhanced parts are supported. analyzerPublicApiBadType: type: lint parameters: String types: "list of types, separated by `, `" problemMessage: "Element makes use of type(s) which is not part of the analyzer public API: #types." hasPublishedDocs: false state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." comment: |- Lint issued if a method, function, getter, or setter in the analyzer public API makes use of a type that's not part of the analyzer public API, or if a non-public type appears in an `extends`, `implements`, `with`, or `on` clause. The reason this is a problem is that it makes it possible for analyzer clients to implicitly reference analyzer internal types. This can happen in many ways; here are some examples: - If `C` is a public API class that implements `B`, and `B` is a private class with a getter called `x`, then a client can access `B.x` via `C`. - If `f` has return type `T`, and `T` is a private class with a getter called `x`, then a client can access `T.x` via `f().x`. - If `f` has type `void Function(T)`, and `T` is a private class with a getter called `x`, then a client can access `T.x` via `var g = f; g = (t) { print(t.x); }`. This lint can be suppressed either with an `ignore` comment, or by marking the referenced type with `@AnalyzerPublicApi(...)`. The advantage of marking the referenced type with `@AnalyzerPublicApi(...)` is that it causes the members of referenced type to be checked by this lint. analyzerPublicApiExperimentalInconsistency: type: lint parameters: String types: "list of types, separated by `, `" problemMessage: "Element makes use of experimental type(s), but is not itself marked with `@experimental`: #types." hasPublishedDocs: false state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." comment: |- Lint issued if an element in the analyzer public API makes use of a type that's annotated `@experimental`, but the element itself is not annotated `@experimental`. The reason this is a problem is that it makes it possible for analyzer clients to implicitly reference analyzer experimental types. This can happen in many ways; here are some examples: - If `C` is a non-experimental public API class that implements `B`, and `B` is an experimental public API class with a getter called `x`, then a client can access `B.x` via `C`. - If `f` has return type `T`, and `T` is an experimental public API class with a getter called `x`, then a client can access `T.x` via `f().x`. - If `f` has type `void Function(T)`, and `T` is an experimental public API class with a getter called `x`, then a client can access `T.x` via `var g = f; g = (t) { print(t.x); }`. analyzerPublicApiExportsNonPublicName: type: lint parameters: String elements: "List of elements, separated by `, `" problemMessage: "Export directive exports element(s) that are not part of the analyzer public API: #elements." hasPublishedDocs: false state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." comment: |- Lint issued if a file in the analyzer public API contains an `export` directive that exports a name that's not part of the analyzer public API. This lint can be suppressed either with an `ignore` comment, or by marking the exported declaration with `@AnalyzerPublicApi(...)`. The advantage of marking the exported declaration with `@AnalyzerPublicApi(...)` is that it causes the members of the exported declaration to be checked by this lint. analyzerPublicApiImplInPublicApi: type: lint parameters: none problemMessage: 'Declarations in the analyzer public API should not end in "Impl".' hasPublishedDocs: false state: internal: "3.10" categories: [publicInterface] deprecatedDetails: "For internal use only." comment: |- Lint issued if a top level declaration in the analyzer public API has a name ending in `Impl`. Such declarations are not meant to be members of the analyzer public API, so if they are either declared outside of `package:analyzer/src`, or marked with `@AnalyzerPublicApi(...)`, that is almost certainly a mistake. annotateOverrides: type: lint parameters: Object p0: undocumented problemMessage: "The member '#p0' 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() {} } ``` annotateRedeclares: type: lint parameters: Object p0: undocumented problemMessage: "The member '#p0' is redeclaring but isn't annotated with '@redeclare'." correctionMessage: "Try adding the '@redeclare' annotation." state: experimental: "3.2" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when an extension type member redeclares a member from an implemented interface without the `@redeclare` annotation. #### Example The following code produces this diagnostic because the `f` method in the extension type E redeclares the `f` method from `C` without the `@redeclare` annotation: ```dart class C { void f() { } } extension type E(C c) implements C { void [!f!]() { } } ``` #### Common fixes Add the `@redeclare` annotation to make the redeclaration explicit: ```dart import 'package:meta/meta.dart'; class C { void f() { } } extension type E(C c) implements C { @redeclare void f() { } } ``` 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() { ... } } ``` asyncReturnWithNoAwait: type: lint parameters: none problemMessage: "Returning a 'Future' without 'await'." correctionMessage: "Try adding an 'await' or making the body non-async." state: stable: "3.13" categories: [errorProne] hasPublishedDocs: false documentation: |- #### Description The analyzer produces this diagnostic when a `Future` is returned from an `async` function without using `await`. Returning an unawaited `Future` from an `async` function means any exception thrown by the `Future` might not propagate as expected. Having the exception thrown at the `await` site helps identify the source of the exception and makes it easier to debug. #### Example The following code produces this diagnostic because it returns the `Future` from `futureString` without using `await`: ```dart Future futureString(Future value) async { [!return!] value; } ``` #### Common fixes Add `await` before the returned `Future`: ```dart Future futureString(Future value) async { return await value; } ``` If you don't need to use `await`, then remove `async` from the function body: ```dart Future futureString(Future value) { return value; } ``` deprecatedDetails: |- **DO** use `await` when returning a `Future` from an `async` function. **BAD:** ```dart Future futureString(Future value) async { return value; } Future futureInt(Future value) async => value; ``` **GOOD:** ```dart Future futureString(Future value) async { return await value; } Future futureInt(Future value) => value; ``` avoidAnnotatingWithDynamic: type: lint parameters: none problemMessage: "Unnecessary 'dynamic' type annotation." correctionMessage: "Try removing the type 'dynamic'." state: stable: "2.0" categories: [brevity, style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a parameter has an explicit `dynamic` type annotation. Because `dynamic` is the default type for parameters without a type annotation, the annotation is unnecessary. #### Example The following code produces this diagnostic because the parameter `p` is explicitly annotated with `dynamic`: ```dart void f([!dynamic p!]) {} ``` #### Common fixes Remove the `dynamic` type annotation: ```dart void f(p) {} ``` 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; } ``` avoidAs: type: lint parameters: none 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; ``` avoidBoolLiteralsInConditionalExpressions: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when a conditional expression uses a boolean literal, and both branches are booleans. You can simplify these expressions using `&&` or `||`. #### Examples The following code produces this diagnostic because the then expression is the `bool` literal `true`: ```dart bool f(bool a, bool b) => [!a ? true : b!]; ``` The following code produces this diagnostic because the else expression is the `bool` literal `false`: ```dart bool f(bool a, bool b) => [!a ? b : false!]; ``` #### Common fixes Replace the conditional expression with the equivalent logical expression. If the then expression is a boolean literal, replace it with one of the following: ```dart bool f(bool a, bool b) => a || b; // replaces: a ? true : b bool g(bool a, bool b) => !a && b; // replaces: a ? false : b ``` If the else expression is a boolean literal, replace it with one of the following: ```dart bool f(bool a, bool b) => !a || b; // replaces: a ? b : true bool g(bool a, bool b) => a && b; // replaces: a ? b : 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 ``` avoidCatchesWithoutOnClauses: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when a `catch` clause lacks an `on` clause to specify the exception type. Catching all exceptions can mask unexpected errors and make debugging more difficult. #### Example The following code produces this diagnostic because the `catch` clause has no `on` clause to specify the exception type: ```dart void f() { try { int.parse('?'); } [!catch!] (e) { print(e); } } ``` #### Common fixes Add an `on` clause to specify the type of exception to catch: ```dart void f() { try { int.parse('?'); } on FormatException catch (e) { print(e); } } ``` 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." avoidCatchingErrorsClass: type: lint parameters: none sharedName: avoidCatchingErrors 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); } ``` avoidCatchingErrorsSubclass: type: lint parameters: Object p0: undocumented sharedName: avoidCatchingErrors problemMessage: "The type '#p0' should not be caught because it is a subclass of 'Error'." correctionMessage: "Try removing the catch or catching an 'Exception' instead." hasPublishedDocs: false avoidClassesWithOnlyStaticMembers: type: lint parameters: none 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 dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } } class _Favorites { static const mammal = 'weasel'; } ``` **GOOD:** ```dart DateTime mostRecent(List dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } const _favoriteMammal = 'weasel'; ``` avoidDoubleAndIntChecks: type: lint parameters: none problemMessage: "Explicit check for double or int." correctionMessage: "Try removing the check." state: stable: "2.0" categories: [errorProne, web] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when an `if` statement tests the type of a variable with `is double` and the following `else if` tests the same variable with `is int`. When compiled to JavaScript, both `int` and `double` values are represented as JavaScript `Number` values. Because every `int` value also satisfies the `is double` check, the `is int` branch is unreachable. To learn more about how Dart represents numbers on different platforms, including when compiled to JavaScript, check out [Numbers in Dart](https://dart.dev/resources/language/number-representation). #### Example The following code produces this diagnostic because `x` is type tested with `is double` and then `is int`, which makes the `is int` branch unreachable when compiled to JavaScript: ```dart void f(Object x) { if (x is double) { print('double'); } else if ([!x is int!]) { print('int'); } } ``` #### Common fixes If the distinction between `int` and `double` isn't meaningful, then check if the type is `num` instead: ```dart void f(Object x) { if (x is num) { print('num'); } } ``` If both branches are needed and it's ok for integer `double` values (such as `3.0`) to take the `is int` branch, then check `is int` first. This ensures that integer values take the `is int` branch on all platforms: ```dart void f(Object x) { if (x is int) { print('int'); } else if (x is double) { print('double'); } } ``` 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 { ... } } ``` avoidDynamicCalls: type: lint parameters: none 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(); } 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(); } void inferredType(SomeWrapper wrapper) { var object = wrapper.doSomething(); object.foo(); } void functionTypeWithParameters(Function() function) { function(); } ``` avoidEmptyElse: type: lint parameters: none 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'); ``` avoidEqualsAndHashCodeOnMutableClasses: type: lint parameters: Object p0: undocumented problemMessage: "The method '#p0' 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; } ``` avoidEscapingInnerQuotes: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "Unnecessary escape of '#p0'." correctionMessage: "Try changing the outer quotes to '#p1'." 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"; ``` avoidFieldInitializersInConstClasses: type: lint parameters: none 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(); } ``` avoidFinalParameters: type: lint parameters: none problemMessage: "Parameters should not be marked as 'final'." correctionMessage: "Try removing the keyword 'final'." state: stable: "2.16" categories: [style] hasPublishedDocs: true documentation: |- NOTE: This rule is removed in Dart 3.13.0; it is no longer functional. #### Description The analyzer produces this diagnostic when a parameter declaration is marked with the `final` keyword. #### Examples The following code produces this diagnostic because the parameter `a` is marked as `final`: ```dart // @dart=3.12 void f([!final!] String a) { print(a); } ``` The following code produces this diagnostic because the closure parameter `a` is marked as `final`: ```dart // @dart=3.12 var f = ([!final!] int a) => print(a); ``` #### Common fixes Remove the `final` keyword from the parameter declaration: ```dart void f(String a) { print(a); } ``` ```dart var f = (int a) => print(a); ``` 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 ``` avoidFunctionLiteralsInForeachCalls: type: lint parameters: none 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 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 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 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) { ... } ``` avoidFutureorVoid: type: lint parameters: none problemMessage: "Don't use the type 'FutureOr'." correctionMessage: "Try using 'Future?' or 'void'." state: experimental: "3.6" categories: [errorProne, unintentional] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when the type `FutureOr` is used as the type of a result (to be precise: it is used in a position that isn't contravariant). The type `FutureOr` is problematic because it may appear to encode that a result is either a `Future`, 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` (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!] m() => null; ``` #### Common fixes A replacement for the type `FutureOr` which is often useful is `Future?`. This type encodes that a result is either a `Future` 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?` as a replacement for the type `FutureOr`, 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` by the type `void`. deprecatedDetails: |- **AVOID** using `FutureOr` as the type of a result. This type is problematic because it may appear to encode that a result is either a `Future`, 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` (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` which is often useful is `Future?`. This type encodes that the result is either a `Future` 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?` as a replacement for the type `FutureOr`, 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` by the type `void`. **BAD:** ```dart FutureOr m() {...} ``` **GOOD:** ```dart Future? m() {...} ``` **This rule is experimental.** It is being evaluated, and it might be changed or removed. Feedback on its behavior is welcome! The primary relevant issue is [dart-lang/sdk#59292](https://github.com/dart-lang/sdk/issues/59232). avoidImplementingValueTypes: type: lint parameters: none 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); }); } ``` avoidInitToNull: type: lint parameters: none 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 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 cart) { Item? bestItem; for (final item in cart) { if (bestItem == null || item.price < bestItem.price) { bestItem = item; } } return bestItem; } ``` avoidJsRoundedInts: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when an `int` literal's value can't be represented exactly as a JavaScript `Number`. When Dart code is compiled to JavaScript, integers whose values fall outside the range `-(2^53 - 1)` to `2^53 - 1` might be rounded to the nearest representable value. This silently changes the literal's value on the web. To learn more about how Dart represents numbers on different platforms, including when compiled to JavaScript, check out [Numbers in Dart](https://dart.dev/resources/language/number-representation). #### Example The following code produces this diagnostic because the literal `9007199254740993` (2^53 + 1) can't be represented exactly as a JavaScript `Number` is rounded to `9007199254740992` at run time when compiled to JavaScript: ```dart final i = [!9007199254740993!]; ``` #### Common fixes If the value needs to be exact on all platforms, including when compiled to JavaScript, then use a `BigInt` to represent it: ```dart final i = BigInt.parse('9007199254740993'); ``` 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'); ``` avoidMultipleDeclarationsPerLine: type: lint parameters: none 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; ``` avoidNullChecksInEqualityOperators: type: lint parameters: none problemMessage: "Unnecessary null comparison in implementation of '=='." correctionMessage: "Try removing the comparison." state: stable: "2.0" deprecated: "3.11" 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; } ``` avoidPositionalBooleanParameters: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when a non-overriding, public function has a positional parameter of type `bool`. Positional boolean parameters can cause ambiguity when the function is invoked because the function of the specified boolean value might not be clear from the value alone. Named parameters make their intent explicit. #### Example The following code produces this diagnostic because the function `f` has a positional parameter with a type of `bool`: ```dart void f([!bool b!]) {} ``` #### Common fixes Convert the positional parameter to a named parameter: ```dart void f({bool b = 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); ``` avoidPrint: type: lint parameters: none 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'); } ... } ``` avoidPrivateTypedefFunctions: type: lint parameters: none 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" deprecated: "3.13" categories: [style] hasPublishedDocs: false deprecatedDetails: |- **NOTE:** As a private typedef can make some code more readable, this lint rule has been deprecated as of Dart 3.13 and is set to be removed in a future release of the Dart SDK. Remove all inclusions of this lint from your analysis options. If you wish to keep enforcing it, consider implementing the rule with an [analyzer plugin](https://dart.dev/tools/analyzer-plugins). **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); ``` avoidRedundantArgumentValues: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when an argument is passed to an optional parameter of a function, but the argument's value is the same as the parameter's default value. The duplicative argument can often be removed without changing the behavior of the code. When invoking methods, because the redundancy check is based on the static type of the invocation target, there can be false positives when a method override changes a parameter's default value. If the static type has one default value specified but the actual runtime type has another, the diagnostic might not be accurate. #### Examples The following code produces this diagnostic because the named argument `b` has the same value as its default value of `true`: ```dart void g({bool b = true}) {} void f() { g(b: [!true!]); } ``` The following code produces this diagnostic because the positional argument `1` has the same value as the default value of the second parameter of `g`: ```dart void g([int? a, int? b = 1]) {} void f() { g(0, [!1!]); } ``` #### Common fixes Remove the redundant argument from the invocation: ```dart void g({bool b = true}) {} void f() { g(); } ``` ```dart void g([int? a, int? b = 1]) {} void f() { g(0); } ``` 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(); } ``` avoidRelativeLibImports: type: lint parameters: none 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'; ... ``` avoidRenamingMethodParameters: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "The parameter name '#p0' doesn't match the name '#p1' in the overridden method." correctionMessage: "Try changing the name to '#p1'." 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); } ``` avoidReturnTypesOnSetters: type: lint parameters: none 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); ``` avoidReturningNull: type: lint parameters: none 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; ``` avoidReturningNullForFuture: type: lint parameters: none 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. avoidReturningNullForVoidFromFunction: type: lint parameters: none sharedName: avoidReturningNullForVoid 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 f2() async { return null; } ``` **GOOD:** ```dart void f1() { return; } Future f2() async { return; } ``` avoidReturningNullForVoidFromMethod: type: lint parameters: none sharedName: avoidReturningNullForVoid problemMessage: "Don't return 'null' from a method with a return type of 'void'." correctionMessage: "Try removing the 'null'." hasPublishedDocs: true avoidReturningThis: type: lint parameters: none 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'); ``` avoidSettersWithoutGetters: type: lint parameters: none 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; } } ``` avoidShadowingTypeParameters: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "The type parameter '#p0' shadows a type parameter from the enclosing #p1." 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 { void m<[!T!]>() {} } ``` #### Common fixes Rename one of the type parameters: ```dart class C { void m() {} } ``` deprecatedDetails: |- **AVOID** shadowing type parameters. **BAD:** ```dart class A { void fn() {} } ``` **GOOD:** ```dart class A { void fn() {} } ``` avoidSingleCascadeInExpressionStatements: type: lint parameters: Object p0: undocumented problemMessage: "Unnecessary cascade expression." correctionMessage: "Try using the operator '#p0'." 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(); ``` avoidSlowAsyncIo: type: lint parameters: none 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 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 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 someFunction() async { var file = File('/path/to/my/file'); var now = DateTime.now(); if (file.lastModifiedSync().isBefore(now)) print('before'); // OK } ``` avoidTypeToString: type: lint parameters: none 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 .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); } ``` avoidTypesAsParameterNamesFormalParameter: type: lint parameters: Object p0: undocumented sharedName: avoidTypesAsParameterNames problemMessage: "The parameter name '#p0' 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 avoidTypesAsParameterNamesTypeParameter: type: lint parameters: Object p0: undocumented sharedName: avoidTypesAsParameterNames problemMessage: "The type parameter name '#p0' 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)); ``` avoidTypesOnClosureParameters: type: lint parameters: none problemMessage: "Unnecessary type annotation on a function expression parameter." correctionMessage: "Try removing the type annotation." state: stable: "2.0" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a parameter of a function expression (closure) has an explicit type annotation, and the closure is in a context where the parameter type can be inferred. #### Example The following code produces this diagnostic because the parameter `x` in the closure passed to `l.map` has an explicit type annotation of `int`, which is unnecessary because the type can be inferred from the list's type: ```dart void f(List l) { l.map(([!int!] x) => x.isEven); } ``` #### Common fixes Remove the type annotation: ```dart void f(List l) { l.map((x) => x.isEven); } ``` 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); ``` avoidUnnecessaryContainers: type: lint parameters: none 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: [ const MyLogo(), const Expanded( child: Text('...'), ), ], ) ); } ``` **GOOD:** ```dart Widget buildRow() { return Row( children: [ const MyLogo(), const Expanded( child: Text('...'), ), ], ); } ``` avoidUnstableFinalFields: type: lint parameters: none state: experimental: "3.3" removed: "3.3" hasPublishedDocs: false deprecatedDetails: |- This rule has been removed. avoidUnusedConstructorParameters: type: lint parameters: Object p0: undocumented problemMessage: "The parameter '#p0' 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: true documentation: |- #### Description The analyzer produces this diagnostic when a constructor parameter isn't used in the constructor body or initializer list, and isn't an initializing formal parameter (`this.x`), a super parameter (`super.x`), or a declaring parameter. Parameters that are only declared but never referenced are likely unintentional and add unnecessary complexity to the constructor. #### Examples The following code produces this diagnostic because the parameter `x` isn't used in the constructor: ```dart class C { C([!int x!]); } ``` The following code produces this diagnostic because the parameter `c` isn't used in the constructor initializer list: ```dart class C { int x; C(int a, int b, [!int c!]): x = a + b { print(x); } } ``` #### Common fixes If the parameter is meant to initialize a field, then use an initializing formal parameter: ```dart class C { int x; C(this.x); } ``` If the parameter isn't needed, then remove it: ```dart class C { int x; C(int a, int b): x = a + b { print(x); } } ``` 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; } } ``` avoidVoidAsync: type: lint parameters: none 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`. When declaring an `async` method or function which does not return a value, declare that it returns `Future` and not just `void`. **BAD:** ```dart void f() async {} void f2() async => null; ``` **GOOD:** ```dart Future f() async {} Future 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 f() async {} void main() async { await f(); } ``` avoidWebLibrariesInFlutter: type: lint parameters: none 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 %ignore=unused_import 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 %ignore=unused_import 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. awaitOnlyFutures: type: lint parameters: Object p0: undocumented problemMessage: "Uses 'await' on an instance of '#p0', 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`, `FutureOr`, `Future?`, `FutureOr?` 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`, `FutureOr`, `Future?`, `FutureOr?` 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); } ``` camelCaseExtensions: type: lint parameters: Object p0: undocumented problemMessage: "The extension name '#p0' 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 on List { // ... } extension SmartIterable on Iterable { // ... } ``` camelCaseTypes: type: lint parameters: Object p0: undocumented problemMessage: "The type name '#p0' 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); ``` cancelSubscriptions: type: lint parameters: none 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. cascadeInvocations: type: lint parameters: none 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(); ``` castNullableToNonNullable: type: lint parameters: none 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!; ``` closeSinks: type: lint parameters: none 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. collectionMethodsUnrelatedType: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "The argument type '#p0' isn't related to '#p1'." 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.contains` should be related to `E` - an argument to `List.remove` should be related to `E` - an argument to `Map.containsKey` should be related to `K` - an argument to `Map.containsValue` should be related to `V` - an argument to `Map.remove` should be related to `K` - an argument to `Map.[]` should be related to `K` - an argument to `Queue.remove` should be related to `E` - an argument to `Set.lookup` should be related to `E` - an argument to `Set.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 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 l) => l.contains(1); ``` If the argument type is correct, then change the element type: ```dart bool f(List 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.contains` should be related to `E` * an argument to `List.remove` should be related to `E` * an argument to `Map.containsKey` should be related to `K` * an argument to `Map.containsValue` should be related to `V` * an argument to `Map.remove` should be related to `K` * an argument to `Map.[]` should be related to `K` * an argument to `Queue.remove` should be related to `E` * an argument to `Set.lookup` should be related to `E` * an argument to `Set.remove` should be related to `E` **BAD:** ```dart void someFunction() { var list = []; if (list.contains('1')) print('someFunction'); // LINT } ``` **BAD:** ```dart void someFunction() { var set = {}; set.remove('1'); // LINT } ``` **GOOD:** ```dart void someFunction() { var list = []; if (list.contains(1)) print('someFunction'); // OK } ``` **GOOD:** ```dart void someFunction() { var set = {}; set.remove(1); // OK } ``` combinatorsOrdering: type: lint parameters: none 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; ``` commentReferences: type: lint parameters: none 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. conditionalUriDoesNotExist: type: lint parameters: Object p0: undocumented problemMessage: "The target of the conditional URI '#p0' 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'; ``` constantIdentifierNames: type: lint parameters: Object p0: undocumented problemMessage: "The constant name '#p0' 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(); } ``` controlFlowInFinally: type: lint parameters: Object p0: undocumented problemMessage: "Use of '#p0' 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 void f(void Function() g) { try { g(); } catch (e) { print(e); } finally { [!return;!] } } ``` #### Common fixes If the statement isn't needed, then remove the statement, and remove the `finally` clause if the block is empty: ```dart void f(void Function() g) { try { g(); } catch (e) { print(e); } } ``` If the statement is needed, then move the statement outside the `finally` block: ```dart void f(void Function() g) { try { g(); } catch (e) { print(e); } return; } ``` 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; } } ``` curlyBracesInFlowControlStructures: type: lint parameters: Object p0: undocumented problemMessage: "Statements in #p0 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; } ``` danglingLibraryDocComments: type: lint parameters: none 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. dependOnReferencedPackages: type: lint parameters: Object p0: undocumented problemMessage: "The imported package '#p0' isn't a dependency of the importing package." correctionMessage: "Try adding a dependency for '#p0' 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 %ignore=uri_does_not_exist 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 ``` deprecatedConsistencyConstructor: type: lint parameters: none sharedName: deprecatedConsistency 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}); } ``` deprecatedConsistencyField: type: lint parameters: none sharedName: deprecatedConsistency problemMessage: "Fields that are initialized by a deprecated parameter should be deprecated." correctionMessage: "Try marking the field as deprecated." hasPublishedDocs: false deprecatedConsistencyParameter: type: lint parameters: none sharedName: deprecatedConsistency problemMessage: "Parameters that initialize a deprecated field should be deprecated." correctionMessage: "Try marking the parameter as deprecated." hasPublishedDocs: false deprecatedMemberUseFromSamePackageWithMessage: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: deprecatedMemberUseFromSamePackage problemMessage: "'#p0' is deprecated and shouldn't be used. #p1" 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; } ``` deprecatedMemberUseFromSamePackageWithoutMessage: type: lint parameters: Object p0: undocumented sharedName: deprecatedMemberUseFromSamePackage problemMessage: "'#p0' 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 diagnosticDescribeAllProperties: type: lint parameters: none 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/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('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/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('p1', p1)); properties.add(DiagnosticsProperty('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('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('absorbing', absorbing)); properties.add(DiagnosticsProperty('ignoringSemantics', ignoringSemantics)); } } ``` directivesOrderingAlphabetical: type: lint parameters: none sharedName: directivesOrdering 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 ``` directivesOrderingDart: type: lint parameters: Object p0: undocumented sharedName: directivesOrdering problemMessage: "Place 'dart:' #p0 before other #p0." correctionMessage: "Try sorting the directives." hasPublishedDocs: false directivesOrderingExports: type: lint parameters: none sharedName: directivesOrdering problemMessage: "Specify exports in a separate section after all imports." correctionMessage: "Try sorting the directives." hasPublishedDocs: false directivesOrderingPackageBeforeRelative: type: lint parameters: Object p0: undocumented sharedName: directivesOrdering problemMessage: "Place 'package:' #p0 before relative #p0." correctionMessage: "Try sorting the directives." hasPublishedDocs: false discardedFutures: type: lint parameters: none 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 deleteDir(String path) async {} Future createDir(String path) async {} ``` **GOOD:** ```dart Future recreateDir(String path) async { await deleteDir(path); await createDir(path); } Future deleteDir(String path) async {} Future createDir(String path) async {} ``` doNotUseEnvironment: type: lint parameters: none 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; ``` documentIgnores: type: lint parameters: none 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; ``` emptyCatches: type: lint parameters: none 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); } ``` emptyConstructorBodies: type: lint parameters: none 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); } ``` emptyContainerBodies: type: lint parameters: String containerKind: The kind of the container, such as 'class' or 'enum'. problemMessage: "Empty #containerKind bodies should be written using a ';' rather than '{}'." correctionMessage: "Try replacing the #containerKind body with ';'." state: experimental: "3.13" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Use `;` instead of `{}` for empty container (class, enum, etc.) bodies. emptyStatements: type: lint parameters: none 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(); ``` enableNullSafety: type: lint parameters: none 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() { } ``` eolAtEndOfFile: type: lint parameters: none 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 ``` eraseDartTypeExtensionTypes: # TODO(nshahan): Update. type: lint parameters: none 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 deprecatedDetails: |- Experimental WIP lint to help ensure `DartType` accesses are safe in the dev_compiler. **For internal use only.** exhaustiveCases: type: lint parameters: Object p0: undocumented problemMessage: "Missing case clauses for some constants in '#p0'." 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; } } ``` fileNames: type: lint parameters: Object p0: undocumented problemMessage: "The file name '#p0' 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. flutterStyleTodos: type: lint parameters: none 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. ``` hashAndEquals: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "Missing a corresponding override of '#p0'." correctionMessage: "Try overriding '#p0' or removing '#p1'." 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; } ``` implementationImports: type: lint parameters: none 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 %ignore=uri_does_not_exist 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 %ignore=unused_import 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'; ``` implicitCallTearoffs: type: lint parameters: none 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); ``` implicitReopen: type: lint parameters: Object p0: undocumented Object p1: undocumented Object p2: undocumented Object p3: undocumented problemMessage: "The #p0 '#p1' reopens '#p2' because it is not marked '#p3'." correctionMessage: "Try marking '#p1' '#p3' 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 {} ``` initializeInFieldDeclaration: type: lint parameters: none problemMessage: "Field should be initialized in the field declaration." correctionMessage: "Try initializing the field where it's declared." state: experimental: "3.13" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Initialize fields where they're declared when possible. invalidCasePatterns: type: lint parameters: none 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 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: ... } ``` invalidRuntimeCheckWithJsInteropTypesCatchClauseJsInteropType: type: lint parameters: Object p0: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Catch clause with type '#p0' checks whether the caught value is a JS interop type, which might not be platform-consistent." correctionMessage: "Remove the type in the catch clause and try using 'isA' from 'dart:js_interop' within the catch block to check if the value is a JS interop type." hasPublishedDocs: false invalidRuntimeCheckWithJsInteropTypesDartAsJs: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Cast from '#p0' to '#p1' 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 l) => [!l is List!]; ``` 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(); ``` 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 lo, List 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; // LINT, JS interop type argument and Dart type argument // are incompatible ls is List; // LINT, Dart type argument and JS interop type argument // are incompatible lo is List; // LINT, comparing JS interop type argument with // different JS interop type argument lo is List; // 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 l, JSObject o, HTMLElement e, Object obj) { a.isA; // OK, uses JS interop to check it is a JS string l[0].isA; // OK, uses JS interop to check it is a JS string o.isA(); // OK, uses JS interop to check `o` is an HTMLElement e.isA(); // OK, uses JS interop to check `e` is an // HTMLDivElement obj.isA(); // OK, uses JS interop to check `obj` is a JSObject } ``` **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 l, List 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; // LINT, casting Dart value with Dart type argument to // Dart type with JS interop type argument lo as List; // LINT, casting Dart value with JS interop type argument // to Dart type with Dart type argument lo as List; // 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 a, List ls, JSObject o, List 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; // OK, JSObject and JSArray are compatible la as List; // OK, JSAny and JSString are compatible (o as Object) as JSObject; // OK, Object is a supertype of JSAny } **DON'T** use a JS interop type in a catch clause. If the code in the try block is expected to throw a JS value, don't use a type at all in the catch clause. **BAD:** ```dart @JS() external void throwSomething(); extension type JSError(JSObject _) implements JSObject {} void compute() { try { throwSomething(); } on JSString catch (e) { // LINT, checking that the caught value is a JS type print('string $e'); } on JSError catch (e) { // LINT, checking that the caught value is a JS // interop type print('JSError: $e'); } on List catch (e) { // LINT, type contains a JS interop type print('List: $e'); } on bool catch (e) { // NO LINT, but may be platform-dependent print('bool: $e'); } } ``` Use `isA` from `dart:js_interop` to check if a value is a JS interop type within the catch block. If the code in the try block is expected to throw a JS value, leave the catch clause untyped and check for all JS interop types first using `isA` before checking for Dart types. **GOOD:** ```dart @JS() external void throwSomething(); extension type JSError(JSObject _) implements JSObject {} void compute() { try { throwSomething(); } catch (e) { if (e.isA()) { // OK, uses JS interop to check it is a JS string print('string: $e'); } else if (e.isA()) { // OK, uses JS interop to check it is a JSError print('Error: $e'); } else if (e.isA()) { // OK, checks all interop types before Dart types print('JSAny: $e'); } else if (e is bool) { // OK, `e` can't be a JS value print('boolean: $e'); } } } ``` invalidRuntimeCheckWithJsInteropTypesDartIsJs: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Runtime check between '#p0' and '#p1' checks whether a Dart value is a JS interop type, which might not be platform-consistent." correctionMessage: "Try using 'isA' from 'dart:js_interop' to check if the Dart value is a JS interop type." hasPublishedDocs: false invalidRuntimeCheckWithJsInteropTypesJsAsDart: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Cast from '#p0' to '#p1' 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 invalidRuntimeCheckWithJsInteropTypesJsAsIncompatibleJs: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Cast from '#p0' to '#p1' casts a JS interop value to an incompatible JS interop type, which might not be platform-consistent." hasPublishedDocs: false invalidRuntimeCheckWithJsInteropTypesJsIsDart: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Runtime check between '#p0' and '#p1' checks whether a JS interop value is a Dart type, which might not be platform-consistent." hasPublishedDocs: false invalidRuntimeCheckWithJsInteropTypesJsIsInconsistentJs: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Runtime check between '#p0' and '#p1' 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 invalidRuntimeCheckWithJsInteropTypesJsIsUnrelatedJs: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: invalidRuntimeCheckWithJsInteropTypes problemMessage: "Runtime check between '#p0' and '#p1' 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 invariantBooleans: type: lint parameters: none 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 } ``` iterableContainsUnrelatedType: type: lint parameters: none 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 = []; if (list.contains('1')) print('someFunction'); // LINT } ``` **BAD:** ```dart void someFunction3() { List list = []; if (list.contains('1')) print('someFunction3'); // LINT } ``` **BAD:** ```dart void someFunction8() { List list = []; DerivedClass3 instance; if (list.contains(instance)) print('someFunction8'); // LINT } ``` **BAD:** ```dart abstract class SomeIterable implements Iterable {} abstract class MyClass implements SomeIterable { 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 = []; if (list.contains(1)) print('someFunction1'); // OK } ``` **GOOD:** ```dart void someFunction4() { List list = []; if (list.contains(1)) print('someFunction4'); // OK } ``` **GOOD:** ```dart void someFunction5() { List list = []; DerivedClass1 instance; if (list.contains(instance)) print('someFunction5'); // OK } abstract class ClassBase {} class DerivedClass1 extends ClassBase {} ``` **GOOD:** ```dart void someFunction6() { List list = []; 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 list = []; DerivedClass3 instance; if (list.contains(instance)) print('someFunction7'); // OK } abstract class ClassBase {} abstract class Mixin {} class DerivedClass3 extends ClassBase implements Mixin {} ``` joinReturnWithAssignment: type: lint parameters: none 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(); } ``` leadingNewlinesInMultilineStrings: type: lint parameters: none 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.'''; ``` libraryAnnotations: type: lint parameters: none 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. libraryNames: type: lint parameters: Object p0: undocumented problemMessage: "The library name '#p0' 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. libraryPrefixes: type: lint parameters: Object p0: undocumented problemMessage: "The prefix '#p0' 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 %ignore=unused_import import 'package:ffi/ffi.dart' as [!ffiSupport!]; ``` #### Common fixes Convert the prefix to use the lower_case_with_underscores naming convention: ```dart %ignore=unused_import 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; ``` libraryPrivateTypesInPublicApi: type: lint parameters: none 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 %ignore=unused_element 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) { ... } ``` linesLongerThan80Chars: type: lint parameters: none 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. listRemoveUnrelatedType: type: lint parameters: none 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 = []; if (list.remove('1')) print('someFunction'); // LINT } ``` **BAD:** ```dart void someFunction3() { List list = []; if (list.remove('1')) print('someFunction3'); // LINT } ``` **BAD:** ```dart void someFunction8() { List list = []; DerivedClass3 instance; if (list.remove(instance)) print('someFunction8'); // LINT } ``` **BAD:** ```dart abstract class SomeList implements List {} abstract class MyClass implements SomeList { 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 = []; if (list.remove(1)) print('someFunction1'); // OK } ``` **GOOD:** ```dart void someFunction4() { List list = []; if (list.remove(1)) print('someFunction4'); // OK } ``` **GOOD:** ```dart void someFunction5() { List list = []; DerivedClass1 instance; if (list.remove(instance)) print('someFunction5'); // OK } abstract class ClassBase {} class DerivedClass1 extends ClassBase {} ``` **GOOD:** ```dart void someFunction6() { List list = []; 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 list = []; DerivedClass3 instance; if (list.remove(instance)) print('someFunction7'); // OK } abstract class ClassBase {} abstract class Mixin {} class DerivedClass3 extends ClassBase implements Mixin {} ``` literalOnlyBooleanExpressions: type: lint parameters: none 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. } } ``` matchingSuperParameters: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "The super parameter named '#p0'' does not share the same name as the corresponding parameter in the super constructor, '#p1'." 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, ); } ``` missingCodeBlockLanguageInDocComment: type: lint parameters: none 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 {} ``` missingWhitespaceBetweenAdjacentStrings: type: lint parameters: none 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'; ``` noAdjacentStringsInList: type: lint parameters: none 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 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 list = ['a', 'b', 'c']; ``` If the two strings are intended to be a single concatenated string, then either manually merge the strings: ```dart List list = ['ab', 'c']; ``` Or use the `+` operator to concatenate the strings: ```dart List list = ['a' + 'b', 'c']; ``` deprecatedDetails: |- **DON'T** use adjacent strings in a list. This can indicate a forgotten comma. **BAD:** ```dart List list = [ 'a' 'b', 'c', ]; ``` **GOOD:** ```dart List list = [ 'a' + 'b', 'c', ]; ``` noDefaultCases: type: lint parameters: none 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; ``` noDuplicateCaseValues: type: lint parameters: Object p0: undocumented Object p1: undocumented problemMessage: "The value of the case clause ('#p0') is equal to the value of an earlier case clause ('#p1')." 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. noDynamicCasts: type: lint parameters: none problemMessage: "Implicit cast from 'dynamic'." correctionMessage: "Try adding an explicit cast or changing the target type." state: stable: "3.13" categories: [errorProne] hasPublishedDocs: false deprecatedDetails: |- **DO** avoid implicit casts from `dynamic`. Assigning a `dynamic`-typed expression to a non-`dynamic`, non-`Object?` target is a form of implicit casting. It is better to make such a cast explicit, so that it is visible to developers. **BAD:** ```dart void f(dynamic x) { int y = x; } ``` **GOOD:** ```dart void f(dynamic x) { int y = x as int; } ``` noLeadingUnderscoresForLibraryPrefixes: type: lint parameters: Object p0: undocumented problemMessage: "The library prefix '#p0' 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; ``` noLeadingUnderscoresForLocalIdentifiers: type: lint parameters: Object p0: undocumented problemMessage: "The local variable '#p0' 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')); ``` noLiteralBoolComparisons: type: lint parameters: none 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!'); } ``` noLogicInCreateState: type: lint parameters: none 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); Widget build(BuildContext context) => MyWidget(); } ``` #### 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(); Widget build(BuildContext context) => MyWidget(); } ``` 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(); } } ``` noRawTypes: type: lint parameters: Type type: the name of the generic type problemMessage: "The generic type '#type' should have explicit type arguments but doesn't." correctionMessage: "Use explicit type arguments for '#type'." state: stable: "3.13" categories: [errorProne] hasPublishedDocs: false documentation: |- #### Description The analyzer produces this diagnostic when a generic type is used without explicit type arguments, meaning it is a raw type. #### Example The following code produces this diagnostic because the generic class `C` is used without a type argument: ```dart class C {} [!C!] c = C(); ``` #### Common fixes Provide explicit type arguments: ```dart class C {} C c = C(); ``` deprecatedDetails: |- **DON'T** use raw types. A raw type is a type annotation for a generic type which omits type arguments. Developers may mistakenly believe that the type arguments are inferred, but in fact each type parameter's bound is used, which can lead to lost type information. **BAD:** ```dart List list = [1, 2, 3]; ``` **GOOD:** ```dart List list = [1, 2, 3]; ``` noRuntimetypeTostring: type: lint parameters: none 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 noSelfAssignments: type: lint parameters: none 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; } } ``` noSoloTests: type: lint parameters: none problemMessage: "Don't commit soloed tests." correctionMessage: "Try removing the 'soloTest' annotation or 'solo_' prefix." hasPublishedDocs: true state: internal: "3.10" categories: [errorProne] deprecatedDetails: "For internal use only." noTrailingSpaces: type: lint parameters: none problemMessage: "Don't create string literals with trailing spaces in tests." correctionMessage: 'Try removing the trailing spaces.' hasPublishedDocs: true state: internal: "3.10" categories: [errorProne] deprecatedDetails: "For internal use only." noWildcardVariableUses: type: lint parameters: none 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]; ``` nonConstantIdentifierNames: type: lint parameters: Object p0: undocumented problemMessage: "The variable name '#p0' 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) { // ... } ``` noopPrimitiveOperations: type: lint parameters: none 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' ''; ``` nullCheckOnNullableTypeParameter: type: lint parameters: none 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[!!!]; ``` #### Common fixes Use the type parameter to cast the variable: ```dart T f(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 callback()) { T? result; (() { result = callback(); })(); return result!; } ``` **GOOD:** ```dart T run(T callback()) { T? result; (() { result = callback(); })(); return result as T; } ``` nullClosures: type: lint parameters: none 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); ``` omitLocalVariableTypes: type: lint parameters: none 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> possibleDesserts(Set pantry) { List> desserts = >[]; for (final List recipe in cookbook) { if (pantry.containsAll(recipe)) { desserts.add(recipe); } } return desserts; } ``` **GOOD:** ```dart List> possibleDesserts(Set pantry) { var desserts = >[]; 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; } ``` omitObviousLocalVariableTypes: type: lint parameters: none problemMessage: "Omit the type annotation on a local variable when the type is obvious." correctionMessage: "Try removing the type annotation." state: experimental: "3.6" stable: "3.11" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Don't type annotate initialized local variables when the type is [obvious](https://dart.dev/glossary/obviously-typed). 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](https://dart.dev/glossary/obviously-typed) should be omitted. **BAD:** ```dart List> possibleDesserts(Set pantry) { List> desserts = >[]; for (final List recipe in cookbook) { if (pantry.containsAll(recipe)) { desserts.add(recipe); } } return desserts; } const cookbook = >[....]; ``` **GOOD:** ```dart List> possibleDesserts(Set pantry) { var desserts = >[]; for (final List recipe in cookbook) { if (pantry.containsAll(recipe)) { desserts.add(recipe); } } return desserts; } const cookbook = >[....]; ``` 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; } ``` omitObviousPropertyTypes: type: lint parameters: none problemMessage: "The type annotation isn't needed because it is obvious." correctionMessage: "Try removing the type annotation." state: experimental: "3.7" stable: "3.11" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Don't type annotate initialized top-level or static variables when the type is [obvious](https://dart.dev/glossary/obviously-typed). **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'; } ``` oneMemberAbstracts: type: lint parameters: Object p0: undocumented problemMessage: "Unnecessary use of an abstract class." correctionMessage: "Try making '#p0' a top-level function and removing the class." state: stable: "2.0" deprecated: "3.13" categories: [effectiveDart, languageFeatureUsage, style] hasPublishedDocs: false deprecatedDetails: |- **NOTE:** As one member abstracts are often a stepping stone, this lint rule has been deprecated as of Dart 3.13 and is set to be removed in a future release of the Dart SDK. Remove all inclusions of this lint from your analysis options. If you wish to keep enforcing it, consider implementing the rule with an [analyzer plugin](https://dart.dev/tools/analyzer-plugins). 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); ``` onlyThrowErrors: type: lint parameters: none 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 } ``` overriddenFields: type: lint parameters: Object p0: undocumented problemMessage: "Field overrides a field inherited from '#p0'." 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 } ``` packageApiDocs: type: lint parameters: none 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). packageNames: type: lint parameters: Object p0: undocumented problemMessage: "The package name '#p0' 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. packagePrefixedLibraryNames: type: lint parameters: Object p0: undocumented problemMessage: "The library name is not a dot-separated path prefixed by the package name." correctionMessage: "Try changing the name to '#p0'." 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; ``` parameterAssignments: type: lint parameters: Object p0: undocumented problemMessage: "Invalid assignment to the parameter '#p0'." correctionMessage: "Try using a local variable in place of the parameter." state: stable: "2.0" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a parameter is reassigned within a function body. Reassigning parameters can make it harder to understand what value a parameter holds at any given point in a function. All types of assignments are considered, including: - Direct variable assignments (with `=`). - Null-aware assignments (with `??=`). - Compound assignments (such as with `+=`). - Increment and decrement operators (such as with `++`). - Variable pattern assignments (such as in `var (a, b) = (1, 2);`). There's an exception for a single null-aware assignment (`??=`) at the beginning of a function for nullable parameters that don't have a default value, as this is a common pattern for providing defaults. #### Examples The following code produces this diagnostic because the parameter `x` is reassigned a new value: ```dart void f(int x) { [!x = 4!]; print(x); } ``` The following code produces this diagnostic because the parameter `x` is modified with a postfix increment: ```dart void f(int x) { [!x++!]; } ``` #### Common fixes Introduce a local variable to hold the modified value instead of reassigning the parameter: ```dart void f(int x) { var y = x + 4; print(y); } ``` 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); } } ``` preferAdjacentStringConcatenation: type: lint parameters: none 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.'); ``` preferAssertsInInitializerLists: type: lint parameters: none 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); } ``` preferAssertsWithMessage: type: lint parameters: none 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'); } ``` preferBoolInAsserts: type: lint parameters: none 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; }()); ``` preferCollectionLiterals: type: lint parameters: none 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()!]; ``` #### Common fixes Use the literal representation: ```dart var m = {}; ``` deprecatedDetails: |- **DO** use collection literals when possible. **BAD:** ```dart var addresses = Map(); var uniqueNames = Set(); var ids = LinkedHashSet(); var coordinates = LinkedHashMap(); ``` **GOOD:** ```dart var addresses = {}; var uniqueNames = {}; var ids = {}; var coordinates = {}; ``` **EXCEPTIONS:** When a `LinkedHashSet` or `LinkedHashMap` is expected, a collection literal is not preferred (or allowed). ```dart void main() { LinkedHashSet linkedHashSet = LinkedHashSet.from([1, 2, 3]); // OK LinkedHashMap linkedHashMap = LinkedHashMap(); // OK printSet(LinkedHashSet()); // LINT printHashSet(LinkedHashSet()); // OK printMap(LinkedHashMap()); // LINT printHashMap(LinkedHashMap()); // OK } void printSet(Set ids) => print('$ids!'); void printHashSet(LinkedHashSet ids) => printSet(ids); void printMap(Map map) => print('$map!'); void printHashMap(LinkedHashMap map) => printMap(map); ``` preferConditionalAssignment: type: lint parameters: none 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); } ``` preferConstConstructors: type: lint parameters: none 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); ``` preferConstConstructorsInImmutables: type: lint parameters: none 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); } ``` preferConstDeclarations: type: lint parameters: none 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 []!]; ``` 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 []!]; } ``` 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 []!]; print(v); } ``` #### Common fixes Replace the keyword `final` with `const` and remove `const` from the initializer: ```dart class C { static const f = []; } ``` 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 []; class A { static final o = const []; } ``` **GOOD:** ```dart const o = []; class A { static const o = []; } ``` preferConstLiteralsToCreateImmutables: type: lint parameters: none 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 {}); ``` preferConstructorsOverStaticMethods: type: lint parameters: none 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); } ``` preferContainsAlwaysFalse: # TODO(brianwilkerson): Should be warning rather than lint, # as represents a bug rather than style preference. type: lint parameters: none sharedName: preferContains problemMessage: "Always 'false' because 'indexOf' is always greater than or equal to -1." categories: [style] hasPublishedDocs: false preferContainsAlwaysTrue: # TODO(brianwilkerson): Should be warning rather than lint, # as represents a bug rather than style preference. type: lint parameters: none sharedName: preferContains problemMessage: "Always 'true' because 'indexOf' is always greater than or equal to -1." hasPublishedDocs: false preferContainsUseContains: type: lint parameters: none sharedName: preferContains 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 l, String s) { if ([!l.indexOf(s) < 0!]) { // ... } } ``` #### Common fixes Use `contains` instead, negating the condition when necessary: ```dart void f(List 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...'; ``` preferDoubleQuotes: type: lint parameters: none 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'}"); ``` preferEqualForDefaultValues: type: lint parameters: none 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}) ``` preferExpressionFunctionBodies: type: lint parameters: none 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); ``` preferFinalFields: type: lint parameters: Object p0: undocumented problemMessage: "The private field #p0 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'; } ``` preferFinalInForEachPattern: type: lint parameters: none sharedName: preferFinalInForEach 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 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 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'); } ``` preferFinalInForEachVariable: type: lint parameters: Object p0: undocumented sharedName: preferFinalInForEach problemMessage: "The variable '#p0' should be final." correctionMessage: "Try making the variable final." hasPublishedDocs: false preferFinalLocals: type: lint parameters: none 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); } ``` preferFinalParameters: type: lint parameters: Object p0: undocumented problemMessage: "The parameter '#p0' should be final." correctionMessage: "Try making the parameter final." state: stable: "2.14" deprecated: "3.11" categories: [style] hasPublishedDocs: true documentation: |- NOTE: This rule is removed in Dart 3.13.0; it is no longer functional. #### 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 // @dart=3.12 String f([!String s!]) => s; ``` #### Common fixes Add the modifier `final` to the parameter: ```dart // @dart=3.12 String f(final String s) => s; ``` deprecatedDetails: |- **Note:** This lint rule was deprecated in Dart 3.11 and is set to be removed in a future release of the Dart SDK. Also note that the lint is not applied to code that is opted in to the `primary-constructors` language feature where using `final` for a parameter becomes a compile-time error. If you want to ensure parameters aren't reassigned in function bodies, consider enabling the [`parameter_assignments`](https://dart.dev/lints/parameter_assignments) lint rule instead. **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); } ``` preferForElementsToMapFromiterable: type: lint parameters: none 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 data) { [!Map.fromIterable( data, key: (element) => element, value: (element) => element.length, )!]; } ``` #### Common fixes Use a `for` element to build the map: ```dart void f(Iterable data) { { 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.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 is not required, type is inferred automatically. final pizzaRecipients = { ...studentLeaders, for (var student in classG) if (student.isPassing) student.id: student, }; ``` preferForeach: type: lint parameters: none 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 m) { [!for (final key in m.keys) { print(key); }!] } ``` #### Common fixes Replace the for loop with an invocation of `forEach`: ```dart void f(Map 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. ``` preferFunctionDeclarationsOverVariables: type: lint parameters: none 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() { ... } } ``` preferGenericFunctionTypeAliases: type: lint parameters: Object p0: undocumented problemMessage: "Use the generic function type syntax in 'typedef's." correctionMessage: "Try using the generic function type syntax ('#p0')." 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!](); ``` #### Common fixes Rewrite the typedef to use the newer syntax: ```dart typedef F = 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(); ``` preferIfElementsToConditionalExpressions: type: lint parameters: none 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']; ``` preferIfNullOperators: type: lint parameters: none 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; ``` preferInitializingFormals: type: lint parameters: Object p0: undocumented problemMessage: "Use an initializing formal to assign a parameter to a field." correctionMessage: "Try using an initialing formal ('this.#p0') 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; } ``` preferInlinedAddsMultiple: type: lint parameters: none sharedName: preferInlinedAdds 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']; ``` preferInlinedAddsSingle: type: lint parameters: none sharedName: preferInlinedAdds 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 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 f(String a, List 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 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 f(String a, List b) { return [a, ...b]; } ``` preferIntLiterals: type: lint parameters: none problemMessage: "Unnecessary use of a 'double' literal." correctionMessage: "Try using an 'int' literal." state: stable: "2.1" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a `double` literal's value has a fractional part of 0 (such as `8.0`) and is used where the context type is `double`. In these cases, you can use an `int` literal instead, because it would evaluate to the same `double` value. #### Examples The following code produces this diagnostic because the literal `8.0` is used to initialize a variable of type `double`, but its value has a fractional part of `0`: ```dart double d = [!8.0!]; ``` The following code produces this diagnostic because the literal `7.1e2` evaluates to `710.0`, which has a fractional part of `0`, and is used to initialize a variable of type `double`: ```dart double d = [!7.1e2!]; ``` #### Common fixes Replace the `double` literal with an equivalent `int` literal: ```dart double d = 8; ``` ```dart double d = 710; ``` 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); } ``` preferInterpolationToComposeStrings: type: lint parameters: none 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 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}.' ``` preferIsEmptyAlwaysFalse: # TODO(brianwilkerson): Should be warning rather than lint, # as represents a bug rather than style preference. type: lint parameters: none sharedName: preferIsEmpty problemMessage: "The comparison is always 'false' because the length is always greater than or equal to 0." categories: [errorProne] hasPublishedDocs: false preferIsEmptyAlwaysTrue: # TODO(brianwilkerson): Should be warning rather than lint, # as represents a bug rather than style preference. type: lint parameters: none sharedName: preferIsEmpty problemMessage: "The comparison is always 'true' because the length is always greater than or equal to 0." hasPublishedDocs: false preferIsEmptyUseIsEmpty: type: lint parameters: none sharedName: preferIsEmpty 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 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 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(' '); ``` preferIsEmptyUseIsNotEmpty: type: lint parameters: none sharedName: preferIsEmpty problemMessage: "Use 'isNotEmpty' instead of 'length' to test whether the collection is empty." correctionMessage: "Try rewriting the expression to use 'isNotEmpty'." hasPublishedDocs: true preferIsNotEmpty: type: lint parameters: none 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 p) => [!!p.isEmpty!] ? p.first : 0; ``` #### Common fixes Rewrite the code to use `isNotEmpty`: ```dart void f(Iterable 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); } ``` preferIsNotOperator: type: lint parameters: none 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) { ... } ``` preferIterableWheretype: type: lint parameters: none 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 f(Iterable p) => p.[!where!]((e) => e is String); ``` #### Common fixes Rewrite the code to use `whereType`: ```dart Iterable f(Iterable p) => p.whereType(); ``` This might also allow you to tighten the types in your code or remove other type checks. deprecatedDetails: |- **PREFER** `iterable.whereType()` over `iterable.where((e) => e is T)`. **BAD:** ```dart iterable.where((e) => e is MyClass); ``` **GOOD:** ```dart iterable.whereType(); ``` preferMixin: type: lint parameters: Object p0: undocumented problemMessage: "Only mixins should be mixed in." correctionMessage: "Try converting '#p0' 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 {} ``` preferNullAwareMethodCalls: type: lint parameters: none 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(); ``` preferNullAwareOperators: type: lint parameters: none 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? p) { return [!p == null ? null : p.length!]; } ``` #### Common fixes Use a null-aware access operator instead: ```dart int? f(List? 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; ``` preferRelativeImports: type: lint parameters: none 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'; ``` preferSingleQuotes: type: lint parameters: none 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"}'); ``` preferSpreadCollections: type: lint parameters: none 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]; ``` preferTypingUninitializedVariablesForField: type: lint parameters: none sharedName: preferTypingUninitializedVariables 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; ... } } ``` preferTypingUninitializedVariablesForLocalVariable: type: lint parameters: none sharedName: preferTypingUninitializedVariables problemMessage: "An uninitialized variable should have an explicit type annotation." correctionMessage: "Try adding a type annotation." hasPublishedDocs: true preferVoidToNull: type: lint parameters: none 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 f() async {} ``` deprecatedDetails: |- **DON'T** use the type Null where void would work. **BAD:** ```dart Null f() {} Future f() {} Stream f() {} f(Null x) {} ``` **GOOD:** ```dart void f() {} Future f() {} Stream 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 []; {}; ``` provideDeprecationMessage: type: lint parameters: none 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) {} ``` publicMemberApiDocs: type: lint parameters: none 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. recursiveGetters: type: lint parameters: Object p0: undocumented problemMessage: "The getter '#p0' 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 %ignore=unused_field 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; ``` removeDeprecationsInBreakingVersions: type: lint parameters: none problemMessage: "Remove deprecated elements in breaking versions." correctionMessage: "Try removing the deprecated element." state: stable: "3.10" categories: [publicInterface] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic in packages that have a "breaking" version number (`x.0.0` or `0.x.0`) for every declaration that has a `@Deprecated` annotation. #### Example Given a package with a `pubspec.yaml` file containing: ```yaml %uri="pubspec.yaml" name: p version: 2.0.0 environment: sdk: ^3.9.0 ``` The following code produces this diagnostic because the function `f` is annotated with `@deprecated`: ```dart @[!deprecated!] void f() {} void g() {} ``` #### Common fixes If the declaration should be removed in the next release of the package, then remove the declaration: ```dart void g() {} ``` If you are not making a breaking change, then use a minor or patch version increment for the package: ```yaml %uri="pubspec.yaml" name: p version: 1.0.1 environment: sdk: ^3.9.0 ``` deprecatedDetails: |- **DO** Remove deprecated elements in breaking version numbers. Breaking version numbers are on the form `x.0.0` or `0.x.0`. For example given a package with a `pubspec.yaml` file containing: ```yaml name: p version: 2.0.0 environment: sdk: ^3.9.0 ``` **BAD:** ```dart @deprecated void f() {} ``` **GOOD:** ```dart // (f is removed). ``` **GOOD:** ```yaml name: p version: 1.0.1 environment: sdk: ^3.9.0 ``` requireTrailingCommas: type: lint parameters: none 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. securePubspecUrls: type: lint parameters: Object p0: undocumented problemMessage: "The '#p0' 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 ``` simpleDirectivePaths: type: lint parameters: none problemMessage: "Use simple directive paths." correctionMessage: "Try simplifying the directive path." state: stable: "3.12" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a directive uses a path that is not simple (for example, a path containing redundant `./` or backtracking `../` segments). #### Example Given a file named `bar.dart` in the `lib/src` directory: ```dart %uri="lib/src/bar.dart" class Bar {} ``` The following code produces this diagnostic because it uses an unnecessarily complex relative URI: ```dart import [!'./src/bar.dart'!]; void f(Bar b) {} ``` #### Common fixes Use a minimal relative URI: ```dart import 'src/bar.dart'; void f(Bar b) {} ``` deprecatedDetails: |- **PREFER** simple directive paths. Using simple directive paths (avoiding redundant `./` or backtracking `../` segments) makes the code cleaner, more consistent, and easier to read. It also reduces the risk of confusion when resolving paths relative to the source file. **BAD:** ```dart import '../src/bar.dart'; ``` **GOOD:** ```dart import 'bar.dart'; ``` simplifyVariablePattern: type: lint parameters: String memberName: The redundant member name. String memberType: The type of the matched object. Whether a field, getter, or method. problemMessage: "The #memberType identification '#memberName:' is redundant and can be removed." correctionMessage: "Try removing the redundant #memberType identification." state: stable: "3.11" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a variable pattern includes a redundant type member name. #### Example The following code produces this diagnostic because the variable pattern includes a redundant getter name: ```dart void f(Object o) { if (o case String([!length!]: var length)) { print('string is $length characters long'); } } ``` #### Common fixes Remove the redundant member name: ```dart void f(Object o) { if (o case String(:var length)) { print('string is $length characters long'); } } ``` deprecatedDetails: |- **AVOID** redundant member names in variable patterns. When a variable pattern declares a variable with the same name as a member of the matched type, the member name is redundant and can be omitted. **BAD:** ```dart void f(Object o) { if (o case String([!length!]: var length)) { print('string is $length characters long'); } } ``` **GOOD:** ```dart void f(Object o) { if (o case String(:var length)) { print('string is $length characters long'); } } ``` sizedBoxForWhitespace: type: lint parameters: none 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: [ 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: [ 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: [ const MyLogo(), Container(width: 4), const Expanded( child: Text('...'), ), ], ); } ``` **GOOD:** ```dart Widget buildRow() { return Row( children: const [ MyLogo(), SizedBox(width: 4), Expanded( child: Text('...'), ), ], ); } ``` sizedBoxShrinkExpand: type: lint parameters: Object p0: undocumented problemMessage: "Use 'SizedBox.#p0' to avoid needing to specify the 'height' and 'width'." correctionMessage: "Try using 'SizedBox.#p0' 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(), ); } ``` slashForDocComments: type: lint parameters: none 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. sortChildPropertiesLast: type: lint parameters: Object p0: undocumented problemMessage: "The '#p0' 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: [ 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: [ 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. sortConstructorsFirst: type: lint parameters: none 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 { const Animation(this.value); double value; void addListener(VoidCallback listener); } ``` sortPubDependencies: type: lint parameters: none 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. sortUnnamedConstructorsFirst: type: lint parameters: none 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 implements Future { factory CancelableFuture(computation()) => ... factory CancelableFuture.delayed(Duration duration, [computation()]) => ... ... } ``` specifyNonobviousLocalVariableTypes: type: lint parameters: none problemMessage: "Specify the type of a local variable when the type is non-obvious." correctionMessage: "Try adding a type annotation." state: experimental: "3.6" stable: "3.11" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Do type annotate initialized local variables when the type is [non-obvious](https://dart.dev/glossary/obviously-typed). 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). **BAD:** ```dart List> possibleDesserts(Set pantry) { var desserts = genericFunctionDeclaredFarAway([42], 'Something'); for (final recipe in cookbook) { if (pantry.containsAll(recipe)) { desserts.add(recipe); } } return desserts; } const List> cookbook = ...; ``` **GOOD:** ```dart List> possibleDesserts(Set pantry) { List> desserts = genericFunctionDeclaredFarAway( [42], 'Something', ); for (final List recipe in cookbook) { if (pantry.containsAll(recipe)) { desserts.add(recipe); } } return desserts; } const List> cookbook = ...; ``` specifyNonobviousPropertyTypes: type: lint parameters: none problemMessage: "A type annotation is needed because it isn't obvious." correctionMessage: "Try adding a type annotation." state: experimental: "3.7" stable: "3.11" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Do type annotate initialized top-level or static variables when the type is [non-obvious](https://dart.dev/glossary/obviously-typed). 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). **BAD:** ```dart final myTopLevelVariable = genericFunctionWrittenByOtherFolks(with, args); class A { static var myStaticVariable = myTopLevelVariable.update('foo', null); } ``` **GOOD:** ```dart final Map myTopLevelVariable = genericFunctionWrittenByOtherFolks(with, args); class A { static Map myStaticVariable = myTopLevelVariable.update('foo', null); } ``` strictTopLevelInferenceAddType: type: lint parameters: none sharedName: strictTopLevelInference 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; ``` strictTopLevelInferenceReplaceKeyword: type: lint parameters: Object p0: undocumented sharedName: strictTopLevelInference problemMessage: "Missing type annotation." correctionMessage: "Try replacing '#p0' with a type annotation." hasPublishedDocs: false strictTopLevelInferenceSplitToTypes: type: lint parameters: none sharedName: strictTopLevelInference problemMessage: "Missing type annotation." correctionMessage: "Try splitting the declaration and specify the different type annotations." hasPublishedDocs: false superGoesLast: type: lint parameters: none 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) { ``` switchOnType: type: lint parameters: none 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'); } } ``` testTypesInEquals: type: lint parameters: Object p0: undocumented problemMessage: "Missing type test for '#p0' in '=='." correctionMessage: "Try testing the type of '#p0'." 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; } } ``` throwInFinally: type: lint parameters: Object p0: undocumented problemMessage: "Use of '#p0' in 'finally' block." correctionMessage: "Try moving the '#p0' 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; } } ``` tightenTypeOfInitializingFormals: type: lint parameters: none 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); } ``` typeAnnotatePublicApis: type: lint parameters: none 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 install(PackageId id, String destination) { // ... } ``` With types, all of this is clarified. typeInitFormals: type: lint parameters: none 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); } ``` typeLiteralInConstantPattern: type: lint parameters: none 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'); } } ``` unawaitedFutures: type: lint parameters: none 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 f() async { [!g!](); } Future 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 f() async { await g(); } Future 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 f() async { unawaited(g()); } Future 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. } ``` unintendedHtmlInDocComment: type: lint parameters: none problemMessage: "Angle brackets will be interpreted as HTML." correctionMessage: "Try using backticks around the content with angle brackets, or try replacing `<` with `<` and `>` with `>`." 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 ``, which isn't one of the allowed exceptions: ```dart /// Converts a List[!!] to a comma-separated String. String f(List 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` to a comma-separated String. String f(List l) => ''; ``` If the text was intended to be part of a link, then add square brackets around the code: ```dart /// Converts a [List] to a comma-separated String. String f(List 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\ to a comma-separated String. String f(List 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, `T1`. 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 ``, 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 ``. Any other other occurrence of `` or `` is likely a mistake and this lint will warn about it. If something looks like an HTML tag, meaning it starts with `<` or ``, 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 is ...`, where `` looks like an HTML tag. Missing the end quote of a code span can have the same effect: ``The type `List is ...`` will also treat `` as an HTML tag. Allows the following HTML directives: HTML comments, ``, processing instructions, ``, CDATA-sections, and `<[CDATA...]>`. Allows DartDoc links like `[List]` 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. /// -> = ``` **GOOD:** ```dart /// The type `List`. /// The type [List] /// ` -> = ` /// \ -> \ = \` /// ``` unnecessaryAsync: type: lint parameters: none 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: true documentation: |- #### Description The analyzer produces this diagnostic when a function, method, or closure is marked `async` but doesn't contain any `await` expressions or `await for` statements. The `async` modifier is unnecessary in these cases and can be removed without changing the behavior of the code. #### Example The following code produces this diagnostic because the function `f` is marked `async` but doesn't use `await`: ```dart void f() [!async!] { print('done'); } ``` #### Common fixes Remove the `async` modifier: ```dart void f() { print('done'); } ``` 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); } ``` unnecessaryAwaitInReturn: type: lint parameters: none problemMessage: "Unnecessary 'await'." correctionMessage: "Try removing the 'await'." state: stable: "2.1" categories: [style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when an `async` function or method returns an `await` expression and the static type of the awaited `Future` is a [subtype][] of the declared return type. The `await` is unnecessary because returning a `Future` from an `async` function already produces a `Future` that completes with the same result. The analyzer doesn't report this diagnostic for `await` expressions inside a `try` block because removing the `await` changes how errors from the awaited `Future` are handled. [subtype]: https://dart.dev/resources/glossary#subtype #### Example The following code produces this diagnostic because the function `f` has a return type of `Future` and returns an awaited `Future` whose static type is also `Future`: ```dart Future f(Future future) async { return [!await!] future; } ``` #### Common fixes Remove the unnecessary `await`: ```dart Future f(Future future) async { return future; } ``` deprecatedDetails: |- Avoid returning an awaited expression when the expression type is assignable to the function's return type. **BAD:** ```dart Future future; Future f1() async => await future; Future f2() async { return await future; } ``` **GOOD:** ```dart Future future; Future f1() => future; Future f2() { return future; } ``` unnecessaryBraceInStringInterps: type: lint parameters: none 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!"); ``` unnecessaryBreaks: type: lint parameters: none problemMessage: "Unnecessary 'break' statement." correctionMessage: "Try removing the 'break'." state: stable: "3.0" categories: [brevity, style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a `break` statement appears at the end of a non-empty switch case or default clause. In Dart 3.0 and later, switch cases don't fall through to the next case, so a `break` at the end of a non-empty case body is redundant. #### Example The following code produces this diagnostic because the `break` is at the end of a non-empty `case` body: ```dart void f(int x) { switch (x) { case 1: print('one'); [!break;!] case 2: print('two'); } } ``` #### Common fixes Remove the `break` statement: ```dart void f(int x) { switch (x) { case 1: print('one'); case 2: print('two'); } } ``` 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. unnecessaryConst: type: lint parameters: none 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!] []; ``` The list is implicitly `const` because of the keyword `const` on the variable declaration. #### Common fixes Remove the unnecessary keyword: ```dart const l = []; ``` 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()]; } ``` unnecessaryConstInEnumConstructor: type: lint parameters: none problemMessage: "Unnecessary 'const' keyword in an enum constructor." correctionMessage: "Try removing the keyword." state: experimental: "3.13" categories: [brevity, style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when the keyword `const` is used in a generative enum constructor. Generative enum constructors are implicitly `const`. #### Examples The following code produces this diagnostic because the keyword `const` in the enum's primary constructor isn't needed: ```dart %experiments=primary-constructors enum [!const!] E(final int i) { a(1), b(2); } ``` The following code produces this diagnostic because the keyword `const` in the enum's secondary constructor isn't needed: ```dart %experiments=primary-constructors enum E { a(1), b(2); [!const!] E(this.i); final int i; } ``` #### Common fixes Remove the unnecessary keyword: ```dart %experiments=primary-constructors enum E(final int i) { a(1), b(2); } ``` ```dart %experiments=primary-constructors enum E { a(1), b(2); E(this.i); final int i; } ``` deprecatedDetails: |- Don't use an explicit `const` in a generative enum constructor. Generative enum constructors are implicitly `const`. **BAD:** ```dart enum const E(final int i) { a(1), b(2); } ``` ```dart enum E { a(1), b(2); const E(this.i); final int i; } ``` **GOOD:** ```dart enum E(final int i) { a(1), b(2); } ``` ```dart enum E { a(1), b(2); E(this.i); final int i; } ``` unnecessaryConstructorName: type: lint parameters: none 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; ``` unnecessaryFinalWithType: type: lint parameters: none sharedName: unnecessaryFinal 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); } } ``` unnecessaryFinalWithoutType: type: lint parameters: none sharedName: unnecessaryFinal problemMessage: "Local variables should not be marked as 'final'." correctionMessage: "Replace 'final' with 'var'." hasPublishedDocs: false unnecessaryGettersSetters: type: lint parameters: none 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; } ``` unnecessaryIgnore: type: lint parameters: String name: The diagnostic name. sharedName: unnecessaryIgnore problemMessage: "The diagnostic '#name' 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. unnecessaryIgnoreFile: type: lint parameters: String name: The diagnostic name. sharedName: unnecessaryIgnore problemMessage: "The diagnostic '#name' isn't produced in this file so it doesn't need to be ignored." correctionMessage: "Try removing the ignore comment." hasPublishedDocs: false unnecessaryIgnoreName: type: lint parameters: String name: The diagnostic name. sharedName: unnecessaryIgnore problemMessage: "The diagnostic '#name' isn't produced at this location so it doesn't need to be ignored." correctionMessage: "Try removing the name from the list." hasPublishedDocs: false unnecessaryIgnoreNameFile: type: lint parameters: String name: The diagnostic name. sharedName: unnecessaryIgnore problemMessage: "The diagnostic '#name' isn't produced in this file so it doesn't need to be ignored." correctionMessage: "Try removing the name from the list." hasPublishedDocs: false unnecessaryLambdas: type: lint parameters: none 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 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 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); ``` unnecessaryLate: type: lint parameters: none 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; } ``` unnecessaryLibraryDirective: type: lint parameters: none problemMessage: "Library directives without comments or annotations should be avoided." correctionMessage: "Try deleting the library directive." state: stable: "2.19" categories: [brevity] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a `library` directive doesn't have a documentation comment or any annotations. If no documentation comment or annotation precedes the library directive, then either it's unnecessary or the documentation comment and/or annotations are misplaced and should be moved. #### Examples The following code produces this diagnostic because the `library` directive doesn't have a documentation comment or annotation: ```dart [!library;!] class C {} ``` The following code produces this diagnostic because the library's documentation comment is below the `library` directive: ```dart [!library;!] /// This library provides the [C] class. /// The [C] class. class C {} ``` #### Common fixes If you don't want to add a documentation comment or annotation to the library, then remove the `library` directive: ```dart class C {} ``` If you intend to add a documentation comment or annotation, then add or move it to the `library` directive: ```dart /// This library provides the [C] class. library; /// The [C] class. class C {} ``` 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. unnecessaryLibraryName: type: lint parameters: none 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";` ``` unnecessaryNew: type: lint parameters: none 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(); } ``` unnecessaryNullAwareAssignments: type: lint parameters: none 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; ``` unnecessaryNullAwareOperatorOnExtensionOnNullable: type: lint parameters: none 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(); ``` unnecessaryNullChecks: type: lint parameters: none problemMessage: "Unnecessary use of a null check ('!')." correctionMessage: "Try removing the null check." state: experimental: "2.12" stable: "3.13" 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); } ``` unnecessaryNullInIfNullOperators: type: lint parameters: none 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; ``` unnecessaryNullableForFinalVariableDeclarations: type: lint parameters: none 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; ``` unnecessaryOverrides: type: lint parameters: none 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. unnecessaryParenthesis: type: lint parameters: none 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`. unnecessaryPrimaryConstructorBody: type: lint parameters: none problemMessage: "Unnecessary primary constructor body." correctionMessage: "Try removing the body." state: experimental: "3.13" categories: [brevity, style] hasPublishedDocs: false deprecatedDetails: |- Don't include an empty primary constructor body. **BAD:** ```dart class C() { this; } ``` **GOOD:** ```dart class C(); ``` unnecessaryRawStrings: type: lint parameters: none 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'; ``` unnecessaryStatements: type: lint parameters: none 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; ``` unnecessaryStringEscapes: type: lint parameters: none 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' "; ``` unnecessaryStringInterpolations: type: lint parameters: none 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; ``` unnecessaryThis: type: lint parameters: none 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; } } ``` unnecessaryToListInSpreads: type: lint parameters: none 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 toLowercase(List strings) { return [ ...strings.map((String s) => s.toLowerCase()).[!toList!](), ]; } ``` #### Common fixes Remove the invocation of `toList`: ```dart List toLowercase(List strings) { return [ ...strings.map((String s) => s.toLowerCase()), ]; } ``` deprecatedDetails: |- Unnecessary `toList()` in spreads. **BAD:** ```dart children: [ ...['foo', 'bar', 'baz'].map((String s) => Text(s)).toList(), ] ``` **GOOD:** ```dart children: [ ...['foo', 'bar', 'baz'].map((String s) => Text(s)), ] ``` unnecessaryTypeNameInConstructor: type: lint parameters: none problemMessage: "Unnecessary type name in a constructor." correctionMessage: "Try removing the type name." state: stable: "3.13" categories: [brevity, style] hasPublishedDocs: true documentation: |- #### Description The analyzer produces this diagnostic when a secondary constructor declaration includes a type name. #### Examples The following code produces this diagnostic because the generative constructor declaration includes the type name: ```dart %experiments=primary-constructors class C { [!C!](); } ``` The following code produces this diagnostic because the factory constructor declaration includes the type name: ```dart %experiments=primary-constructors class C { factory [!C!]() => C._(); new _() {} } ``` #### Common fixes Remove the type name from the constructor. If the constructor is named, also remove the period before the name: ```dart %experiments=primary-constructors class C { new (); } ``` or ```dart %experiments=primary-constructors class C { factory () => C._(); new _() {} } ``` deprecatedDetails: |- Don't include the type name in a constructor declaration. It isn't necessary, and the code is shorter and cleaner without it. **BAD:** ```dart class C { C(); C.name(); } ``` **GOOD:** ```dart class C { new (); new name(); } ``` unnecessaryUnawaited: type: lint parameters: none 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 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 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 log(String message) { ... } void f() { unawaited(log('Message.')); } ``` **GOOD:** ```dart @awaitNotRequired Future log(String message) { ... } void f() { log('Message.'); } ``` unnecessaryUnderscores: type: lint parameters: none 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 _) { } ``` unreachableFromMain: type: lint parameters: Object p0: undocumented problemMessage: "Unreachable member '#p0' 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() {} ``` unrelatedTypeEqualityChecksInExpression: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: unrelatedTypeEqualityChecks problemMessage: "The type of the right operand ('#p0') isn't a subtype or a supertype of the left operand ('#p1')." 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 {} ``` unrelatedTypeEqualityChecksInPattern: type: lint parameters: Object p0: undocumented Object p1: undocumented sharedName: unrelatedTypeEqualityChecks problemMessage: "The type of the operand ('#p0') isn't a subtype or a supertype of the value being matched ('#p1')." correctionMessage: "Try changing one or both of the operands." hasPublishedDocs: true unsafeHtmlAttribute: type: lint parameters: Object p0: undocumented sharedName: unsafeHtml problemMessage: "Assigning to the attribute '#p0' 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. unsafeHtmlConstructor: type: lint parameters: Object p0: undocumented sharedName: unsafeHtml problemMessage: "Invoking the constructor '#p0' is unsafe." correctionMessage: "Try finding a different way to implement the page." hasPublishedDocs: false unsafeHtmlMethod: type: lint parameters: Object p0: undocumented sharedName: unsafeHtml problemMessage: "Invoking the method '#p0' is unsafe." correctionMessage: "Try finding a different way to implement the page." hasPublishedDocs: false unsafeVariance: type: lint parameters: none 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 { bool Function([!X!]) f; C(this.f); } ``` This is unsafe: If `c` has static type `C` and run-time type `C` 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 { // 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 { bool Function(Never) f; C(this.f); } ``` If `c` has static type `C` 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 { 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 {...}`, 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 { final bool Function([!X!]) fun; // LINT C(this.fun); } void main() { C c = C((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 { // ignore: unsafe_variance final bool Function(X) _fun; bool fun(X x) => _fun(x); C(this._fun); } void main() { C c = C((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 Function(X); typedef C = _C>; class _C> { // ignore: unsafe_variance final bool Function(X) fun; // Safe! _C(this.fun); } void main() { C c = C((i) => i.isEven); c.fun(10); // Succeeds. } ``` With this approach, `C` is not a subtype of `C`, 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 { final bool Function(Never) fun; C(this.fun); } void main() { C c = C((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. } ``` useBuildContextSynchronouslyAsyncUse: type: lint parameters: none sharedName: useBuildContextSynchronously 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 { void foo() async { await Future.delayed(const Duration(seconds: 1)); if (!mounted) return; // Checks `this.mounted`, not `context.mounted`. Navigator.of(context).pop(); } } ``` useBuildContextSynchronouslyWrongMounted: type: lint parameters: none sharedName: useBuildContextSynchronously 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 useColoredBox: type: lint parameters: none 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'), ); } ``` useDeclaringParameters: type: lint parameters: none problemMessage: "Use a declaring parameter." correctionMessage: "Try using a declaring parameter." state: experimental: "3.13" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Use a declaring parameter everywhere it's valid to do so. useDecoratedBox: type: lint parameters: none 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('...'), ); } ``` useEnums: type: lint parameters: none 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); } ``` useFullHexValuesForFlutterColors: type: lint parameters: none 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); ``` useFunctionTypeSyntaxForParameters: type: lint parameters: Object p0: undocumented problemMessage: "Use the generic function type syntax to declare the parameter '#p0'." 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 where(bool predicate(T element)) {} ``` **GOOD:** ```dart Iterable where(bool Function(T) predicate) {} ``` useIfNullToConvertNullsToBools: type: lint parameters: none problemMessage: "Use an if-null operator to convert a 'null' to a 'bool'." correctionMessage: "Try using an if-null operator." state: stable: "2.13" deprecated: "3.11" 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) { } ``` useIsEvenRatherThanModulo: type: lint parameters: Object p0: undocumented problemMessage: "Use '#p0' rather than '% 2'." correctionMessage: "Try using '#p0'." 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; ``` useKeyInWidgetConstructors: type: lint parameters: none 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}); } ``` useLateForPrivateFieldsAndVariables: type: lint parameters: none 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; } ``` useNamedConstants: type: lint parameters: Object p0: undocumented problemMessage: "Use the constant '#p0' rather than a constructor returning the same object." correctionMessage: "Try using '#p0'." 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; ``` useNullAwareElements: type: lint parameters: none 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"}; ``` usePrimaryConstructors: type: lint parameters: none problemMessage: "Use a primary constructor." correctionMessage: "Try using a primary constructor." state: experimental: "3.13" categories: [style] hasPublishedDocs: false deprecatedDetails: |- Use a primary constructor everywhere it's valid to do so. useRawStrings: type: lint parameters: none 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 $'; ``` useRethrowWhenPossible: type: lint parameters: none 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); } ``` useSettersToChangeProperties: type: lint parameters: none 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 %ignore=unused_field class C { int _f = 0; void [!setF!](int value) => _f = value; } ``` #### Common fixes Convert the method to a setter: ```dart %ignore=unused_field 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; ``` useStringBuffers: type: lint parameters: none 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(); } ``` useStringInPartOfDirectives: type: lint parameters: none 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'; ``` useSuperParametersMultiple: type: lint parameters: Object p0: undocumented sharedName: useSuperParameters problemMessage: "Parameters '#p0' could be super parameters." correctionMessage: "Trying converting '#p0' 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}); } ``` useSuperParametersSingle: type: lint parameters: Object p0: undocumented sharedName: useSuperParameters problemMessage: "Parameter '#p0' could be a super parameter." correctionMessage: "Trying converting '#p0' to a super parameter." hasPublishedDocs: true useTestThrowsMatchers: type: lint parameters: none 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().having((Error error) => error.message, 'message', contains('some message'))), ); // async code await expectLater( () => someAsyncFunctionThatThrows(), throwsA(isA().having((Error error) => error.message, 'message', contains('some message'))), ); ``` useToAndAsIfApplicable: type: lint parameters: none 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); } } ``` useTruncatingDivision: type: lint parameters: none 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; ``` validRegexps: type: lint parameters: none 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()')); ``` varWithNoTypeAnnotation: type: lint parameters: none problemMessage: "Avoid declaring parameters with `var` and no type annotation." correctionMessage: "Try removing the keyword 'var' or replacing `var` with a type annotation." state: experimental: "3.12" categories: [languageFeatureUsage] hasPublishedDocs: true documentation: |- NOTE: This rule is removed in Dart 3.13.0; it is no longer functional. #### Description The analyzer produces this diagnostic when a parameter is declared using the keyword `var` without a type annotation. This pattern should be avoided as it likely will be a compile-time error in a future version of Dart. Beyond this, using `var` without an explicit type results in the parameter having a type of `dynamic`, disabling static type checking for that parameter. #### Examples The following code produces this diagnostic because the parameter `x` is declared with `var`: ```dart // @dart=3.12 void f([!var!] x) { print(x); } ``` The following code produces this diagnostic because the initializing formal parameter `x` is declared with `var`: ```dart // @dart=3.12 class C { int x; C([!var!] this.x); } ``` #### Common fixes If you know the desired type of the parameter, then replace `var` with a type annotation: ```dart void f(String x) { print(x); } ``` If you don't know or don't want any specific type for the parameter, then replace `var` with a type of `Object?` or `dynamic` to make the lack of any more specific type explicit: ```dart void f(Object? x) { print(x); } ``` deprecatedDetails: |- **AVOID** declaring parameters with `var` and no type annotation. Declaring formal parameters using `var` and no type annotation will be a compile-time error when primary constructors are enabled. This lint flags those parameters to ease migration. **BAD:** ```dart void func(var x) { // LINT print(x); } ``` **GOOD:** ```dart void func(String x) { // OK print(x); } ``` **BAD:** ```dart [1, 4, 6, 8].forEach((var value) => print(value + 2)); // LINT ``` **GOOD:** ```dart [1, 4, 6, 8].forEach((value) => print(value + 2)); // OK ``` visitRegisteredNodes: type: lint parameters: none problemMessage: "Declare 'visit' methods for all registered node types." correctionMessage: "Try declaring a 'visit' method for all registered node types." hasPublishedDocs: true state: internal: "3.10" categories: [errorProne] deprecatedDetails: "For internal use only." voidChecks: type: lint parameters: none 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? value; } void f(A 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 { void m(T p) { } } void f(A 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? value; } void f(A a) { a.value = 1; } ``` If the type of the variable is correct, then remove the assignment: ```dart class A { T? value; } void f(A a) {} ``` deprecatedDetails: |- **DON'T** assign to `void`. **BAD:** ```dart class A { T value; void test(T arg) { } } void main() { A a = A(); a.value = 1; // LINT a.test(1); // LINT } ```