unreachable-from-main
Same as unreachable_from_main in Dart lints
- Group
- Style
- Path
lint/style/unreachable-from-main- Default
- Off, opt in
- Origin
- Dart lints
- Rule
- 477 of 512
Report public declarations that no entry point of an executable library reaches.
A library — its defining unit plus every part file — is executable when it
declares a top-level function named main, or a top-level function
annotated @pragma('vm:entry-point') whose pragma provably resolves to
dart:core. Starting from those entry points (and from top-level functions
annotated with a widget-preview @Preview), the rule follows references:
identifiers, invocations, constructor names and tear-offs, annotations,
user-defined operators, object-pattern fields, doc comment references,
supertypes named in a class's extends/with/implements clause or an
extension type's implements clause, implicit super-constructor calls,
typedef and extension-type names, type literals, type arguments, and the
types of external members. Type parameters shadow same-named library
declarations. A plain type annotation is not a reference, and
constructor invocations inside constant patterns do not count. Instance
toJson methods are reachable with their container, because dart:convert
calls them dynamically.
Documentation references use the shared Dartdoc parser, excluding Markdown
link display text and link definitions, inline and block code, and Dartdoc
directives. Reference-style destination labels remain references.
A block documentation comment replaces immediately preceding line docs,
following the shared documentation grouping used by other rules.
The candidates are the library's top-level declarations and the public
constructors (except enum constructors), fields, methods, getters, setters,
and operators of public classes, enums, mixins, extensions, and extension
types. A member that overrides a supertype member is not a candidate, nor
are the test-harness methods test_*, solo_test_*, setUp, tearDown,
setUpClass, and tearDownClass. Unreached public candidates are reported
unless annotated @visibleForTesting or a widget preview; a member other
than a field is not reported again when its enclosing declaration already
is (the analyzer reports unreachable fields of an unreachable class too).
Libraries that declare a top-level name twice are not analyzed.
Facts falcon cannot prove are resolved toward reachability, so uncertainty causes misses rather than false positives: a member whose container has a supertype with an incomplete indexed hierarchy may override it and is not a candidate. Known receiver types resolve members and operators before considering extensions. An unknown receiver reaches same-named members only in extensions or classes named outside their own declaration (a class never named cannot be its static type); an identifier counts unless it resolves to a local. A library with a part that does not resolve to an analyzed file is not analyzed.
Invalid
void main() {
Used();
print(Used.new);
Child();
Holder().value;
print(Shade.dark);
helper();
var shadowed = 1;
print(shadowed);
Object probe = 1;
if (probe is OnlyInIsCheck) {}
if (probe case const OnlyInConstantPattern()) {}
Shadower().run();
if (probe case OnlyInObjectPattern()) {}
dynamic untyped = probe;
untyped.sharedName();
}
void helper() {}
class NeverNamed {
void sharedName() {}
}
class Shadower {
void run() {
print(label());
}
String label() => 'member';
}
String label() => 'top-level';
void orphanFunction() {}
int orphanVariable = 1;
int shadowed = 2;
int get orphanGetter => 7;
set orphanSetter(int value) {}
typedef OrphanAlias = String;
class OrphanClass {
void memberOfUnreachableClass() {}
}
class OrphanWithField {
int orphanField = 0;
static const orphanConstant = 1;
}
mixin OrphanMixin {}
enum OrphanEnum { a, b }
extension OrphanExtension on int {}
extension type OrphanExtensionType(int value) {}
@pragma('other')
void unrelatedPragma() {}
void setUpClass() {}
class Used {
Used();
Used.named();
void unusedMethod() {}
int? unusedField;
static void unusedStatic() {}
int get unusedGetter => 0;
set unusedSetter(int value) {}
Used operator +(Used other) => this;
}
class Base {
void overridden() {}
}
class Child extends Base {
@override
void overridden() {}
}
class OnlyInTypeAnnotation {}
class Holder {
OnlyInTypeAnnotation? value;
}
class OnlyInIsCheck {}
class OnlyInConstantPattern {
const OnlyInConstantPattern();
}
class OnlyInObjectPattern {}
enum Shade {
dark,
light;
static void unusedEnumStatic() {}
}
extension IntExtension on int {
void unusedExtensionMethod() {}
} class NeverNamed { String label() => 'top-level'; void orphanFunction() {} int orphanVariable = 1; int shadowed = 2; int get orphanGetter => 7; set orphanSetter(int value) {} typedef OrphanAlias = String; class OrphanClass { class OrphanWithField {class OrphanWithField { int orphanField = 0; int orphanField = 0; static const orphanConstant = 1; mixin OrphanMixin {} enum OrphanEnum { a, b } extension OrphanExtension on int {} extension type OrphanExtensionType(int value) {}@pragma('other')void unrelatedPragma() {} void setUpClass() {} Used(); Used.named(); void unusedMethod() {} void unusedMethod() {} int? unusedField; int? unusedField; static void unusedStatic() {} static void unusedStatic() {} int get unusedGetter => 0; int get unusedGetter => 0; set unusedSetter(int value) {} set unusedSetter(int value) {} Used operator +(Used other) => this;class Base { void overridden() {} class OnlyInTypeAnnotation {} class OnlyInIsCheck {} class OnlyInConstantPattern { class OnlyInObjectPattern {} static void unusedEnumStatic() {} extension IntExtension on int {Valid
import 'dart:convert';
import 'package:meta/meta.dart';
/// The entry point; see [DocumentedOnly] and [Service.describe].
void main() {
final service = Service.create();
service.run();
service.counter += 1;
print(service[0]);
print(-service);
print(service + 1);
print(TypeLiteralOnly);
print(<TypeArgumentOnly>[]);
Callback? callback;
callback = () {};
callback();
print(1 as Wrapped);
print(jsonEncode([Serializable()]));
print(Palette.red.label);
print(Box(1).unwrap());
final point = Point(1, 2);
if (point case Point(:final x)) {
print(x + point.y);
}
print(Derived().inherited());
print(Holder.instance);
print(OutsideError().detail);
topLevelSetter = 3;
print(topLevelGetter);
annotatedByConstant();
}
class DocumentedOnly {}
class Service {
Service._();
factory Service.create() = Service._;
int counter = 0;
void run() {
_helper();
}
void _helper() {}
static void describe() {}
int operator [](int index) => index;
Service operator -() => this;
Service operator +(int other) => this;
@visibleForTesting
void inspect() {}
void test_harnessMethod() {}
void setUp() {}
}
class TypeLiteralOnly {}
class TypeArgumentOnly {}
typedef Callback = void Function();
extension type Wrapped(int value) {}
class Serializable {
List<Object> toJson() => const ['value'];
}
enum Palette {
red('red');
const Palette(this.label);
final String label;
}
class Box<T> {
Box(this.value);
final T value;
T unwrap() => value;
}
class Point {
Point(this.x, this.y);
final int x;
final int y;
}
class Parent {
Parent();
String inherited() => 'parent';
}
class Derived extends Parent {}
class Holder {
static final Holder instance = Holder._();
Holder._();
}
class OutsideError extends Error {
String get detail => 'outside';
}
set topLevelSetter(int value) {}
int get topLevelGetter => 0;
const entry = pragma('vm:entry-point');
@entry
void annotatedByConstant() {}
@pragma('vm:entry-point')
void nativeCallback() {
calledFromCallback();
}
void calledFromCallback() {}
@visibleForTesting
void testOnlyHook() {}Configure unreachable-from-main
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"style": {
"unreachable-from-main": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/style/unreachable-from-main: <reason>More style rules
- use-colored-box
use_colored_boxrecommendedflutterPrefers
ColoredBoxover aContainerthat only paints a color behind its child. - use-decorated-box
use_decorated_boxrecommendedflutterPrefers
DecoratedBoxover aContainerthat only decorates its child. - use-design-system-item
use-design-system-itemflutterFlags construction of a widget or type that should be replaced by its design-system equivalent.
- use-enums
use_enumsFlags classes that emulate an enum and could be declared as one.
- use-existing-destructuring
Reuse or extend an existing record destructuring instead of rereading a field.
- use-existing-variable
Reuse a local for stable SDK arithmetic and String.length/int parity getters.
- use-full-hex-values-for-flutter-colors
use_full_hex_values_for_flutter_colorsrecommendedflutterRequire an eight-digit hexadecimal integer for the canonical Flutter Color default constructor.
- use-function-type-syntax-for-parameters
use_function_type_syntax_for_parametersrecommendedFlags an old-style function-typed parameter written with inline parameter syntax.