Skip to content

Commit

Permalink
Migrate files in aggregateddeps to XProcessing.
Browse files Browse the repository at this point in the history
RELNOTES=n/a
PiperOrigin-RevId: 520004065
  • Loading branch information
kuanyingchou authored and Dagger Team committed Mar 28, 2023
1 parent 70f99e7 commit 023985b
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 168 deletions.
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

0 comments on commit 023985b

Please sign in to comment.