saropa_lints 5.0.3
saropa_lints: ^5.0.3 copied to clipboard
1796 custom lint rules with 292 quick fixes for Flutter and Dart. Static analysis for security, accessibility, and performance.
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. Dates are not included in version headers — pub.dev displays publish dates separately.
Looking for older changes?
See CHANGELOG_ARCHIVE.md for versions 0.1.0 through 4.15.1.
** See the current published changelog: saropa_lints/changelog
5.0.3 #
Added #
avoid_string_env_parsing: warns whenfromEnvironment()is called withoutdefaultValue(Recommended)avoid_connectivity_equals_internet: warns whenConnectivityResultis used as a proxy for internet access (Essential)avoid_platform_specific_imports: warns whendart:iois imported in shared/web-capable code (Recommended)avoid_shared_prefs_sync_race: warns when SharedPreferences writes are not awaited in async code (Recommended)avoid_multiple_animation_controllers: warns when a State class has 3+ AnimationController fields (Professional)avoid_form_validation_on_change: warns whenvalidate()is called insideonChanged(Professional)avoid_stack_trace_in_production: warns when stack traces are exposed to users (OWASP M10) (Recommended)avoid_expensive_did_change_dependencies: warns when expensive operations run indidChangeDependencies()(Professional)avoid_permission_request_loop: warns whenPermission.request()is called inside a loop (Professional)avoid_entitlement_without_server: warns when IAP purchases are verified client-side only (OWASP M1/M4) (Professional)avoid_webview_cors_issues: warns whenallowUniversalAccessFromFileURLsorallowFileAccessFromFileURLsis set totrue(OWASP M8/A05) (Professional)
Fixed #
prefer_trailing_comma_always: suppress false positive when the last argument is a callback/closure whose body spans multiple linesinitwalkthrough: skipped stylistic rules now marked as reviewed so they are not re-prompted on subsequent runs// ignore:directives now work correctly on declarations with doc comments; previously, diagnostics reported onMethodDeclaration/FunctionDeclaration/ClassDeclarationnodes started at the doc comment offset, making// ignore:before the signature invisible to the analysis server (47 rules affected)avoid_long_parameter_list: diagnostic now highlights the parameter list instead of the entire declaration
Changed #
- Added
exampleBad/exampleGoodto 26 conflicting stylistic rules for clearer wizard descriptions
Build Process #
initwalkthrough: show GOOD example before BAD for clearer readabilityinitwalkthrough: restructured 77-rule "Opinionated prefer_* rules" bucket into 27 conflicting pick-one categories (e.g.,prefer_await_over_thenvsprefer_then_over_await) plus 32 non-conflicting opinionated rulesinitwalkthrough: skip prompt now says "keeps current" to clarify the rule won't be re-asked
5.0.2 #
Fixed #
prefer_list_first: suppress false positives when the same collection is accessed with sibling indices (list[0]alongsidelist[1]), on assignment targets (list[0] = value), on String subscripts (string[0]), and on Map access (map[0])prefer_list_last: same false positive suppression — assignment targets, String/Map types, and sibling index accessesprefer_catch_over_on: reversed rule logic — now only flagson Object catchandon dynamic catch(redundant, equivalent to barecatch), no longer flags specificonclauses likeon FormatException catchwhich are intentional type filtering. Added quick fix to remove the redundanton Objectclause.avoid_dynamic_type: exemptdynamicin type arguments (List<dynamic>,Map<dynamic, dynamic>), closure/lambda parameters, and for-in loop variables — eliminates false positives in JSON utility codeavoid_ignoring_return_values: addupdate,putIfAbsent,updateAll,addEntriesto safe-to-ignore list — these Map mutation methods are called for their side effect, not their return valueavoid_medium_length_files(and all 8 file length rules): count only code lines, excluding comments and blank lines — well-documented files are no longer penalised for thorough dartdocavoid_long_functions: count only code lines in function bodies, excluding comments and blank lines — well-documented functions are no longer penalised for thorough comments (v5)prefer_no_commented_out_code: tighten keyword and type-name patterns, add prose guard with strong-code-indicator bypass — fixes false positives on section headers (// Iterable extensions), inline prose (// this is non-null), and comments containing type names in natural language
Removed #
avoid_ignore_trailing_commentrule,MoveTrailingCommentFixquick fix, andtrailingCommentOnIgnoreregex — the native Dart analyzer handles ignore directive trailing comments correctly, making this rule produce false positives- Trailing-comment fixer functions from
bin/init.dart(_fixTrailingIgnoreComments,_splitIgnoreParts, etc.) — existed only to support the removed rule scripts/run_custom_lint_all.py— obsolete v4 scriptexample/custom_lint.yaml— v4 configuration artifact
Changed #
- All CLI tools (
bin/baseline.dart,bin/impact_report.dart) now usedart analyzeinstead ofdart run custom_lint - YAML config examples updated from v4
custom_lint:format to v5 nativeplugins: saropa_lints:format across lib/, docs, and scripts - Tier parser in
_analyze_pubspec.pyupdated to read v5plugins.saropa_lints.diagnosticsstructure - Removed
_offer_custom_lint()from publish script (no longer applicable) - VSCode extension updated to run
dart analyzeinstead ofdart run custom_lint
5.0.1 #
Added #
- Quick fixes for 5 blank-line formatting rules:
prefer_blank_line_before_case,prefer_blank_line_before_constructor,prefer_blank_line_before_method,prefer_blank_line_after_declarations,prefer_blank_lines_between_members - Test fixtures for 4 auto_route rules (
avoid_auto_route_context_navigation,avoid_auto_route_keep_history_misuse,require_auto_route_guard_resume,require_auto_route_full_hierarchy) - Test fixtures for
avoid_behavior_subject_last_value(rxdart) - Test fixtures for 3 migration rules (
avoid_asset_manifest_json,prefer_dropdown_initial_value,prefer_on_pop_with_result) - Unit test files for auto_route and rxdart rule categories
- Implemented
prefer_mock_verifyandrequire_mock_http_clientfixture examples (replaced stubs) - Uncommented
prefer_semantics_containerandavoid_redundant_semanticsfixture code (addedcontainerparameter to Semantics mock)
Fixed #
- Publish report: test coverage "Overall" percentage now caps per-category fixture counts at rule counts, preventing excess fixtures from masking gaps
prefer_static_class: no longer fires onabstract final classdeclarations (regression from beta.15 fix)avoid_hardcoded_locale: skip locale-pattern strings inside collection literals (Set, List, Map lookup data)avoid_datetime_comparison_without_precision: skip comparisons against compile-time constants (e.g., epoch sentinel checks)avoid_unsafe_collection_methods: strengthen guard detection with source-text fallback for length/isNotEmpty checksavoid_medium_length_files: exempt files containing onlyabstract finalutility namespace classesprefer_single_declaration_per_file: exempt files where all classes areabstract finalstatic-only namespacesprefer_no_continue_statement: exempt early-skip guard pattern (if (cond) { continue; }at top of loop body)
Changed #
avoid_high_cyclomatic_complexity: raise threshold from 10 to 15 to align with industry standards (SonarQube, ESLint)
5.0.0-beta.15 #
Added #
avoid_cached_image_web: warns when CachedNetworkImage is used inside akIsWebbranch where it provides no caching benefit (Recommended tier)avoid_clip_during_animation: warns when Clip widgets are nested inside animated widgets, causing expensive per-frame rasterization (Professional tier)avoid_auto_route_context_navigation: warns when string-basedcontext.push/context.gois used in auto_route projects instead of typed routes (Professional tier)avoid_auto_route_keep_history_misuse: warns whenreplaceAll/popUntilRootis used outside authentication flows, destroying navigation history (Professional tier)avoid_accessing_other_classes_private_members: warns when code accesses another class's private members through same-file library privacy (Professional tier)avoid_closure_capture_leaks: warns whensetStateis called inside Timer/Future.delayed callbacks without amountedcheck (Professional tier, quick fix)avoid_behavior_subject_last_value: warns when.valueis accessed on a BehaviorSubject inside anisClosedtrue-branch (Professional tier)avoid_cache_stampede: warns when async methods use a Map cache without in-flight request deduplication (Professional tier)avoid_deep_nesting: warns when code blocks are nested more than 5 levels deep (Professional tier)avoid_high_cyclomatic_complexity: warns when functions exceed cyclomatic complexity of 10 (Professional tier)avoid_void_async: warns when async functions returnvoidinstead ofFuture<void>(Recommended tier)avoid_redundant_await: warns whenawaitis used on a non-Future expression (Recommended tier)avoid_unused_constructor_parameters: warns when constructor parameters are not stored or used (Recommended tier)avoid_returning_null_for_void: warns whenreturn nullis used in void functions (Recommended tier)avoid_returning_null_for_future: warns whennullis returned from non-async Future functions (Recommended tier)avoid_shadowing_type_parameters: warns when method type parameters shadow class type parameters (Recommended tier)avoid_redundant_null_check: warns when non-nullable values are compared to null (Recommended tier)avoid_collection_mutating_methods: warns when collections are mutated in-place inside setState (Professional tier)avoid_equatable_nested_equality: warns when mutable collections are included in Equatable props (Professional tier)avoid_getx_rx_nested_obs: warns when GetX Rx observables are nested (Professional tier)avoid_freezed_any_map_issue: warns when @freezed class with fromJson lacks @JsonSerializable(anyMap: true) (Professional tier)avoid_hive_datetime_local: warns when DateTime is stored in Hive without UTC conversion (Professional tier)avoid_hive_type_modification: warns when @HiveField indices are duplicated (Professional tier)avoid_hive_large_single_entry: warns when large objects are stored as single Hive entries (Professional tier)require_auto_route_guard_resume: warns when AutoRouteGuard may not call resolver.next() on all paths (Essential tier)require_auto_route_full_hierarchy: warns when push() is used instead of navigate() in auto_route (Essential tier)avoid_firebase_user_data_in_auth: warns when too many custom claims are accessed from Firebase auth tokens (Professional tier)require_firebase_app_check_production: warns when Firebase is initialized without App Check (Professional tier)
Fixed #
avoid_god_class: false positive on static-constant namespace classes —static constandstatic finalfields are now excluded from the field count since they represent compile-time constants, not instance stateprefer_static_class: conflicting diagnostic withprefer_abstract_final_static_classon classes with private constructors —prefer_static_classnow defers toprefer_abstract_final_static_classwhen a private constructor is presentavoid_similar_names: false positive on single-character variable pairs (y,m,d,h,s) — edit distance is always 1 for any two single-char names, which is not meaningful; confusable-char detection (1/l, 0/O) still catches genuinely dangerous casesavoid_unused_assignment: false positive on definite assignment via if/else branches — assignments in mutually exclusive branches of the same if/else are now recognized as alternatives, not sequential overwrites
5.0.0-beta.14 #
Fixed #
avoid_variable_shadowing: false positive on sequential for/while/do loops reusing the same variable name — loop variables are scoped to their body and don't shadow each otheravoid_unused_assignment: false positive on conditional reassignment (x = x.toLowerCase()inside if-blocks) — now skips loop-body assignments, may-overwrite conditionals, and self-referencing RHSprefer_switch_expression: false positive on switch cases containing control flow (if/for/while) or multiple statements — also detects non-exhaustive switches with post-switch codeno_magic_number: false positive on numeric literals used as default parameter values — the parameter name provides context, making the number self-documentingavoid_unnecessary_to_list/avoid_large_list_copy: false positive when.toList()is required by return type, method chain, expression function body, or argument positionprefer_named_boolean_parameters: false positive on lambda/closure parameters — their signature is constrained by the expected function typeavoid_unnecessary_nullable_return_type: false positive on ternary expressions with null branches, map[]operator, and nullable method delegation — now checks static type nullability recursivelyavoid_duplicate_string_literals/avoid_duplicate_string_literals_pair: false positive on domain-inherent literals ('true','false','null','none') that are self-documentingavoid_excessive_expressions: false positive on guard clauses (early-return if-statements) and symmetric structural patterns — guard clauses now allowed up to 10 operators, symmetric repeating patterns are exemptprefer_digit_separators: false positive on 5-digit numbers — threshold raised from 10,000 to 100,000 (6+ digits) to match common style guide recommendationsrequire_list_preallocate: false positive whenList.add()is inside a conditional branch within a loop — preallocation is impossible when the number of additions is data-dependent
5.0.0-beta.13 #
Fixed #
prefer_match_file_name: false positive on Windows — backslash paths caused file name extraction to fail, reporting every correctly-named classprefer_match_file_name: false positive when file has multiple public classes — second class was reported even when first class matchedavoid_unnecessary_nullable_return_type: false positive on expression-bodied functions — ternaries with null branches, map lookups, and other nullable expressions were not recognizedprefer_unique_test_names: false positives when same test name appears in differentgroup()blocks — now builds fully-qualified names from group hierarchy, matching Flutter's test runner behavioravoid_dynamic_type: false positives forMap<String, dynamic>— the canonical Dart JSON type is now exemptno_magic_number_in_tests: expanded allowed integers to include 6–31 (day/month numbers), common round numbers (10000, 100000, 1000000), and exemptions for DateTime constructor arguments and expect() callsno_magic_string_in_tests: false positives for test fixture data — strings passed as arguments to functions under test and strings in expect() calls are now exemptavoid_large_list_copy: false positives for required copies —List<T>.from()with explicit type arguments (type-casting pattern) is now exempt;.toList()is exempt when returned, assigned, or otherwise structurally required
Changed #
- Merged duplicate rule
prefer_sorted_membersintoprefer_member_ordering;prefer_sorted_memberscontinues to work as a config alias - Clarified correction messages for
prefer_boolean_prefixes,prefer_descriptive_bool_names, andprefer_descriptive_bool_names_strictto distinguish scope (fields-only vs all booleans)
Publishing #
- Publish audit: consolidated quality checks into a single pass/warn/fail list instead of separate subsections per check
- Publish audit: US English spelling check displayed as a simple bullet instead of a standalone subsection
- Publish audit: bug reports grouped by status (done, in progress, unsolved) with scaled bars per group
- Publish audit: test coverage columns dynamically aligned to longest category name
- Init: "what's new" summary now shows all items (no
+N moreor section truncation) — only individual lines are truncated at 78 chars - Init: tier default changed from
comprehensivetoessentialfor fresh setups; re-runs default to the previously selected tier - Init: stale config version warning now tells the user how to fix it (
re-run "dart run saropa_lints" to update) - Init: stylistic walkthrough shows per-rule progress counter (
4/120 — 3%) and[quick fix]indicator for rules with IDE auto-fixes - Init: stylistic walkthrough rule descriptions rendered in default terminal color instead of dim gray for readability
5.0.0-beta.12 #
Added #
- Init: interactive stylistic rule walkthrough — shows code examples and lets users enable/disable each rule individually with y/n/skip/abort support and resume via
[reviewed]markers - Init:
--stylistic-allflag for bulk-enabling all stylistic rules (replaces old--stylisticbehavior);--no-stylisticto skip walkthrough;--reset-stylisticto clear reviewed markers - Init: auto-detect project type from pubspec.yaml — Flutter widget rules are skipped for pure Dart projects, package-specific rules filtered by dependencies
SaropaLintRule:exampleBad/exampleGoodproperties for concise terminal-friendly code snippets (40 rules covered)tiers.dart:flutterStylisticRulesset for widget-specific stylistic rules filtered by platform- Init: "what's new" summary shown during
dart run saropa_lints:init, with line truncation and a link to the full changelog - New rule:
prefer_sorted_imports(Comprehensive) — detects unsorted imports within each group (dart, package, relative) with quick fix to sort A-Z - New rule:
prefer_import_group_comments(Stylistic) — detects missing///section headers between import groups with quick fix to add them - New rule:
avoid_asset_manifest_json(Essential) — detects usage of removedAssetManifest.jsonpath (Flutter 3.38.0); runtime crash since the file no longer exists in built bundles - New rule:
prefer_dropdown_initial_value(Recommended) — detects deprecatedvalueparameter onDropdownButtonFormField, suggestsinitialValue(Flutter 3.35.0) with quick fix - New rule:
prefer_on_pop_with_result(Recommended) — detects deprecatedonPopcallback on routes, suggestsonPopWithResult(Flutter 3.35.0) with quick fix
Fixed #
no_empty_string: only flag empty strings in equality comparisons (== '',!= '') where.isEmpty/.isNotEmptyis a viable alternative — skip return values, default params, null-coalescing, replacement argsprefer_cached_getter: skip methods inside extensions and extension types (cannot have instance fields) and static methods (cannot cache to instance fields)prefer_compute_for_heavy_work: only flag encode/decode/compress calls inside widget lifecycle methods (build,initState, etc.) — library utility methods have no UI thread to protectprefer_keep_alive: check forTabBarView/PageViewidentifiers instead of naivecontains('Tab')/contains('Page')substring matchingprefer_prefixed_global_constants: case-insensitive descriptive pattern check for lowerCamelCase constants; expand pattern list (width, height, padding, etc.); narrow threshold to only flag names < 5 charsprefer_secure_random: only flagRandom()in security-related contexts (variable/method names containing token, password, encrypt, etc.); skip.shuffle()usage and literal-seeded constructorsprefer_static_method: skip methods inside extensions and extension types (cannot be made static in Dart)require_currency_code_with_amount: split into strong (price, amount, cost, fee) and weak (total, balance, rate) monetary signals; weak signals require 2+ matches with double/Decimal type; skip non-monetary class names (stats, count, metric, score, etc.)require_dispose_pattern: skip classes withconstconstructors (hold borrowed references, not owned resources)require_envied_obfuscation: skip class-level@Enviedwarning when all@EnviedFieldannotations explicitly specifyobfuscaterequire_https_only_test: skip HTTP URLs inside test infrastructure calls (test(),expect(),group(), etc.) since URL utility tests must exercise HTTPrequire_ios_callkit_integration: replace brand name string matching (Agora, Twilio, Vonage, WebRTC) with import-based detection for 13 VoIP packages; keep only unambiguous technical terms for string matchingavoid_barrel_files: skip files withlibrarydirective and the mandatory package entry point (lib/<package_name>.dart)avoid_duplicate_number_elements: only flagSetliterals — duplicate numeric values inListliterals are intentional (e.g. days-in-month)avoid_ignoring_return_values: skip property setter assignments (obj.prop = value) which have no return valueavoid_money_arithmetic_on_double: use camelCase word-boundary matching instead of substring matching to avoid false positives ontotalWidth,frameRate, etc.avoid_non_ascii_symbols: narrow from all non-ASCII to invisible/confusable characters only (zero-width, invisible formatters, non-standard whitespace)avoid_static_state: skipstatic constandstatic finalwith known-immutable types (RegExp,DateTime, etc.); retain detection ofstatic finalmutable collectionsavoid_stream_subscription_in_field: skip.listen()calls whose return value is passed as an argument (e.g.subs.add(stream.listen(...)))avoid_string_concatenation_l10n: skip numeric-only interpolated strings (e.g.'$a / $b') that contain no translatable word contentavoid_unmarked_public_class: skip classes where all constructors are private (extension already prevented)
Package Publishing Changes #
- Publish audit: added 3 new blocking checks —
flutterStylisticRulessubset validation,packageRuleSetstier consistency,exampleBad/exampleGoodpairing - Publish audit: doc comment auto-fix (angle brackets, references) now runs during audit step instead of only during analysis step
5.0.0-beta.11 #
Changed #
- CLI defaults to
initcommand when run without arguments (dart run saropa_lintsnow equivalent todart run saropa_lints init) - Publish script:
dart formatnow targets specific top-level paths, excludingexample*/directories upfront instead of tolerating exit-code 65 after the fact - Publish script: roadmap summary now includes color-coded bug report breakdown (unsolved/categorized/resolved) from sibling
saropa_dart_utils/bugs/directory - Deferred
avoid_misused_hooksrule removed from ROADMAP_DEFERRED (hook rules vary by context — not viable as static lint)
5.0.0-beta.10 #
Fixed #
- Init:
_stylisticRuleCategoriessynced withtiers.stylisticRules— removed obsoleteprefer_async_only_when_awaiting, added ~40 rules to proper categories instead of "Other stylistic rules" catch-all - Init: obsolete stylistic rules in consumer
analysis_options_custom.yamlare now cleaned up during rebuild, with warnings for user-enabled rules being dropped - Init: stylistic rules redundantly placed in RULE OVERRIDES section are detected — interactive prompt offers to move them to the STYLISTIC RULES section
- Init:
_buildStylisticSection()now filters againsttiers.stylisticRulesto prevent future category/tier desyncs dart analyzeexit codes 1-2 (issues found) no longer reported as "failed" — only exit code 3+ (analyzer error) is treated as failure- Progress bar stuck at ~83% — recalibration threshold no longer inflates expected file count when discovery overcounts
- Progress bar now shows 100% completion before the summary box
- Publish script: restored post-publish version bump (pubspec +
[Unreleased]section) — accidentally removed in v4.9.17 refactor - Publish script: optional
_offer_custom_lintprompt no longer blocks success status or timing summary on interrupt
Changed #
- Init log (
*_saropa_lints_init.log) now contains only setup/configuration data; rawdart analyzeoutput is no longer mixed in — the plugin's report (*_saropa_lint_report.log) covers analysis results - Init log written before analysis prompt so the path is available upfront
- Plugin report path displayed after analysis completes (with retry for async flush)
- Old report files in
reports/root are automatically migrated toreports/YYYYMMDD/date subfolders during init - Stream drain and exit code now awaited together via
Future.waitto prevent interleaved output - Persistent cache files (
rule_version_cache.json, export directories) moved fromreports/root toreports/_cache/subfolder
5.0.0-beta.9 #
Fixed #
- Plugin silently ignored by
dart analyze— generatedanalysis_options.yamlwas missing the requiredversion:key underplugins: saropa_lints:; the Dart SDK's plugin loader returnsnullwhen no version/path constraint is present, causing zero lint issues to be reported - Analysis server crash loop (FormatException) —
ProgressTrackerwas writing ANSI progress bars tostdout, which corrupts the JSON-RPC protocol used by the analysis server; all output now routes throughstderr
Added #
- Pre-flight validation checks in
init: verifies pubspec dependency, Dart SDK >= 3.6, and audits existing config for stalecustom_lint:sections or missingversion:keys - Post-write validation: confirms the generated file has
plugins:,version:,diagnostics:sections and expected rule count - Analysis results now captured in the init log file (previously only shown on terminal)
- Log summary section with version, tier, rule counts, and collected warnings
Changed #
dart analyzeoutput is now captured and streamed (wasinheritStdiowith no capture)- Log file write deferred until after analysis completes so the report includes everything
- All tier YAML files now include
version: "^5.0.0-beta.8"for direct-include users - All report-generating scripts now write to
reports/YYYYMMDD/date subfolders with timestamped filenames (todo audit, full audit, lint candidates, rule versions)
Archive #
- Rules 4.15.1 and older moved to CHANGELOG_ARCHIVE.md
5.0.0-beta.7 #
Added #
- Init log file now includes a detailed rule-by-rule report listing every rule with its status, severity, tier, and any override/filter notes
Changed #
- Report files now write into
reports/YYYYMMDD/date subfolders instead of flat inreports/— reduces clutter when many reports accumulate --tier/--outputflags without a value now warn instead of silently using defaultsdart run saropa_lints:initwithout--tiernow prompts for interactive tier selection (was silently defaulting to comprehensive)
Fixed #
.pubignorepatterntest/was excludinglib/src/fixes/test/from published package — anchored to/test/so only the root test directory is excluded; this causeddart run saropa_lints:initto fail with a missing import error forreplace_expect_with_expect_later_fix.dart- Publish script
dart formatstep failed on fixture files using future language features (extension types, digit separators, non-ASCII identifiers) — now tolerates exit code 65 when all unparseable files are in example fixture directories
5.0.0-beta.6 #
Added #
- Quick fix for
require_subscription_status_check— inserts TODO reminder to verify subscription status in build methods getLineIndent()utility onSaropaFixProducerbase class for consistent indentation in fix output
Changed #
- Moved generated export folders (
dart_code_exports/,dart_sdk_exports/,flutter_sdk_exports/) and report caches fromscripts/toreports/— scripts now write output to the gitignoredreports/directory, keepingscripts/clean - Filled TODO placeholders in 745 fixture files across all example directories — core and async fixtures now have real bad/good triggering code; widget, package, and platform fixtures have NOTE placeholders documenting rule requirements
- Expanded ROADMAP task backlog with 138 detailed implementation specs
- Deduplicated
_getIndentfrom 5 fix files into sharedSaropaFixProducer.getLineIndent()
Fixed #
- Audit script
get_rules_with_corrections()now handles variable-referenced rule names (e.g.LintCode(_name, ...)) — previously undercounted correction messages by 1 (no_empty_block) - OWASP M2 coverage now correctly reported as 10/10 — audit scanner regex updated to match both single-line and dart-formatted multiline
OwaspMappinggetters;avoid_dynamic_code_loadingandavoid_unverified_native_library(M2),avoid_hardcoded_signing_config(M7), andavoid_sudo_shell_commands(M1) were previously invisible to the scanner - Completed test fixtures for
avoid_unverified_native_libraryandavoid_sudo_shell_commands(previously empty stubs) - Removed 4 dead references to unimplemented rule classes from registration and tier files (
require_ios_platform_check,avoid_ios_background_fetch_abuse,require_method_channel_error_handling,require_universal_link_validation) — tracked asbugs/todo_001throughtodo_004
5.0.0-beta.5 #
Added #
- Auto-migration from v4 (custom_lint) to v5 (native plugin) —
dart run saropa_lints:initauto-detects and converts v4 config, with--fix-ignoresfor ignore comment conversion - Plugin reads
diagnostics:section fromanalysis_options.yamlto determine which rules are enabled/disabled — previously the generated config was not consumed by the plugin - Registration-time rule filtering — disabled rules are never registered with the analyzer, improving startup performance
Fixed #
- Plugin now respects rule enable/disable config from
dart run saropa_lints:init— previously all rules were registered unconditionally regardless of tier selection - V4 migration no longer imports all rule settings as overrides — only settings that differ from the selected v5 tier defaults are preserved, preventing mass rule disablement
- Init script scans and auto-fixes broken ignore comments — detects trailing explanations (
// ignore: rule // reasonor// ignore: rule - reason) that silently break suppression, and moves the text to the line above - Quick fix support for 108 rules via native
SaropaFixProducersystem — enables IDE lightbulb fixes anddart fix --apply - 3 reusable fix base classes:
InsertTextFix,ReplaceNodeFix,DeleteNodeFixinlib/src/fixes/common/ - 108 individual fix implementation files in
lib/src/fixes/<category>/, all with real implementations (zero TODO placeholders) - Test coverage for all 95 rule categories (Phase 1-3): every category now has a dedicated
test/*_rules_test.dartfile with fixture verification and semantic test stubs - 506 missing fixture stubs across all example directories (Phase 1-4)
- 12 new package fixture directories: flutter_hooks, workmanager, supabase, qr_scanner, get_it, geolocator, flame, sqflite, graphql, firebase, riverpod, url_launcher
Changed #
- PERFORMANCE.md rewritten for v5 native plugin architecture — replaced all custom_lint references with
dart analyze, updated rule counts, documented lazy rule instantiation and compile-time constant tier sets, added rule deferral info
Fixed #
- Test fixture paths for bloc, firebase, riverpod, provider, and url_launcher now point to individual category directories instead of shared
packages/directory - Platform fixture paths reorganized from shared
platforms/directory to per-platform directories (ios/,macos/,android/,web/,linux/,windows/) — fixes 0% coverage report for all platform categories - Coverage script fallback search for fixture files in subdirectories, with prefix-match anchoring and OS error handling
5.0.0-beta.4 #
Fixed #
- Untrack
.github/copilot-instructions.md— was gitignored but tracked, causingdart pub publish --dry-runto exit 65 (warning) - Publish workflow dry-run step now tolerates warnings (exit 65) but still fails on errors (exit 66)
- Publish script now waits for GitHub Actions workflow to complete and reports real success/failure — previously printed "PUBLISHED" immediately without checking CI status
5.0.0-beta.3 #
Fixed #
- Add
analyzeras explicit dependency —dart pub publishrejected transitive-only imports, causing silent publish failure - Remove
|| [ $? -eq 65 ]from publish workflow — was silently swallowing publish failures
5.0.0-beta.2 #
Fixed #
- Publish script regex patterns updated for v5 positional
LintCodeconstructor — tier integrity, audit checks, OWASP coverage, prefix validation, and correction message stats now match both v5 positional and v4 named parameter formats - Publish script version utilities now support pre-release versions (
5.0.0-beta.1→5.0.0-beta.2) — version parsing, comparison, pubspec read/write, changelog extraction, and input validation all handle-suffix.Nformat
5.0.0-beta.1 — Native Plugin Migration #
Migrated from custom_lint_builder to the native analysis_server_plugin system. This is a breaking change for consumers (v4 → v5).
Why this matters:
- Quick fixes now work in IDE — the old analyzer_plugin protocol never forwarded fix requests to custom_lint plugins (Dart SDK #61491). The native system delivers fixes properly.
- Per-file filtering is enforced — 425+ uses of
applicableFileTypes,requiredPatterns,requiresWidgets, etc. were defined but never checked. Now enforced viaSaropaContext._wrapCallback(), cached per file. - Future-proof — the old
analyzer_pluginprotocol is being deprecated (Dart SDK #62164). custom_lint was the primary client. - ~18K lines removed — native API eliminates boilerplate (no more
CustomLintResolver/ErrorReporter/CustomLintContextparameter triples).
Added #
- Native plugin entry point (
lib/main.dart) withSaropaLintsPlugin SaropaFixProducerbase class for quick fixes (analysis_server_plugin)fixGeneratorsgetter onSaropaLintRulefor automatic fix registrationSaropaContextwith per-file filtering wrapper on all 83addXxx()methodsCompatVisitorbridging callbacks to nativeSimpleAstVisitordispatch- PoC quick fixes:
CommentOutDebugPrintFix,RemoveEmptySetStateFix - Native framework provides ignore-comment fixes automatically (no custom code needed)
- Config loader (
config_loader.dart) readsanalysis_options_custom.yamlat startup - Severity overrides via
severities:section (ERROR/WARNING/INFO/false per rule) - Baseline suppression wired into reporter — checks
BaselineManagerbefore every report - Impact tracking — every violation recorded in
ImpactTrackerby impact level - Progress tracking — files and violations tracked in
ProgressTrackerper file/rule Plugin.start()lifecycle hook for one-time config loading- Tier preset YAML files updated to native
plugins: saropa_lints: diagnostics:format - Migration guide (
MIGRATION_V5.md) for v4 to v5 upgrade
Changed #
bin/init.dartgenerates nativeplugins:format (wascustom_lint:)- Tier presets use
diagnostics:map entries (wasrules:list entries) - Init command runs
dart analyzeafter generation (wasdart run custom_lint) - All 96 rule files migrated to native
AnalysisRuleAPI SaropaLintRulenow extendsAnalysisRule(wasDartLintRule)LintCodeuses positional constructor:LintCode('name', 'message')(was named params)runWithReporterdropsCustomLintResolverparametercontext.addXxx()replacescontext.registry.addXxx()reporter.atNode(node)replacesreporter.atNode(node, code)(code is implicit)- Dependencies:
analysis_server_plugin: ^0.3.3replacescustom_lint_builder - README updated for v5:
dart analyzereplacesdart run custom_lint, tier preset includes, v4 migration FAQ
Removed #
custom_lint_builderdependency andlib/custom_lint_client.dart- Redundant PoC files (
saropa_analysis_rule.dart,poc_rules.dart,saropa_reporter.dart) - Old v4 ignore-fix classes — superseded by native framework
4.15.1 and Earlier #
For details on the initial release and versions 0.1.0 through 4.15.1, please refer to CHANGELOG_ARCHIVE.md.