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