• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Dagger Authors.
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 
17 package dagger.internal.codegen.binding;
18 
19 import static dagger.model.BindingKind.MEMBERS_INJECTOR;
20 
21 import com.google.auto.value.AutoValue;
22 import com.google.common.base.CaseFormat;
23 import com.squareup.javapoet.ClassName;
24 import com.squareup.javapoet.ParameterizedTypeName;
25 import com.squareup.javapoet.TypeName;
26 import java.util.Optional;
27 import javax.lang.model.element.Element;
28 import javax.lang.model.element.ElementVisitor;
29 import javax.lang.model.element.ExecutableElement;
30 import javax.lang.model.element.TypeElement;
31 import javax.lang.model.element.VariableElement;
32 import javax.lang.model.type.TypeMirror;
33 import javax.lang.model.util.ElementKindVisitor8;
34 
35 /**
36  * A value object that represents a field in the generated Component class.
37  *
38  * <p>Examples:
39  *
40  * <ul>
41  *   <li>{@code Provider<String>}
42  *   <li>{@code Producer<Widget>}
43  *   <li>{@code Provider<Map<SomeMapKey, MapValue>>}.
44  * </ul>
45  */
46 @AutoValue
47 public abstract class FrameworkField {
48 
49   /**
50    * Creates a framework field.
51    *
52    * @param frameworkClassName the name of the framework class (e.g., {@link javax.inject.Provider})
53    * @param valueTypeName the name of the type parameter of the framework class (e.g., {@code Foo}
54    *     for {@code Provider<Foo>}
55    * @param fieldName the name of the field
56    */
create( ClassName frameworkClassName, TypeName valueTypeName, String fieldName)57   public static FrameworkField create(
58       ClassName frameworkClassName, TypeName valueTypeName, String fieldName) {
59     String suffix = frameworkClassName.simpleName();
60     return new AutoValue_FrameworkField(
61         ParameterizedTypeName.get(frameworkClassName, valueTypeName),
62         fieldName.endsWith(suffix) ? fieldName : fieldName + suffix);
63   }
64 
65   /**
66    * A framework field for a {@link ContributionBinding}.
67    *
68    * @param frameworkClass if present, the field will use this framework class instead of the normal
69    *     one for the binding's type.
70    */
forBinding( ContributionBinding binding, Optional<ClassName> frameworkClass)71   public static FrameworkField forBinding(
72       ContributionBinding binding, Optional<ClassName> frameworkClass) {
73     return create(
74         frameworkClass.orElse(
75             ClassName.get(
76                 FrameworkType.forBindingType(binding.bindingType()).frameworkClass())),
77         TypeName.get(fieldValueType(binding)),
78         frameworkFieldName(binding));
79   }
80 
fieldValueType(ContributionBinding binding)81   private static TypeMirror fieldValueType(ContributionBinding binding) {
82     return binding.contributionType().isMultibinding()
83         ? binding.contributedType()
84         : binding.key().type();
85   }
86 
frameworkFieldName(ContributionBinding binding)87   private static String frameworkFieldName(ContributionBinding binding) {
88     if (binding.bindingElement().isPresent()) {
89       String name = BINDING_ELEMENT_NAME.visit(binding.bindingElement().get(), binding);
90       return binding.kind().equals(MEMBERS_INJECTOR) ? name + "MembersInjector" : name;
91     }
92     return KeyVariableNamer.name(binding.key());
93   }
94 
95   private static final ElementVisitor<String, Binding> BINDING_ELEMENT_NAME =
96       new ElementKindVisitor8<String, Binding>() {
97 
98         @Override
99         protected String defaultAction(Element e, Binding p) {
100           throw new IllegalArgumentException("Unexpected binding " + p);
101         }
102 
103         @Override
104         public String visitExecutableAsConstructor(ExecutableElement e, Binding p) {
105           return visit(e.getEnclosingElement(), p);
106         }
107 
108         @Override
109         public String visitExecutableAsMethod(ExecutableElement e, Binding p) {
110           return e.getSimpleName().toString();
111         }
112 
113         @Override
114         public String visitType(TypeElement e, Binding p) {
115           return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, e.getSimpleName().toString());
116         }
117 
118         @Override
119         public String visitVariableAsParameter(VariableElement e, Binding p) {
120           return e.getSimpleName().toString();
121         }
122       };
123 
type()124   public abstract ParameterizedTypeName type();
125 
name()126   public abstract String name();
127 }
128