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.common.collect.Iterables.getOnlyElement; 20 import static dagger.internal.codegen.base.ComponentAnnotation.anyComponentAnnotation; 21 import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation; 22 import static javax.lang.model.element.Modifier.ABSTRACT; 23 24 import com.google.auto.common.MoreElements; 25 import dagger.internal.codegen.base.ModuleAnnotation; 26 import dagger.internal.codegen.binding.InjectionAnnotations; 27 import java.util.List; 28 import java.util.Optional; 29 import javax.inject.Inject; 30 import javax.lang.model.element.ExecutableElement; 31 import javax.lang.model.element.TypeElement; 32 import javax.lang.model.element.VariableElement; 33 import javax.lang.model.type.TypeMirror; 34 35 final class BindsInstanceMethodValidator extends BindsInstanceElementValidator<ExecutableElement> { 36 @Inject BindsInstanceMethodValidator(InjectionAnnotations injectionAnnotations)37 BindsInstanceMethodValidator(InjectionAnnotations injectionAnnotations) { 38 super(injectionAnnotations); 39 } 40 41 @Override elementValidator(ExecutableElement element)42 protected ElementValidator elementValidator(ExecutableElement element) { 43 return new Validator(element); 44 } 45 46 private class Validator extends ElementValidator { Validator(ExecutableElement element)47 Validator(ExecutableElement element) { 48 super(element); 49 } 50 51 @Override checkAdditionalProperties()52 protected void checkAdditionalProperties() { 53 if (!element.getModifiers().contains(ABSTRACT)) { 54 report.addError("@BindsInstance methods must be abstract"); 55 } 56 if (element.getParameters().size() != 1) { 57 report.addError( 58 "@BindsInstance methods should have exactly one parameter for the bound type"); 59 } 60 TypeElement enclosingType = MoreElements.asType(element.getEnclosingElement()); 61 moduleAnnotation(enclosingType) 62 .ifPresent(moduleAnnotation -> report.addError(didYouMeanBinds(moduleAnnotation))); 63 anyComponentAnnotation(enclosingType) 64 .ifPresent( 65 componentAnnotation -> 66 report.addError( 67 String.format( 68 "@BindsInstance methods should not be included in @%1$ss. " 69 + "Did you mean to put it in a @%1$s.Builder?", 70 componentAnnotation.simpleName()))); 71 } 72 73 @Override bindingElementType()74 protected Optional<TypeMirror> bindingElementType() { 75 List<? extends VariableElement> parameters = 76 MoreElements.asExecutable(element).getParameters(); 77 return parameters.size() == 1 78 ? Optional.of(getOnlyElement(parameters).asType()) 79 : Optional.empty(); 80 } 81 } 82 didYouMeanBinds(ModuleAnnotation moduleAnnotation)83 private static String didYouMeanBinds(ModuleAnnotation moduleAnnotation) { 84 return String.format( 85 "@BindsInstance methods should not be included in @%ss. Did you mean @Binds?", 86 moduleAnnotation.annotationName()); 87 } 88 } 89