use-late-for-private-fields-and-variables
Same as use_late_for_private_fields_and_variables in Dart lints
- Group
- Style
- Path
lint/style/use-late-for-private-fields-and-variables- Default
- Off, opt in
- Origin
- Dart lints
- Rule
- 495 of 512
Flags a private nullable field or top-level variable that is only ever
assigned non-null values and read through !, so it could be late with a
non-nullable type.
When every read of a private variable is a null assertion and every write
stores a non-nullable value, the nullable type only exists to defer
initialization; late expresses that and moves the null check into the
runtime. Candidates are private (underscore) top-level variables and private
fields (instance or static), plus every field of a private extension; instance
fields of extension types, fields of classes with a const constructor, and
all enum members are skipped, as are late, const, external, and
abstract declarations. Any other use — a plain read, a this._x
initializing formal, a : _x = ... initializer, a compound or ??=
assignment, or an assignment whose value is not proven non-nullable —
disqualifies the referenced declaration. Qualified and cascade accesses are
attributed to their resolved declaration, not every implementation of an
interface member. Uses in every resolved library part are checked together;
unresolved parts prevent proving a candidate safe.
int? _i; // flagged
void f() {
_i = 1;
print(_i!);
}
Invalid
int? _i;
String? _name;
void setUp() {
_i = 1;
_name = 'falcon';
}
void use() {
print(_i!);
print(_name!.length);
}
class Cache {
List<int>? _items;
static String? _label;
Object? _value = Object();
void init() {
_items = [1, 2, 3];
_label = 'cache';
}
int get first => _items!.first;
String get label => _label!;
Object get value => _value!;
}
class Counter {
int? _count;
void reset() {
this._count = 0;
}
int next() => _count! + 1;
}
// Each class's field is its own declaration: a plain read of the other
// class's same-named field does not disqualify this one.
class NullAsserted {
int? _count;
int next() => _count! + 1;
}
// A read inside a class with a const constructor is not visited.
class ConstReader {
const ConstReader();
int? read() => _i;
}
// Writes through a type name keep the field lateable.
class Qualified {
static int? _shared;
static int read() => _shared!;
}
void initShared() {
Qualified._shared = 1;
}
extension _Helpers on String {
static int? cached;
int get size {
cached = 3;
return cached!;
}
}int? _i; String? _name;class Cache { List<int>? _items; List<int>? _items; static String? _label; static String? _label; Object? _value = Object();class Counter { int? _count;class NullAsserted { int? _count;class Qualified { static int? _shared;extension _Helpers on String { static int? cached;Valid
late int _lateInt;
int? publicNullable;
int? _readPlain;
int? _assignedNull;
int _nonNullable = 0;
void use() {
_lateInt = 1;
print(_lateInt);
publicNullable = 1;
print(publicNullable!);
print(_readPlain);
_assignedNull = null;
print(_assignedNull!);
_nonNullable = 2;
print(_nonNullable);
}
int? _compound;
void bump() {
_compound ??= 1;
print(_compound!);
}
class Holder {
int? _initialized;
int? _publicRead;
int? _nullableWrite;
Holder(this._initialized);
int get value => _initialized!;
int? get raw => _publicRead;
void write(int? next) {
_nullableWrite = next;
print(_nullableWrite!);
}
}
class ConstHolder {
final int? _value;
const ConstHolder(this._value);
int get value => _value!;
}
enum Mode {
a;
static int? _cached;
static int get cached => _cached!;
}
class Initialized {
String? _name;
Initialized() : _name = 'x';
String get name => _name!;
}
// Through `this.` or another receiver, the analyzer also visits the bare
// property name, which counts as a nullable read even under `!`.
class ThisAsserted {
int? _count;
void reset() {
this._count = 0;
}
int next() => this._count! + 1;
}
class PlainReader {
int? _count;
void reset() {
_count = 0;
}
int? peek(PlainReader other) => other._count;
}
class Shadowed {
int? _total;
void reset() {
_total = 0;
}
int? read() => _total;
}
// `Type._x!` is a prefixed identifier: its bare name is a nullable read.
class QualifiedRead {
static int? _shared;
static void init() {
_shared = 1;
}
}
int sharedValue() => QualifiedRead._shared! + 1;Configure use-late-for-private-fields-and-variables
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"style": {
"use-late-for-private-fields-and-variables": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/style/use-late-for-private-fields-and-variables: <reason>More style rules
- use-named-constants
use_named_constantsrecommendedPrefers a class's predefined static constant to constructing an equal constant.
- use-raw-strings
use_raw_stringsFlags string literals whose only escapes are
\\and\$, which a raw string would express without any backslash. - use-setters-to-change-properties
use_setters_to_change_propertiesFlags one-parameter
voidmethods that only assign that parameter to a field. - use-spacer-as-expanded-child
use_spacer_as_expanded_childrecommendedflutterFlags an
Expandedwrapping an emptySizedBoxorContainerthat should be aSpacer. - use-string-in-part-of-directives
use_string_in_part_of_directivesrecommendedFlags a
part ofdirective that names its library instead of using a string URI. - use-super-parameters
use_super_parametersrecommendedPrefer super parameters when a constructor only forwards parameters to its superclass.
- use-test-throws-matchers
use_test_throws_matchersrecommendedPrefers
throwsAmatchers overtry { ...; fail(...); } catch (...) {}. - use-to-and-as-if-applicable
use_to_and_as_if_applicableFlags conversion methods not named
to…oras….