Skip to content

Commit 0f936b5

Browse files
damianwDagger Team
authored andcommitted
Permit @Multibinds with values that are also allowed by @IntoSet/@Intomap.
Closes #4459. RELNOTES=Permit @Multibinds with values that are also allowed by @IntoSet/@Intomap. PiperOrigin-RevId: 688325348
1 parent d9e2f10 commit 0f936b5

File tree

8 files changed

+88
-17
lines changed

8 files changed

+88
-17
lines changed

java/dagger/internal/codegen/validation/MultibindsMethodValidator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
package dagger.internal.codegen.validation;
1818

19-
import static dagger.internal.codegen.base.FrameworkTypes.isFrameworkType;
19+
import static dagger.internal.codegen.base.FrameworkTypes.isMapValueFrameworkType;
20+
import static dagger.internal.codegen.base.FrameworkTypes.isSetValueFrameworkType;
2021
import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
2122
import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING;
2223
import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
@@ -95,7 +96,7 @@ private void checkMapType(MapType mapType) {
9596
} else if (isWildcard(mapType.valueType())) {
9697
report.addError(
9798
bindingMethods("return type cannot use a wildcard as the Map value type."));
98-
} else if (isFrameworkType(mapType.valueType())) {
99+
} else if (isMapValueFrameworkType(mapType.valueType())) {
99100
String frameworkTypeName = getSimpleName(mapType.valueType().getTypeElement());
100101
report.addError(
101102
bindingMethods(
@@ -108,7 +109,7 @@ private void checkSetType(SetType setType) {
108109
report.addError(bindingMethods("return type cannot be a raw Set type"));
109110
} else if (isWildcard(setType.elementType())) {
110111
report.addError(bindingMethods("return type cannot use a wildcard as the Set value type."));
111-
} else if (isFrameworkType(setType.elementType())) {
112+
} else if (isSetValueFrameworkType(setType.elementType())) {
112113
String frameworkTypeName = getSimpleName(setType.elementType().getTypeElement());
113114
report.addError(
114115
bindingMethods(

javatests/dagger/functional/multibindings/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ GenJavaTests(
3737
"MultibindsModule.java",
3838
"NestedAnnotationContainer.java",
3939
"NumberClassKey.java",
40+
"RequiresFieldInjection.java",
4041
"ShortKey.java",
4142
"UnwrappedAnnotationKey.java",
4243
"WrappedAnnotationKey.java",

javatests/dagger/functional/multibindings/MultibindingComponent.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package dagger.functional.multibindings;
1818

1919
import dagger.Component;
20+
import dagger.MembersInjector;
2021
import dagger.functional.multibindings.subpackage.ContributionsModule;
2122
import dagger.multibindings.StringKey;
2223
import java.util.Collection;
@@ -67,4 +68,8 @@ interface MultibindingComponent {
6768

6869
@Named("complexQualifier")
6970
Map<String, CharSequence> maybeEmptyQualifiedMap();
71+
72+
Map<Class<?>, MembersInjector<?>> membersInjectorMap();
73+
74+
Set<MembersInjector<?>> membersInjectorSet();
7075
}

javatests/dagger/functional/multibindings/MultibindingModule.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package dagger.functional.multibindings;
1818

19+
import dagger.MembersInjector;
1920
import dagger.Module;
2021
import dagger.Provides;
2122
import dagger.multibindings.ClassKey;
@@ -95,6 +96,27 @@ static Collection<String> provideMapValues(Map<String, String> map) {
9596
return map.values();
9697
}
9798

99+
@Provides
100+
@Named("fieldInjectedValue")
101+
static String provideFieldInjectedValue() {
102+
return "fieldInjectedValue";
103+
}
104+
105+
@Provides
106+
@IntoMap
107+
@ClassKey(RequiresFieldInjection.class)
108+
static MembersInjector<?> provideMembersInjectorIntoMap(
109+
MembersInjector<RequiresFieldInjection> injector) {
110+
return injector;
111+
}
112+
113+
@Provides
114+
@IntoSet
115+
static MembersInjector<?> provideMembersInjectorIntoSet(
116+
MembersInjector<RequiresFieldInjection> injector) {
117+
return injector;
118+
}
119+
98120
@Provides
99121
@IntoMap
100122
@NestedAnnotationContainer.NestedWrappedKey(Integer.class)

javatests/dagger/functional/multibindings/MultibindingTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020

2121
import com.google.auto.value.AutoAnnotation;
22+
import dagger.MembersInjector;
2223
import dagger.multibindings.ClassKey;
2324
import dagger.multibindings.StringKey;
2425
import java.math.BigDecimal;
2526
import java.math.BigInteger;
2627
import java.util.Map;
28+
import java.util.Set;
2729
import javax.inject.Provider;
2830
import org.junit.Test;
2931
import org.junit.runner.RunWith;
@@ -183,6 +185,29 @@ public void maybeEmptyQualifiedMap() {
183185
.containsEntry("key", "qualified foo value");
184186
}
185187

188+
@SuppressWarnings("unchecked") // We know the single type in the set
189+
@Test
190+
public void membersInjectorSet() {
191+
Set<MembersInjector<?>> injectors = multibindingComponent.membersInjectorSet();
192+
assertThat(injectors).hasSize(1);
193+
RequiresFieldInjection injected = new RequiresFieldInjection();
194+
assertThat(injected.value).isNull();
195+
((MembersInjector<RequiresFieldInjection>) injectors.iterator().next()).injectMembers(injected);
196+
assertThat(injected.value).isEqualTo("fieldInjectedValue");
197+
}
198+
199+
@SuppressWarnings("unchecked") // We know the single type in the map
200+
@Test
201+
public void membersInjectorMap() {
202+
Map<Class<?>, MembersInjector<?>> injectors = multibindingComponent.membersInjectorMap();
203+
assertThat(injectors).hasSize(1);
204+
RequiresFieldInjection injected = new RequiresFieldInjection();
205+
assertThat(injected.value).isNull();
206+
((MembersInjector<RequiresFieldInjection>) injectors.get(RequiresFieldInjection.class))
207+
.injectMembers(injected);
208+
assertThat(injected.value).isEqualTo("fieldInjectedValue");
209+
}
210+
186211
@AutoAnnotation
187212
static StringKey testStringKey(String value) {
188213
return new AutoAnnotation_MultibindingTest_testStringKey(value);

javatests/dagger/functional/multibindings/MultibindsModule.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package dagger.functional.multibindings;
1818

19+
import dagger.MembersInjector;
1920
import dagger.Module;
2021
import dagger.multibindings.Multibinds;
2122
import java.util.Map;
@@ -38,9 +39,15 @@ abstract class MultibindsModule {
3839
@Multibinds
3940
abstract Set<CharSequence> set();
4041

42+
@Multibinds
43+
abstract Set<MembersInjector<?>> membersInjectorSet();
44+
4145
@Multibinds
4246
abstract Map<String, CharSequence> map();
4347

48+
@Multibinds
49+
abstract Map<Class<?>, MembersInjector<?>> membersInjectorMap();
50+
4451
@Multibinds
4552
@Named("complexQualifier")
4653
abstract Set<Object> emptyQualifiedSet();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (C) 2024 The Dagger Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package dagger.functional.multibindings;
18+
19+
import javax.inject.Inject;
20+
import javax.inject.Named;
21+
22+
public final class RequiresFieldInjection {
23+
@Inject @Named("fieldInjectedValue") String value;
24+
}

javatests/dagger/internal/codegen/MultibindsValidationTest.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,6 @@ public void wildcardSetWithBounds() {
141141
.hasError("return type cannot use a wildcard as the Set value type.");
142142
}
143143

144-
@Test
145-
public void providerSet() {
146-
assertThatModuleMethod("@Multibinds abstract Set<Provider<Object>> providerSet();")
147-
.withDeclaration(moduleDeclaration)
148-
.hasError("return type cannot use 'Provider' in the Set value type.");
149-
}
150-
151-
@Test
152-
public void producerSet() {
153-
assertThatModuleMethod("@Multibinds abstract Set<Producer<Object>> producerSet();")
154-
.withDeclaration(moduleDeclaration)
155-
.hasError("return type cannot use 'Producer' in the Set value type.");
156-
}
157-
158144
@Test
159145
public void producedSet() {
160146
assertThatModuleMethod("@Multibinds abstract Set<Produced<Object>> producedSet();")

0 commit comments

Comments
 (0)