saropa_lints 1.2.0
saropa_lints: ^1.2.0 copied to clipboard
500+ custom lint rules for Flutter and Dart. Static analysis for security, accessibility, and performance. Free and open source. 5 tiers from Essential to Insanity.

saropa_lints #
Developed by Saropa. Making the world of Dart & Flutter better, one lint at a time.
Why saropa_lints? #
Linting vs static analysis #
flutter analyze checks syntax and style. Static analysis checks behavior.
Your linter catches unused variables and formatting issues. It doesn't catch undisposed controllers, hardcoded credentials, or setState after dispose — because these require understanding what the code does, not just how it's written.
In mature ecosystems, tools like SonarQube, Coverity, and Checkmarx fill this gap. Flutter hasn't had an equivalent — until now.
What it catches #
Code that compiles but fails at runtime:
// Memory leak — controller never disposed
final _controller = TextEditingController();
// Crash — setState after widget disposed
await api.fetchData();
setState(() => _data = data); // boom
// State loss — new GlobalKey every build
Widget build(context) {
final key = GlobalKey<FormState>(); // wrong
return Form(key: key, ...);
}
saropa_lints detects these patterns and hundreds more:
- Security — Hardcoded credentials, sensitive data in logs, unsafe deserialization
- Accessibility — Missing semantics, inadequate touch targets, screen reader issues
- Performance — Unnecessary rebuilds, memory leaks, expensive operations in build
- Lifecycle — setState after dispose, missing mounted checks, undisposed resources
Why it matters #
The European Accessibility Act takes effect June 2025, requiring accessible apps in retail, banking, and travel. GitHub detected 39 million leaked secrets in repositories during 2024.
These aren't edge cases. They're compliance requirements and security basics that standard linters miss.
Free and open #
Good options exist, but many are paid or closed-source. We believe these fundamentals should be free and open. A rising tide lifts all boats.
The tier system lets you adopt gradually — start with 50 critical rules, work up to 475 when you're ready.
Quick Start #
1. Add dependencies #
# pubspec.yaml
dev_dependencies:
custom_lint: ^0.8.0
saropa_lints: ^1.2.0
2. Enable custom_lint #
# analysis_options.yaml
analyzer:
plugins:
- custom_lint
3. Choose your tier #
# analysis_options.yaml
custom_lint:
saropa_lints:
tier: recommended # essential | recommended | professional | comprehensive | insanity
4. Run the linter #
dart run custom_lint
Migrating from other tools? #
The 5 Tiers #
Pick the tier that matches your team:
| Tier | Rules | Best For |
|---|---|---|
| Essential | ~50 | Every project. Prevents crashes, memory leaks, security holes. |
| Recommended | ~150 | Most teams. Adds performance, accessibility, null safety, collection bounds. |
| Professional | ~250 | Enterprise. Adds architecture, documentation, comprehensive testing. |
| Comprehensive | ~400 | Quality obsessed. Best practices everywhere. |
| Insanity | ~475 | Greenfield projects. Every single rule. |
Using a tier #
# analysis_options.yaml
custom_lint:
saropa_lints:
tier: recommended # Most teams start here
Available tiers: essential, recommended, professional, comprehensive, insanity
Customizing rules #
After choosing a tier, you can enable or disable specific rules.
IMPORTANT: Rules must use YAML list format (with - prefix), not map format:
custom_lint:
saropa_lints:
tier: recommended
rules:
# Disable a rule from the tier
- avoid_hardcoded_strings_in_ui: false
# Enable a rule from a higher tier
- require_public_api_documentation: true
Wrong (map format - rules will be silently ignored):
rules:
avoid_hardcoded_strings_in_ui: false # NO DASH = NOT PARSED!
Correct (list format):
rules:
- avoid_hardcoded_strings_in_ui: false # DASH = PARSED!
Rule Categories #
| Category | Description |
|---|---|
| Flutter Widgets | Lifecycle, setState, keys, performance |
| State Management | Provider, Riverpod, Bloc patterns |
| Performance | Build optimization, memory, caching |
| Security | Credentials, encryption, input validation |
| Accessibility | Screen readers, touch targets, semantics |
| Testing | Assertions, mocking, flaky test prevention |
| Architecture | Clean architecture, DI, SOLID principles |
| Error Handling | Exceptions, logging, recovery |
| Async | Futures, Streams, cancellation |
| API & Network | Timeouts, retries, caching |
| Internationalization | Localization, RTL, plurals |
| Documentation | Public API, examples, deprecation |
Performance #
Running all 1000 rules uses significant memory. The tier system helps:
- Rules set to
falseare not loaded - Start with
essentialorrecommended - Upgrade tiers as you fix warnings
# GOOD: Start with recommended tier
custom_lint:
saropa_lints:
tier: recommended
# BAD: Enabling everything at once on a legacy codebase
custom_lint:
saropa_lints:
tier: insanity # May show thousands of warnings
Adoption Strategy #
New Projects #
Start with professional or comprehensive. Fix issues as you write code.
Existing Projects #
- Enable
essential. Fix critical issues first. - Move to
recommended. Fix warnings as you touch files. - Enable higher tiers when the noise is manageable.
Suppressing Warnings #
When a rule doesn't apply to specific code:
// ignore: avoid_hardcoded_strings_in_ui
const debugText = 'DEBUG MODE';
// For entire files:
// ignore_for_file: avoid_print_in_production
Always add a comment explaining why you're suppressing.
Running the Linter #
Command line (recommended - always works):
dart run custom_lint
IDE Integration (unreliable):
custom_lint uses the Dart analyzer plugin system, which has known reliability issues. IDE integration may or may not work depending on your setup. If you don't see warnings in your IDE:
- Run
flutter pub get - Restart VS Code completely (not just the analysis server)
- Check View → Output → Dart Analysis Server for errors
- If still not working, use the CLI - it's reliable
If custom_lint crashes:
If you see native crashes (e.g., ExceptionCode=-1073741819 on Windows), clear the analysis cache:
# Windows
rmdir /s /q .dart_tool && flutter pub get
# macOS/Linux
rm -rf .dart_tool && flutter pub get
Then run dart run custom_lint again.
For reliable workflows, use:
- Pre-commit hooks
- CI/CD checks
- VS Code tasks (see below)
VS Code Task Setup (Recommended) #
Create .vscode/tasks.json in your project root:
{
"version": "2.0.0",
"tasks": [
{
"label": "custom_lint",
"type": "shell",
"command": "dart run custom_lint",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "dedicated"
},
"problemMatcher": {
"owner": "custom_lint",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^\\s*(.+):(\\d+):(\\d+)\\s+•\\s+(.+)\\s+•\\s+(\\w+)\\s+•\\s+(ERROR|WARNING|INFO)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5,
"severity": 6
}
}
}
]
}
Usage:
- Press Ctrl+Shift+B (or Cmd+Shift+B on Mac) to run custom_lint
- Warnings appear in the Problems panel (Ctrl+Shift+M)
- Click any warning to jump to that line in your code
This is more reliable than IDE integration because it runs the actual CLI tool rather than depending on the analyzer plugin system.
Contributing #
We believe great tools are built by communities, not companies. Contributions and feedback are always welcome.
If you think a rule is:
- Wrong - tell us why, we'll fix it or remove it
- Too strict - maybe it belongs in a higher tier
- Too lenient - maybe it should be stricter or have options
- Missing - propose it, or better yet, implement it
We don't have all the answers. If you've shipped production Flutter apps and have opinions, we want to hear them.
How to contribute #
See CONTRIBUTING.md for detailed guidelines.
Adding a new rule:
- Create rule in appropriate
lib/src/rules/*.dartfile - Add to the appropriate tier(s) in
lib/tiers/*.yaml - Add tests in
test/rules/*_test.dart - Update CHANGELOG.md
Reporting issues:
- Include a minimal code sample that triggers (or should trigger) the rule
- Explain what you expected vs what happened
- If you disagree with a rule's premise, say so directly
Discussing rules #
Not sure if something is a bug or a design decision? Open a discussion issue. We're happy to explain our reasoning and change our minds when presented with good arguments.
Professional Services #
Optional paid services for teams that want hands-on help. See ENTERPRISE.md for details.
| Service | Description |
|---|---|
| Codebase Assessment | We analyze your codebase, prioritize findings, create a remediation roadmap |
| Remediation | We fix the issues — you stay focused on features |
| Custom Rules | Rules specific to your architecture and compliance requirements |
| Training | Team workshops on Flutter best practices |
Contact: saropa.com | lints@saropa.com
Badge #
To indicate your project is using saropa_lints:
[](https://pub.flutter-io.cn/packages/saropa_lints)
License #
MIT - see LICENSE. Use it however you like.
Built with care by the Flutter community. Questions? Ideas? We'd love to hear from you.
pub.flutter-io.cn | GitHub | Issues | Saropa