Skip to content

saropa/saropa_lints

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

saropa_lints banner

Saropa Lints

ci pub package pub points rules License: MIT style: saropa lints

Developed by Saropa. Making the world of Dart & Flutter better, one lint at a time.

license

💬 Have feedback on Saropa Lints? Share it by opening an issue on GitHub!


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

Accuracy focused: Rules use proper AST type checking instead of string matching, reducing false positives on variable names like "upstream" or "spinning".

Essential for popular packages

If you use GetX, Riverpod, Provider, Bloc, Isar, Hive, or Firebase, these audits are critical. These libraries are powerful but have patterns that fail silently at runtime:

Library Common issues caught Guide
GetX Undisposed controllers, memory leaks from workers, missing super calls Using with GetX
Riverpod Circular provider deps, ref.read() in build, missing ProviderScope Using with Riverpod
Provider Provider.of in build causing rebuilds, recreated providers losing state Using with Provider
Bloc Events in constructor, mutable state, unclosed Blocs, BlocListener in build Using with Bloc
Isar Enum fields causing data corruption on schema changes; caching Isar streams (runtime crash risk) Using with Isar
Hive Missing init, unclosed boxes, hardcoded encryption keys, type adapter issues Using with Hive
Firebase Unbounded queries, missing batch writes, invalid Analytics events, FCM token leaks Using with Firebase

Standard linters don't understand these libraries. They see valid Dart code. Saropa Lints has 50+ rules specifically for library-specific anti-patterns that cause crashes, memory leaks, cost overruns, and data corruption in production. Recent update: require_camera_permission_check no longer triggers on non-camera controllers (e.g., IsarStreamController), eliminating a key false positive for Isar users. The new avoid_cached_isar_stream rule (with quick fix) prevents a common Isar runtime error.

Legend: Roadmap Markers

Marker Meaning Example
🐙 Tracked as GitHub issue #0000
💡 Planned enhancement tracked as GitHub Discussion Discussion: Diagnostic Statistics

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.

OWASP Compliance Mapping

Security rules are mapped to OWASP Mobile Top 10 (2024) and OWASP Top 10 (2021) standards. This enables:

  • Compliance reporting for security audits
  • Risk categorization aligned with industry standards
  • Coverage analysis across OWASP categories
OWASP Mobile Coverage OWASP Web Coverage
M1 Credential Usage 5+ rules A01 Broken Access Control 4+ rules
M3 Authentication 5+ rules A02 Cryptographic Failures 10+ rules
M4 Input Validation 6+ rules A03 Injection 6+ rules
M5 Communication 2+ rules A05 Misconfiguration 4+ rules
M6 Privacy Controls 5+ rules A07 Authentication 8+ rules
M8 Misconfiguration 4+ rules A09 Logging Failures 2+ rules
M9 Data Storage 7+ rules
M10 Cryptography 4+ rules

Gaps: M2 (Supply Chain) and M7 (Binary Protection) require separate tooling — dependency scanners and build-time protections. A06 (Outdated Components) similarly requires dependency scanning.

Rules expose their OWASP mapping programmatically:

// Query a rule's OWASP categories
final rule = AvoidHardcodedCredentialsRule();
print(rule.owasp); // Mobile: M1 | Web: A07

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 ~100 critical rules, work up to 1674+ when you're ready.


Quick Start

1. Add dependencies

# pubspec.yaml
dev_dependencies:
  custom_lint: ^0.8.0
  saropa_lints: ^4.6.0

2. Enable custom_lint

# analysis_options.yaml
analyzer:
  plugins:
    - custom_lint

3. Generate tier configuration

dart run saropa_lints:init --tier comprehensive

This generates analysis_options.yaml with explicit true/false for every rule.

Available tiers: essential (1), recommended (2), professional (3), comprehensive (4), insanity (5)

Why a CLI tool? The custom_lint plugin doesn't reliably pass configuration like tier: recommended to plugins. The CLI tool bypasses this limitation by generating explicit rule lists that work 100% of the time.

4. Run the linter

dart run custom_lint

Migrating from other tools?

