saropa_lints 10.8.0
saropa_lints: ^10.8.0 copied to clipboard
2134 custom lint rules with 254 quick fixes for Flutter and Dart. Static analysis for security, accessibility, and performance.
Changelog #
2100+ custom lint rules with 250+ quick fixes for Flutter and Dart — static analysis for security, accessibility, performance, and library-specific patterns. Includes a VS Code extension with Package Vibrancy scoring.
Looking for older changes? See CHANGELOG_ARCHIVE.md for versions 0.1.0 through 9.5.1.
Package — pub.dev / packages / saropa_lints
Score — pub.dev / packages / saropa_lints / score
Releases — github.com / saropa / saropa_lints / releases
VS Code Marketplace — marketplace.visualstudio.com / items ? itemName=saropa.saropa-lints
Open VSX Registry — open-vsx.org / extension / saropa / saropa-lints
10.8.0 #
Added #
- Vibrancy Report: New "Issues" and "PRs" columns show open GitHub issue and pull request counts, linking directly to the repository's issues and pulls pages
- Drift Advisor: Toolbar toggle button in the Drift Advisor view —
$(plug)enables integration,$(circle-slash)disables it. No more hunting through Settings to findsaropaLints.driftAdvisor.integration.
10.7.0 #
Changed #
- Vibrancy: Renamed health categories for clarity — "Quiet" → Stable, "Legacy-Locked" → Outdated, "Stale" → Abandoned. Vibrant and End of Life are unchanged.
- Vibrancy: Raised Abandoned threshold from score <10 to score <20 so packages untouched for 4+ years with only bonus points are correctly flagged instead of escaping into Outdated
- Vibrancy Report: Overrides summary card is now clickable — filters the table to show only overridden packages
- Vibrancy Report: All table column headings now have tooltips explaining what each column represents (e.g. Published = "Date the installed version was published to pub.dev")
Added #
- Vibrancy Report: Copy-as-JSON button appears on row hover — copies a detailed JSON of all package fields and links to clipboard
- Vibrancy Report: New "Files" column shows how many source files import each package, with clickable file paths in the detail view that open at the exact import line
- Vibrancy Report: "Single-use" summary card filters to packages imported from only one file
- Vibrancy Report: Exported JSON and Markdown reports now include per-package file-usage data (file paths and line numbers)
Fixed #
- Vibrancy Report: Commented-out imports (e.g.
// import 'package:foo/foo.dart') are no longer counted as active usage for unused-package detection
Breaking #
- Vibrancy Settings:
budget.maxStalerenamed tobudget.maxAbandoned;budget.maxLegacyLockedrenamed tobudget.maxOutdated. Users who customized these settings will need to update their config. - Vibrancy Exports: JSON/Markdown export schemas use new category keys (
stable,outdated,abandonedinstead ofquiet,legacy_locked,stale) - Generated CI scripts: Previously generated CI workflows reference old threshold variable names. Regenerate after updating.
10.6.0 #
Extension UX refinements — split workspace options into Settings and Issues sections, hide "Apply fix" for unfixable violations, and auto-expand violations tree on programmatic navigation. — log
Changed #
- Extension: Overview sidebar splits the former "Workspace options" section into two focused sections: Settings (lint integration, tier, detected packages, config actions) and Issues (triage groups by violation count); Issues hides when no analysis data exists
- Extension: "Apply fix" context menu item is now hidden for violations without a quick fix, instead of showing a dead-end "No quick fix available" message
- Extension: Violations tree now auto-expands all levels when navigated to from settings, dashboard links, summary counts, or triage groups
Fixed #
- Extension:
rulesWithFixesfromviolations.jsonwas not extracted, causing all violations to appear fixable regardless of actual fix availability
10.5.0 #
Replacement complexity metric — analyzes local pub cache to estimate feasibility of inlining, forking, or replacing each dependency; removed inline vibrancy summary diagnostic. — log
Added #
- (Extension) Package Vibrancy: replacement complexity metric — analyzes local pub cache to count source lines in each dependency's
lib/directory and classifies how feasible it would be to inline, fork, or replace (trivial / small / moderate / large / native). Shown in Size tree group, detail sidebar, and CodeLens for stale/end-of-life packages with feasible migration
Changed #
- (Extension) Removed the
vibrancy-summaryinline diagnostic frompubspec.yaml— the Package Vibrancy sidebar and report already surface this information. TheinlineDiagnosticssetting no longer offers a"summary"mode; the default is now"critical"(end-of-life packages only)
10.4.1 #
Fixed VS Code Marketplace publishing blocked by TypeScript 5.9 bug; modularized publish script into focused modules. — log
Fixed #
- (Extension) Fixed VS Code Marketplace publishing blocked since v10.2.2 by TypeScript 5.9 bug —
tsc --noEmitfails with "Unknown compiler option" because TS 5.9'screateOptionNameMap()readsoption.lowerCaseName(a property that doesn't exist on any option declaration), building an empty lookup map; pinned TypeScript to~5.8.3to restore extension compilation and Marketplace publishing
Changed #
- Modularized
scripts/publish.py(1,246 → 202 lines) into three focused modules:_publish_workflow.py(pipeline orchestration), version prompting/sync into_version_changelog.py, and store verification into_extension_publish.py - Added
scripts/README.mdwith architecture diagram, module map, exit codes, and troubleshooting - Added pub.dev publication verification: polls the pub.dev API after publish to confirm the new version is live
10.4.0 #
Vibrancy Report overhaul — auto-hiding blank columns, clickable summary cards and chart segments for filtering, search box, richer version/health tooltips, and pub.dev deep links throughout. — log
Vibrancy Report #
- (Extension) Auto-hide blank columns: Transitives, Vulns, and Status columns are hidden when all values are empty
- (Extension) Summary cards now toggle table filters on click (vibrant, quiet, stale, updates, unused, vulns)
- (Extension) Chart bars and donut segments toggle a package filter instead of scrolling
- (Extension) Search box added above the table for filtering packages by name
- (Extension) "Open pubspec.yaml" toolbar button sends message to open the file in the editor
- (Extension) Version column links to pub.dev/versions; shows compact age suffix (e.g.
(4mo),(2y)) - (Extension) Version column tooltip shows installed version date, latest version, creation date, and constraint
- (Extension) Health column merged from separate Score/Drift; tooltip shows score breakdown (Resolution Velocity, Engagement Level, Popularity, Publisher Trust)
- (Extension) License column links to pub.dev/license; Update column links to pub.dev/changelog
- (Extension) Stars column right-aligned with comma formatting; Size column now shows KB
- (Extension) Section badges (
dev,transitive) shown in Package column - (Extension) Description info icon column with tooltip on hover
- (Extension) Override count shown in summary cards
- (Extension)
createdDatefield added to pub.dev metadata - (Extension)
installedVersionDatefield added to vibrancy results
10.3.0 #
Analyzer 12 migration — rewrites ~500 call sites across 70+ rule files to the new AST API, adds vibrancy scan cancel/supersede support. — log
Changed #
- Analyzer upgraded from ^9.0.0 to ^12.0.0 — migrated ~500 call sites across 70+ rule files to the new AST API (
ClassDeclaration.body.members,ClassNamePart.typeName,PrimaryConstructorDeclaration,DottedName, etc.) - Removed analyzer-9 compatibility extensions —
DiagnosticCodeLowerCaseandLintCodeLowerCaseshims removed;lowerCaseNameis now native in analyzer 12 - Updated
CapturingRuleVisitorRegistry— added 5 new visitor methods and removed 4 obsolete ones to match the analyzer 12RuleVisitorRegistryinterface - Updated test registry —
PluginRegistryinterface changes:enabled()method,DiagnosticCodeparameter onregisterFixForRule
Added #
- Vibrancy scan cancel button — the progress notification now shows a Cancel button so users can abort a long-running scan
- Scan supersede — starting a new vibrancy scan automatically cancels any in-progress scan instead of silently dropping the request
10.2.2 #
10.2.1 #
VS Code extension polish — clearer status bar when lint health and Package Vibrancy are both shown. — log
Fixed #
- (Extension) Unified status bar now uses compact disambiguation for mixed metrics when vibrancy is shown:
Saropa: 90% · V4/10(prevents confusion between lint%and vibrancy/10without adding verbose labels)
10.2.0 #
Stream subscription detection improvements — fixes false negatives on rxdart and custom Stream subclasses, and aligns rule description with actual behavior. — log
Added #
- New rule:
avoid_removed_null_thrown_error— flags removedNullThrownErrortype (Dart 3.0); quick fix renames toTypeError - New rule:
avoid_deprecated_file_system_delete_event_is_directory— flags deprecatedFileSystemDeleteEvent.isDirectory(Dart 3.4) which always returns false - New rule:
avoid_removed_render_object_element_methods— flags removedinsertChildRenderObject,moveChildRenderObject,removeChildRenderObject(Flutter 3.0); quick fix renames to replacement methods - New rule:
avoid_deprecated_animated_list_typedefs— flags deprecatedAnimatedListItemBuilder/AnimatedListRemovedItemBuilder(Flutter 3.7); quick fix renames toAnimatedItemBuilder/AnimatedRemovedItemBuilder - New rule:
avoid_deprecated_use_material3_copy_with— flags misleadinguseMaterial3parameter inThemeData.copyWith()(Flutter 3.16); quick fix removes the parameter - New rule:
avoid_deprecated_on_surface_destroyed— flags deprecatedSurfaceProducer.onSurfaceDestroyed(Flutter 3.29); quick fix renames toonSurfaceCleanup
Fixed #
avoid_stream_subscription_in_fieldnow detects uncaptured.listen()calls on Stream subclasses (e.g. rxdartMergeStream,BehaviorSubject) that were previously missed by string-based type checkingavoid_stream_subscription_in_fieldproblem message and correction message now accurately describe the rule's behavior (detecting uncaptured.listen()calls) instead of incorrectly claiming it checksdispose()- Test fixture for
avoid_stream_subscription_in_fieldnow uses properly-typedStream<int>variables instead of undefineddynamicreferences that bypassed the type check - (Extension) Violations sidebar no longer opens a "file not found" error when source files have been moved or renamed since the last analysis; affected items show a warning icon with "(file moved or deleted)" label
- (Extension) "Fix all in this file" command now shows a user-friendly warning instead of silently failing on moved/deleted files
10.1.1 #
Package Vibrancy accuracy pass — removes false "End of Life" flags on healthy packages and adds a pub points quality floor so high-scoring packages are never labeled Stale. — log
Fixed #
- (Extension) 8 packages falsely classified as End of Life in
known_issues.jsonhave been downgraded tocautionoractive—local_auth,font_awesome_flutter,animations,flutter_email_sender,flutter_sticky_header,flutter_rating_bar,workmanager,flutter_phone_direct_callerwere contradicted by their own pub.dev scores (135-160/160 points). - (Extension) Packages with >= 140/160 pub points can no longer classify as Stale — the pub points quality floor promotes them to Legacy-Locked at minimum, preventing high-quality quiet packages from appearing abandoned.
- (Extension)
calcPopularitypub points normalization cap corrected from 150 to 160 (the actual pub.dev maximum). - (Extension) Fixed dead-code status string mismatch in
adoption-classifier.tsandtransitive-analyzer.ts— checks for'end-of-life'(hyphenated) now correctly use'end_of_life'(underscored) to matchknown_issues.jsonformat.
10.1.0 #
This release focuses on Flutter SDK alignment (new migration lints and a shared identifier→element helper) and on the VS Code extension: Package Vibrancy now uses a single trusted publishers list so first-party and Google-published packages are not mislabeled Quiet when GitHub-activity scoring sits in the mid tier. — log
Added #
-
prefer_dropdown_menu_item_button_opacity_animation(Recommended, INFO) — Flutter 3.32 (PR #164795) typesopacityAnimationonDropdownMenuItemButtonstate as non-null (late CurvedAnimation). The rule flags nullableCurvedAnimation? opacityAnimationfields and redundantopacityAnimation!when resolved types showState<DropdownMenuItemButton<…>>or aDropdownMenuItemButtonreceiver. Quick fixes: remove!(RemoveNullAssertionFix) and rewrite the field tolate CurvedAnimation(prefer_dropdown_menu_item_button_opacity_animation_field_fix.dart). Fixture:example/lib/migration/prefer_dropdown_menu_item_button_opacity_animation_fixture.dart; mock:DropdownMenuItemButtoninexample/lib/flutter_mocks.dart. -
prefer_image_filter_quality_medium(Comprehensive, INFO) — FlagsfilterQuality: FilterQuality.lowon Flutter SDKImage/RawImage/FadeInImage/DecorationImageso apps align with Flutter 3.24 image defaults (PR #148799). Quick fix rewriteslow→medium(preserves enum prefix). Does not apply toTexture. Detection:lib/src/rules/widget/image_filter_quality_detection.dart; rule:lib/src/rules/widget/image_filter_quality_migration_rules.dart. -
avoid_deprecated_flutter_test_window(Recommended, WARNING) — Flagspackage:flutter_testTestWindow and TestWidgetsFlutterBinding.window, deprecated in Flutter 3.10 (PR #122824); migrate toWidgetTester.platformDispatcherandWidgetTester.view/viewOf. Detection uses resolved elements only. Shared predicates:lib/src/rules/config/flutter_test_window_deprecation_utils.dart(unit-tested URI boundary);example/analysis_options_template.yamllists the override.
Changed #
-
Package Vibrancy (VS Code extension) — Introduces
extension/src/vibrancy/scoring/trusted-publishers.ts:TRUSTED_PUBLISHERS(dart.dev,google.dev,flutter.dev,firebase.google.com) andisTrustedPublisher(). The same set controls (1) thepublisherTrustBonusscoring bonus and (2) promoting Quiet → Vibrant when the raw score is in the mid band but the dependency is from a trusted publisher—so pubspec CodeLens and reports match maintainer intent. EOL still wins: discontinued packages, known end-of-life entries, and archived GitHub repos are unchanged; publisher IDs are matched case-sensitively (as on pub.dev).saropaLints.packageVibrancy.publisherTrustBonussetting description updated to describe the trusted list. Tests:npm testrunsvibrancy-calculator.test.ts(trust bonus for every trusted ID) and extendedstatus-classifier.test.ts(trusted upgrade, non-trusted quiet, wrong-case publisher, EOL overrides). -
Analyzer identifier → element — Shared
elementFromAstIdentifierinlib/src/element_identifier_utils.darttries.elementthen.staticElementwith optionallogFailures. Used byimage_filter_quality_detectionand deprecated-API checks incode_quality_avoid_rules.dart. Documented in CODE_INDEX.md. Tests:test/element_identifier_utils_test.dart.
10.0.2 #
This patch wires ten compile-time mirror rules into the public rule list and tiers, updates existing rules for Analyzer 9 element APIs, and fixes a require_data_encryption false positive and unsafe file:// root parsing in project metadata. — log
Fixed #
- Plan additional rules 31–40 — The ten compile-time / doc / style mirror rules (
abstract_field_initializer,abi_specific_integer_invalid,annotate_redeclares,deprecated_new_in_comment_reference,document_ignores,non_constant_map_element,return_in_generator,subtype_of_disallowed_type,undefined_enum_constructor,yield_in_non_generator) were present in source but missing fromsaropa_lints.dart_allRuleFactoriesand fromessentialRules; they are now registered so tiers and tooling load them. - Analyzer 9 (migration / fixes) —
prefer_dropdown_menu_item_button_opacity_animationusesdeclaredFragment?.elementon class and field declarations,DartType.nullabilitySuffixfor nullableCurvedAnimation?, [SimpleIdentifier.element] for!operands, andreporter.atTokenfor field names.PreferDropdownMenuItemButtonOpacityAnimationFieldFixusesNamedType.name.lexemeandVariableDeclarationList.lateKeyword/keywordfor insertion offsets.image_filter_quality_detectionusesSimpleIdentifier.elementonly (removedstaticElement). require_data_encryption— Thepinkeyword is matched only when not immediately preceded by an ASCII letter, so identifiers such asOwaspMapping(whereMappingembeds…p-i-n…) no longer false-positive on ordinarywrite/writeAsStringcalls. Regression coverage:test/require_data_encryption_pin_pattern_test.dart; fixture:example_async/lib/security/require_data_encryption_fixture.dart.rootUriToPath—file://roots useUri.tryParseso invalid URIs return null instead of throwing; satisfiesprefer_try_parse_for_dynamic_datafor package_config paths. Tests:test/project_info_root_uri_test.dart.
10.0.0 #
In this milestone update work centers on the composite analyzer plugin hook (registerSaropaLintRules), rule packs end-to-end (analyzer merge, CLI init, VS Code Rule Packs webview, generated registry), extension UX that defaults integration on with clearer commands and TODOs workspace scan as opt-in, and a wave of new lints—compile-time shape alignment, Dart 3.0 removed-API migration rules, and targeted Flutter fixes. — log
Fixed #
• Publish / tier integrity — scripts/modules/_tier_integrity.py get_registered_rule_names now resolves rule classes when the extends clause starts on the line after the class name (valid Dart; previously produced a false phantom for avoid_removed_nosuchmethoderror_default_constructor). AvoidRemovedNoSuchMethodErrorDefaultConstructorRule header documented to stay single-line for consistency with adjacent migration rules. Python regression coverage: scripts/tests/test_tier_integrity_registered_names.py.
• VS Code extension — Violations tree: enable canSelectMany on saropaLints.issues so Ctrl/Cmd+click multi-select works with Copy as JSON (command already preferred the selection array; the UI could not select multiple rows before). Selection resolution moved to extension/src/copyTreeAsJsonSelection.ts for unit tests without the VS Code runtime. Tests: extension/src/test/copyTreeAsJson.test.ts.
• VS Code extension — Code cleanup: batch context.subscriptions.push where it was split unnecessarily (extension.ts), and refactor vibrancy “Copy as JSON” serialization into small matchers with documented dispatch order (treeSerializers.ts). Adds unit tests for serializeVibrancyNode (including false-positive guards for partial package/problem/suggestion payloads).
Changed #
• VS Code extension — Default-on UX: saropaLints.enabled defaults true; Overview always shows workspace options and sidebar toggles for Dart projects (no empty tree + “off” welcome). Config and Rule Packs views depend on saropaLints.isDartProject + sidebar settings, not on enabled. TODOs & Hacks workspace scan is opt-in via new saropaLints.todosAndHacks.workspaceScanEnabled (default false) with command TODOs & Hacks: Enable workspace scan. Commands renamed for clarity (Set Up Project / Turn Off Lint Integration). Sidebar section counts still reflect violations.json even when integration is off; Vibrancy package count is supplied by the extension host (getLatestResults().length) so sidebarSectionCounts stays testable. New modules/tests: suggestionCounts.ts, suggestionCounts.test.ts, sidebarSectionCounts.test.ts.
Added #
• Composite analyzer plugin API — registerSaropaLintRules(PluginRegistry) on package:saropa_lints/saropa_lints.dart (used by lib/main.dart); skips rules via SaropaLintRule.isDisabled (canonical name or configAliases). Re-export loadNativePluginConfig, loadOutputConfigFromProjectRoot, loadRulePacksConfigFromProjectRoot for meta-plugins. Guide: doc/guides/composite_analyzer_plugin.md. Tests: test/saropa_plugin_registration_test.dart. Template note: example/analysis_options_template.yaml.
• VS Code extension — Rule Packs sidebar webview: per-pack row (label, detected in pubspec, enable toggle, rule count, “Rules” opens Quick Pick of rule codes), plus target platforms table (android/ios/web/windows/macos/linux) when embedder folders exist. Writes plugins.saropa_lints.rule_packs.enabled in analysis_options.yaml.
• Analyzer plugin — rule_packs.enabled under plugins.saropa_lints merges rule codes from lib/src/config/rule_packs.dart via mergeRulePacksIntoEnabled (skips codes in diagnostics/severities disables). Config load order documented in config_loader.dart.
• Rule packs (Phase 3) — pubspec.lock resolved versions (cached by mtime) gate optional packs via kRulePackDependencyGates; example collection_compat merges only when collection satisfies >=1.19.0. loadRulePacksConfigFromProjectRoot re-merges packs when the analyzer discovers the project root. Dependency: pub_semver.
• Rule packs (Phase 4 / CLI) — dart run saropa_lints:init --list-packs lists applicable packs from pubspec + lockfile; --enable-pack <id> (repeatable) merges into rule_packs.enabled. Init / write_config preserve existing rule_packs when regenerating the plugins section (unless --reset).
• Rule packs (Phase 5 / registry codegen) — lib/src/config/rule_pack_codes_generated.dart is produced from lib/src/rules/packages/*_rules.dart by dart run tool/generate_rule_pack_registry.dart (also refreshes extension/src/rulePacks/rulePackDefinitions.ts). kRulePackRuleCodes / kRulePackPubspecMarkers in rule_packs.dart spread the generated maps and add collection_compat. dart run tool/rule_pack_audit.dart checks file extraction vs the merged registry (shared composite map for cross-pack rules such as avoid_isar_import_with_drift).
• Lint rules — compile-time Dart shape (ERROR/WARNING, Essential): ten rules aligned with analyzer compile-time diagnostics — duplicate_constructor, conflicting_constructor_and_static_member, duplicate_field_name, field_initializer_redirecting_constructor, invalid_super_formal_parameter_location, illegal_concrete_enum_member, invalid_extension_argument_count, invalid_field_name (keyword-tokens on record labels when present in AST), invalid_literal_annotation, invalid_non_virtual_annotation. Implementation: lib/src/rules/architecture/compile_time_syntax_rules.dart, record/extension rules in type_rules.dart; fixture example/lib/plan_additional_rules_21_30_fixture.dart.
• Lint rules — Dart SDK 3.0 removed APIs (WARNING, Recommended): fifteen migration rules with targeted quick fixes where safe — avoid_deprecated_list_constructor, avoid_removed_proxy_annotation, avoid_removed_provisional_annotation, avoid_deprecated_expires_getter, avoid_removed_cast_error, avoid_removed_fall_through_error, avoid_removed_abstract_class_instantiation_error, avoid_removed_cyclic_initialization_error, avoid_removed_nosuchmethoderror_default_constructor, avoid_removed_bidirectional_iterator, avoid_removed_deferred_library, avoid_deprecated_has_next_iterator, avoid_removed_max_user_tags_constant, avoid_removed_dart_developer_metrics, avoid_deprecated_network_interface_list_supported. See lib/src/rules/config/dart_sdk_3_removal_rules.dart.
• Lint rule — avoid_implicit_animation_dispose_cast (WARNING, Professional, high impact): flags (animation as CurvedAnimation).dispose() in ImplicitlyAnimatedWidgetState subclasses; the framework disposes that animation in super.dispose() (Flutter 3.7 / PR #111849). Quick fix removes the redundant statement. Shared AST helper: lib/src/implicit_animation_dispose_cast_ast.dart. Tests: test/avoid_implicit_animation_dispose_cast_rule_test.dart.
• Lint rule — prefer_overflow_bar_over_button_bar (INFO, Recommended): flags ButtonBar usage; prefer OverflowBar for Material action layouts (Flutter 3.13 guidance, PR #128437).
Changed #
• VS Code extension — Overview & options sidebar: Workspace options embeds the same tree as the standalone Config view; section toggles show counts in the label (e.g. Package Vibrancy (2)) with On/Off in the description; intro links (pub.dev, About, Getting Started) remain visible whenever Saropa is enabled; standalone Config defaults off (saropaLints.sidebar.showConfig). Command Saropa Lints: Open package on pub.dev (saropaLints.openPubDevSaropaLints). Overview Copy as JSON recurses through nested children. Embedded config nodes are allowlisted by kind (overviewEmbeddedConfigKinds.ts); sidebar label formatting lives in sidebarToggleLabel.ts for Node tests. Unit tests: sidebarToggleLabel, overviewEmbeddedConfigKinds, serializeOverviewNode.
• Rule packs — Maintainer workflow documented in doc/guides/rule_packs.md (regenerate, composite map, audit). Added test/rule_pack_registry_test.dart (composite avoid_isar_import_with_drift on drift + isar; collection_compat merge) and expanded pubspec-marker false-positive coverage. README badge rule count aligned with pubspec.yaml (2105).
• VS Code extension — TODOs & Hacks default includeGlobs no longer scans **/*.md (Markdown READMEs/plans often match tag words in prose). Defaults remain Dart, YAML, TypeScript, and JavaScript; add **/*.md in settings if you want docs included. package.json defaults and todosAndHacksDefaults.ts stay in sync (unit test).
• Dart SDK — example* and self_check pubspec.yaml floors aligned to >=3.9.0 with the main package (PACKAGE_VIBRANCY.md legacy-support baseline), replacing stale lower example constraints.
• Dart SDK 3.0 migration rules — avoid_removed_max_user_tags_constant and avoid_removed_dart_developer_metrics use high [LintImpact] (removed APIs are compile failures on Dart 3). File header and rule DartDocs in dart_sdk_3_removal_rules.dart expanded for reviewers and false-positive contracts.
• ListView extent hints — avoid_listview_without_item_extent, prefer_item_extent, prefer_prototype_item, prefer_itemextent_when_known, and require_item_extent_for_large_lists now treat itemExtentBuilder (Flutter 3.16+, PR #131393) as a valid alternative to itemExtent / prototypeItem where applicable. avoid_listview_without_item_extent also applies to ListView.separated.
• Lint rules — Flutter migration / widget consistency (INFO; prefer_super_key in Comprehensive, avoid_chip_delete_inkwell_circle_border in stylistic + flutterStylisticRules only — mutually exclusive tier sets):
- prefer_super_key: flags
Key? keywithsuper(key: key)onStatelessWidget/StatefulWidget/*Widgetsubclasses; prefersuper.key(Flutter PR #147621). Quick fix rewrites the constructor. - avoid_chip_delete_inkwell_circle_border: flags chip
deleteIconsubtrees that useInkWellwithcustomBorder: CircleBorder(), which mismatches the square chip delete region fixed in Flutter 3.22 (PR #144319). Handles bothInstanceCreationExpressionand unqualifiedMethodInvocationchip calls, and nestedInkWell/CircleBorderparse shapes.
9.10.0 #
This release adds version-gap awareness: see which PRs and issues landed between your pinned version and latest, triage them with a persistent review checklist, and focus your pubspec tooltip on must-know stats with a "View Full Details" link to a full-detail panel. — log
Added #
• Version-gap PR/issue viewer — new "Package Details" webview panel shows merged PRs and closed issues between your current package version and latest, fetched from GitHub on demand. Includes searchable/filterable/sortable table with per-item review controls.
• Review checklist — persistent triage state for version-gap items. Mark each PR/issue as reviewed, applicable, or not-applicable. State persists across sessions and auto-prunes when package versions change.
• Full-detail package panel — new command Show Package Details opens a comprehensive editor-area panel with version info, community metrics, alerts, vulnerabilities, version-gap table, platforms, and suggestions.
• "View Full Details" links — compact hover tooltip and sidebar detail view now include a "View Full Details" button that opens the full panel.
• Version-gap configuration — new setting saropaLints.packageVibrancy.enableVersionGap (default: off) to enable GitHub version-gap fetching. Recommended with a GitHub token for best results.
Changed #
• Compact hover tooltip — pubspec dependency hover reduced from 60-100+ lines to ~10 lines of must-know stats (score, update, license, vulnerabilities, critical alerts, action item count).
9.9.1 #
Flutter deprecation migration rules and ROADMAP additional rules 11–20. — log
Added #
• Lint rules — 7 new Flutter deprecation migration rules (WARNING, Recommended tier):
- prefer_m3_text_theme: flags deprecated 2018-era TextTheme member names (headline1–6, subtitle1–2, bodyText1–2, caption, button, overline) removed in Flutter 3.22. Quick fix renames to M3 equivalents.
- prefer_keepalive_dispose: flags
KeepAliveHandle.release()removed after Flutter 3.19; usedispose()instead. Quick fix renames the method call. - prefer_pan_axis: flags
InteractiveViewer.alignPanAxisremoved after Flutter 3.19; usepanAxisenum parameter instead. - prefer_context_menu_builder: flags
CupertinoContextMenu.previewBuilderremoved after Flutter 3.19; usebuilder(callback signature changed, manual migration required). - prefer_button_style_icon_alignment: flags
iconAlignmentparameter on button constructors deprecated in Flutter 3.28; move toButtonStyle.iconAlignment. - prefer_key_event: flags deprecated
RawKeyEvent/RawKeyboardsystem deprecated in Flutter 3.18; migrate toKeyEvent/HardwareKeyboard. - prefer_platform_menu_bar_child: flags
PlatformMenuBar.bodyremoved after Flutter 3.16; usechildinstead. Quick fix renames the parameter.
• Lint rules — prefer_tabbar_theme_indicator_color: flags ThemeData.indicatorColor usage deprecated in Flutter 3.32.0; migrate to TabBarThemeData.indicatorColor (WARNING, Recommended tier). Quick fix removes the deprecated argument.
• Lint rules — 10 new rules from ROADMAP additional rules 11–20:
- uri_does_not_exist (ERROR, Essential): import/export/part URI refers to a non-existent file.
- depend_on_referenced_packages (WARNING, Essential): imported package not listed in pubspec.yaml dependencies.
- secure_pubspec_urls (WARNING, Recommended): flags insecure http:// or git:// URLs in pubspec dependency sources.
- package_names (WARNING, Recommended): package name in pubspec must be lowercase_with_underscores.
- prefer_for_elements_to_map_from_iterable (WARNING, Professional): prefer for-element map literal over Map.fromIterable with key/value closures.
- missing_code_block_language_in_doc_comment (INFO, Comprehensive): fenced code block in doc comment missing language identifier.
- unintended_html_in_doc_comment (INFO, Comprehensive): angle brackets in doc comment prose interpreted as HTML.
- uri_does_not_exist_in_doc_import (INFO, Comprehensive): @docImport URI refers to a non-existent file.
- invalid_visible_outside_template_annotation (WARNING, Comprehensive): @visibleOutsideTemplate used on wrong declaration type.
- sort_pub_dependencies (INFO, Comprehensive): pubspec dependencies not sorted alphabetically.
9.9.0 #
Import graph tracking, scan API, TODOs & Hacks view, and new lint rules. — log
Fixed #
• Package — Analysis log report sections FILE IMPORTANCE, FIX PRIORITY, and PROJECT STRUCTURE now receive import graph data: ImportGraphTracker.collectImports runs from SaropaContext on each analyzed file (right after the file is recorded for progress), and ImportGraphTracker.setProjectInfo runs from AnalysisReporter.initialize so package: self-imports resolve. If the reporter is never initialized (e.g. progress reporting off), collectImports infers project root and package name from the file path once. Windows path keys (\ vs /) are aligned when resolving edges so the graph matches analyzer file paths.
• Package — Cross-isolate import graph: each batch file (.batches/*.json) now includes optional ig (raw import/export URIs per file). ReportConsolidator merges ig across isolates into ConsolidatedData.mergedRawImports; the combined report hydrates ImportGraphTracker from that merge so FILE IMPORTANCE / PROJECT STRUCTURE reflect the whole session. Legacy batches without ig still use in-memory graph data from the writing isolate. Path alignment: consolidated violations use project-relative paths; ImportGraphTracker resolves scores and FILE IMPORTANCE issue counts against graph keys via canonical path matching.
• Package — Priority report correctness: progress/report counts are now deduplicated by ruleName:offset (offset-based) instead of ruleName:line, preventing inflated FIX PRIORITY / FILE IMPORTANCE counts when the same rule emits multiple diagnostics at the same location. The combined report also omits the legacy flat ALL VIOLATIONS section so developers work from the prioritized view.
Added #
• Package — Performance benchmark: added test/import_graph_tracker_perf_test.dart to measure ordering overhead for FILE IMPORTANCE / FIX PRIORITY / PROJECT STRUCTURE sections. Synthetic “200-file chain + 500 violations” took ~60-80ms in unit test (the “<20ms” target still needs optimization).
• Extension — Added setting saropaLints.runAnalysisOpenEditorsOnly to run dart/flutter analyze only for Dart files currently open in VS Code (faster turnaround during focused work).
• Extension — Drift Advisor integration (optional): When using a Dart/Drift project and a running Saropa Drift Advisor server, enable saropaLints.driftAdvisor.integration in settings. The extension discovers the server (ports 8642–8649 by default via GET /api/health), fetches index suggestions and anomalies (GET /api/issues when supported, else legacy endpoints), maps table/column to Dart file/line via PascalCase/camelCase heuristics, and shows issues in the Drift Advisor sidebar view and optionally in the Problems list (source "Saropa Drift Advisor"). Settings: integration, portRange, pollIntervalMs, showInProblems. Commands: Refresh, Open in Browser. No dependency on the Drift Advisor extension at install time. See About Saropa Lints and plan in bugs/history.
• Extension — Log Capture integration: Public API for other extensions (e.g. Saropa Log Capture). When the extension is activated, exports provides: getViolationsData(), getViolationsPath(), getHealthScoreParams(), runAnalysis(), runAnalysisForFiles(files), getVersion(). Consumers use vscode.extensions.getExtension('saropa.saropa-lints')?.exports. No progress UI when runAnalysisForFiles is invoked via API unless showProgress: true; file list is normalized, deduplicated, sorted, and capped at 50. See extension README “API for other extensions” and bugs/plan/plan_log_capture_integration.md.
• Package — Consumer manifest: reports/.saropa_lints/consumer_contract.json is written after every violation export with schemaVersion, healthScore (impactWeights, decayRate), and tierRuleSets (rule names per tier: essential, recommended, professional, comprehensive, pedantic, stylistic). Single source for health score constants: lib/src/report/health_score_constants.dart; extension’s healthScore.ts and the manifest stay in sync. Documented in VIOLATION_EXPORT_API.md “Consumer manifest” section.
• Package — Rule metadata API: RuleType, RuleStatus, and AccuracyTarget (lib/src/rule_metadata.dart); optional getters on SaropaLintRule (ruleType, accuracyTarget, ruleStatus, cweIds, certIds, tags). Exported from package:saropa_lints/saropa_lints.dart. Bulk ruleType/tags by category: scripts/bulk_rule_metadata.py. Security follow-up: populated cweIds and added securityHotspot + review-required (WebView/redirects) via scripts/apply_security_metadata_cwe_hotspots.py where human review is expected. See bugs/discussion/RULE_METADATA_BULK_STATUS.md.
• Scan — Public programmatic API and CLI extensions: (1) Public API: package:saropa_lints/scan.dart exports ScanRunner, ScanConfig, ScanDiagnostic, loadScanConfig, scanDiagnosticsToJson, scanDiagnosticsToJsonString, and ScanMessageSink for running scans from code without the CLI. (2) File-list support: ScanRunner(dartFiles: [...]) and CLI --files <path>... and --files-from-stdin (one path per line) to scan only specified files; relative paths resolved against project root; optional exclusions applied. (3) Tier override: ScanRunner(tier: 'essential'|...) and CLI --tier <name> to use a tier’s rule set for that run without changing analysis_options.yaml. (4) Message sink: optional messageSink callback to redirect or suppress progress/error output. (5) JSON output: --format json writes machine-readable JSON to stdout; same schema via scanDiagnosticsToJson / scanDiagnosticsToJsonString. (6) CLI parser: parseScanArgs in lib/src/scan/scan_cli_args.dart (testable); --tier with no value now exits 2 with clear message. (7) Tests: test/scan_cli_args_test.dart (parseScanArgs + process test), test/scan_runner_test.dart (ScanRunner with tier, dartFiles). Backward-compatible; existing dart run saropa_lints scan [path] unchanged when options omitted. See README “Standalone Scanner” and “Programmatic scan”.
Changed #
• Package Vibrancy — Unused-package detection no longer flags federated platform plugins with non-standard suffixes (e.g. google_maps_flutter_ios_sdk10) when the parent package is in dependencies or dev_dependencies; uses a parent-package heuristic in addition to the existing hard-coded suffix list.
• Package Vibrancy — Report and webview titles use "Package Vibrancy Report" consistently (removed leftover "Saropa " from markdown export and HTML/webview panel).
Added #
• Extension — TODOs & Hacks view: Todo-Tree-style sidebar that lists TODO, FIXME, HACK, XXX, and BUG comment markers by scanning workspace files (no Dart analyzer or violations.json). Tree shows by folder → file → line, or by tag → file → line when "Group by tag" is enabled. Click a line to open the file at that line. Settings: tags, include/exclude globs, maxFilesToScan, autoRefresh (debounced refresh on save), groupByTag, and optional customRegex override. View toolbar: Refresh and Toggle group by tag / folder. "Scanning…" message shown briefly on refresh/toggle. When the scan hits the file cap, a placeholder node explains how to increase the limit. Unit tests for regex and exclude-pattern logic (run npm run test in extension directory). Implementation: core uses regex.exec() with lastIndex reset when global; concurrency guard prevents duplicate full scans when expanding multiple tag nodes.
• Lint rules — no_runtimeType_toString: flags runtimeType.toString() and suggests type checks or direct Type comparison (performance, MAJOR, Recommended tier).
• Lint rules — use_truncating_division: flags (a / b).toInt() and suggests a ~/ b (MAJOR, Recommended tier).
• Lint rules — Eight additional rules from ROADMAP (comprehensive tier): external_with_initializer (external field/variable must not have initializer), illegal_enum_values (enum must not declare instance member named values), wrong_number_of_parameters_for_setter (setter must have exactly one required positional parameter), duplicate_ignore (same diagnostic listed twice in one ignore comment), type_check_with_null (prefer == null / != null over is Null / is! Null), unnecessary_library_name (library directive with only a name and no URI), invalid_runtime_check_with_js_interop_types (is/is! with JS interop type at runtime), argument_must_be_native (Native.addressOf argument must be @Native or native type).
• Extension — Explain rule: right-click any violation in the Issues view (or run Saropa Lints: Explain rule from the command palette) to open a side tab with full rule details: problem message, how to fix, severity, impact, OWASP mapping (when present), and a link to the ROADMAP. The panel reuses a single tab; the documentation link opens in the default browser.
• Extension — Create Saropa Lints Instructions for AI Agents: Command (Overview title bar and Command Palette) creates .cursor/rules/saropa_lints_instructions.mdc in the workspace from a bundled template, so AI agents get project guidelines (essential files, workflow, prohibitions, principles). Uses async file I/O and a short progress notification.
Administration #
• Scripts — publish.py main workflow refactored into smaller helpers (_PublishContext, _run_audit_step, _run_pre_publish_pipeline, _run_badge_validation_docs_dryrun, etc.) to reduce cognitive complexity; behavior unchanged. Extension install/publish prompts centralized in _prompt_extension_install_and_publish. Main docstring documents flow for reviewers. SystemExit from exit_with_error() is caught so finally (timer summary) runs and the intended exit code is returned.
• Scripts — Version prompt in publish.py refactored into smaller helpers (_handle_win_key, _prompt_version_windows, _prompt_version_unix) to satisfy cognitive complexity limits; behavior unchanged.
• Scripts — Gap analysis export: scripts/export_saropa_rules_for_gap.py exports rule names and categories to JSON for comparison with external Dart rule sets. Procedure and inputs/outputs are documented in bugs/discussion/GAP_ANALYSIS_EXTERNAL_DART.md. Rule metadata plan (rule types, accuracy targets, tags, quality gates, etc.) is in bugs/discussion/PLAN_RULE_METADATA_AND_QUALITY.md.
• Extension — First-run notification: score qualifier uses an if/else chain instead of a nested ternary (lint compliance, readability).
• Extension — Prefer .at(-n) for from-end array access in celebration/snapshot logic (lint compliance).
• Extension — Code quality: resolve SonarQube/TypeScript findings (node: imports, reduced cognitive complexity, batched subscriptions, replaceAll, positive conditions, extracted celebration/status-bar helpers); behavior unchanged.
9.8.1 #
Smarter SDK guidance in pubspec and less noise when already on 3.9+. — log
Added #
• Package Vibrancy — SDK constraint diagnostic now includes actionable guidance: "Aim for >=3.10.0; use >=3.9.0 only if you need to support more legacy setups." Quick fixes: Set Dart SDK to >=3.10.0 (preferred) and Set Dart SDK to >=3.9.0 (legacy support); both preserve the existing upper bound (e.g. <4.0.0). Hover on the sdk: or flutter: line in pubspec.yaml shows the Dart/Flutter version history table; diagnostic code links to PACKAGE_VIBRANCY.md.
Changed #
• Package Vibrancy — "Behind latest stable" is no longer shown when the Dart SDK minimum is already >=3.9.0, to avoid nagging projects that have adopted the recommended legacy floor.
9.8.0 #
One-line vibrancy summary in pubspec by default and consistent "Package Vibrancy" naming. — log
Changed #
• Package Vibrancy — Inline diagnostics in pubspec.yaml are now simplified by default: a single summary line (e.g. "Package Vibrancy: 12 stale, 8 legacy-locked — Open Package Vibrancy view for details.") instead of one warning per package. New setting saropaLints.packageVibrancy.inlineDiagnostics: summary (default), critical (only end-of-life/vulnerabilities/family conflicts per-line), all (one diagnostic per package, previous behavior), or none (sidebar only). Reduces noise in large projects while keeping the Package Vibrancy view as the place for full details.
• Package Vibrancy — All user-facing text and diagnostic sources now use "Package Vibrancy" only; the former "Saropa Package Vibrancy" label has been removed from the extension (settings title, report headers, CI-generated comments, and diagnostics).
9.7.0 #
Headless config writer, cross-file analysis CLI, and a polished Issues view. — log
Added #
• Headless config writer (write_config) — New write_config executable and lib/src/init/write_config_runner.dart for writing analysis_options.yaml from tier + analysis_options_custom.yaml without interactive output. Extension now calls dart run saropa_lints:write_config --tier <tier> --target <workspace> instead of init for Enable, Initialize Config, and Set tier. Init remains for CI/scripting. Aligns with 003_INIT_REDESIGN (extension-driven config).
• Cross-file analysis CLI — New cross_file executable: dart run saropa_lints:cross_file <command> with commands unused-files, circular-deps, import-stats, and report. Builds the import graph from lib/, reports files with no importers, circular import chains, and graph statistics. Output: text (default), JSON, or HTML via report --output-dir. Baseline: --baseline <file> and --update-baseline to suppress known issues and fail only on new violations. Exit codes 0/1/2. README and doc/cross_file_ci_example.md for CI. See ROADMAP Part 3.
• Central cache stats — CacheStatsAggregator.getStats() returns a single map aggregating statistics from all project caches (import graph, throttle, speculative, rule batch, baseline, semantic, etc.) for debugging and monitoring.
Changed #
• Extension — Polished Issues view violation context menu with icons for Apply fix / Copy message, a separator between action and hide groups, and clearer suppression behavior (rule vs rule-in-file); extension README documents how to clear and manage suppressions from the toolbar.
9.6.1 #
No more vibrancy warnings for path or git-resolved dependencies. — log
Fixed #
• Package Vibrancy — Do not show the main vibrancy diagnostic (Review/stale/legacy-locked/end-of-life/monitor) for dependencies resolved via path or git override; the resolved artifact is local or from git, so the upstream pub.dev score is not actionable and was causing false positives.
9.6.0 #
Clearer Package Vibrancy scoring and reliable filter-by-type behavior. — log
Added #
• Package Vibrancy — Action Items tree now shows a simple letter grade (A = best … E = stale … F = dangerous) and problem count instead of a numeric “risk” score; aligns with a single, clear scoring system and correct pluralization (“1 problem” / “2 problems”)
Fixed #
• Package Vibrancy — Filter by Problem Type now correctly applies the selected types; resolved QuickPick selections using a shared id+label fallback so filter state is set reliably across environments
9.5.2 #
Keeping your lints fresh — the extension now detects outdated saropa_lints versions and offers one-click upgrades, plus new SDK constraint diagnostics. — log
Added #
• Extension — background upgrade checker: on activation, the extension checks pub.dev for newer saropa_lints versions and shows a non-intrusive notification with Upgrade, View Changelog, and Dismiss actions; throttled to once per 24 hours, remembers dismissed versions, skips path/git dependencies, and respects the new saropaLints.checkForUpdates setting
• Extension — SDK constraint diagnostics: inspects the environment section of pubspec.yaml and reports when Dart SDK or Flutter version constraints are behind the latest stable release; shows Warning when the upper bound excludes latest, Information when behind by a minor version, and Hint for patch-level gaps; fires on file open, on edit (debounced), and after every vibrancy scan
• Extension — overview panel toolbar: added About (info icon) and Run Analysis (play icon) buttons to the overview panel title bar; removed redundant tree items (Run Analysis, Summary, Config, Suggestions) that duplicate existing sidebar views
• Extension — overview tree icons: each overview item now displays a contextual icon (pulse for health score, warning/pass for violations, graph-line for trends, arrow-down for regressions, star-full for celebrations, history for last run)
9.5.1 and Earlier #
For versions 0.1.0 through 9.5.1, see CHANGELOG_ARCHIVE.md.