From 33e7dd7bcc8f693e21ea8903a1c7b86b4cb46aca Mon Sep 17 00:00:00 2001
From: Dagger Team <java-team-github-bot@google.com>
Date: Thu, 26 Sep 2024 11:28:02 -0700
Subject: [PATCH] Retain nullability annotations when building override
 versions of functions.

RELNOTES=n/a
PiperOrigin-RevId: 679227064
---
 .../codegen/xprocessing/MethodSpecs.java      | 17 ++++++--
 .../ComponentRequirementFieldTest.java        | 39 +++++++++++++++++
 ...ance_DEFAULT_MODE_test.DaggerTestComponent | 42 +++++++++++++++++++
 ...ce_FAST_INIT_MODE_test.DaggerTestComponent | 42 +++++++++++++++++++
 ...ance_DEFAULT_MODE_test.DaggerTestComponent | 42 +++++++++++++++++++
 ...ce_FAST_INIT_MODE_test.DaggerTestComponent | 42 +++++++++++++++++++
 6 files changed, 220 insertions(+), 4 deletions(-)
 create mode 100644 javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
 create mode 100644 javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent
 create mode 100644 javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
 create mode 100644 javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent

diff --git a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
index cc8c2f45915..7931b1a39e2 100644
--- a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
+++ b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
@@ -16,15 +16,17 @@
 
 package dagger.internal.codegen.xprocessing;
 
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static javax.lang.model.element.Modifier.PROTECTED;
 import static javax.lang.model.element.Modifier.PUBLIC;
 
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XMethodType;
 import androidx.room.compiler.processing.XType;
+import com.squareup.javapoet.AnnotationSpec;
 import com.squareup.javapoet.MethodSpec;
 import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
 
 // TODO(bcorso): Consider moving these methods into XProcessing library.
 /** A utility class for {@link MethodSpec} helper methods. */
@@ -46,9 +48,16 @@ public static MethodSpec.Builder overriding(XMethodElement method, XType owner)
       builder.addModifiers(PROTECTED);
     }
     for (int i = 0; i < methodType.getParameterTypes().size(); i++) {
-      String parameterName = method.getParameters().get(i).getJvmName();
-      TypeName parameterType = methodType.getParameterTypes().get(i).getTypeName();
-      builder.addParameter(ParameterSpec.builder(parameterType, parameterName).build());
+      XExecutableParameterElement parameter = method.getParameters().get(i);
+      builder.addParameter(
+          ParameterSpec.builder(
+                  methodType.getParameterTypes().get(i).getTypeName(), parameter.getJvmName())
+              // Retain nullability annotations on parameters.
+              .addAnnotations(
+                  Nullability.of(parameter).nullableAnnotations().stream()
+                      .map(annotation -> AnnotationSpec.builder(annotation).build())
+                      .collect(toImmutableList()))
+              .build());
     }
     method.getThrownTypes().stream().map(XType::getTypeName).forEach(builder::addException);
     return builder;
diff --git a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
index 65929e7d926..dfe74bb61b6 100644
--- a/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
+++ b/javatests/dagger/internal/codegen/ComponentRequirementFieldTest.java
@@ -33,6 +33,13 @@ public static Collection<Object[]> parameters() {
     return CompilerMode.TEST_PARAMETERS;
   }
 
+  private static final Source NON_TYPE_USE_NULLABLE =
+      CompilerTests.javaSource(
+          "test.Nullable", // force one-string-per-line format
+          "package test;",
+          "",
+          "public @interface Nullable {}");
+
   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
 
   private final CompilerMode compilerMode;
@@ -73,6 +80,38 @@ public void bindsInstance() throws Exception {
             });
   }
 
+  @Test
+  public void testBindsNullableInstance() throws Exception {
+    Source component =
+        CompilerTests.javaSource(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.BindsInstance;",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface TestComponent {",
+            "  @Component.Factory",
+            "  interface Factory {",
+            "    TestComponent create(@BindsInstance @Nullable Bar arg);",
+            "}",
+            "}");
+    Source bar =
+        CompilerTests.javaSource(
+            "test.Bar", // force one-string-per-line format
+            "package test;",
+            "",
+            "interface Bar {}");
+    CompilerTests.daggerCompiler(component, bar, NON_TYPE_USE_NULLABLE)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
+            });
+  }
+
   @Test
   public void instanceModuleMethod() throws Exception {
     Source module =
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
new file mode 100644
index 00000000000..2fe8226e104
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
@@ -0,0 +1,42 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast",
+    "deprecation"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static TestComponent.Factory factory() {
+    return new Factory();
+  }
+
+  private static final class Factory implements TestComponent.Factory {
+    @Override
+    public TestComponent create(@Nullable Bar arg) {
+      return new TestComponentImpl(arg);
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private TestComponentImpl(Bar argParam) {
+
+
+    }
+  }
+}
\ No newline at end of file
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent
new file mode 100644
index 00000000000..0feb62c2de5
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent
@@ -0,0 +1,42 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast",
+    "deprecation"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static TestComponent.Factory factory() {
+    return new Factory();
+  }
+
+  private static final class Factory implements TestComponent.Factory {
+    @Override
+    public TestComponent create(@Nullable Bar arg) {
+      return new TestComponentImpl(arg);
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private TestComponentImpl(Bar argParam) {
+
+
+    }
+  }
+}
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
new file mode 100644
index 00000000000..0feb62c2de5
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent
@@ -0,0 +1,42 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast",
+    "deprecation"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static TestComponent.Factory factory() {
+    return new Factory();
+  }
+
+  private static final class Factory implements TestComponent.Factory {
+    @Override
+    public TestComponent create(@Nullable Bar arg) {
+      return new TestComponentImpl(arg);
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private TestComponentImpl(Bar argParam) {
+
+
+    }
+  }
+}
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent
new file mode 100644
index 00000000000..0feb62c2de5
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent
@@ -0,0 +1,42 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast",
+    "deprecation"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static TestComponent.Factory factory() {
+    return new Factory();
+  }
+
+  private static final class Factory implements TestComponent.Factory {
+    @Override
+    public TestComponent create(@Nullable Bar arg) {
+      return new TestComponentImpl(arg);
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private TestComponentImpl(Bar argParam) {
+
+
+    }
+  }
+}