1 /*
2  * Copyright (C) 2019 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.android.processor.internal.androidentrypoint;
18 
19 import com.squareup.javapoet.ClassName;
20 import com.squareup.javapoet.JavaFile;
21 import com.squareup.javapoet.MethodSpec;
22 import com.squareup.javapoet.ParameterSpec;
23 import com.squareup.javapoet.TypeSpec;
24 import com.squareup.javapoet.TypeVariableName;
25 import dagger.hilt.android.processor.internal.AndroidClassNames;
26 import dagger.hilt.processor.internal.Processors;
27 import java.io.IOException;
28 import javax.annotation.processing.ProcessingEnvironment;
29 import javax.lang.model.element.Modifier;
30 
31 /** Generates an Hilt Activity class for the @AndroidEntryPoint annotated class. */
32 public final class ActivityGenerator {
33 
34   private final ProcessingEnvironment env;
35   private final AndroidEntryPointMetadata metadata;
36   private final ClassName generatedClassName;
37 
ActivityGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata)38   public ActivityGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
39     this.env = env;
40     this.metadata = metadata;
41 
42     generatedClassName = metadata.generatedClassName();
43   }
44 
45   // @Generated("ActivityGenerator")
46   // abstract class Hilt_$CLASS extends $BASE implements ComponentManager<?> {
47   //   ...
48   // }
generate()49   public void generate() throws IOException {
50     TypeSpec.Builder builder =
51         TypeSpec.classBuilder(generatedClassName.simpleName())
52             .addOriginatingElement(metadata.element())
53             .superclass(metadata.baseClassName())
54             .addModifiers(metadata.generatedClassModifiers());
55 
56     Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
57     Processors.addGeneratedAnnotation(builder, env, getClass());
58 
59       Generators.copyConstructors(metadata.baseElement(), builder);
60       builder.addMethod(onCreate());
61 
62 
63     metadata.baseElement().getTypeParameters().stream()
64         .map(TypeVariableName::get)
65         .forEachOrdered(builder::addTypeVariable);
66 
67     Generators.addComponentOverride(metadata, builder);
68     Generators.copyLintAnnotations(metadata.element(), builder);
69 
70     Generators.addInjectionMethods(metadata, builder);
71 
72     if (Processors.isAssignableFrom(metadata.baseElement(), AndroidClassNames.COMPONENT_ACTIVITY)
73         && !metadata.overridesAndroidEntryPointClass()) {
74       builder.addMethod(getDefaultViewModelProviderFactory());
75     }
76 
77     JavaFile.builder(generatedClassName.packageName(), builder.build())
78         .build()
79         .writeTo(env.getFiler());
80   }
81 
82   // @CallSuper
83   // @Override
84   // protected void onCreate(@Nullable Bundle savedInstanceState) {
85   //   inject();
86   //   super.onCreate(savedInstanceState);
87   // }
onCreate()88   private MethodSpec onCreate() {
89     return MethodSpec.methodBuilder("onCreate")
90         .addAnnotation(AndroidClassNames.CALL_SUPER)
91         .addAnnotation(Override.class)
92         .addModifiers(Modifier.PROTECTED)
93         .addParameter(
94             ParameterSpec.builder(AndroidClassNames.BUNDLE, "savedInstanceState")
95                 .addAnnotation(AndroidClassNames.NULLABLE)
96                 .build())
97         .addStatement("inject()")
98         .addStatement("super.onCreate(savedInstanceState)")
99         .build();
100   }
101 
102   // @Override
103   // public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
104   //   return DefaultViewModelFactories.getActivityFactory(this);
105   // }
getDefaultViewModelProviderFactory()106   private MethodSpec getDefaultViewModelProviderFactory() {
107     return MethodSpec.methodBuilder("getDefaultViewModelProviderFactory")
108         .addAnnotation(Override.class)
109         .addModifiers(Modifier.PUBLIC)
110         .returns(AndroidClassNames.VIEW_MODEL_PROVIDER_FACTORY)
111         .addStatement(
112             "return $T.getActivityFactory(this)",
113             AndroidClassNames.DEFAULT_VIEW_MODEL_FACTORIES)
114         .build();
115   }
116 }
117