14 - Sonar Static Analysis (Flutter)

Run Sonar-style static analysis on the Flutter app, export it as SARIF, and generate a browsable HTML report. Everything runs locally — no SonarQube server required.

What is actually running

Dart has no official "SonarDart" plugin, so we use very_good_analysis (a Sonar-style strict rule set layered on top of flutter_lints) executed by the regular flutter analyze tool. The text output is then converted to a SARIF v2.1 file so the same sarif-tools HTML pipeline as the backend works here too.

How it is wired

flutter_app/pubspec.yamlYAML
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.1
  # Sonar-style strict lint ruleset for Dart/Flutter
  very_good_analysis: ^6.0.0
flutter_app/analysis_options.yamlYAML
include: package:very_good_analysis/analysis_options.yaml

analyzer:
  exclude:
    - build/**
    - "**/*.g.dart"
    - "**/*.freezed.dart"
    - "**/*.mocks.dart"
  errors:
    public_member_api_docs: ignore
    lines_longer_than_80_chars: ignore

linter:
  rules:
    avoid_print: true
    prefer_single_quotes: true

Prerequisites (one-time)

BashInstall sarif-tools (once per machine)
pip install sarif-tools
sarif --version

Step 1 — Run the analyzer

Run flutter analyze twice and capture both outputs. The --write= form gives a stable text file; the default stdout form includes rule names which we need for the SARIF conversion.

BashRefresh the raw analyzer output
cd flutter_app

# Make sure packages are resolved
flutter pub get

# Stdout form (contains rule names) — feeds the SARIF converter
flutter analyze > sonar-report/dart-analyze-stdout.txt

# --write form — feeds aggregate_sonar.js
flutter analyze --write=sonar-report/dart-analyze.txt

Step 2 — Convert to SARIF + aggregate

BashProduce SARIF and text summaries
cd flutter_app

# stdout → SARIF v2.1
node scripts/to_sarif.js

# --write output → rule-grouped summary, noisy files, issues.json
node scripts/aggregate_sonar.js

Step 3 — Generate the HTML report

BashGenerate and open
cd flutter_app
sarif html sonar-report/flutter-analyze.sarif -o sonar-report/flutter-sonar.html
start sonar-report/flutter-sonar.html   # Windows
Where everything lives

All reports are under flutter_app/sonar-report/:

  • flutter-sonar.html — browsable HTML dashboard
  • flutter-analyze.sarif — SARIF v2.1 file (input to sarif-tools)
  • dart-analyze-stdout.txt, dart-analyze.txt — raw Flutter outputs
  • summary.txt, issues.json — text + JSON reports

Full run in one copy-paste

BashEnd-to-end (from flutter_app/)
cd flutter_app
flutter pub get

flutter analyze > sonar-report/dart-analyze-stdout.txt
flutter analyze --write=sonar-report/dart-analyze.txt

node scripts/to_sarif.js
node scripts/aggregate_sonar.js

sarif html sonar-report/flutter-analyze.sarif -o sonar-report/flutter-sonar.html

start sonar-report/flutter-sonar.html

Severity mapping

Dart/Flutter lints come with three severities: error, warning, info. We map them to Sonar-style categories as follows for our fix policy:

Ready-made fixers

Each script is self-documenting at the top. Dart also ships dart fix which auto-applies many rules — we use it for the bulk of the Medium/Low cleanup.

flutter_app/scripts/Available fixers
to_sarif.js               # flutter analyze stdout → SARIF v2.1
aggregate_sonar.js        # Rule-grouped summary from --write output
fix_unawaited.js          # Wrap fire-and-forget Futures with unawaited(...)
fix_inference.js          # Add <void> to Future.delayed / showDialog / showModalBottomSheet
fix_with_opacity.js       # .withOpacity(x) → .withValues(alpha: x)
BashBuilt-in dart fix shortcuts
cd flutter_app

# Preview all auto-fixable rules
dart fix --dry-run

# Apply a specific rule only (used during the April 2026 cleanup)
dart fix --apply --code=avoid_void_async
dart fix --apply --code=unnecessary_null_checks

# Apply everything — big diff, review before committing
dart fix --apply
Script safety note

The fix_unawaited.js script uses column offsets from the analyzer report plus bracket-matching. Running it twice without regenerating the report first can silently corrupt files (we hit this once — an unawaited( was inserted inside a comment). Always re-run flutter analyze --write=... before re-running any fixer.

Editor integration

Android Studio / VS Code / IntelliJ pick up analysis_options.yaml automatically and show the same squiggles live while you type. The SARIF conversion and HTML report only matter for CI or for sharing a snapshot with a reviewer.

Typical report after a clean pass

After the April 2026 Blocker + Critical + High cleanup:

See also