diff --git a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java index 086c5d980a4..0f2a40fd44d 100644 --- a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java +++ b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java @@ -19,17 +19,14 @@ import static androidx.room.compiler.processing.XTypeKt.isVoid; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Iterables.getOnlyElement; import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent; import static dagger.internal.codegen.binding.BindingRequest.bindingRequest; import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock; import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible; import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom; import static dagger.internal.codegen.xprocessing.MethodSpecs.overriding; -import static dagger.internal.codegen.xprocessing.XElements.getSimpleName; import static dagger.internal.codegen.xprocessing.XProcessingEnvs.isPreJava8SourceVersion; -import androidx.room.compiler.processing.XMethodElement; import androidx.room.compiler.processing.XProcessingEnv; import androidx.room.compiler.processing.XType; import com.google.common.collect.ImmutableList; @@ -185,47 +182,26 @@ && isRawTypeAccessible(dependencyType, requestingClass.packageName())) { /** Returns the implementation of a component method. */ public MethodSpec getComponentMethod(ComponentMethodDescriptor componentMethod) { - checkArgument(componentMethod.dependencyRequest().isPresent()); - BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get()); return overriding(componentMethod.methodElement(), graph.componentTypeElement().getType()) - .addCode( - request.isRequestKind(RequestKind.MEMBERS_INJECTION) - ? getMembersInjectionComponentMethodImplementation(request, componentMethod) - : getContributionComponentMethodImplementation(request, componentMethod)) + .addCode(getComponentMethodCodeBlock(componentMethod)) .build(); } - private CodeBlock getMembersInjectionComponentMethodImplementation( - BindingRequest request, ComponentMethodDescriptor componentMethod) { - checkArgument(request.isRequestKind(RequestKind.MEMBERS_INJECTION)); - XMethodElement methodElement = componentMethod.methodElement(); - RequestRepresentation requestRepresentation = getRequestRepresentation(request); - MembersInjectionBinding binding = - ((MembersInjectionRequestRepresentation) requestRepresentation).binding(); - if (binding.injectionSites().isEmpty()) { - // If there are no injection sites either do nothing (if the return type is void) or return - // the input instance as-is. - return isVoid(methodElement.getReturnType()) - ? CodeBlock.of("") - : CodeBlock.of( - "return $L;", getSimpleName(getOnlyElement(methodElement.getParameters()))); + private CodeBlock getComponentMethodCodeBlock(ComponentMethodDescriptor componentMethod) { + Expression expression = getComponentMethodExpression(componentMethod); + if (isVoid(componentMethod.methodElement().getReturnType())) { + return expression.codeBlock().isEmpty() + ? expression.codeBlock() + : CodeBlock.of("$L;", expression.codeBlock()); } - Expression expression = getComponentMethodExpression(requestRepresentation, componentMethod); - return isVoid(methodElement.getReturnType()) - ? CodeBlock.of("$L;", expression.codeBlock()) - : CodeBlock.of("return $L;", expression.codeBlock()); - } - - private CodeBlock getContributionComponentMethodImplementation( - BindingRequest request, ComponentMethodDescriptor componentMethod) { - checkArgument(!request.isRequestKind(RequestKind.MEMBERS_INJECTION)); - Expression expression = - getComponentMethodExpression(getRequestRepresentation(request), componentMethod); return CodeBlock.of("return $L;", expression.codeBlock()); } - private Expression getComponentMethodExpression( - RequestRepresentation requestRepresentation, ComponentMethodDescriptor componentMethod) { + private Expression getComponentMethodExpression(ComponentMethodDescriptor componentMethod) { + checkArgument(componentMethod.dependencyRequest().isPresent()); + BindingRequest request = bindingRequest(componentMethod.dependencyRequest().get()); + RequestRepresentation requestRepresentation = getRequestRepresentation(request); + Expression expression = requestRepresentation.getDependencyExpressionForComponentMethod( componentMethod, componentImplementation); diff --git a/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java b/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java index f8f31a36e7d..a932a38e9d7 100644 --- a/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java +++ b/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java @@ -16,6 +16,7 @@ package dagger.internal.codegen.writing; +import static androidx.room.compiler.processing.XTypeKt.isVoid; import static com.google.common.collect.Iterables.getOnlyElement; import androidx.room.compiler.processing.XExecutableParameterElement; @@ -54,6 +55,15 @@ protected Expression getDependencyExpressionForComponentMethod( ComponentMethodDescriptor componentMethod, ComponentImplementation component) { XMethodElement methodElement = componentMethod.methodElement(); XExecutableParameterElement parameter = getOnlyElement(methodElement.getParameters()); + if (binding.injectionSites().isEmpty()) { + // If there are no injection sites either do nothing (if the return type is void) or return + // the input instance as-is. + return Expression.create( + methodElement.getReturnType(), + isVoid(methodElement.getReturnType()) + ? CodeBlock.of("") + : CodeBlock.of("$L", parameter.getJvmName())); + } return membersInjectionMethods.getInjectExpression( binding.key(), CodeBlock.of("$L", parameter.getJvmName()), component.name()); } diff --git a/javatests/dagger/internal/codegen/MembersInjectionTest.java b/javatests/dagger/internal/codegen/MembersInjectionTest.java index 97bde372b4f..b547ec07693 100644 --- a/javatests/dagger/internal/codegen/MembersInjectionTest.java +++ b/javatests/dagger/internal/codegen/MembersInjectionTest.java @@ -1364,6 +1364,38 @@ public void kotlinNullableFieldInjection() { }); } + @Test + public void testMembersInjectionBindingWithNoInjectionSites() throws Exception { + Source component = + CompilerTests.javaSource( + "test.MyComponent", + "package test;", + "", + "import dagger.Component;", + "", + "@Component", + "public interface MyComponent {", + " void inject(Foo foo);", + "", + " Foo injectAndReturn(Foo foo);", + "}"); + + Source foo = + CompilerTests.javaSource( + "test.Foo", + "package test;", + "", + "class Foo {}"); + + CompilerTests.daggerCompiler(component, foo) + .withProcessingOptions(compilerMode.processorOptions()) + .compile( + subject -> { + subject.hasErrorCount(0); + subject.generatedSource(goldenFileRule.goldenSource("test/DaggerMyComponent")); + }); + } + private Source stripJetbrainsNullable(Source source) { return CompilerTests.javaSource( ((Source.JavaSource) source).getQName(), diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_DEFAULT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_DEFAULT_MODE_test.DaggerMyComponent new file mode 100644 index 00000000000..d47c1f27b03 --- /dev/null +++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_DEFAULT_MODE_test.DaggerMyComponent @@ -0,0 +1,58 @@ +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", + "nullness:initialization.field.uninitialized" +}) +public final class DaggerMyComponent { + private DaggerMyComponent() { + } + + public static Builder builder() { + return new Builder(); + } + + public static MyComponent create() { + return new Builder().build(); + } + + public static final class Builder { + private Builder() { + } + + public MyComponent build() { + return new MyComponentImpl(); + } + } + + private static final class MyComponentImpl implements MyComponent { + private final MyComponentImpl myComponentImpl = this; + + private MyComponentImpl() { + + + } + + @Override + public void inject(Foo foo) { + } + + @Override + public Foo injectAndReturn(Foo foo) { + return foo; + } + } +} \ No newline at end of file diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_FAST_INIT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_FAST_INIT_MODE_test.DaggerMyComponent new file mode 100644 index 00000000000..d47c1f27b03 --- /dev/null +++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingWithNoInjectionSites_FAST_INIT_MODE_test.DaggerMyComponent @@ -0,0 +1,58 @@ +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", + "nullness:initialization.field.uninitialized" +}) +public final class DaggerMyComponent { + private DaggerMyComponent() { + } + + public static Builder builder() { + return new Builder(); + } + + public static MyComponent create() { + return new Builder().build(); + } + + public static final class Builder { + private Builder() { + } + + public MyComponent build() { + return new MyComponentImpl(); + } + } + + private static final class MyComponentImpl implements MyComponent { + private final MyComponentImpl myComponentImpl = this; + + private MyComponentImpl() { + + + } + + @Override + public void inject(Foo foo) { + } + + @Override + public Foo injectAndReturn(Foo foo) { + return foo; + } + } +} \ No newline at end of file