avoid_banned_annotations
Flags annotations you ban, optionally only inside the directories you name. The motivating case is scope: @visibleForTesting is reasonable on a helper and wrong in a production directory.
This rule reports nothing until you configure it.
Why use this rule
Section titled “Why use this rule”@visibleForTesting is a way of saying “this is private, except to tests”. That is a fair trade in a utility, but in a core production type it is how encapsulation erodes: the annotation makes the widening explicit without making it rare, and nothing pushes back when the next test wants one more member.
Banning it in the directories that hold your most-depended-on code forces the alternative — inject the seam the test needs rather than opening the type — while leaving it available everywhere else.
See also: package:meta annotations, visibleForTesting API docs
// in lib/production/payment_service.dart//// With an entry banning 'visibleForTesting' in lib/production/**:class PaymentService { @visibleForTesting // LINT: widens visibility in production code void resetLedger() {}}// in lib/production/payment_service.dart//// Inject what the test needs to control instead of exposing internals.abstract class Ledger { void reset();}
class PaymentService { const PaymentService(this._ledger);
final Ledger _ledger;
void refundAll() => _ledger.reset();}Turning this rule off
Section titled “Turning this rule off”This rule is in no preset, so it is off unless you enable it by name:
rules: avoid_banned_annotations: trueTo turn it off again:
rules: avoid_banned_annotations: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Options
Section titled “Options”many_lints: rules: avoid_banned_annotations: banned: - deny: ['visibleForTesting'] in: ['lib/production/**'] message: 'Production code must not widen visibility for tests.'rules: avoid_banned_annotations: banned: - deny: ['visibleForTesting'] in: ['lib/production/**'] message: 'Production code must not widen visibility for tests.'| Option | Type | Default | Description |
|---|---|---|---|
banned |
list of maps | [] |
The entries to enforce. With none, the rule reports nothing |
Each entry accepts:
| Key | Type | Required | Description |
|---|---|---|---|
deny |
string or list | one of deny / deny_pattern |
Annotation names banned by exact match, written without the @ |
deny_pattern |
string or list | one of deny / deny_pattern |
Regular expressions, anchored to the whole name |
in |
list of globs | no | Paths, relative to the package root, where the entry applies. Omit to apply everywhere |
message |
string | no | A project-specific explanation appended to the diagnostic |
Write the annotation name without the @. Both @visibleForTesting and the prefixed @meta.visibleForTesting match a single visibleForTesting entry, so an import prefix cannot slip past the rule.
Related rules
Section titled “Related rules”avoid_banned_exports— Ban re-exports of specific libraries, optionally scoped by directory.avoid_banned_imports— Ban imports of specific libraries, optionally scoped by directory.avoid_banned_names— Ban specific identifiers from being used as declaration names.avoid_banned_types— Ban specific types from being named, optionally scoped by directory.