El análisis estático no es simplemente una búsqueda de errores de sintaxis; es una inspección profunda de la semántica de tu código sin necesidad de ejecutarlo. Cuando ejecutas dart analyze, el motor del analizador construye un AST (Abstract Syntax Tree) y realiza un análisis de flujo de control para entender cómo se mueven los datos a través de tu aplicación. Esto le permite detectar desde errores de tipado evidentes hasta situaciones complejas como la violación de las reglas de sound null safety o código que nunca se ejecutará.
Este proceso funciona de forma desacoplada de la ejecución para permitirte detectar fallos antes de que lleguen a producción o incluso antes de que los compiles a AOT. Su diseño está orientado a dos pilares: la corrección (que el código sea válido y seguro) y el estilo (que el código sea consistente y legible). Debes usarlo de forma sistemática en tus flujos de integración continua (CI) para evitar que la deuda técnica se acumule. Si ignoras estas alertas, te arriesgas a que el compilador te devuelva errores de tipos en tiempo de ejecución que el analizador podría haber evitado fácilmente con una simple advertencia.
// Para que este código sea efectivo, el analizador debe tener reglas activas.
// En un proyecto real, esto se configura en el archivo `analysis_options.yaml`.
import 'dart:convert'; // Linter: unused_import
void main() {
// Linter: prefer_final_locals (si la regla está activa en el linter)
var contador = 10;
print(contador);
// Linter: unused_local_variable
var variableInutil = 'No se usa';
print(variableInutil);
// Unreachable code: El analizador detecta que este bloque nunca se ejecutará
if (false) {
print('Este código es inalcanzable');
}
// Null Safety: El analizador detecta que el uso de ! es peligroso aquí
int? valorNulo = null;
print(valorNulo!.length);
// Silenciar un warning específico en una sola línea
// ignore: unused_local_variable
var _variableSilenciada = 42;
// Linter: prefer_const_constructors (si se usa una clase con constructor const)
// const punto = Point(1, 2);
print('Proceso completado');
}
class Point {
final int x;
final int y;
const Point(this.x, this.y);
}
El código anterior es un catálogo de situaciones que el analizador detectará inmediatamente. Al ejecutar dart analyze, verás advertencias sobre unused_import debido a la librería dart:convert, la cual se importó pero nunca se utiliza, lo que ensucia el espacio de nombres y aumenta ligeramente el tiempo de compilación.
Fíjate en la variable contador; si en tu analysis_options.yaml has incluido el paquete lints [disponible desde Dart 2.12] y has activado la regla prefer_final_locals, el analizador te obligará a usar final en lugar de var, ya que la variable no se reasigna. Lo mismo ocurre con variableInutil.
El bloque if (false) es un ejemplo clásico de unreachable code. El analizador realiza un análisis de flujo y determina que la condición es constante y falsa, por lo que marcará el cuerpo del if como código muerto. La línea print(valorNulo!.length) es crítica: el analizador realiza un análisis de flujo de nulidad y, al ver que valorNulo se asignó como null justo antes, identifica que el operador de aserción de no nulidad (!) provocará un error en tiempo de ejecución.
Para los casos donde el error es un “falso positivo” o una excepción necesaria, puedes usar // ignore: nombre_de_la_regla para silenciar una línea específica. Esto es mucho más limpio que usar // ignore_for_file, que desactiva la regla para todo el archivo y es una mala práctica si no se justifica con un comentario.
El error frecuente
Un error común en equipos que escalan proyectos es confiar ciegamente en dart fix --apply. Esta herramienta es excelente para aplicar correcciones automáticas (como añadir const o cambiar var por tipos específicos), pero si tienes reglas de linter muy personalizadas o mal configuradas en tu analysis_options.yaml, dart fix podría transformar parte de la lógica de tu código de forma inesperada. Siempre revisa los cambios aplicados por dart fix antes de hacer un commit; la automatización debe ser tu aliada, no tu sustituta en la revisión de lógica.
N° 97