• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 Google, Inc.
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 package dagger.internal.codegen;
17 
18 import com.google.auto.common.MoreElements;
19 import com.google.common.collect.ImmutableList;
20 import dagger.Module;
21 import dagger.producers.ProducerModule;
22 import dagger.producers.ProductionComponent;
23 import javax.lang.model.element.AnnotationMirror;
24 import javax.lang.model.element.TypeElement;
25 import javax.lang.model.type.DeclaredType;
26 import javax.lang.model.type.TypeMirror;
27 import javax.lang.model.util.SimpleTypeVisitor6;
28 
29 import static com.google.auto.common.MoreElements.getAnnotationMirror;
30 import static com.google.common.base.Preconditions.checkState;
31 import static dagger.internal.codegen.ConfigurationAnnotations.getComponentModules;
32 import static javax.lang.model.element.ElementKind.CLASS;
33 import static javax.lang.model.element.ElementKind.INTERFACE;
34 import static javax.lang.model.element.Modifier.ABSTRACT;
35 
36 /**
37  * Performs superficial validation of the contract of the {@link ProductionComponent} annotation.
38  *
39  * @author Jesse Beder
40  */
41 final class ProductionComponentValidator {
validate(final TypeElement subject)42   ValidationReport<TypeElement> validate(final TypeElement subject) {
43     final ValidationReport.Builder<TypeElement> builder = ValidationReport.about(subject);
44 
45     if (!subject.getKind().equals(INTERFACE)
46         && !(subject.getKind().equals(CLASS) && subject.getModifiers().contains(ABSTRACT))) {
47       builder.addError(
48           "@ProductionComponent may only be applied to an interface or abstract class", subject);
49     }
50 
51     AnnotationMirror componentMirror =
52         getAnnotationMirror(subject, ProductionComponent.class).get();
53     ImmutableList<TypeMirror> moduleTypes = getComponentModules(componentMirror);
54 
55     // TODO(gak): make unused modules an error
56     for (TypeMirror moduleType : moduleTypes) {
57       moduleType.accept(
58           new SimpleTypeVisitor6<Void, Void>() {
59             @Override
60             protected Void defaultAction(TypeMirror mirror, Void p) {
61               builder.addError(mirror + " is not a valid module type.", subject);
62               return null;
63             }
64 
65             @Override
66             public Void visitDeclared(DeclaredType t, Void p) {
67               checkState(t.getTypeArguments().isEmpty());
68               TypeElement moduleElement = MoreElements.asType(t.asElement());
69               if (!getAnnotationMirror(moduleElement, Module.class).isPresent()
70                   && !getAnnotationMirror(moduleElement, ProducerModule.class).isPresent()) {
71                 builder.addError(
72                     moduleElement.getQualifiedName()
73                         + " is listed as a module, but is not annotated with @Module or"
74                         + " @ProducerModule",
75                     subject);
76               }
77               return null;
78             }
79           },
80           null);
81     }
82 
83     return builder.build();
84   }
85 }
86