MoveVariableCloserToUsageRule class
Warns when a variable is declared several unrelated statements before its first use and the declaration can move closer without changing semantics.
Since: v0.1.4 | Updated: v14.5.10 | Rule version: v9
Alias: move_variable_closer_to_usage
Distance is measured in intervening sibling statements, not source lines, so a single multi-line initializer never counts as "far". A statement is excluded from that count only when it is genuinely part of the same batch as the declaration being measured: another declaration in the same contiguous run of declarations whose own variable is itself used somewhere (not dead clutter that merely sits nearby), or the first-use statement of another variable from that same run. This lets a deliberate "load N, then consume N" batch (e.g. five awaited loads followed by five assignments consuming them in order) read as one legible unit instead of each member accumulating false distance from its position in the group, while an unrelated declaration that just happens to sit next to a lonely one still counts toward the threshold.
Known limitations, accepted for now: the contiguous-run requirement has zero tolerance for a single incidental non-declaration statement splitting a real batch's load group (e.g. a stray log line between two loads), which would reintroduce the original false positive on the later half of that batch — not yet seen in practice, revisit if reported. A variable counts as "genuinely used" for group-membership purposes even when its only use is nested inside a loop/branch/closure (unlike the direct-child guard the rule itself enforces), on the theory that any recorded use still proves the declaration isn't dead clutter.
The rule stays silent when the first use is nested inside a loop, branch, nested block, or closure: moving an accumulator into a loop would reset it every iteration, and moving a value into one branch would drop it from sibling branches that also read it. See plans/history/2026.05/2026.05.21/move_variable_closer_to_its_usage_false_positive_loop_accumulator.md and plans/history/2026.08/2026.08.15/move_variable_closer_to_its_usage_false_positive_batch_declaration_grouping.md.
Example of bad code:
void foo() {
final x = computeX();
stepOne();
stepTwo();
stepThree();
print(x); // x sat unread through three unrelated statements
}
Example of good code:
void foo() {
stepOne();
stepTwo();
stepThree();
final x = computeX();
print(x);
}
Example of code that is left alone (accumulator must enclose the loop):
List<String> parse(String line) {
final fields = <String>[];
for (int i = 0; i < line.length; i++) {
fields.add(line[i]); // first use is inside the loop — not flagged
}
return fields;
}
Example of code that is left alone (deliberate batch load, then batch assign in the same order — the intervening siblings are themselves declarations, not unrelated statements):
Future<StartupResult> loadStartup() async {
final driftOk = await initDrift();
final prefsOk = await initPrefs();
final permsOk = await initPermissions();
final result = StartupResult();
result.driftOk = driftOk; // not flagged: siblings were declarations
result.prefsOk = prefsOk;
result.permsOk = permsOk;
return result;
}
- Inheritance
-
- Object
- SaropaLintRule
- MoveVariableCloserToUsageRule
Constructors
Properties
- accuracyTarget → AccuracyTarget?
-
Optional accuracy target for this rule (for documentation and tooling).
Does not enforce; used by reports and rule-audit scripts.
no setterinherited
-
applicableFileTypes
→ Set<
FileType> ? -
The file types this rule applies to.
no setterinherited
- canUseParsedResult → bool
-
Indicates whether this analysis rule can work with just the parsed
information or if it requires a resolved unit.
no setterinherited
-
certIds
→ List<
String> -
CERT coding standard identifiers (e.g. STR02-C). Populate only where
there is a clear mapping; leave empty for most rules initially.
no setterinherited
- code → LintCode
-
The lint code for this rule.
no setterinherited
-
configAliases
→ List<
String> -
Alternate config keys that can be used to reference this rule.
no setterinherited
-
conflictingRules
→ List<
String> -
Curated opposite/competing rule names.
no setterinherited
- cost → RuleCost
-
The estimated execution cost of this rule.
no setteroverride
-
cweIds
→ List<
int> -
CWE identifiers this rule helps prevent or detect.
https://cwe.mitre.org/ — e.g. CWE-798 (Hardcoded Credentials).
no setterinherited
- description → String
-
Short description suitable for display in console output and IDEs.
finalinherited
- diagnosticCode → DiagnosticCode
-
The code to report for a violation.
no setterinherited
-
diagnosticCodes
→ List<
DiagnosticCode> -
The diagnostic codes associated with this analysis rule.
no setterinherited
- documentationUrl → String
-
Returns the documentation URL for this rule.
no setterinherited
- effectiveSeverity → DiagnosticSeverity?
-
Get the effective severity for this rule, considering overrides.
no setterinherited
- exampleBad → String?
-
Short code example that VIOLATES this rule (shown in CLI walkthrough).
no setterinherited
- exampleGood → String?
-
Short code example of COMPLIANT code (shown in CLI walkthrough).
no setterinherited
-
fixGenerators
→ List<
SaropaFixGenerator> -
Fix producer generators for this rule.
no setteroverride
- hashCode → int
-
The hash code for this object.
no setterinherited
- hyphenatedName → String
-
Returns the rule name in hyphenated format for display.
no setterinherited
- impact → LintImpact
-
Code quality issue. Review when count exceeds 100.
no setteroverride
-
incompatibleRules
→ List<
String> -
A list of incompatible rule names.
no setterinherited
- isDisabled → bool
-
Check if this rule is disabled via configuration.
no setterinherited
- maximumLineCount → int
-
Maximum line count for this rule to run.
no setterinherited
- minimumLineCount → int
-
Minimum line count for this rule to run.
no setterinherited
- name → String
-
The rule name.
finalinherited
- owasp → OwaspMapping?
-
OWASP categories this rule helps prevent.
no setterinherited
- pubspecVisitor → PubspecVisitor?
-
A visitor that visits a
Pubspecto perform analysis.no setterinherited -
Curated "see also" rule names for discoverability in docs/IDE tooling.
no setterinherited
- reporter ← DiagnosticReporter
-
Sets the
DiagnosticReporterfor theCompilationUnitcurrently being visited.no getterinherited -
requiredPatterns
→ Set<
String> ? -
String patterns that must be present in the file for this rule to run.
no setterinherited
- requiresAsync → bool
-
Whether this rule only applies to async code.
no setterinherited
- requiresBlocImport → bool
-
Whether this rule only applies to files that import Bloc.
no setterinherited
- requiresClassDeclaration → bool
-
Whether this rule only applies to files with class declarations.
no setterinherited
- requiresFlutterImport → bool
-
Whether this rule only applies to files that import Flutter.
no setterinherited
- requiresImports → bool
-
Whether this rule only applies to files with imports.
no setterinherited
- requiresMainFunction → bool
-
Whether this rule only applies to files with a main() function.
no setterinherited
- requiresProviderImport → bool
-
Whether this rule only applies to files that import Provider.
no setterinherited
- requiresRiverpodImport → bool
-
Whether this rule only applies to files that import Riverpod.
no setterinherited
- requiresWidgets → bool
-
Whether this rule only applies to Flutter widget code.
no setterinherited
- ruleStatus → RuleStatus
-
Lifecycle status. Default RuleStatus.ready. Use RuleStatus.beta for
new or heuristic-heavy rules; RuleStatus.deprecated for sunset.
no setterinherited
- ruleType → RuleType?
-
Semantic type of this rule. Default
null= unspecified (legacy). When set, used for quality gates, accuracy targets, and reporting.no setteroverride - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- skipExampleFiles → bool
-
Whether to skip example files (example/**).
no setterinherited
- skipFixtureFiles → bool
-
Whether to skip fixture files (fixture/, fixtures/).
no setterinherited
- skipGeneratedCode → bool
-
Whether to skip generated files (*.g.dart, *.freezed.dart, *.gen.dart).
no setterinherited
- skipTestFiles → bool
-
Whether to skip test files (*_test.dart, test/**).
no setterinherited
- state → RuleState
-
The state of this analysis rule.
finalinherited
-
supersedesRules
→ List<
String> -
Rule names this rule supersedes/replaces.
no setterinherited
-
Tags for filtering and discovery (e.g. in docs, IDE, or CI).
Examples: 'performance', 'accessibility', 'suspicious', 'convention'.
no setteroverride
- testRelevance → TestRelevance
-
How this rule relates to test files.
no setterinherited
- usesTypeResolution → bool
-
Whether this rule triggers lazy cross-library type resolution in the
analyzer (e.g.
.staticType,.library,.allSupertypes,.enclosingElement).no setteroverride
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
registerNodeProcessors(
RuleVisitorRegistry registry, RuleContext context) → void -
Registers node processors in the given
registry.inherited -
reportAtNode(
AstNode? node, {List< Object> arguments = const [], List<DiagnosticMessage> ? contextMessages}) → Diagnostic? -
Reports a diagnostic at
nodewith messageargumentsandcontextMessages.inherited -
reportAtOffset(
int offset, int length, {List< Object> arguments = const [], List<DiagnosticMessage> ? contextMessages}) → Diagnostic -
Reports a diagnostic at
offset, withlength, with messageargumentsandcontextMessages.inherited -
reportAtPubNode(
PubspecNode node, {List< Object> arguments = const [], List<DiagnosticMessage> contextMessages = const []}) → Diagnostic -
Reports a diagnostic at Pubspec
node, with messageargumentsandcontextMessages.inherited -
reportAtSourceRange(
SourceRange sourceRange, {List< Object> arguments = const [], List<DiagnosticMessage> ? contextMessages}) → Diagnostic -
Reports a diagnostic at
sourceRange, with messageargumentsandcontextMessages.inherited -
reportAtToken(
Token token, {List< Object> arguments = const [], List<DiagnosticMessage> ? contextMessages}) → Diagnostic? -
Reports a diagnostic at
token, with messageargumentsandcontextMessages.inherited -
runWithReporter(
SaropaDiagnosticReporter reporter, SaropaContext context) → void -
Override this method to implement your lint rule.
override
-
shouldSkipFile(
String path) → bool -
Check if a file path should be skipped based on context settings.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited