Perché l'analisi statica conta

L'analizzatore statico di Dart è uno degli strumenti più sottovalutati dagli sviluppatori Flutter. Lavora silenziosamente nell'IDE evidenziando errori, potenziali bug e violazioni di stile prima che il codice venga eseguito. Configurarlo correttamente significa intercettare problemi in fase di scrittura, uniformare lo stile del team e ridurre il carico di lavoro durante le code review.

In questo articolo vediamo come dominare il file analysis_options.yaml, cuore della configurazione dell'analizzatore.

Il file analysis_options.yaml

È un file di configurazione YAML posizionato nella root del progetto. Se non esiste, crealo. La struttura base include l'importazione di un set di regole predefinite:

include: package:flutter_lints/flutter.yaml

analyzer:
  language:
    strict-casts: true
    strict-inference: true
    strict-raw-types: true
  errors:
    invalid_annotation_target: ignore

linter:
  rules:
    - prefer_const_constructors
    - avoid_print
    - require_trailing_commas

Il pacchetto flutter_lints è incluso di default nei nuovi progetti Flutter. Un'alternativa più severa e popolare è very_good_analysis, mantenuto da Very Good Ventures.

dev_dependencies:
  flutter_lints: ^5.0.0
  # oppure
  very_good_analysis: ^7.0.0

Le tre modalità strict

Le opzioni sotto language attivano controlli di tipo più rigorosi che ti proteggono da errori sottili:

  • strict-casts: impedisce cast impliciti da dynamic a tipi concreti, forzandoti a esplicitarli.
  • strict-inference: segnala quando il tipo viene inferito come dynamic senza annotazione esplicita.
  • strict-raw-types: richiede parametri generici espliciti, ad esempio List<String> invece di List.

Attivarle fin dall'inizio di un progetto è una best practice: farlo su una codebase esistente può generare centinaia di segnalazioni.

Gestire errori e severità

La sezione errors permette di modificare la severità di ogni diagnostica. I valori possibili sono error, warning, info e ignore:

analyzer:
  errors:
    # Trasforma un warning in errore bloccante
    missing_required_param: error
    # Ignora una regola specifica del progetto
    todo: ignore
    # Declassa a info
    deprecated_member_use: info

Trasformare i lint critici in error è utile nelle pipeline CI: dart analyze restituirà un exit code diverso da zero e bloccherà la build.

Escludere file dall'analisi

I file generati (come quelli di build_runner) non devono essere analizzati. Usa exclude:

analyzer:
  exclude:
    - "**/*.g.dart"
    - "**/*.freezed.dart"
    - "lib/generated_plugin_registrant.dart"
    - "build/**"

Regole utili da attivare

Oltre ai preset, alcune regole valgono la pena di essere aggiunte manualmente per la qualità del codice:

linter:
  rules:
    - always_declare_return_types
    - avoid_dynamic_calls
    - prefer_final_locals
    - unawaited_futures
    - use_build_context_synchronously
    - sort_child_properties_last
    - avoid_redundant_argument_values

La regola use_build_context_synchronously è particolarmente preziosa: segnala l'uso del BuildContext dopo un await, una delle cause più comuni di crash quando il widget viene smontato.

Ignorare regole a livello di codice

A volte una regola non ha senso in un punto specifico. Puoi disabilitarla con un commento, senza toccare la configurazione globale:

// ignore_for_file: avoid_print

void debugLog(String message) {
  // ignore: avoid_print
  print(message);
}

Usa ignore per la singola riga successiva e ignore_for_file per l'intero file. Meglio usarli con parsimonia e documentarne il motivo.

Custom lint con custom_lint

Per regole specifiche del tuo dominio, il pacchetto custom_lint permette di scrivere lint personalizzati. Molti pacchetti popolari lo sfruttano: ad esempio riverpod_lint fornisce regole dedicate a Riverpod.

dev_dependencies:
  custom_lint: ^0.7.0
  riverpod_lint: ^2.6.0

analyzer:
  plugins:
    - custom_lint

Dopo la configurazione, esegui dart run custom_lint per vedere le segnalazioni personalizzate anche fuori dall'IDE.

Integrazione con la CI

Il comando chiave da eseguire nella pipeline è:

dart analyze --fatal-infos

Con --fatal-infos anche le segnalazioni di livello info fanno fallire la build, garantendo il massimo rigore. Combinalo con dart format --set-exit-if-changed . per verificare anche la formattazione.

Conclusione

Un analysis_options.yaml ben curato è un investimento a basso costo con altissimo ritorno: previene bug, standardizza il codice e alleggerisce le review. Parti da un preset solido come very_good_analysis, attiva le modalità strict e aggiungi progressivamente le regole più adatte al tuo team. Il tuo io futuro (e i tuoi colleghi) ti ringrazieranno.