• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 static dagger.hilt.processor.internal.HiltCompilerOptions.getGradleProjectType;
20 import static dagger.hilt.processor.internal.HiltCompilerOptions.useAggregatingRootProcessor;
21 
22 import androidx.room.compiler.processing.XElement;
23 import androidx.room.compiler.processing.XProcessingEnv;
24 import com.google.common.collect.ImmutableSet;
25 import com.squareup.javapoet.ClassName;
26 import dagger.hilt.android.processor.internal.AndroidClassNames;
27 import dagger.hilt.processor.internal.BaseProcessingStep;
28 import dagger.hilt.processor.internal.ProcessorErrors;
29 import dagger.hilt.processor.internal.optionvalues.GradleProjectType;
30 
31 /**
32  * Processor that creates a module for classes marked with {@link
33  * dagger.hilt.android.AndroidEntryPoint}.
34  */
35 public final class AndroidEntryPointProcessingStep extends BaseProcessingStep {
AndroidEntryPointProcessingStep(XProcessingEnv env)36   public AndroidEntryPointProcessingStep(XProcessingEnv env) {
37     super(env);
38   }
39 
40   @Override
annotationClassNames()41   protected ImmutableSet<ClassName> annotationClassNames() {
42     return ImmutableSet.of(
43         AndroidClassNames.ANDROID_ENTRY_POINT, AndroidClassNames.HILT_ANDROID_APP);
44   }
45 
46   @Override
delayErrors()47   public boolean delayErrors() {
48     return true;
49   }
50 
51   @Override
processEach(ClassName annotation, XElement element)52   public void processEach(ClassName annotation, XElement element) throws Exception {
53     AndroidEntryPointMetadata metadata = AndroidEntryPointMetadata.of(element);
54     new InjectorEntryPointGenerator(processingEnv(), metadata).generate();
55     switch (metadata.androidType()) {
56       case APPLICATION:
57         GradleProjectType projectType = getGradleProjectType(processingEnv());
58         if (projectType != GradleProjectType.UNSET) {
59           ProcessorErrors.checkState(
60               projectType == GradleProjectType.APP,
61               element,
62               "Application class, %s, annotated with @HiltAndroidApp must be defined in a "
63                   + "Gradle android application module (i.e. contains a build.gradle file with "
64                   + "`plugins { id 'com.android.application' }`).",
65               metadata.element().getQualifiedName());
66         }
67 
68         // The generated application references the generated component so they must be generated
69         // in the same build unit. Thus, we only generate the application here if we're using the
70         // aggregating root processor. If we're using the Hilt Gradle plugin's aggregating task, we
71         // need to generate the application within ComponentTreeDepsProcessor instead.
72         if (useAggregatingRootProcessor(processingEnv())) {
73           // While we could always generate the application in ComponentTreeDepsProcessor, even if
74           // we're using the aggregating root processor, it can lead to extraneous errors when
75           // things fail before ComponentTreeDepsProcessor runs so we generate it here to avoid that
76           new ApplicationGenerator(processingEnv(), metadata).generate();
77         } else {
78           // If we're not using the aggregating root processor, then make sure the root application
79           // does not extend the generated application directly, and instead uses bytecode injection
80           ProcessorErrors.checkState(
81               metadata.requiresBytecodeInjection(),
82               metadata.element(),
83               "'enableAggregatingTask=true' cannot be used when the application directly "
84                   + "references the generated Hilt class, %s. Either extend %s directly (relying "
85                   + "on the Gradle plugin described in "
86                   + "https://dagger.dev/hilt/gradle-setup#why-use-the-plugin or set "
87                   + "'enableAggregatingTask=false'.",
88               metadata.generatedClassName(),
89               metadata.baseClassName());
90         }
91         break;
92       case ACTIVITY:
93         new ActivityGenerator(processingEnv(), metadata).generate();
94         break;
95       case BROADCAST_RECEIVER:
96         new BroadcastReceiverGenerator(processingEnv(), metadata).generate();
97         break;
98       case FRAGMENT:
99         new FragmentGenerator(processingEnv(), metadata).generate();
100         break;
101       case SERVICE:
102         new ServiceGenerator(processingEnv(), metadata).generate();
103         break;
104       case VIEW:
105         new ViewGenerator(processingEnv(), metadata).generate();
106         break;
107     }
108   }
109 }
110