Aplicación masiva de correcciones

Corregir múltiples problemas de análisis en un solo paso

En Quick fixes for analysis issues vimos el soporte para corregir automáticamente diagnósticos individuales mientras se edita. A veces incluso eso es lento y te gustaría corregir múltiples diagnósticos todos a la vez. Afortunadamente, también hay soporte para eso, que cubrimos en este artículo.

Hay varias formas de corregir múltiples diagnósticos, dependiendo de cuántos diagnósticos quieras corregir, y veremos cada uno por separado.

Corregir múltiples ocurrencias del mismo diagnóstico

#

¿Alguna vez has refactorizado tu código moviendo una clase a un archivo diferente? Si es así, es bastante probable que algunos imports solo se necesitaran por referencias en la clase que se movía, lo que te deja con imports sin usar:

Un fragmento de código en Visual Studio Code mostrando advertencias de imports sin usar.
Visual Studio Code
Un fragmento de código en IntelliJ IDEA mostrando advertencias de imports sin usar.
IntelliJ IDEA

Para cualquier corrección que pueda aplicarse más de una vez dentro del mismo archivo, las herramientas ofrecen una opción para aplicarla en todo el archivo.

Estas correcciones aparecen en los mismos lugares que otras correcciones y suelen estar etiquetadas de forma similar a las correcciones de ubicación única, pero con alguna frase como “in file” añadida. Por ejemplo, así es como aparece esta corrección en tu IDE:

Un menú contextual en Visual Studio Code ofreciendo eliminar todos los imports sin usar en el archivo.
Visual Studio Code
Un menú contextual en IntelliJ IDEA ofreciendo eliminar todos los imports sin usar en el archivo.
IntelliJ IDEA

Seleccionar la corrección “in-file” hace exactamente lo que esperarías — elimina todos los imports sin usar en el archivo:

El fragmento de código en Visual Studio Code después de eliminar los imports sin usar.
Visual Studio Code
El fragmento de código en IntelliJ IDEA después de eliminar los imports sin usar.
IntelliJ IDEA

Corregir todos los diagnósticos en un archivo

#

Eso es genial, pero solo corrige un único tipo de diagnóstico, y requiere que encuentres el lugar donde se está reportando el diagnóstico (ya sea en el editor o en la vista de problemas) para invocar la corrección. Parece que las herramientas podrían hacer más.

Y en Visual Studio Code, puede. Puedes aplicar correcciones para todos los diagnósticos dentro de un solo archivo. Para ver cómo, usaremos el mismo ejemplo de arriba:

Un editor de código mostrando múltiples advertencias de imports sin usar marcadas con líneas onduladas azules.

Si haces clic derecho para abrir el menú contextual, verás lo siguiente:

El menú contextual de clic derecho en Visual Studio Code con 'Source Action...' resaltado.

Si seleccionas Source Action…, se abre un segundo menú:

El menú 'Source Action...' en Visual Studio Code mostrando las opciones 'Sort Members', 'Organize Imports', y 'Fix All'.

Seleccionar Fix All hace que se apliquen correcciones a todos los diagnósticos en el editor, produciendo lo siguiente:

El editor de código después de seleccionar 'Fix All', mostrando que los imports sin usar han sido eliminados exitosamente.

También puedes invocar el comando Fix All desde la paleta de comandos, que puedes abrir seleccionando Command Palette… del menú View, o usando el atajo de teclado (F1 en cualquier plataforma, Control+Shift+P en Windows y Linux, o Command+Shift+P en macOS). Puedes filtrar la lista escribiendo el nombre del comando. La paleta de comandos se ve más o menos así:

La paleta de comandos de Visual Studio Code con 'fix' escrito en la barra de búsqueda, mostrando el comando 'Fix All'.

Corregir todos los diagnósticos en un directorio

#

