• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.internal.codegen.writing;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static dagger.internal.codegen.binding.MapKeys.getMapKeyExpression;
21 import static dagger.internal.codegen.binding.SourceFiles.mapFactoryClassName;
22 import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
23 
24 import androidx.room.compiler.processing.XProcessingEnv;
25 import com.squareup.javapoet.ClassName;
26 import com.squareup.javapoet.CodeBlock;
27 import com.squareup.javapoet.TypeName;
28 import dagger.assisted.Assisted;
29 import dagger.assisted.AssistedFactory;
30 import dagger.assisted.AssistedInject;
31 import dagger.internal.codegen.base.MapType;
32 import dagger.internal.codegen.binding.BindingGraph;
33 import dagger.internal.codegen.binding.ContributionBinding;
34 import dagger.internal.codegen.binding.MapKeys;
35 import dagger.internal.codegen.javapoet.TypeNames;
36 import dagger.internal.codegen.model.DependencyRequest;
37 import java.util.stream.Stream;
38 
39 /** A factory creation expression for a multibound map. */
40 final class MapFactoryCreationExpression extends MultibindingFactoryCreationExpression {
41 
42   private final XProcessingEnv processingEnv;
43   private final ComponentImplementation componentImplementation;
44   private final BindingGraph graph;
45   private final ContributionBinding binding;
46   private final boolean useLazyClassKey;
47   private final LazyClassKeyProviders lazyClassKeyProviders;
48 
49   @AssistedInject
MapFactoryCreationExpression( @ssisted ContributionBinding binding, XProcessingEnv processingEnv, ComponentImplementation componentImplementation, ComponentRequestRepresentations componentRequestRepresentations, BindingGraph graph)50   MapFactoryCreationExpression(
51       @Assisted ContributionBinding binding,
52       XProcessingEnv processingEnv,
53       ComponentImplementation componentImplementation,
54       ComponentRequestRepresentations componentRequestRepresentations,
55       BindingGraph graph) {
56     super(binding, componentImplementation, componentRequestRepresentations);
57     this.processingEnv = processingEnv;
58     this.binding = checkNotNull(binding);
59     this.componentImplementation = componentImplementation;
60     this.graph = graph;
61     this.useLazyClassKey = MapKeys.useLazyClassKey(binding, graph);
62     this.lazyClassKeyProviders =
63         componentImplementation.shardImplementation(binding).getLazyClassKeyProviders();
64   }
65 
66   @Override
creationExpression()67   public CodeBlock creationExpression() {
68     ClassName mapFactoryClassName = mapFactoryClassName(binding);
69     CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName);
70     TypeName valueTypeName = TypeName.OBJECT;
71     if (!useRawType()) {
72       MapType mapType = MapType.from(binding.key());
73       // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
74       // mapType.unwrappedValueType() method that doesn't require a framework type
75       valueTypeName =
76           Stream.of(TypeNames.PROVIDER, TypeNames.PRODUCER, TypeNames.PRODUCED)
77               .filter(mapType::valuesAreTypeOf)
78               .map(mapType::unwrappedValueType)
79               .collect(toOptional())
80               .orElseGet(mapType::valueType)
81               .getTypeName();
82       builder.add(
83           "<$T, $T>",
84           useLazyClassKey ? TypeNames.STRING : mapType.keyType().getTypeName(),
85           valueTypeName);
86     }
87 
88     builder.add("builder($L)", binding.dependencies().size());
89 
90     for (DependencyRequest dependency : binding.dependencies()) {
91       ContributionBinding contributionBinding = graph.contributionBinding(dependency.key());
92       builder.add(
93           ".put($L, $L)",
94           useLazyClassKey
95               ? lazyClassKeyProviders.getMapKeyExpression(dependency.key())
96               : getMapKeyExpression(
97                   contributionBinding, componentImplementation.name(), processingEnv),
98           multibindingDependencyExpression(dependency));
99     }
100 
101     return useLazyClassKey
102         ? CodeBlock.of(
103             "$T.<$T>of($L)",
104             TypeNames.LAZY_CLASS_KEY_MAP_FACTORY,
105             valueTypeName,
106             builder.add(".build()").build())
107         : builder.add(".build()").build();
108   }
109 
110   @AssistedFactory
111   static interface Factory {
create(ContributionBinding binding)112     MapFactoryCreationExpression create(ContributionBinding binding);
113   }
114 }
115