Flutter Lints: Setup, Customize, and Enforce Quality

Flutter

Flutter lints are static rules that catch bugs and style issues before your app runs. This guide shows how to enable them, tune the rules, and enforce quality in CI for consistent, safer code.

Audience: IntermediateTested on: Flutter 3.x, Dart 3.x, macOS 14, Android 14 / iOS 17

Quick start: enable flutter_lints

Start with the official rule set. It strikes a good balance between safety and signal-to-noise.

# pubspec.yaml (excerpt)
dev_dependencies:
  flutter_lints: ^<latest>   # use the latest from pub.dev

# Create analysis_options.yaml at project root:
# analysis_options.yaml
include: package:flutter_lints/flutter.yaml
analyzer:
  exclude:
    - build/**
linter:
  rules:
    # add project-specific tweaks here

Run the analyzer:

dart analyze
# or
flutter analyze

Customize rules without causing churn

Start strict on correctness, lighter on style, then ratchet up. A common pattern:

# analysis_options.yaml (focused additions)
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    always_declare_return_types: true
    avoid_print: true
    prefer_const_constructors: true
    prefer_final_locals: true
    unawaited_futures: true

analyzer:
  language:
    strict-casts: true
    strict-inference: true
  errors:
    # escalate or downgrade severities (info | warning | error)
    dead_code: error
    unnecessary_cast: warning

Need an exception in code? Prefer targeted ignores:

// ignore: prefer_const_constructors
final w = Widget();

Linting for Flutter-specific patterns

  • prefer_const_constructors: Build faster UIs by marking widgets constant.
  • use_key_in_widget_constructors: Keep widget identity stable for diffing.
  • avoid_redundant_argument_values: Let defaults speak; clearer APIs.
  • unnecessary_await_in_return: Avoid extra microtasks in async code.

Organize options for mono-repos

Put a shared config in tool/analysis_options.yaml and have packages include it:

# package A/B/C analysis_options.yaml
include: ../../tool/analysis_options.yaml

Wire lints into CI

Fail builds when new warnings appear. Example GitHub Actions step:

- name: Analyze
  run: |
    flutter pub get
    dart analyze --fatal-infos --fatal-warnings

For incremental adoption, start with dart analyze, then add --fatal-warnings after the backlog is cleaned.

Security & pitfalls

  • Too many global ignores: They hide real defects; prefer narrow // ignore: lines.
  • Over-styling: Style-only rules can drown signal; focus first on correctness and performance.
  • Dead code drift: Keep dead_code as error to prevent unused branches accumulating.

FAQ

Q. flutter_lints vs. custom rules?
A. Start with flutter_lints for broad coverage; add a handful of custom rules that reflect your team’s priorities.

Q. Should warnings fail CI?
A. Yes—once the backlog is zero. Until then, gate only on errors to avoid blocking progress.

Q. How do I silence false positives?
A. Prefer targeted // ignore: with a reason. If recurring, adjust the single rule in analysis_options.yaml.

Conclusion

Enable flutter_lints, add a few high-value rules, and enforce them in CI. Tune slowly to keep signal high. The result is a codebase that’s consistent, reviewable, and safer to change.

https://pub.dev/packages/flutter_lints
https://dart.dev/tools/linter-rules
https://docs.flutter.dev/development/tools/analysis
https://github.com/dart-lang/linter

Updated: 2025-10-09

Comment

Copied title and URL