The 5 Tiers

Pick the tier that matches your team's needs. Each tier builds on the previous one.

Tier Purpose Target User Example Rules
Essential Prevents crashes, data loss, security breaches, and memory leaks. These are rules where a single violation can cause real harm - app crashes, user data exposed, resources never released. If your app violates these, something bad will happen. Every project, every team. Non-negotiable baseline. require_field_dispose (memory leak), avoid_hardcoded_credentials (security breach), check_mounted_after_async (crash), avoid_null_assertion (runtime exception), require_firebase_init_before_use (crash)
Recommended Catches common bugs, basic performance issues, and accessibility fundamentals. These are mistakes that cause real problems but may not immediately crash your app - poor UX, sluggish performance, inaccessible interfaces, silent failures. Most teams. The sensible default for production apps. require_semantics_label (accessibility), avoid_expensive_build (performance), require_json_decode_try_catch (error handling), avoid_shrinkwrap_in_scrollview (performance), require_image_error_builder (UX)
Professional Enforces architecture, testability, maintainability, and documentation standards. Code that works but is hard to test, hard to change, or hard to understand. Technical debt that slows teams down over time. Enterprise teams, long-lived codebases, teams with multiple developers. avoid_god_class (architecture), require_public_api_documentation (docs), prefer_result_pattern (error handling), require_test_cleanup (testing), avoid_hardcoded_strings_in_ui (i18n)
Comprehensive Stricter patterns, optimization hints, and thorough edge case coverage. Rules that catch subtle issues, enforce consistency, and push toward optimal patterns. Helpful but not critical. Quality-obsessed teams, libraries/packages, teams that want maximum coverage. prefer_element_rebuild (subtle perf), prefer_immutable_bloc_state (strict pattern), require_test_documentation (maintainability), prefer_fake_platform (test quality)
Insanity Everything, including pedantic and highly opinionated rules. Rules that most teams would find excessive but are valuable for greenfield projects or teams that want zero compromise. New projects starting fresh, teams that want maximum strictness from day one. prefer_custom_single_child_layout (micro-optimization), prefer_feature_folder_structure (opinionated architecture), avoid_returning_widgets (pedantic)

Stylistic Rules (Separate Track)

100+ stylistic rules for formatting, ordering, and naming conventions.

To include stylistic rules when generating configuration:

dart run saropa_lints:init --tier comprehensive --stylistic

Or enable specific stylistic rules in your generated config by changing false to true.

Conflicting pairs (e.g., prefer_single_quotes vs prefer_double_quotes) must be enabled individually - you choose which style your team prefers.

Stylistic rules are orthogonal to correctness. Your code can be perfectly correct while violating every stylistic rule, or perfectly formatted while crashing on every screen. That's why they're separate.

Configuration template

See example/analysis_options_template.yaml for a complete reference with all 1674+ rules organized by category, tier membership, and examples.

Using a tier

Generate configuration for your chosen tier:

# Most teams start here
dart run saropa_lints:init --tier recommended

# See all options
dart run saropa_lints:init --help

# Preview without writing
dart run saropa_lints:init --tier professional --dry-run

Available tiers: essential (1), recommended (2), professional (3), comprehensive (4), insanity (5)

Add --stylistic to include opinionated formatting rules.

Customizing rules

After generating configuration, customize rules by editing analysis_options.yaml:

custom_lint:
  rules:
    # The init tool generates explicit true/false for every rule
    - avoid_hardcoded_strings_in_ui: true  # change to false to disable
    - require_public_api_documentation: false  # change to true to enable

    # Stylistic rules (enable the ones your team prefers)
    - prefer_single_quotes: true
    - prefer_trailing_comma_always: true

IMPORTANT: Rules must use YAML list format (with - prefix):

# ✅ Correct (list format)
rules:
  - avoid_hardcoded_strings_in_ui: false

# ❌ Wrong (map format - rules will be silently ignored)
rules:
  avoid_hardcoded_strings_in_ui: false  # NO DASH = NOT PARSED!

To change tiers, re-run the init tool:

dart run saropa_lints:init --tier professional

