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.value.AutoValue; 19 import com.google.common.base.Optional; 20 import com.google.common.collect.ImmutableSet; 21 import dagger.Component; 22 import dagger.internal.codegen.writer.ClassName; 23 import dagger.internal.codegen.writer.ClassWriter; 24 import dagger.internal.codegen.writer.FieldWriter; 25 import dagger.internal.codegen.writer.JavaWriter; 26 import dagger.internal.codegen.writer.Snippet; 27 import dagger.internal.codegen.writer.TypeName; 28 import javax.annotation.processing.Filer; 29 import javax.lang.model.element.Element; 30 import javax.lang.model.util.Elements; 31 import javax.lang.model.util.Types; 32 import javax.tools.Diagnostic; 33 34 /** 35 * Generates the implementation of the abstract types annotated with {@link Component}. 36 * 37 * @author Gregory Kick 38 * @since 2.0 39 */ 40 final class ComponentGenerator extends SourceFileGenerator<BindingGraph> { 41 private final Types types; 42 private final Elements elements; 43 private final Key.Factory keyFactory; 44 private final Diagnostic.Kind nullableValidationType; 45 46 ComponentGenerator( 47 Filer filer, 48 Elements elements, 49 Types types, 50 Key.Factory keyFactory, 51 Diagnostic.Kind nullableValidationType) { 52 super(filer); 53 this.types = types; 54 this.elements = elements; 55 this.keyFactory = keyFactory; 56 this.nullableValidationType = nullableValidationType; 57 } 58 59 @Override 60 ClassName nameGeneratedType(BindingGraph input) { 61 ClassName componentDefinitionClassName = 62 ClassName.fromTypeElement(input.componentDescriptor().componentDefinitionType()); 63 String componentName = "Dagger" + componentDefinitionClassName.classFileName('_'); 64 return componentDefinitionClassName.topLevelClassName().peerNamed(componentName); 65 } 66 67 @Override 68 Iterable<? extends Element> getOriginatingElements(BindingGraph input) { 69 return ImmutableSet.of(input.componentDescriptor().componentDefinitionType()); 70 } 71 72 @Override 73 Optional<? extends Element> getElementForErrorReporting(BindingGraph input) { 74 return Optional.of(input.componentDescriptor().componentDefinitionType()); 75 } 76 77 @AutoValue static abstract class MemberSelect { 78 static MemberSelect instanceSelect(ClassName owningClass, Snippet snippet) { 79 return new AutoValue_ComponentGenerator_MemberSelect( 80 Optional.<TypeName> absent(), owningClass, false, snippet); 81 } 82 83 static MemberSelect staticSelect(ClassName owningClass, Snippet snippet) { 84 return new AutoValue_ComponentGenerator_MemberSelect( 85 Optional.<TypeName> absent(), owningClass, true, snippet); 86 } 87 88 static MemberSelect staticMethodInvocationWithCast( 89 ClassName owningClass, Snippet snippet, TypeName castType) { 90 return new AutoValue_ComponentGenerator_MemberSelect( 91 Optional.of(castType), owningClass, true, snippet); 92 } 93 94 /** 95 * This exists only to facilitate edge cases in which we need to select a member, but that 96 * member uses a type parameter that can't be inferred. 97 */ 98 abstract Optional<TypeName> selectedCast(); 99 abstract ClassName owningClass(); 100 abstract boolean staticMember(); 101 abstract Snippet snippet(); 102 103 private Snippet qualifiedSelectSnippet() { 104 return Snippet.format( 105 "%s" + (staticMember() ? "" : ".this") + ".%s", 106 owningClass(), snippet()); 107 } 108 109 Snippet getSnippetWithRawTypeCastFor(ClassName usingClass) { 110 Snippet snippet = getSnippetFor(usingClass); 111 return selectedCast().isPresent() 112 ? Snippet.format("(%s) %s", selectedCast().get(), snippet) 113 : snippet; 114 } 115 116 Snippet getSnippetFor(ClassName usingClass) { 117 return owningClass().equals(usingClass) ? snippet() : qualifiedSelectSnippet(); 118 } 119 } 120 121 @Override 122 ImmutableSet<JavaWriter> write(ClassName componentName, BindingGraph input) { 123 return new ComponentWriter( 124 types, elements, keyFactory, nullableValidationType, componentName, input) 125 .write(); 126 } 127 } 128