diff --git a/java/dagger/internal/codegen/binding/ComponentDeclarations.java b/java/dagger/internal/codegen/binding/ComponentDeclarations.java index b885da19059..401dcf3031f 100644 --- a/java/dagger/internal/codegen/binding/ComponentDeclarations.java +++ b/java/dagger/internal/codegen/binding/ComponentDeclarations.java @@ -79,6 +79,8 @@ ImmutableSet bindings(Key key) { ImmutableSet delegates(Key key) { // @Binds @IntoMap declarations have key Map but may be requested as // Map> keys, so unwrap the multibinding map contribution key first. + // TODO(b/366277730): This can be simplified to "delegates.get(key)" once the flag for + // "useFrameworkTypeInMapMultibindingContributionKey" is removed. return delegates.get( key.multibindingContributionIdentifier().isPresent() // TODO(bcorso): Consider using TypeNameKey here instead of Key, to avoid losing diff --git a/java/dagger/internal/codegen/binding/KeyFactory.java b/java/dagger/internal/codegen/binding/KeyFactory.java index 509b757c464..e03814899bb 100644 --- a/java/dagger/internal/codegen/binding/KeyFactory.java +++ b/java/dagger/internal/codegen/binding/KeyFactory.java @@ -42,6 +42,7 @@ import dagger.internal.codegen.base.OptionalType; import dagger.internal.codegen.base.RequestKinds; import dagger.internal.codegen.base.SetType; +import dagger.internal.codegen.compileroption.CompilerOptions; import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.model.DaggerAnnotation; import dagger.internal.codegen.model.DaggerExecutableElement; @@ -57,11 +58,16 @@ /** A factory for {@link Key}s. */ public final class KeyFactory { private final XProcessingEnv processingEnv; + private final CompilerOptions compilerOptions; private final InjectionAnnotations injectionAnnotations; @Inject - KeyFactory(XProcessingEnv processingEnv, InjectionAnnotations injectionAnnotations) { + KeyFactory( + XProcessingEnv processingEnv, + CompilerOptions compilerOptions, + InjectionAnnotations injectionAnnotations) { this.processingEnv = processingEnv; + this.compilerOptions = compilerOptions; this.injectionAnnotations = injectionAnnotations; } @@ -91,6 +97,10 @@ private XType optionalOf(XType type) { /** Returns {@code Map>}. */ private XType mapOfFrameworkType(XType keyType, ClassName frameworkClassName, XType valueType) { + checkArgument( + MapType.VALID_FRAMEWORK_REQUEST_KINDS.stream() + .map(RequestKinds::frameworkClassName) + .anyMatch(frameworkClassName::equals)); return mapOf( keyType, processingEnv.getDeclaredType( @@ -120,10 +130,12 @@ public Key forSubcomponentCreator(XType creatorType) { } public Key forProvidesMethod(XMethodElement method, XTypeElement contributingModule) { + checkArgument(method.hasAnnotation(TypeNames.PROVIDES)); return forBindingMethod(method, contributingModule, Optional.of(TypeNames.PROVIDER)); } public Key forProducesMethod(XMethodElement method, XTypeElement contributingModule) { + checkArgument(method.hasAnnotation(TypeNames.PRODUCES)); return forBindingMethod(method, contributingModule, Optional.of(TypeNames.PRODUCER)); } @@ -212,7 +224,8 @@ private XType bindingMethodKeyType( method.getAllAnnotations().stream() .map(XAnnotations::toString) .collect(toImmutableList())); - return frameworkClassName.isPresent() + return (frameworkClassName.isPresent() + && compilerOptions.useFrameworkTypeInMapMultibindingContributionKey()) ? mapOfFrameworkType(mapKeyType.get(), frameworkClassName.get(), returnType) : mapOf(mapKeyType.get(), returnType); case SET_VALUES: @@ -226,12 +239,14 @@ private XType bindingMethodKeyType( /** * Returns the key for a binding associated with a {@link DelegateDeclaration}. * - *

If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map} key - * from {@link DelegateDeclaration#key()} to {@code Map>}. If {@code - * delegateDeclaration} is not a map contribution, its key is returned. + *

If {@code delegateDeclaration} is a multibinding map contribution and + * {@link CompilerOptions#useFrameworkTypeInMapMultibindingContributionKey()} is enabled, then + * transforms the {@code Map} key into {@code Map>}, otherwise returns + * the unaltered key. */ Key forDelegateBinding(DelegateDeclaration delegateDeclaration, ClassName frameworkType) { return delegateDeclaration.contributionType().equals(ContributionType.MAP) + && compilerOptions.useFrameworkTypeInMapMultibindingContributionKey() ? wrapMapValue(delegateDeclaration.key(), frameworkType) : delegateDeclaration.key(); } diff --git a/java/dagger/internal/codegen/compileroption/CompilerOptions.java b/java/dagger/internal/codegen/compileroption/CompilerOptions.java index 73f7736f205..1f86ba1a915 100644 --- a/java/dagger/internal/codegen/compileroption/CompilerOptions.java +++ b/java/dagger/internal/codegen/compileroption/CompilerOptions.java @@ -129,6 +129,15 @@ public final boolean doCheckForNulls() { */ public abstract boolean generatedClassExtendsComponent(); + /** + * Returns {@code true} if the key for map multibinding contributions contain a framework type. + * + *

This option is for migration purposes only, and will be removed in a future release. + * + *

The default value is {@code false}. + */ + public abstract boolean useFrameworkTypeInMapMultibindingContributionKey(); + /** Returns the number of bindings allowed per shard. */ public int keysPerComponentShard(XTypeElement component) { return 3500; diff --git a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java b/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java index 81380055a91..2920525ca53 100644 --- a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java +++ b/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java @@ -35,6 +35,7 @@ import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.PLUGINS_VISIT_FULL_BINDING_GRAPHS; import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.STRICT_MULTIBINDING_VALIDATION; import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.STRICT_SUPERFICIAL_VALIDATION; +import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.USE_FRAMEWORK_TYPE_IN_MAP_MULTIBINDING_CONTRIBUTION_KEY; import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES; import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.WARN_IF_INJECTION_FACTORY_NOT_GENERATED_UPSTREAM; import static dagger.internal.codegen.compileroption.ProcessingEnvironmentCompilerOptions.Feature.WRITE_PRODUCER_NAME_IN_TOKEN; @@ -189,6 +190,11 @@ public boolean experimentalDaggerErrorMessages() { return isEnabled(EXPERIMENTAL_DAGGER_ERROR_MESSAGES); } + @Override + public boolean useFrameworkTypeInMapMultibindingContributionKey() { + return isEnabled(USE_FRAMEWORK_TYPE_IN_MAP_MULTIBINDING_CONTRIBUTION_KEY); + } + @Override public boolean ignoreProvisionKeyWildcards() { return isEnabled(IGNORE_PROVISION_KEY_WILDCARDS); @@ -345,6 +351,8 @@ enum Feature implements EnumOption { GENERATED_CLASS_EXTENDS_COMPONENT, + USE_FRAMEWORK_TYPE_IN_MAP_MULTIBINDING_CONTRIBUTION_KEY, + IGNORE_PROVISION_KEY_WILDCARDS(ENABLED), VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES(ENABLED) diff --git a/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java b/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java index e7c5a44d2b5..6c11fff51e7 100644 --- a/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java +++ b/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java @@ -121,6 +121,11 @@ public boolean experimentalDaggerErrorMessages() { return false; } + @Override + public boolean useFrameworkTypeInMapMultibindingContributionKey() { + return false; + } + @Override public boolean strictMultibindingValidation() { return false; diff --git a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java index 68564b21a43..8a8ebbede5a 100644 --- a/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java +++ b/javatests/dagger/internal/codegen/MapMultibindingValidationTest.java @@ -88,7 +88,7 @@ public void duplicateMapKeys_UnwrappedMapKey() { subject -> { subject.hasErrorCount(1); subject.hasErrorContaining( - "The same map key is bound more than once for Map>") + "The same map key is bound more than once for Map") .onSource(module) .onLineContaining("class MapModule"); subject.hasErrorContaining("provideObjectForAKey()"); @@ -285,7 +285,7 @@ public void inconsistentMapKeyAnnotations() { subject -> { subject.hasErrorCount(1); subject.hasErrorContaining( - "Map> uses more than one @MapKey annotation type") + "Map uses more than one @MapKey annotation type") .onSource(module) .onLineContaining("class MapModule"); subject.hasErrorContaining("provideObjectForAKey()"); diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent index 5c9e849fe1d..2cba2e0f321 100644 --- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent @@ -111,10 +111,10 @@ final class DaggerTestComponent { case 0: // java.util.Map> return (T) ImmutableMap.>of(PathEnum.ADMIN, testComponentImpl.provideAdminHandlerProvider, PathEnum.LOGIN, testComponentImpl.provideLoginHandlerProvider); - case 1: // java.util.Map> test.MapModuleOne#provideAdminHandler + case 1: // java.util.Map test.MapModuleOne#provideAdminHandler return (T) MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(testComponentImpl.mapModuleOne); - case 2: // java.util.Map> test.MapModuleTwo#provideLoginHandler + case 2: // java.util.Map test.MapModuleTwo#provideLoginHandler return (T) MapModuleTwo_ProvideLoginHandlerFactory.provideLoginHandler(testComponentImpl.mapModuleTwo); default: throw new AssertionError(id); diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent index 4c44afc9ae6..b8bc7719881 100644 --- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent @@ -111,10 +111,10 @@ final class DaggerTestComponent { case 0: // java.util.Map> return (T) ImmutableMap.>of("Admin", testComponentImpl.provideAdminHandlerProvider, "Login", testComponentImpl.provideLoginHandlerProvider); - case 1: // java.util.Map> test.MapModuleOne#provideAdminHandler + case 1: // java.util.Map test.MapModuleOne#provideAdminHandler return (T) MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(testComponentImpl.mapModuleOne); - case 2: // java.util.Map> test.MapModuleTwo#provideLoginHandler + case 2: // java.util.Map test.MapModuleTwo#provideLoginHandler return (T) MapModuleTwo_ProvideLoginHandlerFactory.provideLoginHandler(testComponentImpl.mapModuleTwo); default: throw new AssertionError(id); diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent index 540120f6e2d..3d11ee40c2b 100644 --- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent @@ -110,16 +110,16 @@ final class DaggerTestComponent { @Override public T get() { switch (id) { - case 0: // java.util.Map> test.MapModule#provideInt + case 0: // java.util.Map test.MapModule#provideInt return (T) (Integer) MapModule.provideInt(); - case 1: // java.util.Map> test.MapModule#provideLong0 + case 1: // java.util.Map test.MapModule#provideLong0 return (T) (Long) MapModule.provideLong0(); - case 2: // java.util.Map> test.MapModule#provideLong1 + case 2: // java.util.Map test.MapModule#provideLong1 return (T) (Long) MapModule.provideLong1(); - case 3: // java.util.Map> test.MapModule#provideLong2 + case 3: // java.util.Map test.MapModule#provideLong2 return (T) (Long) MapModule.provideLong2(); default: throw new AssertionError(id); diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent index 714d91593b6..32c71550499 100644 --- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent @@ -92,13 +92,13 @@ final class DaggerTestComponent { @Override public T get() { switch (id) { - case 0: // java.util.Map> test.SubcomponentMapModule#provideLong3 + case 0: // java.util.Map test.SubcomponentMapModule#provideLong3 return (T) (Long) SubcomponentMapModule.provideLong3(); - case 1: // java.util.Map> test.SubcomponentMapModule#provideLong4 + case 1: // java.util.Map test.SubcomponentMapModule#provideLong4 return (T) (Long) SubcomponentMapModule.provideLong4(); - case 2: // java.util.Map> test.SubcomponentMapModule#provideLong5 + case 2: // java.util.Map test.SubcomponentMapModule#provideLong5 return (T) (Long) SubcomponentMapModule.provideLong5(); default: throw new AssertionError(id); @@ -181,16 +181,16 @@ final class DaggerTestComponent { @Override public T get() { switch (id) { - case 0: // java.util.Map> test.MapModule#provideInt + case 0: // java.util.Map test.MapModule#provideInt return (T) (Integer) MapModule.provideInt(); - case 1: // java.util.Map> test.MapModule#provideLong0 + case 1: // java.util.Map test.MapModule#provideLong0 return (T) (Long) MapModule.provideLong0(); - case 2: // java.util.Map> test.MapModule#provideLong1 + case 2: // java.util.Map test.MapModule#provideLong1 return (T) (Long) MapModule.provideLong1(); - case 3: // java.util.Map> test.MapModule#provideLong2 + case 3: // java.util.Map test.MapModule#provideLong2 return (T) (Long) MapModule.provideLong2(); default: throw new AssertionError(id); diff --git a/test_defs.bzl b/test_defs.bzl index 3b136261ba6..bc98fc0f87c 100644 --- a/test_defs.bzl +++ b/test_defs.bzl @@ -27,7 +27,6 @@ load( _NON_FUNCTIONAL_BUILD_VARIANTS = {None: []} _FUNCTIONAL_BUILD_VARIANTS = { None: [], # The default build variant (no javacopts). - "ExtendsComponent": ["-Adagger.generatedClassExtendsComponent=enabled"], "Shards": ["-Adagger.keysPerComponentShard=2"], "FastInit": ["-Adagger.fastInit=enabled"], "FastInit_Shards": ["-Adagger.fastInit=enabled", "-Adagger.keysPerComponentShard=2"],