• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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