FlutterLint开启规则

- always_declare_return_types

声明方法或函数时,始终要指定返回类型。

void main() { }

_Foo _bar() => _Foo();

class _Foo {
  int _foo() => 42;
}

- annotate_overrides

使用父类参数要用overrides修饰

abstract class Dog {
  String get breed;
  void bark() {}
}

class Husky extends Dog {
  @override
  final String breed = 'Husky';
  @override
  void bark() {}
}

- avoid_bool_literals_in_conditional_expressions

避免在条件表达式中使用bool值。

condition ? true : boolExpression    #BAD
condition ? false : boolExpression   #BAD

condition || boolExpression          #GOOD
!condition && boolExpression         #GOOD

- avoid_empty_else

- avoid_init_to_null

int _nextId = null;      #BAD
int _nextId;             #GOOD

- avoid_null_checks_in_equality_operators

重写==运算符时不要用来判断是否为null,
由于null是一种特殊类型,没有类可以与它等效。因此,检查另一个实例是否为空是多余的。

class Person {
  final String name;

  @override
  operator ==(other) =>
      other != null && other is Person && name == other.name;  #BAD
}

- avoid_equals_and_hash_code_on_mutable_classes

重写==运算符和hashCode的类要添加@immutable标识

#@immutable 加标识
class B {        
  String key;                    #加final
  const B(this.key);
  @override
  operator ==(other) => other is B && other.key == key;
  @override
  int hashCode() => key.hashCode;
}

- always_use_package_imports

统一引用使用绝对路径

- avoid_renaming_method_parameters

重写的方法不要修改参数名

abstract class A {
  m(a);
}

abstract class B extends A {
  m(b);   #BAD  使用m(a);
}

- avoid_return_types_on_setters

set方法不要带返回值

void set speed(int ms);  #BAD

- avoid_returning_null_for_void

声明void返回值的函数不要返回null

void f1() {
  return null;      #BAD
  return;           #GOOD
}
Future<void> f2() async {
  return null;   #BAD
  return;        #GOOD
}

- avoid_shadowing_type_parameters

类型参数不要重复使用,引起歧义

class A<T> {
  void fn<T>() {}  #BAD 
  void fn<U>() {}  #GOOD
}

- avoid_single_cascade_in_expression_statements

不要用级联表达式调用方法

class Student {
  String? name;
  String? age;
  Student({this.name, this.age});
  void doSth() {}
}

abstract class B {
  static Student wrap(B b) {
    Student()..doSth();       #BAD 
    Student().doSth();        #GOOD

    return Student()          #GOOD
      ..name = ''
      ..age = '10';
  }
}

- avoid_slow_async_io

有一些dart:io库中的方法异步方法比同步方法慢很多,尽量使用同步方法

#BAD
    Directory.current.exists();
    Directory.current.stat();
    File('').lastModified();
    File('').exists();
    File('').stat();
    FileSystemEntity.isDirectory('');
    FileSystemEntity.isFile('');
    FileSystemEntity.isLink('');
    FileSystemEntity.type('');

#GOOD
    Directory.current.existsSync();
    Directory.current.statSync();
    File('').lastModifiedSync();
    File('').existsSync();
    File('').statSync();
    FileSystemEntity.isDirectorySync('');
    FileSystemEntity.isFileSync('');
    FileSystemEntity.isLinkSync('');
    FileSystemEntity.typeSync('');

- avoid_type_to_string

判断Type不要使用ToString()

