saropa_lints 1.8.2
saropa_lints: ^1.8.2 copied to clipboard
860+ custom lint rules for Flutter and Dart. Static analysis for security, accessibility, and performance. Free and open source. 5 tiers plus optional stylistic rules.
Changelog #
All notable changes to this project will be documented in this file. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Looking for older changes?
See CHANGELOG_ARCHIVE.md for versions 0.1.0 through 1.6.0.
1.8.2 - 2026-01-10 #
Added #
require_text_editing_controller_dispose: Warns when TextEditingController is not disposed in StatefulWidget - very common source of memory leaks in formsrequire_page_controller_dispose: Warns when PageController is not disposed - prevents memory leaks in PageView widgetsrequire_avatar_alt_text: Warns when CircleAvatar lacks semanticLabel - accessibility requirement for screen readersrequire_badge_semantics: Warns when Badge widget is not wrapped in Semantics - notification badges need accessible labelsrequire_badge_count_limit: Warns when Badge shows count > 99 - UX best practice to show "99+" for large countsavoid_image_rebuild_on_scroll: Warns when Image.network is used in ListView.builder - causes unnecessary rebuilds and network requestsrequire_avatar_fallback: Warns when CircleAvatar with NetworkImage lacks onBackgroundImageError - network failures leave broken avatarsprefer_video_loading_placeholder: Warns when video player widgets (Chewie, BetterPlayer) lack placeholder - improves UX during loadrequire_snackbar_duration: Warns when SnackBar lacks explicit duration - ensures consistent UX timingrequire_dialog_barrier_dismissible: Warns when showDialog lacks explicit barrierDismissible - makes dismiss behavior explicitrequire_dialog_result_handling: Warns when showDialog result is not awaited - prevents missed user confirmationsavoid_snackbar_queue_buildup: Warns when showSnackBar is called without clearing previous - prevents stale message queuesrequire_keyboard_action_type: Warns when TextField/TextFormField lacks textInputAction - improves form navigation UXrequire_keyboard_dismiss_on_scroll: Warns when scroll views lack keyboardDismissBehavior - better form UX on scrollprefer_duration_constants: Warns when Duration can use cleaner units (e.g., seconds: 60 -> minutes: 1)avoid_datetime_now_in_tests: Warns when DateTime.now() is used in test files - causes flaky testsrequire_responsive_breakpoints: Warns when MediaQuery width is compared to magic numbers - promotes named breakpoint constantsprefer_cached_paint_objects: Warns when Paint() is created inside CustomPainter.paint() - recreated every framerequire_custom_painter_shouldrepaint: Warns when shouldRepaint always returns true - causes unnecessary repaintsrequire_currency_formatting_locale: Warns when NumberFormat.currency lacks locale - currency format varies by localerequire_number_formatting_locale: Warns when NumberFormat lacks locale - number format varies by localerequire_graphql_operation_names: Warns when GraphQL query/mutation lacks operation name - harder to debugavoid_badge_without_meaning: Warns when Badge shows count 0 without hiding - empty badges confuse usersprefer_logger_over_print: Warns when print() is used instead of dart:developer log() - better log managementprefer_itemextent_when_known: Warns when ListView.builder lacks itemExtent - improves scroll performancerequire_tab_state_preservation: Warns when TabBarView children may lose state on tab switchavoid_bluetooth_scan_without_timeout: Warns when BLE scan lacks timeout - drains batteryrequire_bluetooth_state_check: Warns when BLE operations start without adapter state checkrequire_ble_disconnect_handling: Warns when BLE connection lacks disconnect state listenerrequire_audio_focus_handling: Warns when audio playback lacks AudioSession configurationrequire_qr_permission_check: Warns when QR scanner is used without camera permission check - critical for app storerequire_qr_scan_feedback: Warns when QR scan callback lacks haptic/visual feedbackavoid_qr_scanner_always_active: Warns when QR scanner lacks lifecycle pause/resume handlingrequire_file_exists_check: Warns when file read operations lack exists() check or try-catchrequire_pdf_error_handling: Warns when PDF loading lacks error handlingrequire_graphql_error_handling: Warns when GraphQL result is used without checking hasExceptionprefer_image_size_constraints: Warns when Image lacks cacheWidth/cacheHeight for memory optimizationrequire_lifecycle_observer: Warns when Timer.periodic is used without WidgetsBindingObserver lifecycle handling
Documentation #
- Migration from solid_lints: Complete rewrite of migration_from_solid_lints.md:
- Corrected rule count: solid_lints has 16 custom rules (not ~50)
- Full rule mapping table: saropa_lints implements 15 of 16 rules (94% coverage)
- Fixed mappings:
avoid_final_with_getter→avoid_unnecessary_getter,avoid_unnecessary_return_variable→prefer_immediate_return - Added
no_magic_numberandavoid_late_keywordmappings that were missing - Documented the one missing rule:
avoid_using_api(configurable API restriction)
- ROADMAP.md: Added
avoid_banned_apito Architecture Rules section (inspired by solid_lints'avoid_using_api) - State management guides: New "Using with" guides for popular libraries:
- using_with_riverpod.md - 8 Riverpod-specific rules with examples
- using_with_bloc.md - 8 Bloc-specific rules with examples
- using_with_provider.md - 4 Provider-specific rules with examples
- using_with_getx.md - 3 GetX-specific rules with examples
- using_with_isar.md - Isar enum corruption prevention
- ROADMAP.md: Added 12 new planned rules based on community research:
- Riverpod: AsyncValue order, navigation patterns, package confusion
- Bloc: BlocSelector usage, state over-engineering, manual dispose
- GetX: Context access patterns, static context testing issues
1.8.1 - 2026-01-10 #
Fixed #
avoid_double_for_money: Fixed remaining false positives:- Switched from substring matching to word-boundary matching - variable names are now split into words (camelCase/snake_case aware) and only exact word matches trigger the rule
- Fixes issues like
audioVolumematchingaudorimageUrlVerticalOffsetPercenttriggering false positives - Removed short currency codes (
usd,eur,gbp,jpy,cad,aud,yen) - still too ambiguous even as complete words (e.g., "cad" for CAD files, "aud" for audio-related)
Changed #
- Refactored rule files for better organization:
- Created
money_rules.dart- movedAvoidDoubleForMoneyRule - Created
media_rules.dart- movedAvoidAutoplayAudioRule - Moved
AvoidSensitiveDataInLogsRuletosecurity_rules.dart - Moved
RequireGetItResetInTestsRuletotest_rules.dart - Moved
RequireWebSocketErrorHandlingRuletoapi_network_rules.dart json_datetime_rules.dartnow only contains JSON and DateTime parsing rules
- Created
Quick Fixes #
avoid_double_for_money: Adds review comment for manual attentionavoid_sensitive_data_in_logs: Comments out the sensitive log statementrequire_getit_reset_in_tests: Adds reminder comment for GetIt resetrequire_websocket_error_handling: Adds onError handler stub
1.8.0 - 2026-01-10 #
Changed #
avoid_double_for_money: BREAKING - Rule is now much stricter to eliminate false positives. Only flags unambiguous money terms:price,money,currency,salary,wage, and currency codes (dollar,euro,yen,usd,eur,gbp,jpy,cad,aud). Generic terms liketotal,amount,balance,cost,fee,tax,discount,payment,revenue,profit,budget,expense,incomeare no longer flagged as they have too many non-monetary uses.
Fixed #
avoid_sensitive_data_in_logs: Fixed false positives for null checks and property access. Now only flags direct value interpolation ($password,${password}), not expressions like${credential != null},${password.length}, or${token?.isEmpty}. Pre-compiled regex patterns for better performance.avoid_hardcoded_encryption_keys: Simplified rule to only detect string literals passed directly toKey.fromUtf8(),Key.fromBase64(), etc. - removes false positives from variable name heuristics
1.7.12 - 2026-01-10 #
Fixed #
require_unique_iv_per_encryption: Improved IV variable name detection to avoid false positives like "activity", "private", "derivative" - now uses proper word boundary detection for camelCase and snake_case patterns
Quick Fixes #
require_unique_iv_per_encryption: Auto-replacesIV.fromUtf8/IV.fromBase64withIV.fromSecureRandom(16)
1.7.11 - 2026-01-10 #
Fixed #
avoid_shrinkwrap_in_scrollview: Rule now properly skips widgets withNeverScrollableScrollPhysics- the recommended fix should no longer trigger the lint- Test fixtures: Updated fixture files with correct
expect_lintannotations and disabled conflicting rules in example analysis_options.yaml
1.7.10 - 2026-01-10 #
Fixed #
- Rule detection for implicit constructors: Fixed
avoid_gradient_in_build,avoid_shrinkwrap_in_scrollview,avoid_nested_scrollables_conflict, andavoid_excessive_bottom_nav_itemsrules not detecting widgets created without explicitnew/constkeywords - AST visitor pattern: Rules now use
GeneralizingAstVisitororaddNamedExpressioncallbacks to properly detect both explicit and implicit constructor calls - Test fixtures: Updated expect_lint positions to match actual lint locations
Changed #
- Rule implementation:
AvoidGradientInBuildRulenow usesGeneralizingAstVisitorwith bothvisitInstanceCreationExpressionandvisitMethodInvocation - Rule implementation:
AvoidShrinkWrapInScrollViewRulenow usesaddNamedExpressionto detectshrinkWrap: truedirectly - Rule implementation:
AvoidNestedScrollablesConflictRulenow uses visitor pattern withRecursiveAstVisitor - Rule implementation:
AvoidExcessiveBottomNavItemsRulenow usesaddNamedExpressionto detect excessive items
1.7.9 - 2026-01-09 #
Added #
- 29 New Rules covering disposal, build method anti-patterns, scroll/list issues, cryptography, and JSON/DateTime handling:
Disposal Rules (2 rules)
require_media_player_dispose- Warns when VideoPlayerController/AudioPlayer is not disposedrequire_tab_controller_dispose- Warns when TabController is not disposed
Build Method Anti-Patterns (8 rules)
avoid_gradient_in_build- Warns when Gradient objects are created inside build()avoid_dialog_in_build- Warns when showDialog is called inside build()avoid_snackbar_in_build- Warns when showSnackBar is called inside build()avoid_analytics_in_build- Warns when analytics calls are made inside build()avoid_json_encode_in_build- Warns when jsonEncode is called inside build()avoid_getit_in_build- Warns when GetIt service locator is used inside build()avoid_canvas_operations_in_build- Warns when Canvas operations are used outside CustomPainteravoid_hardcoded_feature_flags- Warns when if(true)/if(false) patterns are used
Scroll and List Rules (7 rules)
avoid_shrinkwrap_in_scrollview- Warns when shrinkWrap: true is used inside a ScrollViewavoid_nested_scrollables_conflict- Warns when nested scrollables don't have explicit physicsavoid_listview_children_for_large_lists- Suggests ListView.builder for large listsavoid_excessive_bottom_nav_items- Warns when BottomNavigationBar has more than 5 itemsrequire_tab_controller_length_sync- Validates TabController length matches tabs countavoid_refresh_without_await- Ensures RefreshIndicator onRefresh returns Futureavoid_multiple_autofocus- Warns when multiple widgets have autofocus: true
Cryptography Rules (4 rules)
avoid_hardcoded_encryption_keys- Warns when encryption keys are hardcodedprefer_secure_random_for_crypto- Warns when Random() is used for cryptographic purposesavoid_deprecated_crypto_algorithms- Warns when MD5, SHA1, DES are usedrequire_unique_iv_per_encryption- Warns when static or reused IVs are detected
JSON and DateTime Rules (8 rules)
require_json_decode_try_catch- Warns when jsonDecode is used without try-catchavoid_datetime_parse_unvalidated- Warns when DateTime.parse is used without try-catchprefer_try_parse_for_dynamic_data- CRITICAL: Warns when int/double/num.parse is used without try-catchavoid_double_for_money- Warns when double is used for money/currency valuesavoid_sensitive_data_in_logs- Warns when sensitive data appears in log statementsrequire_getit_reset_in_tests- Warns when GetIt is used in tests without resetrequire_websocket_error_handling- Warns when WebSocket listeners lack error handlersavoid_autoplay_audio- Warns when autoPlay: true is set on audio/video players
Changed #
- Docs: Updated rule count from 792+ to 821+
- Impact tuning:
avoid_hardcoded_feature_flagsandavoid_autoplay_audiochanged tolowto match INFO severity - Impact tuning:
avoid_double_for_moneypromoted tocriticalto match ERROR severity (financial bugs)
Quick Fixes #
prefer_secure_random_for_crypto: Auto-replacesRandom()withRandom.secure()avoid_datetime_parse_unvalidated: Auto-replacesDateTime.parsewithDateTime.tryParseprefer_try_parse_for_dynamic_data: Auto-replacesint/double/num.parsewithtryParseavoid_autoplay_audio: Auto-setsautoPlay: falseavoid_hardcoded_feature_flags: Adds TODO comment for feature flag replacement
1.7.8 - 2026-01-09 #
Added #
- 25 New Rules covering network performance, state management, testing, security, and database patterns:
Network Performance (6 rules)
prefer_http_connection_reuse- Warns when HTTP clients are created without connection reuseavoid_redundant_requests- Warns about API calls in build()/initState() without cachingrequire_response_caching- Warns when GET responses aren't cachedprefer_pagination- Warns when APIs return large collections without paginationavoid_over_fetching- Warns when fetching more data than neededrequire_cancel_token- Warns when async requests lack cancellation in StatefulWidgets
State Management (3 rules)
require_riverpod_lint- Warns when Riverpod projects don't include riverpod_lintrequire_multi_provider- Warns about nested Provider widgets instead of MultiProvideravoid_nested_providers- Warns about Provider inside Consumer callbacks
Testing (4 rules)
prefer_fake_over_mock- Warns about excessive mocking vs simpler fakesrequire_edge_case_tests- Warns when tests don't cover edge casesprefer_test_data_builder- Warns about complex test objects without buildersavoid_test_implementation_details- Warns when tests verify internal implementation
Security (6 rules)
require_data_encryption- Warns when sensitive data stored without encryptionprefer_data_masking- Warns when sensitive data displayed without maskingavoid_screenshot_sensitive- Warns about sensitive screens without screenshot protectionrequire_secure_password_field- Warns about password fields without secure keyboard settingsavoid_path_traversal- Warns about file path traversal vulnerabilitiesprefer_html_escape- Warns about user content in WebViews without HTML escaping
Database (6 rules)
require_database_migration- Warns about database schema changes without migration supportrequire_database_index- Warns about queries on non-indexed fieldsprefer_transaction_for_batch- Warns about multiple writes not batched in transactionsrequire_hive_database_close- Warns when database connections not properly closedrequire_type_adapter_registration- Warns about Hive type adapters not registeredprefer_lazy_box_for_large- Warns about large data in regular Hive boxes vs lazy boxes
Changed #
- Docs: Updated rule count from 767+ to 792+
- Impact tuning:
prefer_fake_over_mock,prefer_test_data_builder,require_response_caching,avoid_over_fetchingchanged toopinionated
Quick Fix #
require_secure_password_field: Auto-addsenableSuggestions: falseandautocorrect: false
1.7.7 - 2026-01-09 #
Changed #
- Docs: README now has a Limitations section clarifying Dart-only analysis and dependency_overrides behavior.
1.7.6 - 2026-01-09 #
1.7.5 - 2026-01-09 #
Added #
- Opinionated severity: Added LintImpact.opinionated.
- New rule: prefer_future_void_function_over_async_callback.
- Configuration template: Added example/analysis_options_template.yaml with 767+ rules.
Fixed #
- Empty block warnings in async callback fixture tests.
Changed #
- Docs: Updated counts to reflect 767+ rules.
- Severity: Stylistic rules moved to LintImpact.opinionated.
1.7.4 - 2026-01-08 #
- Updated the banner image to show the project name Saropa Lints.
1.7.3 - 2026-01-08 #
1.7.2 - 2026-01-08 #
Added #
- Impact Classification System: Categorized rules by critical, high, medium, and low.
- Impact Report CLI Tool: dart run saropa_lints:impact_report for prioritized violation reporting.
- 47 New Rules: Covering Riverpod, GetX, Bloc, Accessibility, Security, and Testing.
- 11 New Quick Fixes.
1.7.0 - 2026-01-08 #
Added #
- 50 New Rules: Massive expansion across Riverpod, Build Performance, Testing, Security, and Forms.
- Added support for sealed events in Bloc.
1.6.0 and Earlier #
For details on the initial release and versions 0.1.0 through 1.6.0, please refer to CHANGELOG_ARCHIVE.md.