1 /* 2 * Copyright (C) 2015 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.common.base.Predicate; 19 import com.google.common.collect.Iterables; 20 import dagger.internal.codegen.writer.ClassName; 21 import dagger.internal.codegen.writer.ClassWriter; 22 import dagger.internal.codegen.writer.JavaWriter; 23 import dagger.internal.codegen.writer.MethodWriter; 24 import javax.annotation.Generated; 25 import javax.lang.model.element.TypeElement; 26 import javax.lang.model.util.Elements; 27 import javax.lang.model.util.Types; 28 import javax.tools.Diagnostic.Kind; 29 30 import static dagger.internal.codegen.Util.componentCanMakeNewInstances; 31 import static javax.lang.model.element.Modifier.FINAL; 32 import static javax.lang.model.element.Modifier.PUBLIC; 33 import static javax.lang.model.element.Modifier.STATIC; 34 35 /** 36 * Creates the implementation class for a component. 37 */ 38 class ComponentWriter extends AbstractComponentWriter { 39 40 ComponentWriter( 41 Types types, 42 Elements elements, 43 Key.Factory keyFactory, 44 Kind nullableValidationType, 45 ClassName name, 46 BindingGraph graph) { 47 super(types, elements, keyFactory, nullableValidationType, name, graph); 48 } 49 50 @Override 51 protected ClassWriter createComponentClass() { 52 JavaWriter javaWriter = JavaWriter.inPackage(name.packageName()); 53 javaWriters.add(javaWriter); 54 55 ClassWriter componentWriter = javaWriter.addClass(name.simpleName()); 56 componentWriter.annotate(Generated.class).setValue(ComponentProcessor.class.getCanonicalName()); 57 componentWriter.addModifiers(PUBLIC, FINAL); 58 componentWriter.setSupertype(componentDefinitionType()); 59 return componentWriter; 60 } 61 62 @Override 63 protected ClassWriter createBuilder() { 64 ClassWriter builderWriter = componentWriter.addNestedClass("Builder"); 65 builderWriter.addModifiers(STATIC); 66 67 // Only top-level components have the factory builder() method. 68 // Mirror the user's builder API type if they had one. 69 MethodWriter builderFactoryMethod = 70 graph.componentDescriptor().builderSpec().isPresent() 71 ? componentWriter.addMethod( 72 graph 73 .componentDescriptor() 74 .builderSpec() 75 .get() 76 .builderDefinitionType() 77 .asType(), 78 "builder") 79 : componentWriter.addMethod(builderWriter, "builder"); 80 builderFactoryMethod.addModifiers(PUBLIC, STATIC); 81 builderFactoryMethod.body().addSnippet("return new %s();", builderWriter.name()); 82 return builderWriter; 83 } 84 85 @Override 86 protected void addFactoryMethods() { 87 if (canInstantiateAllRequirements()) { 88 MethodWriter factoryMethod = 89 componentWriter.addMethod(componentDefinitionTypeName(), "create"); 90 factoryMethod.addModifiers(PUBLIC, STATIC); 91 // TODO(gak): replace this with something that doesn't allocate a builder 92 factoryMethod 93 .body() 94 .addSnippet( 95 "return builder().%s();", 96 graph.componentDescriptor().builderSpec().isPresent() 97 ? graph 98 .componentDescriptor() 99 .builderSpec() 100 .get() 101 .buildMethod() 102 .getSimpleName() 103 : "build"); 104 } 105 } 106 107 /** {@code true} if all of the graph's required dependencies can be automatically constructed. */ 108 private boolean canInstantiateAllRequirements() { 109 return Iterables.all( 110 graph.componentRequirements(), 111 new Predicate<TypeElement>() { 112 @Override 113 public boolean apply(TypeElement dependency) { 114 return componentCanMakeNewInstances(dependency); 115 } 116 }); 117 } 118 } 119