void bar(Object other) {
  if (other.runtimeType.toString() == 'Bar') {  #BAD   
  if (other is Bar){                            #GOOD

    doThing();
  }
}

- avoid_types_as_parameter_names

声明参数名不要和已存在的类型相同

m(f(int));      #BAD
m(f(int v));    #GOOD

- avoid_unnecessary_containers

- avoid_void_async

异步方法不要直接返回void

void f() async {}          #BAD
Future<void> f() async {}  #GOOD

- await_only_futures

避免使用await修饰非Future,
null可以作为特殊情况

main() async {
  await 2;      #BAD 
  await null;   #GOOD
}

- cancel_subscriptions

StreamSubscription一定要记得cancel

- cast_nullable_to_non_nullable

不要将可空值? as成不可空值

A? a;
var v = a as B;   #BAD

- control_flow_in_finally

- throw_in_finally

try catch final 的final中不要加return、continue、break、throw

class BadReturn {
  double nonCompliantMethod() {
    try {
      return 1 / 0;
    } catch (e) {
      print(e);
    } finally {
      return 1.0;  # BAD
    }
  }
}

class Ok {
  double compliantMethod() {
    var i = 5;
    try {
      i = 1 / 0;
    } catch (e) {
      print(e);
    }
    return i;  // GOOD
  }
}

- empty_catches

try catch的catch理论上不要传空block,如果有意这么做,需要添加注释ignored,或使用_参数

try {
  ...
} catch(e) {
  // ignored, really.
}

// Alternatively:
try {
  ...
} catch(_) { }

// Better still:
try {
  ...
} catch(e) {
  doSomething(e);
}

- empty_constructor_bodies

构造函数以;分号结尾,替代{}

class Point {
  int x, y;
  Point(this.x, this.y) {}    #BAD 
  Point(this.x, this.y);      #GOOD
}

- type_init_formals

构造方法里不要加参数类型

class Point {
  int x, y;
  Point(int this.x, int this.y);   #BAD
  Point(this.x, this.y);           #GOOD
}

- empty_statements

if后不要使用空语句

if (complicated.expression.foo());   # BAD

- exhaustive_cases

枚举的swich case应该是详尽的

- always_specify_types (暂时没开)

一定要指定类型。
当指定未知类型和省略类型时,避免使用var。如果明确表示类型未知,则使用dynamic。如果您明确地想要一个实现==和hashCode的对象,则使用Object。

#BAD
  var foo = 10;
  final bar = Bar();
  const quux = 20;

#GOOD
  int foo = 10;
  final Bar bar = Bar();
  String baz = 'hello';
  const int quux = 20;

- avoid_dynamic_calls (暂时没开)

避免用dynamic调用方法

void explicitDynamicType(dynamic object) {
  print(object.foo());          #BAD
}

void castedType(dynamic object) {
  (object as Fooable).foo();     #GOOD
}

- camel_case_extensions

- camel_case_types

类名使用使用首字母大写驼峰

- non_constant_identifier_names (暂时没开)

参数名使用首字母小写驼峰

- file_names (暂时没开)

文件名使用 _下划线命名规则

- library_names

library使用 _下划线命名规则

- library_prefixes

library prefix使用 _下划线命名规则

- package_names

包名使用 _下划线命名规则

import 'package:javascript_utils/javascript_utils.dart' as js_utils;

- package_prefixed_library_names

用.来区分包名和路径

// 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;

- flutter_style_todos

使用flutter风格的TODO

// TODO(username): message.
// TODO(username): message, https://URL-to-issue.

- hash_and_equals

重写==运算符时要同步重写hashCode

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;
}

- iterable_contains_unrelated_type

不要在不同参数类型中调用contains

void someFunction() {
  var list = <int>[];
  if (list.contains('1')) print('someFunction');    #BAD
}

- list_remove_unrelated_type

不要在不同参数类型中调用remove

void someFunction3() {
  List<int> list = <int>[];
  if (list.remove('1')) print('someFunction3');   #BAD
}

- leading_newlines_in_multiline_strings

