1 /* 2 * Copyright (C) 2016 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.internal.codegen.validation; 18 19 import static com.google.auto.common.MoreTypes.asTypeElement; 20 import static dagger.internal.codegen.base.Keys.isValidImplicitProvisionKey; 21 import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors; 22 import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS; 23 import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING; 24 import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT; 25 import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS; 26 27 import com.google.common.collect.ImmutableSet; 28 import dagger.BindsOptionalOf; 29 import dagger.Module; 30 import dagger.internal.codegen.binding.InjectionAnnotations; 31 import dagger.internal.codegen.kotlin.KotlinMetadataUtil; 32 import dagger.internal.codegen.langmodel.DaggerElements; 33 import dagger.internal.codegen.langmodel.DaggerTypes; 34 import dagger.producers.ProducerModule; 35 import javax.inject.Inject; 36 import javax.lang.model.element.ExecutableElement; 37 import javax.lang.model.type.TypeMirror; 38 39 /** A validator for {@link BindsOptionalOf} methods. */ 40 final class BindsOptionalOfMethodValidator extends BindingMethodValidator { 41 42 private final DaggerTypes types; 43 private final InjectionAnnotations injectionAnnotations; 44 45 @Inject BindsOptionalOfMethodValidator( DaggerElements elements, DaggerTypes types, KotlinMetadataUtil kotlinMetadataUtil, DependencyRequestValidator dependencyRequestValidator, InjectionAnnotations injectionAnnotations)46 BindsOptionalOfMethodValidator( 47 DaggerElements elements, 48 DaggerTypes types, 49 KotlinMetadataUtil kotlinMetadataUtil, 50 DependencyRequestValidator dependencyRequestValidator, 51 InjectionAnnotations injectionAnnotations) { 52 super( 53 elements, 54 types, 55 kotlinMetadataUtil, 56 BindsOptionalOf.class, 57 ImmutableSet.of(Module.class, ProducerModule.class), 58 dependencyRequestValidator, 59 MUST_BE_ABSTRACT, 60 NO_EXCEPTIONS, 61 NO_MULTIBINDINGS, 62 NO_SCOPING, 63 injectionAnnotations); 64 this.types = types; 65 this.injectionAnnotations = injectionAnnotations; 66 } 67 68 69 @Override elementValidator(ExecutableElement element)70 protected ElementValidator elementValidator(ExecutableElement element) { 71 return new Validator(element); 72 } 73 74 private class Validator extends MethodValidator { Validator(ExecutableElement element)75 Validator(ExecutableElement element) { 76 super(element); 77 } 78 79 @Override checkKeyType(TypeMirror keyType)80 protected void checkKeyType(TypeMirror keyType) { 81 super.checkKeyType(keyType); 82 if (isValidImplicitProvisionKey( 83 injectionAnnotations.getQualifiers(element).stream().findFirst(), keyType, types) 84 && !injectedConstructors(asTypeElement(keyType)).isEmpty()) { 85 report.addError( 86 "@BindsOptionalOf methods cannot return unqualified types that have an @Inject-" 87 + "annotated constructor because those are always present"); 88 } 89 } 90 91 @Override checkParameters()92 protected void checkParameters() { 93 if (!element.getParameters().isEmpty()) { 94 report.addError("@BindsOptionalOf methods cannot have parameters"); 95 } 96 } 97 } 98 } 99