blob: e5a83b63c4586048c3102b5772591faad86cc8b2 [file] [log] [blame]
/*
* Copyright (C) 2020 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.hilt.processor.internal.root;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PROTECTED;
import static javax.lang.model.element.Modifier.PUBLIC;
import com.google.common.collect.ImmutableList;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.Processors;
import java.io.IOException;
import javax.annotation.processing.ProcessingEnvironment;
/** Generates an implementation of {@link dagger.hilt.android.internal.TestComponentDataSupplier} */
public final class TestComponentDataSupplierGenerator {
private static final ClassName TEST_COMPONENT_DATA_SUPPLIER_IMPL =
ClassName.get("dagger.hilt.android.internal.testing", "TestComponentDataSupplierImpl");
private static final ParameterizedTypeName CLASS_TYPE =
ParameterizedTypeName.get(ClassNames.CLASS, WildcardTypeName.subtypeOf(TypeName.OBJECT));
private static final ParameterizedTypeName TEST_COMPONENT_DATA_MAP_TYPE =
ParameterizedTypeName.get(ClassNames.MAP, CLASS_TYPE, ClassNames.TEST_COMPONENT_DATA);
private final ProcessingEnvironment processingEnv;
private final ImmutableList<RootMetadata> rootMetadatas;
public TestComponentDataSupplierGenerator(
ProcessingEnvironment processingEnv,
ImmutableList<RootMetadata> rootMetadatas) {
this.processingEnv = processingEnv;
this.rootMetadatas = rootMetadatas;
}
/**
* <pre><code>{@code
* public final class TestComponentDataSupplierImpl extends TestComponentDataSupplier {
* private final Map<Class<?>, TestComponentData> testComponentDataMap = new HashMap<>();
*
* protected TestComponentDataSupplierImpl() {
* testComponentDataMap.put(FooTest.class, new FooTest_ComponentData());
* testComponentDataMap.put(BarTest.class, new BarTest_ComponentData());
* ...
* }
*
* @Override
* protected Map<Class<?>, TestComponentData> get() {
* return testComponentDataMap;
* }
* }
* }</code></pre>
*/
public void generate() throws IOException {
TypeSpec.Builder generator =
TypeSpec.classBuilder(TEST_COMPONENT_DATA_SUPPLIER_IMPL)
.addModifiers(PUBLIC, FINAL)
.superclass(ClassNames.TEST_COMPONENT_DATA_SUPPLIER)
.addField(
FieldSpec.builder(
TEST_COMPONENT_DATA_MAP_TYPE, "testComponentDataMap", PRIVATE, FINAL)
.initializer("new $T<>($L)", ClassNames.HASH_MAP, rootMetadatas.size())
.build())
.addMethod(constructor())
.addMethod(getMethod());
Processors.addGeneratedAnnotation(
generator, processingEnv, ClassNames.ROOT_PROCESSOR.toString());
JavaFile.builder(TEST_COMPONENT_DATA_SUPPLIER_IMPL.packageName(), generator.build())
.build()
.writeTo(processingEnv.getFiler());
}
private MethodSpec constructor() {
MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
for (RootMetadata rootMetadata : rootMetadatas) {
ClassName testName = rootMetadata.testRootMetadata().testName();
ClassName testComponentDataHolderName =
Processors.append(Processors.getEnclosedClassName(testName), "_ComponentDataHolder");
constructor.addStatement(
"testComponentDataMap.put($T.class, $T.get())",
testName,
testComponentDataHolderName);
}
return constructor.build();
}
private MethodSpec getMethod() {
return MethodSpec.methodBuilder("get")
.addAnnotation(Override.class)
.addModifiers(PROTECTED)
.returns(TEST_COMPONENT_DATA_MAP_TYPE)
.addStatement("return testComponentDataMap")
.build();
}
}