From 863cebe5cd546d7b7ebe077f241c14ee19ce8947 Mon Sep 17 00:00:00 2001
From: Thomas Broyer <t.broyer@ltgt.net>
Date: Thu, 15 Feb 2024 18:20:58 +0100
Subject: [PATCH] Add support for -XepOpt:NullAway:ExtraFuturesClasses

---
 README.md                                                | 1 +
 .../kotlin/net/ltgt/gradle/nullaway/NullAwayOptions.kt   | 9 +++++++++
 src/test/kotlin/net/ltgt/gradle/nullaway/Fixtures.kt     | 2 +-
 .../net/ltgt/gradle/nullaway/GroovyDslIntegrationTest.kt | 1 +
 .../net/ltgt/gradle/nullaway/NullAwayOptionsTest.kt      | 4 ++++
 .../gradle/nullaway/NullAwayPluginIntegrationTest.kt     | 1 +
 6 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b2b2ab4..3822b55 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,7 @@ Each property (except for `severity`) maps to an `-XepOpt:NullAway:[propertyName
 | `customNonnullAnnotations`     | A list of annotations that should be considered equivalent to `@NonNull` annotations, for the cases where NullAway cares about such annotations (see e.g. `acknowledgeRestrictiveAnnotations`).
 | `customGeneratedCodeAnnotations` | A list of annotations that should be considered equivalent to `@Generated` annotations, for the cases where NullAway cares about such annotations (see e.g. `treatGeneratedAsUnannotated`).
 | `jspecifyMode`                   | (`isJSpecifyMode` with Kotlin DSL) If set to true, enables new checks based on JSpecify (like checks for generic types).
+| `extraFuturesClasses`            | A list of classes to be treated equivalently to Guava `Futures` and `FluentFuture`; this special support will likely be removed once NullAway's JSpecify support is more complete.
 
 ### Methods
 
diff --git a/src/main/kotlin/net/ltgt/gradle/nullaway/NullAwayOptions.kt b/src/main/kotlin/net/ltgt/gradle/nullaway/NullAwayOptions.kt
index d3d85bc..2fe223f 100644
--- a/src/main/kotlin/net/ltgt/gradle/nullaway/NullAwayOptions.kt
+++ b/src/main/kotlin/net/ltgt/gradle/nullaway/NullAwayOptions.kt
@@ -173,6 +173,14 @@ open class NullAwayOptions internal constructor(
     @get:Optional
     val isJSpecifyMode = objectFactory.property<Boolean>()
 
+    /**
+     * A list of classes to be treated equivalently to Guava `Futures` and `FluentFuture`; maps to `-XepOpt:NullAway:ExtraFuturesClasses`.
+     *
+     * This special support will likely be removed once NullAway's JSpecify support is more complete.
+     */
+    @get:Input @get:Optional
+    val extraFuturesClasses = objectFactory.listProperty<String>()
+
     /**
      * Enable NullAway.
      *
@@ -229,6 +237,7 @@ open class NullAwayOptions internal constructor(
         listOption("CustomNonnullAnnotations", customNonnullAnnotations),
         listOption("CustomGeneratedCodeAnnotations", customGeneratedCodeAnnotations),
         booleanOption("JSpecifyMode", isJSpecifyMode),
+        listOption("ExtraFuturesClasses", extraFuturesClasses),
     )
         .filterNotNull()
         .asIterable()
diff --git a/src/test/kotlin/net/ltgt/gradle/nullaway/Fixtures.kt b/src/test/kotlin/net/ltgt/gradle/nullaway/Fixtures.kt
index 5db2300..dd21019 100644
--- a/src/test/kotlin/net/ltgt/gradle/nullaway/Fixtures.kt
+++ b/src/test/kotlin/net/ltgt/gradle/nullaway/Fixtures.kt
@@ -12,7 +12,7 @@ val testGradleVersion = System.getProperty("test.gradle-version", GradleVersion.
 
 val errorproneVersion = System.getProperty("errorprone.version")!!
 
-const val nullawayVersion = "0.10.10"
+const val nullawayVersion = "0.10.23"
 
 const val FAILURE_SOURCE_COMPILATION_ERROR = "Failure.java:8: warning: [NullAway]"
 
diff --git a/src/test/kotlin/net/ltgt/gradle/nullaway/GroovyDslIntegrationTest.kt b/src/test/kotlin/net/ltgt/gradle/nullaway/GroovyDslIntegrationTest.kt
index 453b1d4..49052d1 100644
--- a/src/test/kotlin/net/ltgt/gradle/nullaway/GroovyDslIntegrationTest.kt
+++ b/src/test/kotlin/net/ltgt/gradle/nullaway/GroovyDslIntegrationTest.kt
@@ -120,6 +120,7 @@ class GroovyDslIntegrationTest {
                     customNonnullAnnotations = ["com.example.MustNotBeNull"]
                     customGeneratedCodeAnnotations = ["com.example.Generated"]
                     jspecifyMode = true
+                    extraFuturesClasses = ["com.example.Future"]
                 }
             }
             """.trimIndent(),
diff --git a/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayOptionsTest.kt b/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayOptionsTest.kt
index 3e8f08b..2bab5f7 100644
--- a/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayOptionsTest.kt
+++ b/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayOptionsTest.kt
@@ -48,6 +48,7 @@ class NullAwayOptionsTest {
             "NullAway:CustomNonnullAnnotations",
             "NullAway:CustomGeneratedCodeAnnotations",
             "NullAway:JSpecifyMode",
+            "NullAway:ExtraFuturesClasses",
         )
     }
 
@@ -95,6 +96,7 @@ class NullAwayOptionsTest {
         doTestOptions { customNonnullAnnotations.add("com.example.MustNotBeNull") }
         doTestOptions { customGeneratedCodeAnnotations.add("com.example.Generated") }
         doTestOptions { isJSpecifyMode.set(true) }
+        doTestOptions { extraFuturesClasses.add("com.example.Future") }
 
         doTestOptions {
             enable()
@@ -124,6 +126,7 @@ class NullAwayOptionsTest {
             customNonnullAnnotations.add("com.example.MustNotBeNull")
             customGeneratedCodeAnnotations.add("com.example.Generated")
             isJSpecifyMode.set(true)
+            extraFuturesClasses.add("com.example.Future")
         }
     }
 
@@ -182,6 +185,7 @@ class NullAwayOptionsTest {
         assertListOptionEqual(parsedOptions, "NullAway:CustomNonnullAnnotations", options.customNonnullAnnotations)
         assertListOptionEqual(parsedOptions, "NullAway:CustomGeneratedCodeAnnotations", options.customGeneratedCodeAnnotations)
         assertBooleanOptionEqual(parsedOptions, "NullAway:JSpecifyMode", options.isJSpecifyMode)
+        assertListOptionEqual(parsedOptions, "NullAway:ExtraFuturesClasses", options.extraFuturesClasses)
 
         assertThat(parsedOptions.flags.flagsMap.keys - ALL_NULLAWAY_OPTION_NAMES).isEmpty()
         assertThat(parsedOptions.remainingArgs).isEmpty()
diff --git a/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayPluginIntegrationTest.kt b/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayPluginIntegrationTest.kt
index 298de7c..46a2d40 100644
--- a/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayPluginIntegrationTest.kt
+++ b/src/test/kotlin/net/ltgt/gradle/nullaway/NullAwayPluginIntegrationTest.kt
@@ -161,6 +161,7 @@ class NullAwayPluginIntegrationTest {
                     customNullableAnnotations.add("com.example.CouldBeNull")
                     customNonnullAnnotations.add("com.example.MustNotBeNull")
                     isJSpecifyMode.set(true)
+                    extraFuturesClasses.add("com.example.Future")
                 }
             }
             """.trimIndent(),