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