NullAway es una herramienta para ayudar a eliminar NullPointerException
s (NPE) en su código Java. Para usar NullAway, primero agregue anotaciones @Nullable
en su código siempre que un campo, parámetro de método o valor de retorno pueda ser null
. Dadas estas anotaciones, NullAway realiza una serie de comprobaciones locales basadas en tipos para garantizar que cualquier puntero al que se le elimine la referencia en su código no pueda ser null
. NullAway es similar a la verificación de nulidad basada en tipos en los lenguajes Kotlin y Swift, y a los verificadores de nulos Checker Framework y Eradicate para Java.
NullAway es rápido . Está creado como un complemento para Error Prone y puede ejecutarse en cada compilación de su código. En nuestras mediciones, la sobrecarga del tiempo de construcción al ejecutar NullAway suele ser inferior al 10 %. NullAway también es práctico : no evita todos los NPE posibles en su código, pero detecta la mayoría de los NPE que hemos observado en producción al tiempo que impone una carga de anotación razonable, lo que le brinda un excelente "beneficio por su inversión".
NullAway requiere que cree su código con Error Prone, versión 2.14.0 o superior. Consulte la documentación de Error Prone para obtener instrucciones sobre cómo comenzar con Error Prone y la integración con su sistema de compilación. Las instrucciones a continuación suponen que está utilizando Gradle; consulte los documentos para conocer otros sistemas de compilación.
Para integrar NullAway en su proyecto Java que no sea de Android, agregue lo siguiente a su archivo build.gradle
:
plugins {
// we assume you are already using the Java plugin
id " net.ltgt.errorprone " version " <plugin version> "
}
dependencies {
errorprone " com.uber.nullaway:nullaway:<NullAway version> "
// Some source of nullability annotations; JSpecify recommended,
// but others supported as well.
api " org.jspecify:jspecify:1.0.0 "
errorprone " com.google.errorprone:error_prone_core:<Error Prone version> "
}
import net.ltgt.gradle.errorprone.CheckSeverity
tasks . withType( JavaCompile ) {
options . errorprone {
check( " NullAway " , CheckSeverity . ERROR )
option( " NullAway:AnnotatedPackages " , " com.uber " )
}
// Include to disable NullAway on test code
if (name . toLowerCase() . contains( " test " )) {
options . errorprone {
disable( " NullAway " )
}
}
}
Repasemos este guión paso a paso. La sección plugins
incluye el complemento Gradle Error Prone para la integración de Error Prone.
En dependencies
, la primera línea errorprone
carga NullAway y la línea api
carga la biblioteca JSpecify que proporciona anotaciones de nulidad adecuadas, por ejemplo, org.jspecify.annotations.Nullable
. NullAway permite utilizar cualquier anotación @Nullable
, por lo que, por ejemplo, @Nullable
de la biblioteca de anotaciones de AndroidX o las anotaciones de JetBrains también están bien. La segunda línea errorprone
establece la versión de Error Prone que se utiliza.
Finalmente, en la sección tasks.withType(JavaCompile)
, pasamos algunas opciones de configuración a NullAway. First check("NullAway", CheckSeverity.ERROR)
establece los problemas de NullAway en el nivel de error (es equivalente al argumento estándar propenso a errores -Xep:NullAway:ERROR
); de forma predeterminada, NullAway emite advertencias. Luego, option("NullAway:AnnotatedPackages", "com.uber")
(equivalente al argumento estándar propenso a errores -XepOpt:NullAway:AnnotatedPackages=com.uber
) le dice a NullAway que el código fuente de los paquetes bajo el espacio de nombres com.uber
debe ser Se verifican las desreferencias nulas y el uso adecuado de las anotaciones @Nullable
, y se debe asumir que los archivos de clase en estos paquetes tienen un uso correcto de @Nullable
(consulte los documentos para obtener más detalles). NullAway requiere al menos el argumento de configuración AnnotatedPackages
para ejecutarse, a fin de distinguir entre código anotado y no anotado. Consulte los documentos de configuración para conocer otras opciones de configuración útiles. Para una configuración aún más sencilla de las opciones de NullAway, utilice el complemento Gradle NullAway. Finalmente, mostramos cómo desactivar NullAway en el código de prueba, si lo desea.
Recomendamos abordar todos los problemas que informa Error Prone, particularmente aquellos reportados como errores (en lugar de advertencias). Pero, si desea probar NullAway sin ejecutar otras comprobaciones propensas a errores, puede usar options.errorprone.disableAllChecks
(equivalente a pasar "-XepDisableAllChecks"
al compilador, antes de los argumentos específicos de NullAway).
Las versiones 3.0.0 y posteriores del complemento propenso a errores de Gradle ya no son compatibles con Android. Entonces, si está utilizando una versión reciente de este complemento, deberá agregar alguna configuración adicional para ejecutar Error Prone y NullAway. Nuestro archivo de aplicación de muestra build.gradle
muestra una forma de hacer esto, pero su proyecto de Android puede requerir ajustes. Alternativamente, las versiones 2.x del complemento propenso a errores de Gradle aún son compatibles con Android y es posible que aún funcionen con su proyecto.
Más allá de eso, en comparación con la configuración de Java, la dependencia de JSpecify se puede eliminar; en su lugar, puede utilizar la anotación androidx.annotation.Nullable
de la biblioteca de anotaciones de AndroidX.
Algunos procesadores de anotaciones como Dagger y AutoValue generan código en el mismo espacio de nombres de paquete que su propio código. Esto puede causar problemas al configurar NullAway en el nivel ERROR
como se sugirió anteriormente, ya que los errores en este código generado bloquearán la compilación. Actualmente, la mejor solución a este problema es deshabilitar completamente la tendencia a errores en el código generado, usando la opción -XepExcludedPaths
agregada en Error Prone 2.1.3 (documentada aquí, use options.errorprone.excludedPaths=
en Gradle). Para usarlo, averigüe qué directorio contiene el código generado y agregue ese directorio a la expresión regular de la ruta excluida.
Nota para los usuarios de Dagger : las versiones de Dagger anteriores a la 2.12 pueden tener malas interacciones con NullAway; ver aquí. Actualice a Dagger 2.12 para solucionar el problema.
A diferencia de otros procesadores de anotaciones anteriores, Lombok modifica el AST en memoria del código que procesa, lo que es fuente de numerosas incompatibilidades con Error Prone y, en consecuencia, NullAway.
No recomendamos especialmente el uso de NullAway con Lombok. Sin embargo, NullAway codifica algunos conocimientos de anotaciones comunes de Lombok y tratamos de lograr la mejor compatibilidad. En particular, se deben admitir usos comunes como las clases @lombok.Builder
y @Data
.
Para que NullAway detecte con éxito el código generado por Lombok dentro del AST de Java en memoria, se debe pasar la siguiente opción de configuración a Lombok como parte de un archivo lombok.config
aplicable:
lombok.addLombokGeneratedAnnotation = true
Esto hace que Lombok agregue @lombok.Generated
a los métodos/clases que genera. NullAway ignorará (es decir, no comprobará) la implementación de este código generado y lo tratará como sin anotaciones.
Veamos cómo funciona NullAway en un ejemplo de código simple:
static void log ( Object x ) {
System . out . println ( x . toString ());
}
static void foo () {
log ( null );
}
Este código tiene errores: cuando se llama foo()
, la llamada posterior a log()
fallará con un NPE. Puede ver este error en la aplicación de muestra NullAway ejecutando:
cp sample/src/main/java/com/uber/mylib/MyClass.java.buggy sample/src/main/java/com/uber/mylib/MyClass.java
./gradlew build
De forma predeterminada, NullAway asume que cada parámetro del método, valor de retorno y campo no es nulo , es decir, nunca se le puede asignar un valor null
. En el código anterior, se supone que el parámetro x
de log()
no es nulo. Entonces, NullAway informa el siguiente error:
warning: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
log(null);
^
Podemos corregir este error permitiendo que se pase null
a log()
, con una anotación @Nullable
:
static void log ( @ Nullable Object x ) {
System . out . println ( x . toString ());
}
Con esta anotación, NullAway señala la posible desreferencia nula:
warning: [NullAway] dereferenced expression x is @Nullable
System.out.println(x.toString());
^
Podemos solucionar esta advertencia agregando una verificación nula:
static void log ( @ Nullable Object x ) {
if ( x != null ) {
System . out . println ( x . toString ());
}
}
Con este cambio, se solucionan todas las advertencias de NullAway.
Para obtener más detalles sobre las comprobaciones, los mensajes de error y las limitaciones de NullAway, consulte nuestra guía detallada.
No dude en abrir una edición de GitHub si tiene alguna pregunta sobre cómo usar NullAway. O puede unirse al servidor NullAway Discord y hacernos una pregunta allí.
¡Nos encantaría que contribuyeras con NullAway! Tenga en cuenta que una vez que cree una solicitud de extracción, se le pedirá que firme nuestro Acuerdo de licencia de colaborador de Uber.
NullAway tiene la licencia MIT. Consulte el archivo LICENSE.txt para obtener más información.