diff --git a/dagger-compiler/main/java/dagger/internal/codegen/binding/BindingGraph.java b/dagger-compiler/main/java/dagger/internal/codegen/binding/BindingGraph.java index 533b6559bf7..586d6f48581 100644 --- a/dagger-compiler/main/java/dagger/internal/codegen/binding/BindingGraph.java +++ b/dagger-compiler/main/java/dagger/internal/codegen/binding/BindingGraph.java @@ -27,7 +27,9 @@ import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet; import androidx.room3.compiler.processing.XExecutableElement; +import androidx.room3.compiler.processing.XExecutableType; import androidx.room3.compiler.processing.XMethodElement; +import androidx.room3.compiler.processing.XType; import androidx.room3.compiler.processing.XTypeElement; import com.google.auto.value.AutoValue; import com.google.auto.value.extension.memoized.Memoized; @@ -409,8 +411,10 @@ public final Optional factoryMethod() { */ // TODO(dpb): Consider disallowing modules if none of their bindings are used. public final ImmutableSet factoryMethodRequirements() { - return factoryMethod().get().getParameters().stream() - .map(parameter -> ComponentRequirement.forModule(parameter.getType())) + XType parentType = componentPath().parentComponent().xprocessing().getType(); + XExecutableType resolvedFactoryMethod = factoryMethod().get().asMemberOf(parentType); + return resolvedFactoryMethod.getParameterTypes().stream() + .map(ComponentRequirement::forModule) .collect(toImmutableSet()); } diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/GenericSubcomponentFactoryMethodTest.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/GenericSubcomponentFactoryMethodTest.kt new file mode 100644 index 00000000000..30cd17de160 --- /dev/null +++ b/javatests/dagger/functional/kotlinsrc/subcomponent/GenericSubcomponentFactoryMethodTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2026 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dagger.functional.kotlinsrc.subcomponent + +import com.google.common.truth.Truth.assertThat +import dagger.Component +import dagger.Module +import dagger.Provides +import dagger.Subcomponent +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +/** Tests for subcomponent factory methods defined on generic supertypes. */ +@RunWith(JUnit4::class) +class GenericSubcomponentFactoryMethodTest { + @Component(modules = [ParentModule::class]) + internal interface Parent : SubcomponentProvider {} + + @Module + internal class ParentModule { + @Provides fun provideInt(): Int = 42 + } + + @Subcomponent(modules = [ChildModule::class]) + internal interface Child { + fun string(): String + } + + @Module + internal class ChildModule(val s: String) { + @Provides fun provideString(i: Int): String = s + i + } + + interface SubcomponentProvider { + fun createSubcomponent(module: M): C + } + + @Test + fun factoryMethod_genericSupertype() { + val parent: Parent = DaggerGenericSubcomponentFactoryMethodTest_Parent.create() + val child: Child = parent.createSubcomponent(ChildModule("hello ")) + assertThat(child.string()).isEqualTo("hello 42") + } +} diff --git a/javatests/dagger/functional/subcomponent/GenericSubcomponentFactoryMethodTest.java b/javatests/dagger/functional/subcomponent/GenericSubcomponentFactoryMethodTest.java new file mode 100644 index 00000000000..cbbc7799726 --- /dev/null +++ b/javatests/dagger/functional/subcomponent/GenericSubcomponentFactoryMethodTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2026 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dagger.functional.subcomponent; + +import static com.google.common.truth.Truth.assertThat; + +import dagger.Component; +import dagger.Module; +import dagger.Provides; +import dagger.Subcomponent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for subcomponent factory methods defined on generic supertypes. */ +@RunWith(JUnit4.class) +public final class GenericSubcomponentFactoryMethodTest { + + @Component(modules = ParentModule.class) + interface Parent extends SubcomponentProvider {} + + @Module + static class ParentModule { + @Provides + int provideInt() { + return 42; + } + } + + @Subcomponent(modules = ChildModule.class) + interface Child { + String string(); + } + + @Module + static class ChildModule { + final String s; + + ChildModule(String s) { + this.s = s; + } + + @Provides + String provideString(int i) { + return s + i; + } + } + + public interface SubcomponentProvider { + C createSubcomponent(M module); + } + + @Test + public void factoryMethod_genericSupertype() { + Parent parent = DaggerGenericSubcomponentFactoryMethodTest_Parent.create(); + Child child = parent.createSubcomponent(new ChildModule("hello ")); + assertThat(child.string()).isEqualTo("hello 42"); + } +}