Config key names and aliases

Rule config keys match the rule name shown in lint messages (the part in [brackets]):

lib/my_file.dart:42 - [enforce_arguments_ordering] Named arguments should be in alphabetical order.
                       ^^^^^^^^^^^^^^^^^^^^^^^^^ This is the config key

To disable this rule: - enforce_arguments_ordering: false

Aliases: Some rules support shorter aliases for convenience. For example, enforce_arguments_ordering also accepts arguments_ordering:

rules:
  # Both of these work:
  - enforce_arguments_ordering: false  # canonical name
  - arguments_ordering: false          # alias

Aliases are provided for rules where the prefix (enforce_, require_) might be commonly omitted.

enable_all_lint_rules

The enable_all_lint_rules: true setting enables ALL rules, including opinionated stylistic rules:

custom_lint:
  saropa_lints:
    enable_all_lint_rules: true

This is intentional. It forces teams to explicitly review and disable rules they disagree with, ensuring:

  • No rule is accidentally overlooked
  • Your custom_lint.yaml becomes a complete record of team style decisions
  • Mutually exclusive rules (e.g., prefer_single_quotes vs prefer_double_quotes) require explicit choice

If you enable all rules, you will need to disable one rule from each conflicting pair.

Severity levels

Each rule has a fixed severity (ERROR, WARNING, or INFO) defined in the rule itself. Severity cannot be overridden per-project. If a rule's severity doesn't match your needs:

  • Use // ignore: rule_name to suppress individual occurrences
  • Disable the rule entirely with - rule_name: false
  • Open an issue if you think the default severity should change

Baseline for Brownfield Projects

The Problem

You want to adopt saropa_lints on an existing project. You run dart run custom_lint and see:

lib/old_widget.dart:42 - avoid_print
lib/old_widget.dart:87 - no_empty_block
lib/legacy/api.dart:15 - avoid_dynamic
... 500 more violations

That's overwhelming. You can't fix 500 issues before your next sprint. But you also can't ignore linting entirely - new code should be clean.

The Solution: Baseline

The baseline feature records all existing violations and hides them, while still catching violations in new code.

  • Old code: Violations hidden (baselined)
  • New code: Violations reported normally

This lets you adopt linting today without fixing legacy code first.

Quick Start (One Command)

dart run saropa_lints:baseline

This command:

  1. Runs analysis to find all current violations
  2. Creates saropa_baseline.json with those violations
  3. Updates your analysis_options.yaml automatically

Result: Old violations are hidden, new code is still checked.

Three Combinable Baseline Types

Type Config Description Best For
File-based baseline.file JSON listing specific violations "Fix nothing yet"
Date-based baseline.date Git blame - ignore old code "Fix gradually by age"

All three types are combinable - any match suppresses the violation.

Full Configuration

custom_lint:
  saropa_lints:
    tier: recommended
    baseline:
      # Option 1: Specific violations (generated by CLI)
      file: "saropa_baseline.json"

      # Option 2: Ignore code unchanged since this date (uses git blame)
      date: "2025-01-15"

      # Option 3: Ignore entire directories (supports glob patterns)
      paths:
        - "lib/legacy/"
        - "lib/deprecated/"
        - "**/generated/"
        - "*.g.dart"

      # Only baseline certain severities (keep seeing critical issues)
      only_impacts: [low, medium]

Path Pattern Examples

Pattern Matches
lib/legacy/ All files under lib/legacy/
*.g.dart All files ending in .g.dart
lib/**/old_*.dart Files like lib/foo/old_widget.dart

Priority Filtering

Use only_impacts to baseline only certain severity levels while still seeing critical issues:

baseline:
  file: "saropa_baseline.json"
  only_impacts: [low, medium, opinionated] # Still see critical and high

Cleaning Up Over Time

As you fix violations, update the baseline to remove fixed items:

dart run saropa_lints:baseline --update

Output shows what was fixed:

Baseline Update Summary:
  Previous: 150 violations
  Current:  120 violations
  Fixed:    30 violations removed!

CLI Reference

