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