unnecessary-null-aware-operator-on-extension-on-nullable

Same as unnecessary_null_aware_operator_on_extension_on_nullable in Dart lints

Group
Style
Path
lint/style/unnecessary-null-aware-operator-on-extension-on-nullable
Default
Off, opt in
Origin
Dart lints
Rule
463 of 512

Flags a null-aware access whose member comes from an extension on a nullable type.

An extension declared on String? already accepts null, so s?.member skips a call the extension could handle, and s.member is what the author means. The rule fires on ?. property and method access and on ?[] index access when the target is an extension override (E(s)?.member) of an extension on a nullable type, or when the target's static type is nullable and every visible extension supplying that member to the type is on a nullable type. Members the target's own class declares win over extensions and are not checked; for SDK classes falcon uses the loaded SDK sources, or without them its curated dart:core table (e.g. String.length, String.[]).

Every section of a null-aware cascade (x?..m()..n()) is null-aware too; each section's leading member is checked against the cascade target. An extension on dynamic (or void) is on a nullable type.

Imported extensions participate even through prefixed imports, subject to show/hide combinators and exports. Explicit overrides resolve the extension by declaration identity, including qualified names. The rule stays silent when it cannot tell which extensions apply.

Invalid

example.dartdart
extension NullableText on String? {
  bool get isBlank => this == null || this!.trim().isEmpty;
  String orEmpty() => this ?? '';
  int operator [](int index) => this?.codeUnitAt(index) ?? 0;
  set label(String value) {}
}

class Crate {
  const Crate(this.size);
  final int size;
}

extension NullableCrate on Crate? {
  int area() => this == null ? 0 : this!.size * this!.size;
  int operator [](int index) => index;
}

void main(String? text, Crate? box) {
  print(text?.isBlank);
  print(text?.orEmpty());
  text?.label = 'x';
  print(box?[0]);
  print(box?.area());
  print(NullableText(text)?.orEmpty());
  print(box /* ? */
      ?[0]);
  text /* ?. */
      ?.label = 'x';
}
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
18void main(String? text, Crate? box) {
19 print(text?.isBlank);
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
19 print(text?.isBlank);
20 print(text?.orEmpty());
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
20 print(text?.orEmpty());
21 text?.label = 'x';
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
21 text?.label = 'x';
22 print(box?[0]);
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
22 print(box?[0]);
23 print(box?.area());
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
23 print(box?.area());
24 print(NullableText(text)?.orEmpty());
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
25 print(box /* ? */
26 ?[0]);
Remove the unnecessary null-aware operator when invoking this extension method on a nullable type.
27 text /* ?. */
28 ?.label = 'x';

Valid

example.dartdart
extension NullableText on String? {
  bool get isBlank => this == null || this!.trim().isEmpty;
  int get length => 0;
  int operator [](int index) => 0;
}

extension NonNullText on String {
  String shout() => toUpperCase();
}

class Box {
  const Box(this.size);
  final int size;
  int area() => size * size;
}

extension NullableBox on Box? {
  int area() => 0;
}

extension MaybeNum on num? {
  bool get isPositive => this != null && this! > 0;
}

extension NonNullInt on int {
  bool get isPositive => this > 0;
}

void main(String? text, Box? box, int? count) {
  print(text.isBlank);
  print(text?.shout());
  print(box?.area());
  print(text?.length);
  print(count?.isPositive);
  print(NonNullText(text ?? '').shout());
  // `String` declares `length` and `[]`; instance members win over extensions.
  print(text?.length);
  print(text?[0]);
}

Configure unnecessary-null-aware-operator-on-extension-on-nullable

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "unnecessary-null-aware-operator-on-extension-on-nullable": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/unnecessary-null-aware-operator-on-extension-on-nullable: <reason>
  • unnecessary-null-checksunnecessary_null_checks

    Flags a null assertion ! on a value that flows into a nullable context.

  • unnecessary-nullable-for-final-variable-declarationsunnecessary_nullable_for_final_variable_declarationsrecommended

    Flags a final or const variable given a nullable type but initialized to a provably non-null value.

  • unnecessary-parenthesisunnecessary_parenthesisrecommended

    Flags parentheses that can be removed without changing the meaning or hurting readability.

  • unnecessary-raw-stringsunnecessary_raw_stringsrecommended

    Flags raw string literals that contain no backslash or $.

  • unnecessary-string-escapesunnecessary_string_escapesrecommended

    Flags backslashes that do not affect a string's value.

  • unnecessary-string-interpolationsunnecessary_string_interpolationsrecommended

    Flags a string literal whose entire content is a single interpolation of a provably non-nullable String.

  • unnecessary-thisunnecessary_thisrecommended

    Flags a redundant this. qualifier on member access.

  • unreachable-from-mainunreachable_from_main

    Report public declarations that no entry point of an executable library reaches.