prefer-is-empty
Same as prefer_is_empty in Dart lints
- Group
- Style
- Path
lint/style/prefer-is-empty- Default
- On (recommended)
- Origin
- Dart lints
- Rule
- 376 of 512
Flags .length comparisons equivalent to a .isEmpty check.
Collections and strings expose an isEmpty getter that states intent
directly and, for lazy iterables, can be cheaper than computing the full
length. Comparing length against a constant forces the reader to decode
the boundary, so list.isEmpty should replace forms such as length == 0,
length < 1, and length <= 0, together with their operand-swapped mirrors
(0 == length, 1 > length, 0 >= length).
Only a plain .length property access matches against the relevant integer
literal. A null-aware receiver?.length is deliberately left alone: that
comparison also has to account for a null receiver, so isEmpty is not a
drop-in replacement.
Semantic analysis requires declaration identities. Once available, an
unknown receiver still triggers the lint. A TypeIndex can suppress it only
when the receiver is proven to have no isEmpty member and not to be an
Iterable, String, or Map; source-resolved members and subtypes take
precedence. Without a type index, those negative proofs are unavailable,
but source-derived receiver types are still inferred.
Invalid
void bad() {
if (list.length == 0) return;
if (0 == items.length) return;
if (str.length < 1) return;
if (map.length <= 0) return;
if (1 > set.length) return;
if (0 >= names.length) return;
}
// A class implementing a core collection still inherits `isEmpty` (from
// Iterable), so the suggestion is valid and the diagnostic keeps firing.
class Bag implements Iterable<int> {
int get length => 0;
}
// A class whose supertype chain leaves the project is `Unknown`, never
// `ProvenAbsent` — an unresolved ancestor could contribute `isEmpty` — so the
// diagnostic keeps firing (type knowledge suppresses only on positive proof).
class Offsite extends Frobnicator {
int get length => 0;
}
void typedReceivers(Bag b, Offsite o) {
if (b.length == 0) return;
if (o.length == 0) return;
}
// A static method returns some other type (a Map here), not the enclosing class,
// so `Config.load()` is Unknown, never `Config`. Typing it as `Config` (a named
// constructor guess) would wrongly suppress; the diagnostic must keep firing.
class Config {
static Map<String, String> load() => {};
}
void staticCallReceiver() {
if (Config.load().length == 0) return;
}void bad() { if (list.length == 0) return; if (list.length == 0) return; if (0 == items.length) return; if (0 == items.length) return; if (str.length < 1) return; if (str.length < 1) return; if (map.length <= 0) return; if (map.length <= 0) return; if (1 > set.length) return; if (1 > set.length) return; if (0 >= names.length) return;void typedReceivers(Bag b, Offsite o) { if (b.length == 0) return; if (b.length == 0) return; if (o.length == 0) return;void staticCallReceiver() { if (Config.load().length == 0) return;Valid
void good() {
if (list.isEmpty) return;
if (items.length == 2) return;
if (str.length > 0) return;
if (map.length != 0) return;
if (set.length >= 1) return;
if (count == 0) return;
}
// A user class with only a `length` getter — no `isEmpty`, and not a core
// collection/string. Its receiver type is positively proven, so `length == 0`
// is SUPPRESSED: suggesting `isEmpty` would reference a member it does not have.
// (Requires the corpus harness to attach a TypeIndex for this rule; without one
// the receiver is Unknown and this line would fire.)
class Ruler {
int get length => 3;
}
void suppressed(Ruler r) {
if (r.length == 0) return;
}
// A named constructor `Box.zero()` still resolves to a `Box` instance (a real
// constructor is not a declared member), and `Box` has only `length` and is no
// collection — so this stays SUPPRESSED, unlike a static-method call.
class Box {
Box.zero();
int get length => 0;
}
void suppressedCtor() {
if (Box.zero().length == 0) return;
}Configure prefer-is-empty
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"style": {
"prefer-is-empty": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/style/prefer-is-empty: <reason>More style rules
- prefer-is-not-empty
prefer_is_not_emptyrecommendedFlags
.lengthcomparisons equivalent to a.isNotEmptycheck. - prefer-is-not-operator
prefer_is_not_operatorrecommendedFlags a negated type test
!(x is T)that should use theis!operator. - prefer-iterable-of
prefer-iterable-ofrecommendedFlags
.fromcollection constructors in favor of the.ofconstructor. - prefer-iterable-where-type
prefer_iterable_whereTyperecommendedFlags
.where((e) => e is T), which.whereType<T>()expresses directly. - prefer-last
prefer-lastFlags manual last-element indexing in favor of the
.lastgetter. - prefer-match-file-name
Match a file's sole class or enum name to its snake-case basename.
- prefer-mixin
prefer_mixinrecommendedFlags
withclauses that mix in a plain class instead of a mixin. - prefer-multi-bloc-providerbloc
Flatten directly nested
package:flutter_blocBlocProviderswithMultiBlocProvider.