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

Migrate files in aggregateddeps to XProcessing. #3814

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
36 changes: 23 additions & 13 deletions java/dagger/hilt/processor/internal/AggregatedElements.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

package dagger.hilt.processor.internal;

import static androidx.room.compiler.processing.compat.XConverters.toJavac;
import static androidx.room.compiler.processing.compat.XConverters.toXProcessing;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
import static javax.lang.model.element.Modifier.PUBLIC;

import androidx.room.compiler.processing.XProcessingEnv;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.common.MoreElements;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
Expand All @@ -31,35 +34,34 @@
public final class AggregatedElements {

/** Returns the class name of the proxy or {@link Optional#empty()} if a proxy is not needed. */
public static Optional<ClassName> aggregatedElementProxyName(TypeElement aggregatedElement) {
if (aggregatedElement.getModifiers().contains(PUBLIC)) {
public static Optional<ClassName> aggregatedElementProxyName(XTypeElement aggregatedElement) {
if (aggregatedElement.isPublic() && !aggregatedElement.isInternal()) {
// Public aggregated elements do not have proxies.
return Optional.empty();
}
ClassName name = ClassName.get(aggregatedElement);
ClassName name = aggregatedElement.getClassName();
// To avoid going over the class name size limit, just prepend a single character.
return Optional.of(name.peerClass("_" + name.simpleName()));
}

/** Returns back the set of input {@code aggregatedElements} with all proxies unwrapped. */
public static ImmutableSet<TypeElement> unwrapProxies(
ImmutableSet<TypeElement> aggregatedElements, Elements elements) {
public static ImmutableSet<XTypeElement> unwrapProxies(
ImmutableSet<XTypeElement> aggregatedElements) {
return aggregatedElements.stream()
.map(aggregatedElement -> unwrapProxy(aggregatedElement, elements))
.map(AggregatedElements::unwrapProxy)
.collect(toImmutableSet());
}

private static TypeElement unwrapProxy(TypeElement element, Elements elements) {
return Processors.hasAnnotation(element, ClassNames.AGGREGATED_ELEMENT_PROXY)
private static XTypeElement unwrapProxy(XTypeElement element) {
return element.hasAnnotation(ClassNames.AGGREGATED_ELEMENT_PROXY)
? Processors.getAnnotationClassValue(
elements,
Processors.getAnnotationMirror(element, ClassNames.AGGREGATED_ELEMENT_PROXY),
"value")
element.getAnnotation(ClassNames.AGGREGATED_ELEMENT_PROXY), "value")
: element;
}

// TODO(kuanyingchou): Migrate this once we have suitable APIs for packages in XProcessing.
/** Returns all aggregated elements in the aggregating package after validating them. */
public static ImmutableSet<TypeElement> from(
private static ImmutableSet<TypeElement> from(
String aggregatingPackage, ClassName aggregatingAnnotation, Elements elements) {
PackageElement packageElement = elements.getPackageElement(aggregatingPackage);

Expand Down Expand Up @@ -95,5 +97,13 @@ public static ImmutableSet<TypeElement> from(
return aggregatedElements;
}

/** Returns all aggregated elements in the aggregating package after validating them. */
public static ImmutableSet<XTypeElement> from(
String aggregatingPackage, ClassName aggregatingAnnotation, XProcessingEnv env) {
return from(aggregatingPackage, aggregatingAnnotation, toJavac(env).getElementUtils()).stream()
.map(element -> toXProcessing(element, env))
.collect(toImmutableSet());
}

private AggregatedElements() {}
}
1 change: 1 addition & 0 deletions java/dagger/hilt/processor/internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ java_library(
":processor_errors",
":processors",
"//java/dagger/internal/codegen/extension",
"//java/dagger/internal/codegen/xprocessing",
"//third_party/java/auto:common",
"//third_party/java/guava/collect",
"//third_party/java/javapoet",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,18 @@
import static com.google.common.collect.Iterables.getOnlyElement;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;

import androidx.room.compiler.processing.XAnnotation;
import androidx.room.compiler.processing.XAnnotationValue;
import androidx.room.compiler.processing.XProcessingEnv;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.ClassName;
import dagger.hilt.processor.internal.AggregatedElements;
import dagger.hilt.processor.internal.AnnotationValues;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.Processors;
import dagger.hilt.processor.internal.root.ir.AggregatedDepsIr;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;

/**
* A class that represents the values stored in an {@link
Expand All @@ -52,97 +49,94 @@ enum DependencyType {
}

/** Returns the aggregating element */
public abstract TypeElement aggregatingElement();
public abstract XTypeElement aggregatingElement();

public abstract Optional<TypeElement> testElement();
public abstract Optional<XTypeElement> testElement();

public abstract ImmutableSet<TypeElement> componentElements();
public abstract ImmutableSet<XTypeElement> componentElements();

abstract DependencyType dependencyType();

public abstract TypeElement dependency();
public abstract XTypeElement dependency();

public abstract ImmutableSet<TypeElement> replacedDependencies();
public abstract ImmutableSet<XTypeElement> replacedDependencies();

public boolean isModule() {
return dependencyType() == DependencyType.MODULE;
}

/** Returns metadata for all aggregated elements in the aggregating package. */
public static ImmutableSet<AggregatedDepsMetadata> from(Elements elements) {
public static ImmutableSet<AggregatedDepsMetadata> from(XProcessingEnv env) {
return from(
AggregatedElements.from(AGGREGATED_DEPS_PACKAGE, ClassNames.AGGREGATED_DEPS, elements),
elements);
AggregatedElements.from(AGGREGATED_DEPS_PACKAGE, ClassNames.AGGREGATED_DEPS, env), env);
}

/** Returns metadata for each aggregated element. */
public static ImmutableSet<AggregatedDepsMetadata> from(
ImmutableSet<TypeElement> aggregatedElements, Elements elements) {
ImmutableSet<XTypeElement> aggregatedElements, XProcessingEnv env) {
return aggregatedElements.stream()
.map(aggregatedElement -> create(aggregatedElement, elements))
.map(aggregatedElement -> create(aggregatedElement, env))
.collect(toImmutableSet());
}

public static AggregatedDepsIr toIr(AggregatedDepsMetadata metadata) {
return new AggregatedDepsIr(
ClassName.get(metadata.aggregatingElement()),
metadata.aggregatingElement().getClassName(),
metadata.componentElements().stream()
.map(ClassName::get)
.map(XTypeElement::getClassName)
.map(ClassName::canonicalName)
.collect(Collectors.toList()),
metadata.testElement()
.map(ClassName::get)
metadata
.testElement()
.map(XTypeElement::getClassName)
.map(ClassName::canonicalName)
.orElse(null),
metadata.replacedDependencies().stream()
.map(ClassName::get)
.map(XTypeElement::getClassName)
.map(ClassName::canonicalName)
.collect(Collectors.toList()),
metadata.dependencyType() == DependencyType.MODULE
? ClassName.get(metadata.dependency()).canonicalName()
? metadata.dependency().getClassName().canonicalName()
: null,
metadata.dependencyType() == DependencyType.ENTRY_POINT
? ClassName.get(metadata.dependency()).canonicalName()
? metadata.dependency().getClassName().canonicalName()
: null,
metadata.dependencyType() == DependencyType.COMPONENT_ENTRY_POINT
? ClassName.get(metadata.dependency()).canonicalName()
? metadata.dependency().getClassName().canonicalName()
: null);
}

private static AggregatedDepsMetadata create(TypeElement element, Elements elements) {
AnnotationMirror annotationMirror =
Processors.getAnnotationMirror(element, ClassNames.AGGREGATED_DEPS);

ImmutableMap<String, AnnotationValue> values =
Processors.getAnnotationValues(elements, annotationMirror);
private static AggregatedDepsMetadata create(XTypeElement element, XProcessingEnv env) {
XAnnotation annotation = element.getAnnotation(ClassNames.AGGREGATED_DEPS);

return new AutoValue_AggregatedDepsMetadata(
element,
getTestElement(values.get("test"), elements),
getComponents(values.get("components"), elements),
getTestElement(annotation.getAnnotationValue("test"), env),
getComponents(annotation.getAnnotationValue("components"), env),
getDependencyType(
values.get("modules"), values.get("entryPoints"), values.get("componentEntryPoints")),
annotation.getAnnotationValue("modules"),
annotation.getAnnotationValue("entryPoints"),
annotation.getAnnotationValue("componentEntryPoints")),
getDependency(
values.get("modules"),
values.get("entryPoints"),
values.get("componentEntryPoints"),
elements),
getReplacedDependencies(values.get("replaces"), elements));
annotation.getAnnotationValue("modules"),
annotation.getAnnotationValue("entryPoints"),
annotation.getAnnotationValue("componentEntryPoints"),
env),
getReplacedDependencies(annotation.getAnnotationValue("replaces"), env));
}

private static Optional<TypeElement> getTestElement(
AnnotationValue testValue, Elements elements) {
private static Optional<XTypeElement> getTestElement(
XAnnotationValue testValue, XProcessingEnv env) {
checkNotNull(testValue);
String test = AnnotationValues.getString(testValue);
return test.isEmpty() ? Optional.empty() : Optional.of(elements.getTypeElement(test));
String test = testValue.asString();
return test.isEmpty() ? Optional.empty() : Optional.of(env.findTypeElement(test));
}

private static ImmutableSet<TypeElement> getComponents(
AnnotationValue componentsValue, Elements elements) {
private static ImmutableSet<XTypeElement> getComponents(
XAnnotationValue componentsValue, XProcessingEnv env) {
checkNotNull(componentsValue);
ImmutableSet<TypeElement> componentNames =
AnnotationValues.getAnnotationValues(componentsValue).stream()
.map(AnnotationValues::getString)
ImmutableSet<XTypeElement> componentNames =
componentsValue.asStringList().stream()
.map(
// This is a temporary hack to map the old ApplicationComponent to the new
// SingletonComponent. Technically, this is only needed for backwards compatibility
Expand All @@ -153,71 +147,70 @@ private static ImmutableSet<TypeElement> getComponents(
"dagger.hilt.android.components.ApplicationComponent")
? ClassNames.SINGLETON_COMPONENT.canonicalName()
: componentName)
.map(elements::getTypeElement)
.map(env::requireTypeElement)
.collect(toImmutableSet());
checkState(!componentNames.isEmpty());
return componentNames;
}

private static DependencyType getDependencyType(
AnnotationValue modulesValue,
AnnotationValue entryPointsValue,
AnnotationValue componentEntryPointsValue) {
XAnnotationValue modulesValue,
XAnnotationValue entryPointsValue,
XAnnotationValue componentEntryPointsValue) {
checkNotNull(modulesValue);
checkNotNull(entryPointsValue);
checkNotNull(componentEntryPointsValue);

ImmutableSet.Builder<DependencyType> dependencyTypes = ImmutableSet.builder();
if (!AnnotationValues.getAnnotationValues(modulesValue).isEmpty()) {
if (!modulesValue.asAnnotationValueList().isEmpty()) {
dependencyTypes.add(DependencyType.MODULE);
}
if (!AnnotationValues.getAnnotationValues(entryPointsValue).isEmpty()) {
if (!entryPointsValue.asAnnotationValueList().isEmpty()) {
dependencyTypes.add(DependencyType.ENTRY_POINT);
}
if (!AnnotationValues.getAnnotationValues(componentEntryPointsValue).isEmpty()) {
if (!componentEntryPointsValue.asAnnotationValueList().isEmpty()) {
dependencyTypes.add(DependencyType.COMPONENT_ENTRY_POINT);
}
return getOnlyElement(dependencyTypes.build());
}

private static TypeElement getDependency(
AnnotationValue modulesValue,
AnnotationValue entryPointsValue,
AnnotationValue componentEntryPointsValue,
Elements elements) {
private static XTypeElement getDependency(
XAnnotationValue modulesValue,
XAnnotationValue entryPointsValue,
XAnnotationValue componentEntryPointsValue,
XProcessingEnv env) {
checkNotNull(modulesValue);
checkNotNull(entryPointsValue);
checkNotNull(componentEntryPointsValue);

String dependencyName =
AnnotationValues.getString(
getOnlyElement(
ImmutableSet.<AnnotationValue>builder()
.addAll(AnnotationValues.getAnnotationValues(modulesValue))
.addAll(AnnotationValues.getAnnotationValues(entryPointsValue))
.addAll(AnnotationValues.getAnnotationValues(componentEntryPointsValue))
.build()));
TypeElement dependency = elements.getTypeElement(dependencyName);
getOnlyElement(
ImmutableSet.<XAnnotationValue>builder()
.addAll(modulesValue.asAnnotationValueList())
.addAll(entryPointsValue.asAnnotationValueList())
.addAll(componentEntryPointsValue.asAnnotationValueList())
.build())
.asString();
XTypeElement dependency = env.findTypeElement(dependencyName);
checkNotNull(dependency, "Could not get element for %s", dependencyName);
return dependency;
}

private static ImmutableSet<TypeElement> getReplacedDependencies(
AnnotationValue replacedDependenciesValue, Elements elements) {
private static ImmutableSet<XTypeElement> getReplacedDependencies(
XAnnotationValue replacedDependenciesValue, XProcessingEnv env) {
// Allow null values to support libraries using a Hilt version before @TestInstallIn was added
return replacedDependenciesValue == null
? ImmutableSet.of()
: AnnotationValues.getAnnotationValues(replacedDependenciesValue).stream()
.map(AnnotationValues::getString)
.map(elements::getTypeElement)
.map(replacedDep -> getPublicDependency(replacedDep, elements))
: replacedDependenciesValue.asStringList().stream()
.map(env::requireTypeElement)
.map(replacedDep -> getPublicDependency(replacedDep, env))
.collect(toImmutableSet());
}

/** Returns the public Hilt wrapper module, or the module itself if its already public. */
private static TypeElement getPublicDependency(TypeElement dependency, Elements elements) {
return PkgPrivateMetadata.of(elements, dependency, ClassNames.MODULE)
.map(metadata -> elements.getTypeElement(metadata.generatedClassName().toString()))
private static XTypeElement getPublicDependency(XTypeElement dependency, XProcessingEnv env) {
return PkgPrivateMetadata.of(dependency, ClassNames.MODULE)
.map(metadata -> env.requireTypeElement(metadata.generatedClassName().toString()))
.orElse(dependency);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ private void generateAggregatedDeps(
ImmutableSet<ClassName> components = Components.getComponents(element);

if (isValidKind(element)) {
Optional<PkgPrivateMetadata> pkgPrivateMetadata =
PkgPrivateMetadata.of(processingEnv(), element, annotation);
Optional<PkgPrivateMetadata> pkgPrivateMetadata = PkgPrivateMetadata.of(element, annotation);
if (pkgPrivateMetadata.isPresent()) {
if (key.contentEquals("modules")) {
new PkgPrivateModuleGenerator(processingEnv(), pkgPrivateMetadata.get()).generate();
Expand Down
1 change: 1 addition & 0 deletions java/dagger/hilt/processor/internal/aggregateddeps/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ java_library(
"//java/dagger/hilt/processor/internal/root/ir",
"//java/dagger/hilt/processor/internal/uninstallmodules:aggregated_uninstall_modules_metadata",
"//java/dagger/internal/codegen/extension",
"//java/dagger/internal/codegen/xprocessing",
"//third_party/java/auto:value",
"//third_party/java/guava/base",
"//third_party/java/guava/collect",
Expand Down