• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.hilt.processor.internal.root;
18 
19 import static javax.lang.model.element.Modifier.FINAL;
20 import static javax.lang.model.element.Modifier.PRIVATE;
21 import static javax.lang.model.element.Modifier.PROTECTED;
22 import static javax.lang.model.element.Modifier.PUBLIC;
23 
24 import com.google.common.collect.ImmutableList;
25 import com.squareup.javapoet.ClassName;
26 import com.squareup.javapoet.FieldSpec;
27 import com.squareup.javapoet.JavaFile;
28 import com.squareup.javapoet.MethodSpec;
29 import com.squareup.javapoet.ParameterizedTypeName;
30 import com.squareup.javapoet.TypeName;
31 import com.squareup.javapoet.TypeSpec;
32 import com.squareup.javapoet.WildcardTypeName;
33 import dagger.hilt.processor.internal.ClassNames;
34 import dagger.hilt.processor.internal.Processors;
35 import java.io.IOException;
36 import javax.annotation.processing.ProcessingEnvironment;
37 
38 /** Generates an implementation of {@link dagger.hilt.android.internal.TestComponentDataSupplier} */
39 public final class TestComponentDataSupplierGenerator {
40   private static final ClassName TEST_COMPONENT_DATA_SUPPLIER_IMPL =
41       ClassName.get("dagger.hilt.android.internal.testing", "TestComponentDataSupplierImpl");
42   private static final ParameterizedTypeName CLASS_TYPE =
43       ParameterizedTypeName.get(ClassNames.CLASS, WildcardTypeName.subtypeOf(TypeName.OBJECT));
44   private static final ParameterizedTypeName TEST_COMPONENT_DATA_MAP_TYPE =
45       ParameterizedTypeName.get(ClassNames.MAP, CLASS_TYPE, ClassNames.TEST_COMPONENT_DATA);
46 
47   private final ProcessingEnvironment processingEnv;
48   private final ImmutableList<RootMetadata> rootMetadatas;
49 
TestComponentDataSupplierGenerator( ProcessingEnvironment processingEnv, ImmutableList<RootMetadata> rootMetadatas)50   public TestComponentDataSupplierGenerator(
51       ProcessingEnvironment processingEnv,
52       ImmutableList<RootMetadata> rootMetadatas) {
53     this.processingEnv = processingEnv;
54     this.rootMetadatas = rootMetadatas;
55   }
56 
57   /**
58    * <pre><code>{@code
59    * public final class TestComponentDataSupplierImpl extends TestComponentDataSupplier {
60    *   private final Map<Class<?>, TestComponentData> testComponentDataMap = new HashMap<>();
61    *
62    *   protected TestComponentDataSupplierImpl() {
63    *     testComponentDataMap.put(FooTest.class, new FooTest_ComponentData());
64    *     testComponentDataMap.put(BarTest.class, new BarTest_ComponentData());
65    *     ...
66    *   }
67    *
68    *   @Override
69    *   protected Map<Class<?>, TestComponentData> get() {
70    *     return testComponentDataMap;
71    *   }
72    * }
73    * }</code></pre>
74    */
generate()75   public void generate() throws IOException {
76     TypeSpec.Builder generator =
77         TypeSpec.classBuilder(TEST_COMPONENT_DATA_SUPPLIER_IMPL)
78             .addModifiers(PUBLIC, FINAL)
79             .superclass(ClassNames.TEST_COMPONENT_DATA_SUPPLIER)
80             .addField(
81                 FieldSpec.builder(
82                         TEST_COMPONENT_DATA_MAP_TYPE, "testComponentDataMap", PRIVATE, FINAL)
83                     .initializer("new $T<>($L)", ClassNames.HASH_MAP, rootMetadatas.size())
84                     .build())
85             .addMethod(constructor())
86             .addMethod(getMethod());
87 
88     Processors.addGeneratedAnnotation(
89         generator, processingEnv, ClassNames.ROOT_PROCESSOR.toString());
90 
91     JavaFile.builder(TEST_COMPONENT_DATA_SUPPLIER_IMPL.packageName(), generator.build())
92         .build()
93         .writeTo(processingEnv.getFiler());
94   }
95 
96 
constructor()97   private MethodSpec constructor() {
98     MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
99     for (RootMetadata rootMetadata : rootMetadatas) {
100       ClassName testName = rootMetadata.testRootMetadata().testName();
101       ClassName testComponentDataHolderName =
102           Processors.append(Processors.getEnclosedClassName(testName), "_ComponentDataHolder");
103       constructor.addStatement(
104           "testComponentDataMap.put($T.class, $T.get())",
105           testName,
106           testComponentDataHolderName);
107     }
108     return constructor.build();
109   }
110 
getMethod()111   private MethodSpec getMethod() {
112     return MethodSpec.methodBuilder("get")
113         .addAnnotation(Override.class)
114         .addModifiers(PROTECTED)
115         .returns(TEST_COMPONENT_DATA_MAP_TYPE)
116         .addStatement("return testComponentDataMap")
117         .build();
118   }
119 }
120