多行的multilineString使用时要另起一行

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.''';

- no_adjacent_strings_in_list

list中不要使用 adjacent strings

#BAD
List<String> list = <String>[
  'a'
  'b',    
  'c',
];

#GOOD
List<String> list = <String>[
  'a' +
  'b',    
  'c',
];

- no_duplicate_case_values

Switch case 中case不要重复

switch (v) {
  case 1:
  case 2:
  case A:
  case 2:  # BAD
}

- no_logic_in_create_state

createState()中不要写逻辑代码

class MyStateful extends StatefulWidget {
  @override
  MyState createState() {
    return MyState();    #GOOD
  }
}

- null_check_on_nullable_type_parameter

不要对可能为空的对象使用 !

- null_closures

不要在可能使用的闭包中传入null

[1, 3, 5].firstWhere((e) => e.isOdd, orElse: null);       # BAD
[1, 3, 5].firstWhere((e) => e.isOdd, orElse: () => null); # GOOD

- package_api_docs

公用API要提供注释

- prefer_collection_literals (暂时没开)

#BAD
var points = List();
var addresses = Map();
var uniqueNames = Set();
var ids = LinkedHashSet();
var coordinates = LinkedHashMap();

#GOOD
var points = [];
var addresses = <String,String>{};
var uniqueNames = <String>{};
var ids = <int>{};
var coordinates = <int,int>{};

- prefer_conditional_assignment

使用 ??= 代替判断null

#BAD
String get fullName {
  if (_fullName == null) {
    _fullName = getFullUserName(this);
  }
  return _fullName;
}

# GOOD
String get fullName {
  return _fullName ??= getFullUserName(this);
}

- prefer_contains

在String和List中优先使用contains 代替indexOf

- prefer_equal_for_default_values

使用=将命名参数与其默认值分开。

m({a: 1})   #BAD
m({a = 1}) #GOOD

- prefer_final_in_for_each

在for each中不可变值使用final

for (final element in elements) {
  print('Element: $element');
}

- prefer_foreach

尽可能的多使用foreach

- prefer_function_declarations_over_variables

尽可能的使用函数声明

#BAD
void main() {
  var localFunction = () {
    ...
  };
}

#GOOD
void main() {
  localFunction() {
    ...
  }
}

- prefer_generic_function_type_aliases

使用泛型类型的函数别名

typedef F = void Function();

- prefer_if_null_operators

v = a == null ? b : a; #BAD
v = a ?? b;            #GOOD

- prefer_initializing_formals

#BAD
class Point {
  num x, y;
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}

#GOOD
class Point {
  num x, y;
  Point(this.x, this.y);
}

- prefer_inlined_adds

在列表初始化时就尽量声明全部参数,而不是后续使用add和addAll

var l2 = ['a']..addAll(['b', 'c'])  #BAD
var 2 = ['a', 'b', 'c'];            #GOOD

- prefer_is_empty

- prefer_is_not_empty

尽可能多用isEmpty和isNotEmpty代替判断length

- prefer_is_not_operator

#BAD
if (!(foo is Foo)) {
  ...
}

#GOOD
if (foo is! Foo) {
  ...
}

- prefer_iterable_whereType

iterable.where((e) => e is MyClass)  #BAD
iterable.whereType<MyClass>()        #GOOD

- prefer_null_aware_operators

v = a == null ? null : a.b;     #BAD
v = a?.b;                       #GOOD

- prefer_spread_collections

var things;

var l = ['a']..addAll(things ?? const []);  #BAD
var l = ['a', ...?things];                  #GOOD

 ListView(
      children: [
        Tab2Header(),
      ]..addAll(buildTab2Conversation()), #BAD
    ),

 ListView(
      children: [
        Tab2Header(),
        ...buildTab2Conversation(),    #GOOD
      ],
    ),

- prefer_void_to_null

如果void能使用的都用void代替使用null

Null f() {}     #BAD
void f() {}     #GOOD

- recursive_getters

get方法不要返回自身

int get field => field;   #BAD
int get field => _field;  #GOOD

- sized_box_for_whitespace

布局添加空白使用sizebox代替container,sizeBox更轻量,而且可以用const

- unnecessary_await_in_return

不必要的await不使用

Future<int> future;
Future<int> f1() async => await future;   #BAD 去掉await

- unnecessary_brace_in_string_interps

不必要的大括号不使用

print("Hi, ${name}!");     #BAD 去掉大括号
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容