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

dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationMetadata Maven / Gradle / Ivy

There is a newer version: 2.45-kim-rc1
Show newest version
/*
 * 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.customtestapplication;

import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;

import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.squareup.javapoet.ClassName;
import dagger.hilt.processor.internal.ClassNames;
import dagger.hilt.processor.internal.ProcessorErrors;
import dagger.hilt.processor.internal.Processors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;

/** Stores the metadata for a custom base test application. */
@AutoValue
abstract class CustomTestApplicationMetadata {
  /** Returns the annotated element. */
  abstract TypeElement element();

  /** Returns the name of the base application. */
  abstract ClassName baseAppName();

  /** Returns the name of the generated application */
  ClassName appName() {
    return Processors.append(
        Processors.getEnclosedClassName(ClassName.get(element())), "_Application");
  }

  static CustomTestApplicationMetadata of(Element element, Elements elements) {
    Preconditions.checkState(
        Processors.hasAnnotation(element, ClassNames.CUSTOM_TEST_APPLICATION),
        "The given element, %s, is not annotated with @%s.",
        element,
        ClassNames.CUSTOM_TEST_APPLICATION.simpleName());

    ProcessorErrors.checkState(
        MoreElements.isType(element),
        element,
        "@%s should only be used on classes or interfaces but found: %s",
        ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
        element);

    TypeElement baseAppElement = getBaseElement(element, elements);

    return new AutoValue_CustomTestApplicationMetadata(
        MoreElements.asType(element), ClassName.get(baseAppElement));
  }

  private static TypeElement getBaseElement(Element element, Elements elements) {
    TypeElement baseElement =
        Processors.getAnnotationClassValue(
            elements,
            Processors.getAnnotationMirror(element, ClassNames.CUSTOM_TEST_APPLICATION),
            "value");

    TypeElement baseSuperclassElement = baseElement;
    while (!baseSuperclassElement.getSuperclass().getKind().equals(TypeKind.NONE)) {
      ProcessorErrors.checkState(
          !Processors.hasAnnotation(baseSuperclassElement, ClassNames.HILT_ANDROID_APP),
          element,
          "@%s value cannot be annotated with @%s. Found: %s",
          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
          ClassNames.HILT_ANDROID_APP.simpleName(),
          baseSuperclassElement);

      ImmutableList injectFields =
          ElementFilter.fieldsIn(baseSuperclassElement.getEnclosedElements()).stream()
              .filter(field -> Processors.hasAnnotation(field, ClassNames.INJECT))
              .collect(toImmutableList());
      ProcessorErrors.checkState(
          injectFields.isEmpty(),
          element,
          "@%s does not support application classes (or super classes) with @Inject fields. Found "
              + "%s with @Inject fields %s.",
          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
          baseSuperclassElement,
          injectFields);

      ImmutableList injectMethods =
          ElementFilter.methodsIn(baseSuperclassElement.getEnclosedElements()).stream()
              .filter(method -> Processors.hasAnnotation(method, ClassNames.INJECT))
              .collect(toImmutableList());
      ProcessorErrors.checkState(
          injectMethods.isEmpty(),
          element,
          "@%s does not support application classes (or super classes) with @Inject methods. Found "
              + "%s with @Inject methods %s.",
          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
          baseSuperclassElement,
          injectMethods);

      ImmutableList injectConstructors =
          ElementFilter.constructorsIn(baseSuperclassElement.getEnclosedElements()).stream()
              .filter(method -> Processors.hasAnnotation(method, ClassNames.INJECT))
              .collect(toImmutableList());
      ProcessorErrors.checkState(
          injectConstructors.isEmpty(),
          element,
          "@%s does not support application classes (or super classes) with @Inject constructors. "
              + "Found %s with @Inject constructors %s.",
          ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
          baseSuperclassElement,
          injectConstructors);

      baseSuperclassElement = MoreTypes.asTypeElement(baseSuperclassElement.getSuperclass());
    }

    // We check this last because if the base type is a @HiltAndroidApp we'd accidentally fail
    // with this message instead of the one above when the superclass hasn't yet been generated.
    ProcessorErrors.checkState(
        Processors.isAssignableFrom(baseElement, ClassNames.APPLICATION),
        element,
        "@%s value should be an instance of %s. Found: %s",
        ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
        ClassNames.APPLICATION,
        baseElement);

    return baseElement;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy