• 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 import static dagger.internal.codegen.langmodel.DaggerTypes.unwrapType;
22 import static dagger.internal.codegen.xprocessing.XTypes.isTypeOf;
23 
24 import androidx.room.compiler.processing.XType;
25 import com.google.auto.value.AutoValue;
26 import com.squareup.javapoet.ClassName;
27 import com.squareup.javapoet.TypeName;
28 import dagger.internal.codegen.javapoet.TypeNames;
29 import dagger.spi.model.Key;
30 import javax.lang.model.type.TypeMirror;
31 
32 /** Information about a {@link java.util.Map} {@link TypeMirror}. */
33 @AutoValue
34 public abstract class MapType {
35   private XType type;
36 
37   /** The map type itself. */
typeName()38   abstract TypeName typeName();
39 
40   /** The map type itself. */
type()41   private XType type() {
42     return type;
43   }
44 
45   /** {@code true} if the map type is the raw {@link java.util.Map} type. */
isRawType()46   public boolean isRawType() {
47     return type().getTypeArguments().isEmpty();
48   }
49 
50   /**
51    * The map key type.
52    *
53    * @throws IllegalStateException if {@link #isRawType()} is true.
54    */
keyType()55   public XType keyType() {
56     checkState(!isRawType());
57     return type().getTypeArguments().get(0);
58   }
59 
60   /**
61    * The map value type.
62    *
63    * @throws IllegalStateException if {@link #isRawType()} is true.
64    */
valueType()65   public XType valueType() {
66     checkState(!isRawType());
67     return type().getTypeArguments().get(1);
68   }
69 
70   /** Returns {@code true} if the raw type of {@link #valueType()} is {@code className}. */
valuesAreTypeOf(ClassName className)71   public boolean valuesAreTypeOf(ClassName className) {
72     return !isRawType() && isTypeOf(valueType(), className);
73   }
74 
75   /** Returns {@code true} if the raw type of {@link #valueType()} is a framework type. */
valuesAreFrameworkType()76   public boolean valuesAreFrameworkType() {
77     return FrameworkTypes.isFrameworkType(valueType());
78   }
79 
80   /**
81    * {@code V} if {@link #valueType()} is a framework type like {@code Provider<V>} or {@code
82    * Producer<V>}.
83    *
84    * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
85    *     framework type
86    */
unwrappedFrameworkValueType()87   public XType unwrappedFrameworkValueType() {
88     checkState(valuesAreFrameworkType(), "called unwrappedFrameworkValueType() on %s", type());
89     return uncheckedUnwrappedValueType();
90   }
91 
92   /**
93    * {@code V} if {@link #valueType()} is a {@code WrappingClass<V>}.
94    *
95    * @throws IllegalStateException if {@link #isRawType()} is true or {@link #valueType()} is not a
96    *     {@code WrappingClass<V>}
97    */
98   // TODO(b/202033221): Consider using stricter input type, e.g. FrameworkType.
unwrappedValueType(ClassName wrappingClass)99   public XType unwrappedValueType(ClassName wrappingClass) {
100     checkState(valuesAreTypeOf(wrappingClass), "expected values to be %s: %s", wrappingClass, this);
101     return uncheckedUnwrappedValueType();
102   }
103 
uncheckedUnwrappedValueType()104   private XType uncheckedUnwrappedValueType() {
105     return unwrapType(valueType());
106   }
107 
108   /** {@code true} if {@code type} is a {@link java.util.Map} type. */
isMap(XType type)109   public static boolean isMap(XType type) {
110     return isTypeOf(type, TypeNames.MAP);
111   }
112 
113   /** {@code true} if {@code key.type()} is a {@link java.util.Map} type. */
isMap(Key key)114   public static boolean isMap(Key key) {
115     return isMap(key.type().xprocessing());
116   }
117 
118   /**
119    * Returns a {@link MapType} for {@code type}.
120    *
121    * @throws IllegalArgumentException if {@code type} is not a {@link java.util.Map} type
122    */
from(XType type)123   public static MapType from(XType type) {
124     checkArgument(isMap(type), "%s is not a Map", type);
125     MapType mapType = new AutoValue_MapType(type.getTypeName());
126     mapType.type = type;
127     return mapType;
128   }
129 
130   /**
131    * Returns a {@link MapType} for {@code key}'s {@link Key#type() type}.
132    *
133    * @throws IllegalArgumentException if {@code key.type()} is not a {@link java.util.Map} type
134    */
from(Key key)135   public static MapType from(Key key) {
136     return from(key.type().xprocessing());
137   }
138 }
139