dagger.hilt.android.processor.internal.customtestapplication.CustomTestApplicationMetadata Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hilt-compiler Show documentation
Show all versions of hilt-compiler Show documentation
A fast dependency injector for Android and Java.
The 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 androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XElementKt;
import androidx.room.compiler.processing.XExecutableElement;
import androidx.room.compiler.processing.XFieldElement;
import androidx.room.compiler.processing.XTypeElement;
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 dagger.internal.codegen.xprocessing.XElements;
/** Stores the metadata for a custom base test application. */
@AutoValue
abstract class CustomTestApplicationMetadata {
/** Returns the annotated element. */
abstract XTypeElement 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(element().getClassName()), "_Application");
}
static CustomTestApplicationMetadata of(XElement element) {
Preconditions.checkState(
element.hasAnnotation(ClassNames.CUSTOM_TEST_APPLICATION),
"The given element, %s, is not annotated with @%s.",
XElements.toStableString(element),
ClassNames.CUSTOM_TEST_APPLICATION.simpleName());
ProcessorErrors.checkState(
XElementKt.isTypeElement(element),
element,
"@%s should only be used on classes or interfaces but found: %s",
ClassNames.CUSTOM_TEST_APPLICATION.simpleName(),
XElements.toStableString(element));
XTypeElement baseAppElement = getBaseElement(element);
return new AutoValue_CustomTestApplicationMetadata(
XElements.asTypeElement(element), baseAppElement.getClassName());
}
private static XTypeElement getBaseElement(XElement element) {
XTypeElement baseElement =
element.getAnnotation(ClassNames.CUSTOM_TEST_APPLICATION)
.getAsType("value")
.getTypeElement();
XTypeElement baseSuperclassElement = baseElement;
while (baseSuperclassElement.getSuperClass() != null) {
ProcessorErrors.checkState(
!baseSuperclassElement.hasAnnotation(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.getClassName());
ImmutableList injectFields =
baseSuperclassElement.getDeclaredFields().stream()
.filter(field -> field.hasAnnotation(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.getClassName(),
injectFields.stream().map(XElements::toStableString).collect(toImmutableList()));
ImmutableList injectMethods =
baseSuperclassElement.getDeclaredMethods().stream()
.filter(method -> method.hasAnnotation(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.getClassName(),
injectMethods.stream().map(XElements::toStableString).collect(toImmutableList()));
ImmutableList injectConstructors =
baseSuperclassElement.getConstructors().stream()
.filter(method -> method.hasAnnotation(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.getClassName().canonicalName(),
injectConstructors.stream().map(XElements::toStableString).collect(toImmutableList()));
baseSuperclassElement = baseSuperclassElement.getSuperClass().getTypeElement();
}
// 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.getClassName());
return baseElement;
}
}