Skip to content

Commit

Permalink
[WIP] Migrate the remaining Hilt processors to XProcessingStep
Browse files Browse the repository at this point in the history
RELNOTES=N/A
PiperOrigin-RevId: 539059066
  • Loading branch information
kuanyingchou authored and Dagger Team committed Jun 9, 2023
1 parent 62ade33 commit 69f3846
Show file tree
Hide file tree
Showing 19 changed files with 920 additions and 740 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2020 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dagger.hilt.android.processor.internal.androidentrypoint;

import static dagger.hilt.processor.internal.HiltCompilerOptions.getGradleProjectType;
import static dagger.hilt.processor.internal.HiltCompilerOptions.useAggregatingRootProcessor;

import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XProcessingEnv;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
import dagger.hilt.android.processor.internal.AndroidClassNames;
import dagger.hilt.processor.internal.BaseProcessingStep;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.optionvalues.GradleProjectType;

/**
* Processor that creates a module for classes marked with {@link
* dagger.hilt.android.AndroidEntryPoint}.
*/
public final class AndroidEntryPointProcessingStep extends BaseProcessingStep {
public AndroidEntryPointProcessingStep(XProcessingEnv env) {
super(env);
}

@Override
protected ImmutableSet<ClassName> annotationClassNames() {
return ImmutableSet.of(
AndroidClassNames.ANDROID_ENTRY_POINT, AndroidClassNames.HILT_ANDROID_APP);
}

@Override
public boolean delayErrors() {
return true;
}

@Override
public void processEach(ClassName annotation, XElement element) throws Exception {
AndroidEntryPointMetadata metadata = AndroidEntryPointMetadata.of(element);
new InjectorEntryPointGenerator(processingEnv(), metadata).generate();
switch (metadata.androidType()) {
case APPLICATION:
GradleProjectType projectType = getGradleProjectType(processingEnv());
if (projectType != GradleProjectType.UNSET) {
ProcessorErrors.checkState(
projectType == GradleProjectType.APP,
element,
"Application class, %s, annotated with @HiltAndroidApp must be defined in a "
+ "Gradle android application module (i.e. contains a build.gradle file with "
+ "`plugins { id 'com.android.application' }`).",
metadata.element().getQualifiedName());
}

// The generated application references the generated component so they must be generated
// in the same build unit. Thus, we only generate the application here if we're using the
// aggregating root processor. If we're using the Hilt Gradle plugin's aggregating task, we
// need to generate the application within ComponentTreeDepsProcessor instead.
if (useAggregatingRootProcessor(processingEnv())) {
// While we could always generate the application in ComponentTreeDepsProcessor, even if
// we're using the aggregating root processor, it can lead to extraneous errors when
// things fail before ComponentTreeDepsProcessor runs so we generate it here to avoid that
new ApplicationGenerator(processingEnv(), metadata).generate();
} else {
// If we're not using the aggregating root processor, then make sure the root application
// does not extend the generated application directly, and instead uses bytecode injection
ProcessorErrors.checkState(
metadata.requiresBytecodeInjection(),
metadata.element(),
"'enableAggregatingTask=true' cannot be used when the application directly "
+ "references the generated Hilt class, %s. Either extend %s directly (relying "
+ "on the Gradle plugin described in "
+ "https://dagger.dev/hilt/gradle-setup#why-use-the-plugin or set "
+ "'enableAggregatingTask=false'.",
metadata.generatedClassName(),
metadata.baseClassName());
}
break;
case ACTIVITY:
new ActivityGenerator(processingEnv(), metadata).generate();
break;
case BROADCAST_RECEIVER:
new BroadcastReceiverGenerator(processingEnv(), metadata).generate();
break;
case FRAGMENT:
new FragmentGenerator(processingEnv(), metadata).generate();
break;
case SERVICE:
new ServiceGenerator(processingEnv(), metadata).generate();
break;
case VIEW:
new ViewGenerator(processingEnv(), metadata).generate();
break;
default:
throw new IllegalStateException("Unknown Hilt type: " + metadata.androidType());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,11 @@

package dagger.hilt.android.processor.internal.androidentrypoint;

import static dagger.hilt.processor.internal.HiltCompilerOptions.getGradleProjectType;
import static dagger.hilt.processor.internal.HiltCompilerOptions.useAggregatingRootProcessor;
import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;

import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
import dagger.hilt.android.processor.internal.AndroidClassNames;
import dagger.hilt.processor.internal.BaseProcessor;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.optionvalues.GradleProjectType;
import java.util.Set;
import dagger.hilt.processor.internal.BaseProcessingStep;
import dagger.hilt.processor.internal.JavacBaseProcessingStepProcessor;
import javax.annotation.processing.Processor;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;

Expand All @@ -38,78 +30,9 @@
*/
@IncrementalAnnotationProcessor(ISOLATING)
@AutoService(Processor.class)
public final class AndroidEntryPointProcessor extends BaseProcessor {

@Override
public Set<String> getSupportedAnnotationTypes() {
return ImmutableSet.of(
AndroidClassNames.ANDROID_ENTRY_POINT.toString(),
AndroidClassNames.HILT_ANDROID_APP.toString());
}

public final class AndroidEntryPointProcessor extends JavacBaseProcessingStepProcessor {
@Override
public boolean delayErrors() {
return true;
}

@Override
public void processEach(XTypeElement annotation, XElement element) throws Exception {
AndroidEntryPointMetadata metadata = AndroidEntryPointMetadata.of(element);
new InjectorEntryPointGenerator(processingEnv(), metadata).generate();
switch (metadata.androidType()) {
case APPLICATION:
GradleProjectType projectType = getGradleProjectType(processingEnv());
if (projectType != GradleProjectType.UNSET) {
ProcessorErrors.checkState(
projectType == GradleProjectType.APP,
element,
"Application class, %s, annotated with @HiltAndroidApp must be defined in a "
+ "Gradle android application module (i.e. contains a build.gradle file with "
+ "`plugins { id 'com.android.application' }`).",
metadata.element().getQualifiedName());
}

// The generated application references the generated component so they must be generated
// in the same build unit. Thus, we only generate the application here if we're using the
// aggregating root processor. If we're using the Hilt Gradle plugin's aggregating task, we
// need to generate the application within ComponentTreeDepsProcessor instead.
if (useAggregatingRootProcessor(processingEnv())) {
// While we could always generate the application in ComponentTreeDepsProcessor, even if
// we're using the aggregating root processor, it can lead to extraneous errors when
// things fail before ComponentTreeDepsProcessor runs so we generate it here to avoid that
new ApplicationGenerator(processingEnv(), metadata).generate();
} else {
// If we're not using the aggregating root processor, then make sure the root application
// does not extend the generated application directly, and instead uses bytecode injection
ProcessorErrors.checkState(
metadata.requiresBytecodeInjection(),
metadata.element(),
"'enableAggregatingTask=true' cannot be used when the application directly "
+ "references the generated Hilt class, %s. Either extend %s directly (relying "
+ "on the Gradle plugin described in "
+ "https://dagger.dev/hilt/gradle-setup#why-use-the-plugin or set "
+ "'enableAggregatingTask=false'.",
metadata.generatedClassName(),
metadata.baseClassName());
}
break;
case ACTIVITY:
new ActivityGenerator(processingEnv(), metadata).generate();
break;
case BROADCAST_RECEIVER:
new BroadcastReceiverGenerator(processingEnv(), metadata).generate();
break;
case FRAGMENT:
new FragmentGenerator(processingEnv(), metadata).generate();
break;
case SERVICE:
new ServiceGenerator(processingEnv(), metadata).generate();
break;
case VIEW:
new ViewGenerator(processingEnv(), metadata).generate();
break;
default:
throw new IllegalStateException("Unknown Hilt type: " + metadata.androidType());
}
protected BaseProcessingStep processingStep() {
return new AndroidEntryPointProcessingStep(getXProcessingEnv());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ java_plugin(

java_library(
name = "processor_lib",
srcs = ["AndroidEntryPointProcessor.java"],
srcs = [
"AndroidEntryPointProcessingStep.java",
"AndroidEntryPointProcessor.java",
],
deps = [
":android_generators",
":metadata",
Expand All @@ -45,6 +48,7 @@ java_library(
"//third_party/java/auto:service",
"//third_party/java/guava/collect",
"//third_party/java/incap",
"//third_party/java/javapoet",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import androidx.room.compiler.processing.XAnnotation;
import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XProcessingEnv;
import androidx.room.compiler.processing.XRoundEnv;
import androidx.room.compiler.processing.XTypeElement;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -59,7 +60,7 @@ protected ImmutableSet<ClassName> annotationClassNames() {
}

@Override
protected void preProcess() {
protected void preProcess(XProcessingEnv env, XRoundEnv round) {
testRootMap.clear();
}

Expand All @@ -85,7 +86,7 @@ && asTypeElement(enclosingElement).isClass()
}

@Override
public void postProcess() throws Exception {
protected void postProcess(XProcessingEnv env, XRoundEnv round) throws Exception {
// Generate a module for each testing class with a @BindValue field.
for (Map.Entry<XTypeElement, Collection<XElement>> e : testRootMap.asMap().entrySet()) {
BindValueMetadata metadata = BindValueMetadata.create(e.getKey(), e.getValue());
Expand Down
4 changes: 1 addition & 3 deletions java/dagger/hilt/android/processor/internal/viewmodel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ kt_jvm_library(
srcs = [
"ViewModelMetadata.kt",
"ViewModelModuleGenerator.kt",
"ViewModelProcessingStep.kt",
"ViewModelProcessor.kt",
],
deps = [
Expand All @@ -39,10 +40,7 @@ kt_jvm_library(
"//java/dagger/hilt/processor/internal:processor_errors",
"//java/dagger/hilt/processor/internal:processors",
"//java/dagger/internal/codegen/xprocessing",
"//third_party/java/auto:common",
"//third_party/java/auto:service",
"//third_party/java/guava/collect",
"//third_party/java/incap",
"//third_party/java/javapoet",
],
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dagger.hilt.android.processor.internal.viewmodel

import androidx.room.compiler.processing.ExperimentalProcessingApi
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XRoundEnv
import androidx.room.compiler.processing.XTypeElement
import com.squareup.javapoet.ClassName
import dagger.hilt.android.processor.internal.AndroidClassNames
import dagger.hilt.processor.internal.BaseProcessingStep
import dagger.internal.codegen.xprocessing.XElements

@OptIn(ExperimentalProcessingApi::class)
/** Annotation processor for @ViewModelInject. */
class ViewModelProcessingStep(env: XProcessingEnv) : BaseProcessingStep(env) {
private val parsedElements = mutableSetOf<XTypeElement>()

override fun annotationClassNames(): Set<ClassName> = setOf(AndroidClassNames.HILT_VIEW_MODEL)

override fun processEach(annotation: ClassName, element: XElement) {
val typeElement = XElements.asTypeElement(element)
if (parsedElements.add(typeElement)) {
ViewModelMetadata.create(
processingEnv(),
typeElement,
)
?.let { viewModelMetadata ->
ViewModelModuleGenerator(processingEnv(), viewModelMetadata).generate()
}
}
}

override fun postProcess(env: XProcessingEnv?, round: XRoundEnv?) {
parsedElements.clear()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,17 @@
package dagger.hilt.android.processor.internal.viewmodel

import androidx.room.compiler.processing.ExperimentalProcessingApi
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XRoundEnv
import androidx.room.compiler.processing.XTypeElement
import com.google.auto.service.AutoService
import dagger.hilt.android.processor.internal.AndroidClassNames
import dagger.hilt.processor.internal.BaseProcessor
import dagger.internal.codegen.xprocessing.XElements
import dagger.hilt.processor.internal.BaseProcessingStep
import dagger.hilt.processor.internal.JavacBaseProcessingStepProcessor
import javax.annotation.processing.Processor
import javax.lang.model.SourceVersion
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType

/** Annotation processor for @ViewModelInject. */
@AutoService(Processor::class)
@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.ISOLATING)
class ViewModelProcessor : BaseProcessor() {

private val parsedElements = mutableSetOf<XTypeElement>()

override fun getSupportedAnnotationTypes() = setOf(AndroidClassNames.HILT_VIEW_MODEL.toString())

override fun getSupportedSourceVersion() = SourceVersion.latest()

class ViewModelProcessor : JavacBaseProcessingStepProcessor() {
@OptIn(ExperimentalProcessingApi::class)
override fun processEach(annotation: XTypeElement, element: XElement) {
val typeElement = XElements.asTypeElement(element)
if (parsedElements.add(typeElement)) {
ViewModelMetadata.create(
processingEnv(),
typeElement,
)
?.let { viewModelMetadata ->
ViewModelModuleGenerator(processingEnv(), viewModelMetadata).generate()
}
}
}

override fun postRoundProcess(roundEnv: XRoundEnv) {
parsedElements.clear()
}
override fun processingStep(): BaseProcessingStep = ViewModelProcessingStep(xProcessingEnv)
}

0 comments on commit 69f3846

Please sign in to comment.