Home | History | Annotate | Download | only in codegen
      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 {
     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