-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: update dart analyze .deepsource
- Loading branch information
1 parent
a2ea66b
commit 9425af0
Showing
211 changed files
with
4,771 additions
and
4,680 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,41 @@ | ||
--- | ||
title: "Use interpolation to compose strings and values." | ||
verbose_name: "prefer_interpolation_to_compose_strings" | ||
category: "antipattern" | ||
title: "Avoid relative imports for files in `lib/`" | ||
verbose_name: "always_use_package_imports" | ||
category: "bug-risk" | ||
weight: 70 | ||
severity: "major" | ||
--- | ||
**PREFER** using interpolation to compose strings and values. | ||
**DO** avoid relative imports for files in `lib/`. | ||
|
||
Using interpolation when composing strings and values is usually easier to write | ||
and read than concatenation. | ||
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 | ||
'Hello, ' + person.name + ' from ' + person.city + '.'; | ||
import 'baz.dart'; | ||
import 'src/bag.dart' | ||
import '../lib/baz.dart'; | ||
... | ||
``` | ||
|
||
**GOOD:** | ||
```dart | ||
'Hello, ${person.name} from ${person.city}.' | ||
import 'package:foo/bar.dart'; | ||
import 'package:foo/baz.dart'; | ||
import 'package:foo/src/baz.dart'; | ||
... | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,84 @@ | ||
--- | ||
title: "Don't override fields." | ||
verbose_name: "overridden_fields" | ||
category: "antipattern" | ||
title: "Avoid method calls or property accesses on a "dynamic" target" | ||
verbose_name: "avoid_dynamic_calls" | ||
category: "bug-risk" | ||
weight: 70 | ||
severity: "major" | ||
--- | ||
**DON'T** override fields. | ||
**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. | ||
|
||
Overriding fields is almost always done unintentionally. Regardless, it is a | ||
bad practice to do so. | ||
Additionally, targets typed "dynamic" disables most static analysis, meaning it | ||
is easier to lead to a runtime "NoSuchMethodError" or "NullError" than properly | ||
statically typed Dart code. | ||
|
||
There is an exception to methods and properties that exist on "Object?": | ||
- a.hashCode | ||
- a.runtimeType | ||
- a.noSuchMethod(someInvocation) | ||
- a.toString() | ||
|
||
... these members are dynamically dispatched in the web-based runtimes, but not | ||
in the VM-based ones. Additionally, they are so common that it would be very | ||
punishing to disallow `any.toString()` or `any == true`, for example. | ||
|
||
Note that despite "Function" being a type, the semantics are close to identical | ||
to "dynamic", and calls to an object that is typed "Function" will also trigger | ||
this lint. | ||
|
||
**BAD:** | ||
```dart | ||
class Base { | ||
Object field = 'lorem'; | ||
void explicitDynamicType(dynamic object) { | ||
print(object.foo()); | ||
} | ||
void implicitDynamicType(object) { | ||
print(object.foo()); | ||
} | ||
abstract class SomeWrapper { | ||
T doSomething<T>(); | ||
} | ||
Object something = 'change'; | ||
void inferredDynamicType(SomeWrapper wrapper) { | ||
var object = wrapper.doSomething(); | ||
print(object.foo()); | ||
} | ||
class Bad1 extends Base { | ||
@override | ||
final field = 'ipsum'; // LINT | ||
void callDynamic(dynamic function) { | ||
function(); | ||
} | ||
class Bad2 extends Base { | ||
@override | ||
Object something = 'done'; // LINT | ||
void functionType(Function function) { | ||
function(); | ||
} | ||
``` | ||
|
||
**GOOD:** | ||
```dart | ||
class Base { | ||
Object field = 'lorem'; | ||
Object something = 'change'; | ||
void explicitType(Fooable object) { | ||
object.foo(); | ||
} | ||
class Ok extends Base { | ||
Object newField; // OK | ||
void castedType(dynamic object) { | ||
(object as Fooable).foo(); | ||
} | ||
final Object newFinal = 'ignore'; // OK | ||
abstract class SomeWrapper { | ||
T doSomething<T>(); | ||
} | ||
``` | ||
**GOOD:** | ||
```dart | ||
abstract class BaseLoggingHandler { | ||
Base transformer; | ||
void inferredType(SomeWrapper wrapper) { | ||
var object = wrapper.doSomething<Fooable>(); | ||
object.foo(); | ||
} | ||
class LogPrintHandler implements BaseLoggingHandler { | ||
@override | ||
Derived transformer; // OK | ||
void functionTypeWithParameters(Function() function) { | ||
function(); | ||
} | ||
``` | ||
|
||
|
||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,18 @@ | ||
--- | ||
title: "Don't explicitly initialize variables to null." | ||
verbose_name: "avoid_init_to_null" | ||
category: "antipattern" | ||
title: "Avoid empty else statements" | ||
verbose_name: "avoid_empty_else" | ||
category: "bug-risk" | ||
weight: 70 | ||
severity: "major" | ||
--- | ||
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. | ||
**AVOID** empty else statements. | ||
|
||
**BAD:** | ||
```dart | ||
Item? bestDeal(List<Item> cart) { | ||
Item? bestItem = null; | ||
for (final item in cart) { | ||
if (bestItem == null || item.price < bestItem.price) { | ||
bestItem = item; | ||
} | ||
} | ||
return bestItem; | ||
} | ||
if (x > y) | ||
print("1"); | ||
else ; | ||
print("2"); | ||
``` | ||
|
||
**GOOD:** | ||
```dart | ||
Item? bestDeal(List<Item> cart) { | ||
Item? bestItem; | ||
for (final item in cart) { | ||
if (bestItem == null || item.price < bestItem.price) { | ||
bestItem = item; | ||
} | ||
} | ||
|
||
return bestItem; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,50 @@ | ||
--- | ||
title: "Prefer typing uninitialized variables and fields." | ||
verbose_name: "prefer_typing_uninitialized_variables" | ||
category: "antipattern" | ||
title: "Avoid `print` calls in production code" | ||
verbose_name: "avoid_print" | ||
category: "bug-risk" | ||
weight: 70 | ||
severity: "major" | ||
--- | ||
**PREFER** specifying a type annotation for uninitialized variables and fields. | ||
**DO** avoid `print` calls in production code. | ||
|
||
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. | ||
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 | ||
class BadClass { | ||
static var bar; // LINT | ||
var foo; // LINT | ||
void method() { | ||
var bar; // LINT | ||
bar = 5; | ||
print(bar); | ||
} | ||
void f(int x) { | ||
print('debug: $x'); | ||
... | ||
} | ||
``` | ||
|
||
**BAD:** | ||
|
||
**GOOD:** | ||
```dart | ||
void aFunction() { | ||
var bar; // LINT | ||
bar = 5; | ||
void f(int x) { | ||
debugPrint('debug: $x'); | ||
... | ||
} | ||
``` | ||
|
||
|
||
**GOOD:** | ||
```dart | ||
class GoodClass { | ||
static var bar = 7; | ||
var foo = 42; | ||
int baz; // OK | ||
void method() { | ||
int baz; | ||
var bar = 5; | ||
... | ||
void f(int x) { | ||
log('log: $x'); | ||
... | ||
} | ||
``` | ||
|
||
|
||
**GOOD:** | ||
```dart | ||
void f(int x) { | ||
if (kDebugMode) { | ||
print('debug: $x'); | ||
} | ||
... | ||
} | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,36 @@ | ||
--- | ||
title: "Always override `hashCode` if overriding `==`." | ||
verbose_name: "hash_and_equals" | ||
title: "Avoid relative imports for files in `lib/`" | ||
verbose_name: "avoid_relative_lib_imports" | ||
category: "bug-risk" | ||
weight: 70 | ||
severity: "major" | ||
--- | ||
**DO** override `hashCode` if overriding `==` and prefer overriding `==` if | ||
overriding `hashCode`. | ||
**DO** avoid relative imports for files in `lib/`. | ||
|
||
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. | ||
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 | ||
class Bad { | ||
final int value; | ||
Bad(this.value); | ||
import 'package:foo/bar.dart'; | ||
import '../lib/baz.dart'; | ||
@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; | ||
} | ||
import 'package:foo/bar.dart'; | ||
import 'baz.dart'; | ||
... | ||
``` | ||
|
||
|
Oops, something went wrong.