• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.base;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkState;
21 
22 import com.google.auto.common.MoreTypes;
23 import com.google.auto.value.AutoValue;
24 import com.google.common.base.Equivalence;
25 import dagger.model.Key;
26 import java.util.Map;
27 import javax.lang.model.type.DeclaredType;
28 import javax.lang.model.type.TypeMirror;
29 
30 /**
31  * Information about a {@link Map} {@link TypeMirror}.
32  */
33 @AutoValue
34 public abstract class MapType {
35   /**
36    * The map type itself, wrapped using {@link MoreTypes#equivalence()}. Use
37    * {@link #declaredMapType()} instead.
38    */
wrappedDeclaredMapType()39   protected abstract Equivalence.Wrapper<DeclaredType> wrappedDeclaredMapType();
40 
41   /**
42    * The map type itself.
43    */
declaredMapType()44   private DeclaredType declaredMapType() {
45     return wrappedDeclaredMapType().get();
46   }
47 
48   /**
49    * {@code true} if the map type is the raw {@link Map} type.
50    */
isRawType()51   public boolean isRawType() {
52     return declaredMapType().getTypeArguments().isEmpty();
53   }
54 
55   /**
56    * The map key type.
57    *
58    * @throws IllegalStateException if {@link #isRawType()} is true.
59    */
keyType()60   public TypeMirror keyType() {
61     checkState(!isRawType());
62     return declaredMapType().getTypeArguments().get(0);
63   }
64 
65   /**
66    * The map value type.
67    *
68    * @throws IllegalStateException if {@link #isRawType()} is true.
69    */
valueType()70   public TypeMirror valueType() {
71     checkState(!isRawType());
72     return declaredMapType().getTypeArguments().get(1);
73   }
74 
75   /**
76    * {@code true} if {@link #valueType()} is a {@code clazz}.
77    *
78    * @throws IllegalStateException if {@link #isRawType()} is true.
79    */
valuesAreTypeOf(Class<?> clazz)80   public boolean valuesAreTypeOf(Class<?> clazz) {
81     return MoreTypes.isType(valueType()) && MoreTypes.isTypeOf(clazz, valueType());
82   }
83 
84   /**
85    * Returns {@code true} if the {@linkplain #valueType() value type} of the {@link Map} is a
86    * {@linkplain FrameworkTypes#isFrameworkType(TypeMirror) framework type}.
87    */
valuesAreFrameworkType()88   public boolean valuesAreFrameworkType() {
89     return FrameworkTypes.isFrameworkType(valueType());
90   }
91 
92   /**
93    * {@code V} if {@link #valueType()} is a framework type like {@code Provider<V>} or {@code
94    * Producer<V>}.
95    *
96    * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
97    *     framework type
98    */
unwrappedFrameworkValueType()99   public TypeMirror unwrappedFrameworkValueType() {
100     checkState(
101         valuesAreFrameworkType(), "called unwrappedFrameworkValueType() on %s", declaredMapType());
102     return uncheckedUnwrappedValueType();
103   }
104 
105   /**
106    * {@code V} if {@link #valueType()} is a {@code WrappingClass<V>}.
107    *
108    * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
109    *     {@code WrappingClass<V>}
110    * @throws IllegalArgumentException if {@code wrappingClass} does not have exactly one type
111    *     parameter
112    */
unwrappedValueType(Class<?> wrappingClass)113   public TypeMirror unwrappedValueType(Class<?> wrappingClass) {
114     checkArgument(
115         wrappingClass.getTypeParameters().length == 1,
116         "%s must have exactly one type parameter",
117         wrappingClass);
118     checkState(valuesAreTypeOf(wrappingClass), "expected values to be %s: %s", wrappingClass, this);
119     return uncheckedUnwrappedValueType();
120   }
121 
uncheckedUnwrappedValueType()122   private TypeMirror uncheckedUnwrappedValueType() {
123     return MoreTypes.asDeclared(valueType()).getTypeArguments().get(0);
124   }
125 
126   /**
127    * {@code true} if {@code type} is a {@link Map} type.
128    */
isMap(TypeMirror type)129   public static boolean isMap(TypeMirror type) {
130     return MoreTypes.isType(type) && MoreTypes.isTypeOf(Map.class, type);
131   }
132 
133   /**
134    * {@code true} if {@code key.type()} is a {@link Map} type.
135    */
isMap(Key key)136   public static boolean isMap(Key key) {
137     return isMap(key.type());
138   }
139 
140   /**
141    * Returns a {@link MapType} for {@code type}.
142    *
143    * @throws IllegalArgumentException if {@code type} is not a {@link Map} type
144    */
from(TypeMirror type)145   public static MapType from(TypeMirror type) {
146     checkArgument(isMap(type), "%s is not a Map", type);
147     return new AutoValue_MapType(MoreTypes.equivalence().wrap(MoreTypes.asDeclared(type)));
148   }
149 
150   /**
151    * Returns a {@link MapType} for {@code key}'s {@link Key#type() type}.
152    *
153    * @throws IllegalArgumentException if {@code key.type()} is not a {@link Map} type
154    */
from(Key key)155   public static MapType from(Key key) {
156     return from(key.type());
157   }
158 }
159