La herramienta más completa que tenemos para corregir diagnósticos es la herramienta de línea de comandos [dart fix](https://dart.dev/tools/dart-fix) . Puede corregir todos los diagnósticos en un directorio dado, lo que significa que puedes usarla para corregir todo en tu paquete o aplicación.

Por supuesto, hay un par de advertencias. No corrige todos los diagnósticos, porque aplica las mismas correcciones rápidas que están disponibles en el IDE, y no hay correcciones rápidas para todos los diagnósticos. Tampoco aplica correcciones rápidas para diagnósticos cuando hay múltiples formas igualmente válidas de corregir el problema, porque no puede saber qué corrección prefieres aplicar. Estas advertencias también aplican al comando Fix All descrito en la sección anterior.

Aunque la necesidad de esta herramienta no surge a menudo (que es una razón por la que puede que no la conozcas), hay un par de situaciones donde es especialmente útil.

Primero, considera el caso donde quieres habilitar un nuevo lint, o incluso un conjunto de lints, como uno de los conjuntos de reglas core, recommended, o flutter . Es probable que haya al menos algunas violaciones de las reglas de lint en tu paquete. Si hay una corrección asociada con el lint, entonces es conveniente aplicar esa corrección en todas partes en un solo paso en lugar de aplicar la corrección a cada violación individualmente.

Segundo, considera el caso donde estás actualizando de una versión de Flutter a otra. Si ha habido cambios de API entre las dos versiones, hay una buena posibilidad de que haya una corrección para actualizar tu código para ajustarse a la última versión. De nuevo, es conveniente si todos esos cambios se aplican en una sola operación.

Ahí es donde entra el comando dart fix. Puede aplicar correcciones rápidas para múltiples diagnósticos en múltiples archivos.

El comando tiene dos modos. El modo dry-run te dice cuántos cambios puede aplicar y qué diagnósticos puede corregir, pero sin modificar ningún archivo. El modo apply aplica los cambios.

Puedes proporcionar la ruta al directorio que contiene los archivos a corregir, pero si omites el directorio corrige recursivamente todos los archivos en el directorio actual y sus subdirectorios.

Supongamos que has habilitado el lint prefer_single_quotes, y que tienes un archivo que contiene lo siguiente:

import 'package:logging/logging.dart';

void main() {
  var logger = Logger("myApp");
  logger.info("Entering myApp");
  // Do stuff.
  logger.info("Exiting myApp");
}

Ejecutar el comando dart fix con la opción --dry-run desde el directorio que contiene este archivo produce el siguiente output:

$ dart fix --dry-run
Computing fixes in __bin__ (dry run)... 4.3s

3 proposed fixes in 1 file.

demo.dart
  prefer_single_quotes • 3 fixes

La herramienta ha encontrado tres violaciones del lint y reporta que puede corregir las tres, pero no modifica el archivo.

Ejecutar la herramienta dart fix de nuevo, pero esta vez con la opción --apply, produce casi el mismo output:

$ dart fix --apply
Computing fixes in __bin__... 5.3s
Applying fixes...         0.0s

3 proposed fixes in 1 file.

demo.dart
  prefer_single_quotes • 3 fixes

3 fixes made in 1 file.

Pero esta vez el archivo se actualiza para contener lo siguiente:

import 'package:logging/logging.dart';

void main() {
  var logger = Logger('myApp');
  logger.info('Entering myApp');
  // Do stuff.
  logger.info('Exiting myApp');
}

Como el modo dry-run no produce ningún tipo de output diff que te permita ver los cambios reales que se están proponiendo, considera hacer commit de tus cambios antes de ejecutar la herramienta con la opción --apply. De esa manera es más fácil ver qué cambios ha hecho realmente la herramienta y revertir cualquier cambio que no te guste.

Si no quieres hacer commit antes de ejecutar la herramienta, y estás usando IntelliJ IDEA, puedes usar la función File->Local History para comparar el estado antes y después de aplicar las correcciones. (Para más información ver Add labels to specific states Local History.)

El comando dart fix no puede corregir todos los problemas, pero cuando puede, es mucho más fácil que aplicar manualmente la corrección en todas partes.

Resumen

#

Poder aplicar múltiples correcciones en una sola operación no solo aumenta el poder de las correcciones rápidas, sino que también podría facilitar hacer cambios a mayor escala, como habilitar una nueva regla de lint o actualizar a la última versión de Flutter.

Como siempre, si tienes ideas sobre cómo mejorar estas herramientas, por favor haznoslo saber creando un issue en dart-lang/sdk.

Más de Dart