dart run saropa_lints:baseline              # Generate new baseline
dart run saropa_lints:baseline --update     # Refresh, remove fixed violations
dart run saropa_lints:baseline --dry-run    # Preview without changes
dart run saropa_lints:baseline --skip-config # Don't update analysis_options.yaml
dart run saropa_lints:baseline -o custom.json # Custom output path
dart run saropa_lints:baseline ./my_project  # Run on specific directory
dart run saropa_lints:baseline --help        # See all options

Rule Categories

Category Description
Flutter Widgets Lifecycle, setState, keys, performance
Modern Dart 3.0+ Class modifiers, patterns, records, when guards
Modern Flutter TapRegion, OverlayPortal, SearchAnchor, CarouselView
State Management Provider, Riverpod, Bloc patterns
Performance Build optimization, memory, caching
Security Credentials, encryption, input validation — OWASP mapped
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

Stylistic Rules

20 rules for team preferences — not included in any tier. Enable individually based on your conventions.

Examples: prefer_relative_imports, prefer_single_quotes, prefer_arrow_functions, prefer_trailing_comma_always

See README_STYLISTIC.md for the full list with examples, pros/cons, and quick fixes.

Performance

Running all 1668+ rules uses significant memory. The tier system helps:

  • Rules set to false are not loaded
  • Start with essential or recommended
  • Upgrade tiers as you fix warnings
# GOOD: Start with recommended tier
dart run saropa_lints:init --tier recommended

# CAUTION: Enabling everything on a legacy codebase may show thousands of warnings
dart run saropa_lints:init --tier insanity

Performance Tip: Use Lower Tiers During Development

custom_lint is notoriously slow with large rule sets. For faster iteration during development:

  1. Use essential tier locally (~400 rules) - catches critical bugs, runs 3-5x faster
  2. Use professional or higher in CI - thorough checking where speed matters less
  3. Upgrade tiers gradually - fix warnings before enabling more rules
# Fast local development (~400 rules)
dart run saropa_lints:init --tier essential

# Thorough CI checking (~1400 rules)
dart run saropa_lints:init --tier professional

The tier you choose has a direct impact on analysis speed:

  • essential: ~400 rules → fastest (memory leaks, security, crashes)
  • recommended: ~900 rules → moderate (+ accessibility, performance)
  • professional: ~1400 rules → slower (+ architecture, documentation)
  • comprehensive/insanity: 1668+ rules → slowest (everything)

Adoption Strategy

Static analysis doesn't create problems — it reveals ones that already exist. The tiered system lets you start at any level and progress at your own pace. Findings are for your workflow. You control what you address and when.

New Projects

Start with professional or comprehensive. Fix issues as you write code.

Existing Projects

  1. Enable essential. Fix critical issues first.
  2. Move to recommended. Fix warnings as you touch files.
  3. 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';

// Hyphenated format also works:
// 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.

Automatic File Skipping

Rules automatically skip files that can't be manually fixed:

