• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.CodeBlock;
21 import com.squareup.javapoet.JavaFile;
22 import com.squareup.javapoet.MethodSpec;
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   private final ProcessingEnvironment env;
34   private final AndroidEntryPointMetadata metadata;
35   private final ClassName generatedClassName;
36 
ActivityGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata)37   public ActivityGenerator(ProcessingEnvironment env, AndroidEntryPointMetadata metadata) {
38     this.env = env;
39     this.metadata = metadata;
40 
41     generatedClassName = metadata.generatedClassName();
42   }
43 
44   // @Generated("ActivityGenerator")
45   // abstract class Hilt_$CLASS extends $BASE implements ComponentManager<?> {
46   //   ...
47   // }
generate()48   public void generate() throws IOException {
49     TypeSpec.Builder builder =
50         TypeSpec.classBuilder(generatedClassName.simpleName())
51             .addOriginatingElement(metadata.element())
52             .superclass(metadata.baseClassName())
53             .addModifiers(metadata.generatedClassModifiers());
54 
55     Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
56     Processors.addGeneratedAnnotation(builder, env, getClass());
57 
58       Generators.copyConstructors(
59           metadata.baseElement(),
60           CodeBlock.builder().addStatement("_initHiltInternal()").build(),
61           builder);
62       builder.addMethod(init());
63 
64     metadata.baseElement().getTypeParameters().stream()
65         .map(TypeVariableName::get)
66         .forEachOrdered(builder::addTypeVariable);
67 
68     Generators.addComponentOverride(metadata, builder);
69     Generators.copyLintAnnotations(metadata.element(), builder);
70     Generators.copySuppressAnnotations(metadata.element(), builder);
71 
72     Generators.addInjectionMethods(metadata, builder);
73 
74     if (Processors.isAssignableFrom(metadata.baseElement(), AndroidClassNames.COMPONENT_ACTIVITY)
75         && !metadata.overridesAndroidEntryPointClass()) {
76       builder.addMethod(getDefaultViewModelProviderFactory());
77     }
78 
79     JavaFile.builder(generatedClassName.packageName(), builder.build())
80         .build()
81         .writeTo(env.getFiler());
82   }
83 
84   // private void init() {
85   //   addOnContextAvailableListener(new OnContextAvailableListener() {
86   //     @Override
87   //     public void onContextAvailable(Context context) {
88   //       inject();
89   //     }
90   //   });
91   // }
init()92   private MethodSpec init() {
93     return MethodSpec.methodBuilder("_initHiltInternal")
94         .addModifiers(Modifier.PRIVATE)
95         .addStatement(
96             "addOnContextAvailableListener($L)",
97             TypeSpec.anonymousClassBuilder("")
98                 .addSuperinterface(AndroidClassNames.ON_CONTEXT_AVAILABLE_LISTENER)
99                 .addMethod(
100                     MethodSpec.methodBuilder("onContextAvailable")
101                         .addAnnotation(Override.class)
102                         .addModifiers(Modifier.PUBLIC)
103                         .addParameter(AndroidClassNames.CONTEXT, "context")
104                         .addStatement("inject()")
105                         .build())
106                 .build())
107         .build();
108   }
109 
110   // @Override
111   // public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
112   //   return DefaultViewModelFactories.getActivityFactory(
113   //       this, super.getDefaultViewModelProviderFactory());
114   // }
getDefaultViewModelProviderFactory()115   private MethodSpec getDefaultViewModelProviderFactory() {
116     MethodSpec.Builder builder = MethodSpec.methodBuilder("getDefaultViewModelProviderFactory")
117         .addAnnotation(Override.class)
118         .addModifiers(Modifier.PUBLIC)
119         .returns(AndroidClassNames.VIEW_MODEL_PROVIDER_FACTORY);
120 
121     if (metadata.allowsOptionalInjection()) {
122       builder
123           .beginControlFlow("if (!optionalInjectParentUsesHilt(optionalInjectGetParent()))")
124           .addStatement("return super.getDefaultViewModelProviderFactory()")
125           .endControlFlow();
126     }
127 
128     return builder
129         .addStatement(
130             "return $T.getActivityFactory(this, super.getDefaultViewModelProviderFactory())",
131             AndroidClassNames.DEFAULT_VIEW_MODEL_FACTORIES)
132         .build();
133   }
134 }
135