/* * Copyright (C) 2018 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.internal.codegen.validation; import static androidx.room.compiler.processing.XElementKt.isField; import static androidx.room.compiler.processing.XElementKt.isTypeElement; import static dagger.internal.codegen.base.FrameworkTypes.isFrameworkType; import static dagger.internal.codegen.base.RequestKinds.extractKeyType; import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType; import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedInjectionType; import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType; import static dagger.internal.codegen.xprocessing.XElements.asField; import static dagger.internal.codegen.xprocessing.XElements.asTypeElement; import static dagger.internal.codegen.xprocessing.XElements.getSimpleName; import static dagger.internal.codegen.xprocessing.XTypes.isDeclared; import static dagger.internal.codegen.xprocessing.XTypes.isRawParameterizedType; import static dagger.internal.codegen.xprocessing.XTypes.isTypeOf; import static dagger.internal.codegen.xprocessing.XTypes.isWildcard; import androidx.room.compiler.processing.XAnnotation; import androidx.room.compiler.processing.XElement; import androidx.room.compiler.processing.XFieldElement; import androidx.room.compiler.processing.XProcessingEnv; import androidx.room.compiler.processing.XType; import androidx.room.compiler.processing.XTypeElement; import androidx.room.compiler.processing.XVariableElement; import com.google.common.collect.ImmutableSet; import dagger.internal.codegen.base.FrameworkTypes; import dagger.internal.codegen.base.RequestKinds; import dagger.internal.codegen.binding.InjectionAnnotations; import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.kotlin.KotlinMetadataUtil; import dagger.internal.codegen.model.RequestKind; import dagger.internal.codegen.xprocessing.XTypes; import java.util.Optional; import javax.inject.Inject; /** Validation for dependency requests. */ final class DependencyRequestValidator { private final XProcessingEnv processingEnv; private final MembersInjectionValidator membersInjectionValidator; private final InjectionAnnotations injectionAnnotations; private final KotlinMetadataUtil metadataUtil; @Inject DependencyRequestValidator( XProcessingEnv processingEnv, MembersInjectionValidator membersInjectionValidator, InjectionAnnotations injectionAnnotations, KotlinMetadataUtil metadataUtil) { this.processingEnv = processingEnv; this.membersInjectionValidator = membersInjectionValidator; this.injectionAnnotations = injectionAnnotations; this.metadataUtil = metadataUtil; } /** * Adds an error if the given dependency request has more than one qualifier annotation or is a * non-instance request with a wildcard type. */ void validateDependencyRequest( ValidationReport.Builder report, XElement requestElement, XType requestType) { if (requestElement.hasAnnotation(TypeNames.ASSISTED)) { // Don't validate assisted parameters. These are not dependency requests. return; } if (missingQualifierMetadata(requestElement)) { report.addError( "Unable to read annotations on an injected Kotlin property. " + "The Dagger compiler must also be applied to any project containing @Inject " + "properties.", requestElement); // Skip any further validation if we don't have valid metadata for a type that needs it. return; } new Validator(report, requestElement, requestType).validate(); } /** * Returns {@code true} if a kotlin inject field is missing metadata about its qualifiers. * *
See https://youtrack.jetbrains.com/issue/KT-34684.
*/
private boolean missingQualifierMetadata(XElement requestElement) {
if (isField(requestElement)) {
XFieldElement fieldElement = asField(requestElement);
// static/top-level injected fields are not supported,
// so no need to get qualifier from kotlin metadata
if (!fieldElement.isStatic()
&& isTypeElement(fieldElement.getEnclosingElement())
&& metadataUtil.hasMetadata(fieldElement)
&& metadataUtil.isMissingSyntheticPropertyForAnnotations(fieldElement)) {
Optional Only call this when processing a provision binding.
*/
// TODO(dpb): Should we disallow Producer entry points in non-production components?
void checkNotProducer(ValidationReport.Builder report, XVariableElement requestElement) {
XType requestType = requestElement.getType();
if (FrameworkTypes.isProducerType(requestType)) {
report.addError(
String.format(
"%s may only be injected in @Produces methods",
getSimpleName(requestType.getTypeElement())),
requestElement);
}
}
}