File Pattern Skipped By Default
*.g.dart, *.freezed.dart, *.gen.dart Yes (generated code)
*_fixture.dart, fixture/**, fixtures/** Yes (test fixtures)
*_test.dart, test/** No (override with skipTestFiles)
example/** No (override with skipExampleFiles)

This reduces noise from generated code and intentionally "bad" fixture files.

Limitations

  • Scope: custom_lint (and therefore saropa_lints) only runs rules inside the package where you invoke it. dependency_overrides pointing to local packages are not linted automatically—add saropa_lints to the overridden package and run dart run custom_lint in that package (or wire a workspace task) if you want coverage there.
  • File types: Only Dart source files (.dart) are analyzed. Non-Dart assets (JSON, XML, YAML, scripts, etc.) are out of scope for custom_lint.

Running the Linter

Command line (recommended - always works):

dart run custom_lint

Impact Report

Run lints with results grouped by business impact:

dart run saropa_lints:impact_report

Output shows critical issues first, with actionable guidance:

--- CRITICAL (2) ---
  lib/main.dart:45 - avoid_hardcoded_credentials
  lib/auth.dart:23 - require_dispose

--- HIGH (5) ---
  lib/widget.dart:89 - avoid_icon_buttons_without_tooltip
  ...

Impact Summary
==============
CRITICAL: 2 (fix immediately!)
HIGH:     5 (address soon)
MEDIUM:   12 (tech debt)
LOW:      34 (style)

Total: 53 issues

Impact levels:

  • critical: Each occurrence is serious — even 1-2 is unacceptable (memory leaks, security)
  • high: 10+ requires action (accessibility, performance anti-patterns)
  • medium: 100+ indicates tech debt (error handling, complexity)
  • low: Large counts acceptable (style, naming conventions)

Exit code equals the number of critical issues (capped at 125), making it CI-friendly.

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:

  1. Run flutter pub get
  2. Restart VS Code completely (not just the analysis server)
  3. Check View → Output → Dart Analysis Server for errors
  4. If still not working, use the CLI - it's reliable

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.

VS Code Status Bar Button (Optional)

Want a clickable button instead of remembering the keyboard shortcut? Install the included extension:

python scripts/install_vscode_extension.py

Then restart VS Code.

What you get:

  • A "Lints" button in the status bar (bottom of VS Code)
  • A search icon in the editor title bar when viewing Dart files
  • Both trigger dart run custom_lint and open the Problems panel

Troubleshooting

I'm new and completely lost

Start here:

  1. Install: Add to your pubspec.yaml dev_dependencies:

    dev_dependencies:
      custom_lint: ^0.8.0
      saropa_lints: ^4.2.3
  2. Configure: Add to your analysis_options.yaml:

    analyzer:
      plugins:
        - custom_lint
    
    custom_lint:
      enable_all_lint_rules: true  # Start with all rules
  3. Reload VS Code:

    • Press Ctrl+Shift+P
    • Type "reload"
    • Click "Developer: Reload Window"
  4. Wait: Give it 1-2 minutes to analyze your code

  5. Check: Look at the PROBLEMS panel (View → Problems)

Still not working? See the sections below.

IDE doesn't show lint warnings

Quick Fix (works 90% of the time):

  1. Press Ctrl+Shift+P (or Cmd+Shift+P on Mac)
  2. Type "reload"
  3. Click "Developer: Reload Window"
  4. Wait 1 minute for analysis to complete

If that doesn't work:

  1. Clear the cache: Delete the .dart_tool/custom_lint folder in your project
  2. Reload VS Code again (steps above)
  3. Check View → Output → Dart Analysis Server for errors
  4. Verify configuration is correct (see "Configuration not working" below)

Alternative (command line):

Run dart run custom_lint in your terminal to see all issues immediately.

Configuration not working (tier not loading)

Problem: You set tier: insanity in YAML but only get ~200 rules instead of 1400+.

Cause: The custom_lint plugin doesn't reliably pass configuration to plugins. This is a known limitation.

Solution: Use the CLI tool to generate explicit configuration:

# Generate config for comprehensive tier (1618 rules)
dart run saropa_lints:init --tier comprehensive

# Or for all rules (insanity tier)
dart run saropa_lints:init --tier insanity

This generates analysis_options.yaml with explicit - rule_name: true for every enabled rule, which works 100% of the time.

Verify it worked: Run dart run custom_lint and check the rule count in the output.

Too many warnings! What do I do?

This is normal when first installing. You'll see hundreds or thousands of warnings.

Option 1: Start smaller (recommended for existing projects)

# Start with essential tier (~400 critical rules)
dart run saropa_lints:init --tier essential

Option 2: Use baseline (for brownfield projects)

Generate a baseline to suppress existing issues and only catch new violations:

dart run saropa_lints:baseline

Option 3: Disable noisy rules

Edit your generated analysis_options.yaml and change specific rules from true to false:

rules:
    - prefer_double_quotes: false  # disabled
    - prefer_trailing_comma_always: false
    - no_magic_number: false

Option 4: Use quick fixes

Many rules have automatic fixes:

  • Hover over the warning
  • Click "Quick Fix" or press Ctrl+.
  • Select "Fix all in file" to fix all instances at once

Don't stress about fixing everything immediately. Pick one category (like accessibility or memory leaks) and fix those first.

Out of Memory errors

If you see errors like:

../../runtime/vm/zone.cc: 96: error: Out of memory.
Crash occurred when compiling package:analyzer/... in optimizing JIT mode

Solution 1: Clear the pub cache (most effective)

dart pub cache clean
dart pub get
dart run custom_lint

Solution 2: Increase Dart heap size (PowerShell)

$env:DART_VM_OPTIONS="--old_gen_heap_size=4096"
dart run custom_lint

Solution 3: Delete local build artifacts

# Windows
rmdir /s /q .dart_tool && dart pub get

# macOS/Linux
rm -rf .dart_tool && dart pub get

Native crashes (Windows)

If you see native crashes with error codes like ExceptionCode=-1073741819:

# 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.

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 from you.

How to contribute

See CONTRIBUTING.md for detailed guidelines.

Adding a new rule:

  1. Create rule in appropriate lib/src/rules/*.dart file
  2. Add to the appropriate tier(s) in lib/tiers/*.yaml
  3. Add tests in test/rules/*_test.dart
  4. 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 PROFESSIONAL_SERVICES.md for details.

Service Description
New Projects Development scoped to your stage — MVP, Production, or Enterprise
Upgrade Move existing projects to higher tiers as they grow
Audit Assess codebases you inherited; remediation quoted separately
Custom Rules Rules specific to your architecture and compliance requirements

Contact: saropa.com | services@saropa.com

Documentation

Document Description
README_STYLISTIC.md 100+ optional stylistic rules with examples
PERFORMANCE.md Performance optimization guide and profiling
ROADMAP.md Planned rules and project direction
CONTRIBUTING.md How to contribute rules and report issues
CHANGELOG.md Version history and release notes
SECURITY.md Security policy and reporting vulnerabilities
PROFESSIONAL_SERVICES.md Professional services and custom rules

Package Integration Guides

We provide specialized lint rules for popular Flutter packages. These catch library-specific anti-patterns that standard linters miss.

Category Package Guide
State Management Riverpod Using with Riverpod
Bloc Using with Bloc
Provider Using with Provider
GetX Using with GetX
Databases Isar Using with Isar
Hive Using with Hive
Backend Services Firebase Using with Firebase
Platform iOS/macOS Apple Platform Rules

For Package Authors

Want lint rules for your package? We'd love to collaborate with package maintainers to add rules that catch common gotchas and enforce best practices for your library.

Benefits:

  • Help users avoid common mistakes with your package
  • Reduce support burden from preventable issues
  • Improve developer experience with your library

Contact us via CONTRIBUTING.md or open an issue to discuss adding rules for your package.

Badge

To indicate your project is using saropa_lints:

style: saropa lints

[![style: saropa lints](https://img.shields.io/badge/style-saropa__lints-4B0082.svg)](https://pub.dev/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.dev | GitHub | Issues | Saropa


About This Project

"The bitterness of poor quality remains long after the sweetness of meeting the schedule has been forgotten." — Karl Wiegers

"Quality is not an act, it is a habit." — Aristotle

saropa_lints is a comprehensive static analysis package for Flutter and Dart applications. With 1674+ lint rules organized into 5 progressive tiers (and more planned), it catches memory leaks, security vulnerabilities, accessibility violations, and runtime crashes that standard linters miss. Whether you're building a startup MVP or enterprise software, saropa_lints helps you ship more stable, secure, and accessible apps.

Keywords: Flutter linter, Dart static analysis, custom_lint rules, Flutter code quality, memory leak detection, security scanning, accessibility testing, WCAG compliance, European Accessibility Act, Flutter best practices, Dart analyzer plugin, code review automation, CI/CD linting, Flutter enterprise tools

Hashtags: #Flutter #Dart #StaticAnalysis #CodeQuality #FlutterDev #DartLang #Linting #DevTools #OpenSource #Accessibility #Security #BestPractices


Sources

About

Extra linters made by Saropa for catching code smells

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •