Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Migrate the remaining Hilt processors to XProcessingStep #3900

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
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 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)
}