From 0f936b5ce8bd350d6c1dbf776b991849ff7a8225 Mon Sep 17 00:00:00 2001 From: Damian Wieczorek Date: Mon, 21 Oct 2024 17:10:55 -0700 Subject: [PATCH] Permit @Multibinds with values that are also allowed by @IntoSet/@IntoMap. Closes https://github.com/google/dagger/pull/4459. RELNOTES=Permit @Multibinds with values that are also allowed by @IntoSet/@IntoMap. PiperOrigin-RevId: 688325348 --- .../validation/MultibindsMethodValidator.java | 7 +++--- .../dagger/functional/multibindings/BUILD | 1 + .../multibindings/MultibindingComponent.java | 5 ++++ .../multibindings/MultibindingModule.java | 22 ++++++++++++++++ .../multibindings/MultibindingTest.java | 25 +++++++++++++++++++ .../multibindings/MultibindsModule.java | 7 ++++++ .../multibindings/RequiresFieldInjection.java | 24 ++++++++++++++++++ .../codegen/MultibindsValidationTest.java | 14 ----------- 8 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 javatests/dagger/functional/multibindings/RequiresFieldInjection.java diff --git a/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java b/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java index a63d97426ba..8638614a4a2 100644 --- a/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java +++ b/java/dagger/internal/codegen/validation/MultibindsMethodValidator.java @@ -16,7 +16,8 @@ package dagger.internal.codegen.validation; -import static dagger.internal.codegen.base.FrameworkTypes.isFrameworkType; +import static dagger.internal.codegen.base.FrameworkTypes.isMapValueFrameworkType; +import static dagger.internal.codegen.base.FrameworkTypes.isSetValueFrameworkType; import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS; import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING; import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT; @@ -95,7 +96,7 @@ private void checkMapType(MapType mapType) { } else if (isWildcard(mapType.valueType())) { report.addError( bindingMethods("return type cannot use a wildcard as the Map value type.")); - } else if (isFrameworkType(mapType.valueType())) { + } else if (isMapValueFrameworkType(mapType.valueType())) { String frameworkTypeName = getSimpleName(mapType.valueType().getTypeElement()); report.addError( bindingMethods( @@ -108,7 +109,7 @@ private void checkSetType(SetType setType) { report.addError(bindingMethods("return type cannot be a raw Set type")); } else if (isWildcard(setType.elementType())) { report.addError(bindingMethods("return type cannot use a wildcard as the Set value type.")); - } else if (isFrameworkType(setType.elementType())) { + } else if (isSetValueFrameworkType(setType.elementType())) { String frameworkTypeName = getSimpleName(setType.elementType().getTypeElement()); report.addError( bindingMethods( diff --git a/javatests/dagger/functional/multibindings/BUILD b/javatests/dagger/functional/multibindings/BUILD index ca10daffa46..42153c42a43 100644 --- a/javatests/dagger/functional/multibindings/BUILD +++ b/javatests/dagger/functional/multibindings/BUILD @@ -37,6 +37,7 @@ GenJavaTests( "MultibindsModule.java", "NestedAnnotationContainer.java", "NumberClassKey.java", + "RequiresFieldInjection.java", "ShortKey.java", "UnwrappedAnnotationKey.java", "WrappedAnnotationKey.java", diff --git a/javatests/dagger/functional/multibindings/MultibindingComponent.java b/javatests/dagger/functional/multibindings/MultibindingComponent.java index 8e61ae0b2d1..77eeb53fa5c 100644 --- a/javatests/dagger/functional/multibindings/MultibindingComponent.java +++ b/javatests/dagger/functional/multibindings/MultibindingComponent.java @@ -17,6 +17,7 @@ package dagger.functional.multibindings; import dagger.Component; +import dagger.MembersInjector; import dagger.functional.multibindings.subpackage.ContributionsModule; import dagger.multibindings.StringKey; import java.util.Collection; @@ -67,4 +68,8 @@ interface MultibindingComponent { @Named("complexQualifier") Map maybeEmptyQualifiedMap(); + + Map, MembersInjector> membersInjectorMap(); + + Set> membersInjectorSet(); } diff --git a/javatests/dagger/functional/multibindings/MultibindingModule.java b/javatests/dagger/functional/multibindings/MultibindingModule.java index cc34e24f9c6..af90d3c0094 100644 --- a/javatests/dagger/functional/multibindings/MultibindingModule.java +++ b/javatests/dagger/functional/multibindings/MultibindingModule.java @@ -16,6 +16,7 @@ package dagger.functional.multibindings; +import dagger.MembersInjector; import dagger.Module; import dagger.Provides; import dagger.multibindings.ClassKey; @@ -95,6 +96,27 @@ static Collection provideMapValues(Map map) { return map.values(); } + @Provides + @Named("fieldInjectedValue") + static String provideFieldInjectedValue() { + return "fieldInjectedValue"; + } + + @Provides + @IntoMap + @ClassKey(RequiresFieldInjection.class) + static MembersInjector provideMembersInjectorIntoMap( + MembersInjector injector) { + return injector; + } + + @Provides + @IntoSet + static MembersInjector provideMembersInjectorIntoSet( + MembersInjector injector) { + return injector; + } + @Provides @IntoMap @NestedAnnotationContainer.NestedWrappedKey(Integer.class) diff --git a/javatests/dagger/functional/multibindings/MultibindingTest.java b/javatests/dagger/functional/multibindings/MultibindingTest.java index 9787764214b..96037fe6227 100644 --- a/javatests/dagger/functional/multibindings/MultibindingTest.java +++ b/javatests/dagger/functional/multibindings/MultibindingTest.java @@ -19,11 +19,13 @@ import static com.google.common.truth.Truth.assertThat; import com.google.auto.value.AutoAnnotation; +import dagger.MembersInjector; import dagger.multibindings.ClassKey; import dagger.multibindings.StringKey; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Map; +import java.util.Set; import javax.inject.Provider; import org.junit.Test; import org.junit.runner.RunWith; @@ -183,6 +185,29 @@ public void maybeEmptyQualifiedMap() { .containsEntry("key", "qualified foo value"); } + @SuppressWarnings("unchecked") // We know the single type in the set + @Test + public void membersInjectorSet() { + Set> injectors = multibindingComponent.membersInjectorSet(); + assertThat(injectors).hasSize(1); + RequiresFieldInjection injected = new RequiresFieldInjection(); + assertThat(injected.value).isNull(); + ((MembersInjector) injectors.iterator().next()).injectMembers(injected); + assertThat(injected.value).isEqualTo("fieldInjectedValue"); + } + + @SuppressWarnings("unchecked") // We know the single type in the map + @Test + public void membersInjectorMap() { + Map, MembersInjector> injectors = multibindingComponent.membersInjectorMap(); + assertThat(injectors).hasSize(1); + RequiresFieldInjection injected = new RequiresFieldInjection(); + assertThat(injected.value).isNull(); + ((MembersInjector) injectors.get(RequiresFieldInjection.class)) + .injectMembers(injected); + assertThat(injected.value).isEqualTo("fieldInjectedValue"); + } + @AutoAnnotation static StringKey testStringKey(String value) { return new AutoAnnotation_MultibindingTest_testStringKey(value); diff --git a/javatests/dagger/functional/multibindings/MultibindsModule.java b/javatests/dagger/functional/multibindings/MultibindsModule.java index b678c9e803a..72698eb9ad9 100644 --- a/javatests/dagger/functional/multibindings/MultibindsModule.java +++ b/javatests/dagger/functional/multibindings/MultibindsModule.java @@ -16,6 +16,7 @@ package dagger.functional.multibindings; +import dagger.MembersInjector; import dagger.Module; import dagger.multibindings.Multibinds; import java.util.Map; @@ -38,9 +39,15 @@ abstract class MultibindsModule { @Multibinds abstract Set set(); + @Multibinds + abstract Set> membersInjectorSet(); + @Multibinds abstract Map map(); + @Multibinds + abstract Map, MembersInjector> membersInjectorMap(); + @Multibinds @Named("complexQualifier") abstract Set emptyQualifiedSet(); diff --git a/javatests/dagger/functional/multibindings/RequiresFieldInjection.java b/javatests/dagger/functional/multibindings/RequiresFieldInjection.java new file mode 100644 index 00000000000..2a1a0601b69 --- /dev/null +++ b/javatests/dagger/functional/multibindings/RequiresFieldInjection.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2024 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.multibindings; + +import javax.inject.Inject; +import javax.inject.Named; + +public final class RequiresFieldInjection { + @Inject @Named("fieldInjectedValue") String value; +} diff --git a/javatests/dagger/internal/codegen/MultibindsValidationTest.java b/javatests/dagger/internal/codegen/MultibindsValidationTest.java index a006dfad3f1..0395c70d201 100644 --- a/javatests/dagger/internal/codegen/MultibindsValidationTest.java +++ b/javatests/dagger/internal/codegen/MultibindsValidationTest.java @@ -141,20 +141,6 @@ public void wildcardSetWithBounds() { .hasError("return type cannot use a wildcard as the Set value type."); } - @Test - public void providerSet() { - assertThatModuleMethod("@Multibinds abstract Set> providerSet();") - .withDeclaration(moduleDeclaration) - .hasError("return type cannot use 'Provider' in the Set value type."); - } - - @Test - public void producerSet() { - assertThatModuleMethod("@Multibinds abstract Set> producerSet();") - .withDeclaration(moduleDeclaration) - .hasError("return type cannot use 'Producer' in the Set value type."); - } - @Test public void producedSet() { assertThatModuleMethod("@Multibinds abstract Set> producedSet();")