1 /* 2 * Copyright (C) 2018 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; 18 19 import static com.squareup.javapoet.MethodSpec.constructorBuilder; 20 import static com.squareup.javapoet.MethodSpec.methodBuilder; 21 import static com.squareup.javapoet.TypeSpec.classBuilder; 22 import static dagger.internal.codegen.ModuleKind.checkIsModule; 23 import static dagger.internal.codegen.ModuleProxies.nonPublicNullaryConstructor; 24 import static javax.lang.model.element.Modifier.FINAL; 25 import static javax.lang.model.element.Modifier.PRIVATE; 26 import static javax.lang.model.element.Modifier.PUBLIC; 27 import static javax.lang.model.element.Modifier.STATIC; 28 29 import com.squareup.javapoet.ClassName; 30 import com.squareup.javapoet.TypeSpec; 31 import dagger.internal.codegen.langmodel.DaggerElements; 32 import java.util.Optional; 33 import javax.annotation.processing.Filer; 34 import javax.inject.Inject; 35 import javax.lang.model.SourceVersion; 36 import javax.lang.model.element.Element; 37 import javax.lang.model.element.TypeElement; 38 39 /** 40 * Generates a {@code public static} method that calls {@code new SomeModule()} for modules that 41 * don't have {@linkplain ModuleProxies#nonPublicNullaryConstructor(TypeElement, 42 * DaggerElements) publicly accessible constructors}. 43 */ 44 // TODO(dpb): See if this can become a SourceFileGenerator<ModuleDescriptor> instead. Doing so may 45 // cause ModuleProcessingStep to defer elements multiple times. 46 final class ModuleConstructorProxyGenerator extends SourceFileGenerator<TypeElement> { 47 private final DaggerElements elements; 48 49 @Inject ModuleConstructorProxyGenerator( Filer filer, DaggerElements elements, SourceVersion sourceVersion)50 ModuleConstructorProxyGenerator( 51 Filer filer, DaggerElements elements, SourceVersion sourceVersion) { 52 super(filer, elements, sourceVersion); 53 this.elements = elements; 54 } 55 56 @Override nameGeneratedType(TypeElement moduleElement)57 ClassName nameGeneratedType(TypeElement moduleElement) { 58 return ModuleProxies.constructorProxyTypeName(moduleElement); 59 } 60 61 @Override originatingElement(TypeElement moduleElement)62 Element originatingElement(TypeElement moduleElement) { 63 return moduleElement; 64 } 65 66 @Override write(ClassName generatedTypeName, TypeElement moduleElement)67 Optional<TypeSpec.Builder> write(ClassName generatedTypeName, TypeElement moduleElement) { 68 checkIsModule(moduleElement); 69 return nonPublicNullaryConstructor(moduleElement, elements).isPresent() 70 ? Optional.of(buildProxy(generatedTypeName, moduleElement)) 71 : Optional.empty(); 72 } 73 buildProxy(ClassName generatedTypeName, TypeElement moduleElement)74 private TypeSpec.Builder buildProxy(ClassName generatedTypeName, TypeElement moduleElement) { 75 return classBuilder(generatedTypeName) 76 .addModifiers(PUBLIC, FINAL) 77 .addMethod(constructorBuilder().addModifiers(PRIVATE).build()) 78 .addMethod( 79 methodBuilder("newInstance") 80 .addModifiers(PUBLIC, STATIC) 81 .returns(ClassName.get(moduleElement)) 82 .addStatement("return new $T()", moduleElement) 83 .build()); 84 } 85 } 86