All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dagger.hilt.processor.internal.root.ComponentTreeDepsGenerator Maven / Gradle / Ivy

There is a newer version: 2.45-kim-rc1
Show newest version
/*
 * Copyright (C) 2021 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.processor.internal.root;

import static javax.lang.model.element.Modifier.PUBLIC;

import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import dagger.hilt.processor.internal.AggregatedElements;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.Processors;
import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;

/** Generates an {@link dagger.hilt.internal.componenttreedeps.ComponentTreeDeps}. */
final class ComponentTreeDepsGenerator {
  // Keeps track of already generated proxies. For correctness, this same instance of
  // ComponentTreeDepsGenerator must be used for a given round.
  private final Set generatedProxies = new HashSet<>();
  private final ProcessingEnvironment env;

  ComponentTreeDepsGenerator(ProcessingEnvironment env) {
    this.env = env;
  }

  void generate(ComponentTreeDepsMetadata metadata) throws IOException {
    ClassName name = metadata.name();
    TypeSpec.Builder builder =
        TypeSpec.classBuilder(name)
            // No originating element since this is generated by the aggregating processor.
            .addAnnotation(componentTreeDepsAnnotation(metadata));

    Processors.addGeneratedAnnotation(builder, env, ClassNames.ROOT_PROCESSOR.toString());

    JavaFile.builder(name.packageName(), builder.build()).build().writeTo(env.getFiler());
  }

  AnnotationSpec componentTreeDepsAnnotation(ComponentTreeDepsMetadata metadata)
      throws IOException {
    AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassNames.COMPONENT_TREE_DEPS);
    addDeps(builder, metadata.aggregatedRootDeps(), "rootDeps");
    addDeps(builder, metadata.defineComponentDeps(), "defineComponentDeps");
    addDeps(builder, metadata.aliasOfDeps(), "aliasOfDeps");
    addDeps(builder, metadata.aggregatedDeps(), "aggregatedDeps");
    addDeps(builder, metadata.aggregatedUninstallModulesDeps(), "uninstallModulesDeps");
    addDeps(builder, metadata.aggregatedEarlyEntryPointDeps(), "earlyEntryPointDeps");
    return builder.build();
  }

  private void addDeps(AnnotationSpec.Builder builder, ImmutableSet deps, String name)
      throws IOException {
    for (TypeElement dep : deps) {
      builder.addMember(name, "$T.class", maybeWrapInPublicProxy(dep));
    }
  }

  /**
   * This method will return the public proxy for {@code dep} if it is not public, otherwise it will
   * return {@code dep} itself. It will also generate the proxy if it doesn't already exist.
   *
   * 

Note: These proxies are only used for serialization. The proxy will be unwrapped when * converting to {@link ComponentTreeDepsMetadata}. * *

Note: The public proxy is needed because Hilt versions < 2.35 generated package-private * aggregating elements, which can't be referenced directly in the {@code @ComponentTreeDeps}. */ private ClassName maybeWrapInPublicProxy(TypeElement dep) throws IOException { Optional proxyName = AggregatedElements.aggregatedElementProxyName(dep); if (proxyName.isPresent()) { // Check the set of already generated proxies to ensure we don't regenerate the proxy in // this round. Also check that the element doesn't already exist to ensure we don't regenerate // a proxy generated in a previous round. if (generatedProxies.add(proxyName.get()) && env.getElementUtils().getTypeElement(proxyName.get().canonicalName()) == null) { generateProxy(dep, proxyName.get()); } return proxyName.get(); } return ClassName.get(dep); } private void generateProxy(TypeElement dep, ClassName proxyName) throws IOException { TypeSpec.Builder builder = TypeSpec.classBuilder(proxyName) .addModifiers(PUBLIC) // No originating element since this is generated by the aggregating processor. .addAnnotation( AnnotationSpec.builder(ClassNames.AGGREGATED_ELEMENT_PROXY) .addMember("value", "$T.class", dep) .build()); Processors.addGeneratedAnnotation(builder, env, ClassNames.ROOT_PROCESSOR.toString()); JavaFile.builder(proxyName.packageName(), builder.build()).build().writeTo(env.getFiler()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy