From 5b0aa4affbee3f60e49786228201429e72af4a9c Mon Sep 17 00:00:00 2001 From: Wanying Ding Date: Mon, 22 Apr 2024 14:14:39 -0700 Subject: [PATCH] Support `@LazyClassKey` usage with dagger producers. RELNOTES=n/a PiperOrigin-RevId: 627152997 --- java/dagger/internal/LazyClassKeyMap.java | 37 ++++++++---- .../internal/codegen/javapoet/TypeNames.java | 10 +++- .../writing/MapFactoryCreationExpression.java | 20 ++++++- .../internal/LazyMapOfProducedProducer.java | 56 +++++++++++++++++++ .../internal/LazyMapOfProducerProducer.java | 56 +++++++++++++++++++ .../producers/internal/LazyMapProducer.java | 51 +++++++++++++++++ .../multibindings/MultibindingComponent.java | 7 ++- .../MultibindingProducerModule.java | 10 ++++ ...Keys_DEFAULT_MODE_test.DaggerTestComponent | 2 +- 9 files changed, 234 insertions(+), 15 deletions(-) create mode 100644 java/dagger/producers/internal/LazyMapOfProducedProducer.java create mode 100644 java/dagger/producers/internal/LazyMapOfProducerProducer.java create mode 100644 java/dagger/producers/internal/LazyMapProducer.java diff --git a/java/dagger/internal/LazyClassKeyMap.java b/java/dagger/internal/LazyClassKeyMap.java index defa3d9c7f8..3b10faf1ed8 100644 --- a/java/dagger/internal/LazyClassKeyMap.java +++ b/java/dagger/internal/LazyClassKeyMap.java @@ -111,24 +111,39 @@ public void putAll(Map, ? extends V> map) { throw new UnsupportedOperationException("Dagger map bindings are immutable"); } - // TODO(wanyingd) Support @LazyClassKey on producer - /** A factory for {@code LazyClassKeyMap}. */ - @SuppressWarnings("unchecked") - public static class Factory implements Provider, V>> { - Provider delegate; - - // MapProviderFactory or MapFactory - public static Factory of(Provider delegate) { - return new Factory(delegate); + /** Wrapper around {@link MapFactory}. */ + public static class MapFactory implements Factory, V>> { + Factory> delegate; + + public static MapFactory of(Factory> delegate) { + return new MapFactory(delegate); } - private Factory(Provider delegate) { + private MapFactory(Factory> delegate) { this.delegate = delegate; } @Override public Map, V> get() { - return LazyClassKeyMap.of((Map) delegate.get()); + return LazyClassKeyMap.of(delegate.get()); + } + } + + /** Wrapper around for {@link MapProviderFactory}. */ + public static class MapProviderFactory implements Factory, Provider>> { + Factory>> delegate; + + public static MapProviderFactory of(Factory>> delegate) { + return new MapProviderFactory(delegate); + } + + private MapProviderFactory(Factory>> delegate) { + this.delegate = delegate; + } + + @Override + public Map, Provider> get() { + return LazyClassKeyMap.of(delegate.get()); } } } diff --git a/java/dagger/internal/codegen/javapoet/TypeNames.java b/java/dagger/internal/codegen/javapoet/TypeNames.java index ea89fc033fa..930ec141828 100644 --- a/java/dagger/internal/codegen/javapoet/TypeNames.java +++ b/java/dagger/internal/codegen/javapoet/TypeNames.java @@ -61,7 +61,15 @@ public final class TypeNames { public static final ClassName LAZY_CLASS_KEY_MAP = ClassName.get("dagger.internal", "LazyClassKeyMap"); public static final ClassName LAZY_CLASS_KEY_MAP_FACTORY = - ClassName.get("dagger.internal", "LazyClassKeyMap", "Factory"); + ClassName.get("dagger.internal", "LazyClassKeyMap", "MapFactory"); + public static final ClassName LAZY_CLASS_KEY_MAP_PROVIDER_FACTORY = + ClassName.get("dagger.internal", "LazyClassKeyMap", "MapProviderFactory"); + public static final ClassName LAZY_MAP_OF_PRODUCED_PRODUCER = + ClassName.get("dagger.producers.internal", "LazyMapOfProducedProducer"); + public static final ClassName LAZY_MAP_OF_PRODUCER_PRODUCER = + ClassName.get("dagger.producers.internal", "LazyMapOfProducerProducer"); + public static final ClassName LAZY_MAP_PRODUCER = + ClassName.get("dagger.producers.internal", "LazyMapProducer"); public static final ClassName DELEGATE_FACTORY = ClassName.get("dagger.internal", "DelegateFactory"); diff --git a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java index 0ea382d1f05..b591b9e4a1e 100644 --- a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java +++ b/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java @@ -101,12 +101,30 @@ public CodeBlock creationExpression() { return useLazyClassKey ? CodeBlock.of( "$T.<$T>of($L)", - TypeNames.LAZY_CLASS_KEY_MAP_FACTORY, + lazyMapFactoryClassName(binding), valueTypeName, builder.add(".build()").build()) : builder.add(".build()").build(); } + private static ClassName lazyMapFactoryClassName(ContributionBinding binding) { + MapType mapType = MapType.from(binding.key()); + switch (binding.bindingType()) { + case PROVISION: + return mapType.valuesAreTypeOf(TypeNames.PROVIDER) + ? TypeNames.LAZY_CLASS_KEY_MAP_PROVIDER_FACTORY + : TypeNames.LAZY_CLASS_KEY_MAP_FACTORY; + case PRODUCTION: + return mapType.valuesAreFrameworkType() + ? mapType.valuesAreTypeOf(TypeNames.PRODUCER) + ? TypeNames.LAZY_MAP_OF_PRODUCER_PRODUCER + : TypeNames.LAZY_MAP_OF_PRODUCED_PRODUCER + : TypeNames.LAZY_MAP_PRODUCER; + default: + throw new IllegalArgumentException(binding.bindingType().toString()); + } + } + @AssistedFactory static interface Factory { MapFactoryCreationExpression create(ContributionBinding binding); diff --git a/java/dagger/producers/internal/LazyMapOfProducedProducer.java b/java/dagger/producers/internal/LazyMapOfProducedProducer.java new file mode 100644 index 00000000000..edc3ddb42ba --- /dev/null +++ b/java/dagger/producers/internal/LazyMapOfProducedProducer.java @@ -0,0 +1,56 @@ +/* + * 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.producers.internal; + +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import dagger.internal.LazyClassKeyMap; +import dagger.producers.Produced; +import java.util.Map; + +/** + * Wrapper around {@link MapOfProducedProducer} to be compatible with @LazyClassKey annotated map. + */ +public final class LazyMapOfProducedProducer + extends AbstractProducer, Produced>> { + AbstractProducer>> delegate; + + public static LazyMapOfProducedProducer of( + AbstractProducer>> delegate) { + return new LazyMapOfProducedProducer(delegate); + } + + private LazyMapOfProducedProducer(AbstractProducer>> delegate) { + this.delegate = delegate; + } + + @Override + public ListenableFuture, Produced>> compute() { + return Futures.transform( + delegate.compute(), + new Function>, Map, Produced>>() { + @Override + public Map, Produced> apply(Map> classMap) { + return LazyClassKeyMap.of(classMap); + } + }, + directExecutor()); + } +} diff --git a/java/dagger/producers/internal/LazyMapOfProducerProducer.java b/java/dagger/producers/internal/LazyMapOfProducerProducer.java new file mode 100644 index 00000000000..b7925574b15 --- /dev/null +++ b/java/dagger/producers/internal/LazyMapOfProducerProducer.java @@ -0,0 +1,56 @@ +/* + * 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.producers.internal; + +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import dagger.internal.LazyClassKeyMap; +import dagger.producers.Producer; +import java.util.Map; + +/** + * Wrapper around {@link MapOfProducerProducer} to be compatible with @LazyClassKey annotated map. + */ +public final class LazyMapOfProducerProducer + extends AbstractProducer, Producer>> { + AbstractProducer>> delegate; + + public static LazyMapOfProducerProducer of( + AbstractProducer>> delegate) { + return new LazyMapOfProducerProducer(delegate); + } + + private LazyMapOfProducerProducer(AbstractProducer>> delegate) { + this.delegate = delegate; + } + + @Override + public ListenableFuture, Producer>> compute() { + return Futures.transform( + delegate.compute(), + new Function>, Map, Producer>>() { + @Override + public Map, Producer> apply(Map> classMap) { + return LazyClassKeyMap.of((Map>) classMap); + } + }, + directExecutor()); + } +} diff --git a/java/dagger/producers/internal/LazyMapProducer.java b/java/dagger/producers/internal/LazyMapProducer.java new file mode 100644 index 00000000000..a09795c251d --- /dev/null +++ b/java/dagger/producers/internal/LazyMapProducer.java @@ -0,0 +1,51 @@ +/* + * 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.producers.internal; + +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import dagger.internal.LazyClassKeyMap; +import java.util.Map; + +/** Wrapper around {@link MapProducer} to be compatible with @LazyClassKey annotated map. */ +public final class LazyMapProducer extends AbstractProducer, V>> { + AbstractProducer> delegate; + + public static LazyMapProducer of(AbstractProducer> delegate) { + return new LazyMapProducer(delegate); + } + + private LazyMapProducer(AbstractProducer> delegate) { + this.delegate = delegate; + } + + @Override + public ListenableFuture, V>> compute() { + return Futures.transform( + delegate.compute(), + new Function, Map, V>>() { + @Override + public Map, V> apply(Map classMap) { + return LazyClassKeyMap.of((Map) classMap); + } + }, + directExecutor()); + } +} diff --git a/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java b/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java index 651bdf806d8..69c53b808ef 100644 --- a/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java +++ b/javatests/dagger/functional/producers/multibindings/MultibindingComponent.java @@ -29,7 +29,6 @@ import java.util.Map; import java.util.Set; - @ProductionComponent( modules = {ExecutorModule.class, MultibindingProducerModule.class, MultibindingModule.class} ) @@ -48,6 +47,12 @@ interface MultibindingComponent { ListenableFuture>> mapOfProduced(); + ListenableFuture, Produced>> lazyClassKeyMapOfProduced(); + + ListenableFuture, String>> lazyClassKeyMapOfString(); + + ListenableFuture, Producer>> lazyClassKeyMapOfProducer(); + @PossiblyThrowingMap ListenableFuture> possiblyThrowingMap(); diff --git a/javatests/dagger/functional/producers/multibindings/MultibindingProducerModule.java b/javatests/dagger/functional/producers/multibindings/MultibindingProducerModule.java index 350733b2a27..b04ae7e79f5 100644 --- a/javatests/dagger/functional/producers/multibindings/MultibindingProducerModule.java +++ b/javatests/dagger/functional/producers/multibindings/MultibindingProducerModule.java @@ -27,6 +27,7 @@ import dagger.multibindings.IntKey; import dagger.multibindings.IntoMap; import dagger.multibindings.IntoSet; +import dagger.multibindings.LazyClassKey; import dagger.multibindings.Multibinds; import dagger.producers.Produced; import dagger.producers.ProducerModule; @@ -36,6 +37,8 @@ @ProducerModule abstract class MultibindingProducerModule { + static class Foo {} + @Produces @IntoSet static ListenableFuture futureStr() { @@ -122,6 +125,13 @@ static String throwingValueFor15() { throw new RuntimeException("monkey"); } + @Produces + @IntoMap + @LazyClassKey(Foo.class) + static String produceName() { + return "foo"; + } + @Multibinds abstract Set objs(); diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent index eff6a40b8c4..0d8a4e219a1 100644 --- a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent @@ -66,7 +66,7 @@ final class DaggerTestComponent { @SuppressWarnings("unchecked") private void initialize() { - this.mapOfClassOfAndIntegerProvider = LazyClassKeyMap.Factory.of(MapFactory.builder(1).put(LazyClassKeyProvider.mapkeys_MapKeys_Inaccessible, MapModule_ClassKeyFactory.create()).build()); + this.mapOfClassOfAndIntegerProvider = LazyClassKeyMap.MapFactory.of(MapFactory.builder(1).put(LazyClassKeyProvider.mapkeys_MapKeys_Inaccessible, MapModule_ClassKeyFactory.create()).build()); this.mapOfComplexKeyAndIntegerProvider = MapFactory.builder(3).put(MapModule_ComplexKeyWithInaccessibleValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleValueFactory.create()).put(MapModule_ComplexKeyWithInaccessibleArrayValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleArrayValueFactory.create()).put(MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleAnnotationValueFactory.create()).build(); }