Skip to content

Commit

Permalink
Permit @Multibinds with values that are also allowed by @IntoSet/@Int…
Browse files Browse the repository at this point in the history
…omap.

Closes #4459.

RELNOTES=Permit @Multibinds with values that are also allowed by @IntoSet/@Intomap.
PiperOrigin-RevId: 688325348
  • Loading branch information
damianw authored and Dagger Team committed Oct 22, 2024
1 parent d9e2f10 commit 0f936b5
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand Down
1 change: 1 addition & 0 deletions javatests/dagger/functional/multibindings/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ GenJavaTests(
"MultibindsModule.java",
"NestedAnnotationContainer.java",
"NumberClassKey.java",
"RequiresFieldInjection.java",
"ShortKey.java",
"UnwrappedAnnotationKey.java",
"WrappedAnnotationKey.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -67,4 +68,8 @@ interface MultibindingComponent {

@Named("complexQualifier")
Map<String, CharSequence> maybeEmptyQualifiedMap();

Map<Class<?>, MembersInjector<?>> membersInjectorMap();

Set<MembersInjector<?>> membersInjectorSet();
}
22 changes: 22 additions & 0 deletions javatests/dagger/functional/multibindings/MultibindingModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package dagger.functional.multibindings;

import dagger.MembersInjector;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.ClassKey;
Expand Down Expand Up @@ -95,6 +96,27 @@ static Collection<String> provideMapValues(Map<String, String> map) {
return map.values();
}

@Provides
@Named("fieldInjectedValue")
static String provideFieldInjectedValue() {
return "fieldInjectedValue";
}

@Provides
@IntoMap
@ClassKey(RequiresFieldInjection.class)
static MembersInjector<?> provideMembersInjectorIntoMap(
MembersInjector<RequiresFieldInjection> injector) {
return injector;
}

@Provides
@IntoSet
static MembersInjector<?> provideMembersInjectorIntoSet(
MembersInjector<RequiresFieldInjection> injector) {
return injector;
}

@Provides
@IntoMap
@NestedAnnotationContainer.NestedWrappedKey(Integer.class)
Expand Down
25 changes: 25 additions & 0 deletions javatests/dagger/functional/multibindings/MultibindingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<MembersInjector<?>> injectors = multibindingComponent.membersInjectorSet();
assertThat(injectors).hasSize(1);
RequiresFieldInjection injected = new RequiresFieldInjection();
assertThat(injected.value).isNull();
((MembersInjector<RequiresFieldInjection>) 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<Class<?>, MembersInjector<?>> injectors = multibindingComponent.membersInjectorMap();
assertThat(injectors).hasSize(1);
RequiresFieldInjection injected = new RequiresFieldInjection();
assertThat(injected.value).isNull();
((MembersInjector<RequiresFieldInjection>) injectors.get(RequiresFieldInjection.class))
.injectMembers(injected);
assertThat(injected.value).isEqualTo("fieldInjectedValue");
}

@AutoAnnotation
static StringKey testStringKey(String value) {
return new AutoAnnotation_MultibindingTest_testStringKey(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package dagger.functional.multibindings;

import dagger.MembersInjector;
import dagger.Module;
import dagger.multibindings.Multibinds;
import java.util.Map;
Expand All @@ -38,9 +39,15 @@ abstract class MultibindsModule {
@Multibinds
abstract Set<CharSequence> set();

@Multibinds
abstract Set<MembersInjector<?>> membersInjectorSet();

@Multibinds
abstract Map<String, CharSequence> map();

@Multibinds
abstract Map<Class<?>, MembersInjector<?>> membersInjectorMap();

@Multibinds
@Named("complexQualifier")
abstract Set<Object> emptyQualifiedSet();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
14 changes: 0 additions & 14 deletions javatests/dagger/internal/codegen/MultibindsValidationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<Provider<Object>> providerSet();")
.withDeclaration(moduleDeclaration)
.hasError("return type cannot use 'Provider' in the Set value type.");
}

@Test
public void producerSet() {
assertThatModuleMethod("@Multibinds abstract Set<Producer<Object>> producerSet();")
.withDeclaration(moduleDeclaration)
.hasError("return type cannot use 'Producer' in the Set value type.");
}

@Test
public void producedSet() {
assertThatModuleMethod("@Multibinds abstract Set<Produced<Object>> producedSet();")
Expand Down

0 comments on commit 0f936b5

Please sign in to comment.