• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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