1 /* 2 * Copyright (C) 2016 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.langmodel; 18 19 import static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 import static com.google.common.collect.Iterables.getOnlyElement; 22 23 import com.google.auto.common.MoreElements; 24 import com.google.auto.common.MoreTypes; 25 import com.google.common.collect.ImmutableSet; 26 import com.google.common.graph.Traverser; 27 import com.google.common.util.concurrent.FluentFuture; 28 import com.google.common.util.concurrent.ListenableFuture; 29 import com.squareup.javapoet.ClassName; 30 import java.util.List; 31 import java.util.Optional; 32 import java.util.function.Predicate; 33 import javax.inject.Inject; 34 import javax.lang.model.element.Element; 35 import javax.lang.model.element.ExecutableElement; 36 import javax.lang.model.element.TypeElement; 37 import javax.lang.model.type.ArrayType; 38 import javax.lang.model.type.DeclaredType; 39 import javax.lang.model.type.ErrorType; 40 import javax.lang.model.type.ExecutableType; 41 import javax.lang.model.type.NoType; 42 import javax.lang.model.type.NullType; 43 import javax.lang.model.type.PrimitiveType; 44 import javax.lang.model.type.TypeKind; 45 import javax.lang.model.type.TypeMirror; 46 import javax.lang.model.type.TypeVariable; 47 import javax.lang.model.type.WildcardType; 48 import javax.lang.model.util.SimpleTypeVisitor8; 49 import javax.lang.model.util.Types; 50 51 /** Extension of {@link Types} that adds Dagger-specific methods. */ 52 public final class DaggerTypes implements Types { 53 private final Types types; 54 private final DaggerElements elements; 55 56 @Inject DaggerTypes(Types types, DaggerElements elements)57 public DaggerTypes(Types types, DaggerElements elements) { 58 this.types = checkNotNull(types); 59 this.elements = checkNotNull(elements); 60 } 61 62 /** 63 * Returns the non-{@link Object} superclass of the type with the proper type parameters. An empty 64 * {@link Optional} is returned if there is no non-{@link Object} superclass. 65 */ nonObjectSuperclass(DeclaredType type)66 public Optional<DeclaredType> nonObjectSuperclass(DeclaredType type) { 67 return Optional.ofNullable(MoreTypes.nonObjectSuperclass(types, elements, type).orNull()); 68 } 69 70 /** 71 * Returns the {@linkplain #directSupertypes(TypeMirror) supertype}s of a type in breadth-first 72 * order. 73 */ supertypes(TypeMirror type)74 public Iterable<TypeMirror> supertypes(TypeMirror type) { 75 return Traverser.<TypeMirror>forGraph(this::directSupertypes).breadthFirst(type); 76 } 77 78 /** 79 * Returns {@code type}'s single type argument. 80 * 81 * <p>For example, if {@code type} is {@code List<Number>} this will return {@code Number}. 82 * 83 * @throws IllegalArgumentException if {@code type} is not a declared type or has zero or more 84 * than one type arguments. 85 */ unwrapType(TypeMirror type)86 public static TypeMirror unwrapType(TypeMirror type) { 87 TypeMirror unwrapped = unwrapTypeOrDefault(type, null); 88 checkArgument(unwrapped != null, "%s is a raw type", type); 89 return unwrapped; 90 } 91 92 /** 93 * Returns {@code type}'s single type argument, if one exists, or {@link Object} if not. 94 * 95 * <p>For example, if {@code type} is {@code List<Number>} this will return {@code Number}. 96 * 97 * @throws IllegalArgumentException if {@code type} is not a declared type or has more than one 98 * type argument. 99 */ unwrapTypeOrObject(TypeMirror type)100 public TypeMirror unwrapTypeOrObject(TypeMirror type) { 101 return unwrapTypeOrDefault(type, elements.getTypeElement(Object.class).asType()); 102 } 103 unwrapTypeOrDefault(TypeMirror type, TypeMirror defaultType)104 private static TypeMirror unwrapTypeOrDefault(TypeMirror type, TypeMirror defaultType) { 105 DeclaredType declaredType = MoreTypes.asDeclared(type); 106 TypeElement typeElement = MoreElements.asType(declaredType.asElement()); 107 checkArgument( 108 !typeElement.getTypeParameters().isEmpty(), 109 "%s does not have a type parameter", 110 typeElement.getQualifiedName()); 111 return getOnlyElement(declaredType.getTypeArguments(), defaultType); 112 } 113 114 /** 115 * Returns {@code type} wrapped in {@code wrappingClass}. 116 * 117 * <p>For example, if {@code type} is {@code List<Number>} and {@code wrappingClass} is {@code 118 * Set.class}, this will return {@code Set<List<Number>>}. 119 */ wrapType(TypeMirror type, Class<?> wrappingClass)120 public DeclaredType wrapType(TypeMirror type, Class<?> wrappingClass) { 121 return types.getDeclaredType(elements.getTypeElement(wrappingClass), type); 122 } 123 124 /** 125 * Returns {@code type}'s single type argument wrapped in {@code wrappingClass}. 126 * 127 * <p>For example, if {@code type} is {@code List<Number>} and {@code wrappingClass} is {@code 128 * Set.class}, this will return {@code Set<Number>}. 129 * 130 * <p>If {@code type} has no type parameters, returns a {@link TypeMirror} for {@code 131 * wrappingClass} as a raw type. 132 * 133 * @throws IllegalArgumentException if {@code} has more than one type argument. 134 */ rewrapType(TypeMirror type, Class<?> wrappingClass)135 public DeclaredType rewrapType(TypeMirror type, Class<?> wrappingClass) { 136 List<? extends TypeMirror> typeArguments = MoreTypes.asDeclared(type).getTypeArguments(); 137 TypeElement wrappingType = elements.getTypeElement(wrappingClass); 138 switch (typeArguments.size()) { 139 case 0: 140 return getDeclaredType(wrappingType); 141 case 1: 142 return getDeclaredType(wrappingType, getOnlyElement(typeArguments)); 143 default: 144 throw new IllegalArgumentException(type + " has more than 1 type argument"); 145 } 146 } 147 148 /** 149 * Returns a publicly accessible type based on {@code type}: 150 * 151 * <ul> 152 * <li>If {@code type} is publicly accessible, returns it. 153 * <li>If not, but {@code type}'s raw type is publicly accessible, returns the raw type. 154 * <li>Otherwise returns {@link Object}. 155 * </ul> 156 */ publiclyAccessibleType(TypeMirror type)157 public TypeMirror publiclyAccessibleType(TypeMirror type) { 158 return accessibleType( 159 type, Accessibility::isTypePubliclyAccessible, Accessibility::isRawTypePubliclyAccessible); 160 } 161 162 /** 163 * Returns an accessible type in {@code requestingClass}'s package based on {@code type}: 164 * 165 * <ul> 166 * <li>If {@code type} is accessible from the package, returns it. 167 * <li>If not, but {@code type}'s raw type is accessible from the package, returns the raw type. 168 * <li>Otherwise returns {@link Object}. 169 * </ul> 170 */ accessibleType(TypeMirror type, ClassName requestingClass)171 public TypeMirror accessibleType(TypeMirror type, ClassName requestingClass) { 172 return accessibleType( 173 type, 174 t -> Accessibility.isTypeAccessibleFrom(t, requestingClass.packageName()), 175 t -> Accessibility.isRawTypeAccessible(t, requestingClass.packageName())); 176 } 177 accessibleType( TypeMirror type, Predicate<TypeMirror> accessibilityPredicate, Predicate<TypeMirror> rawTypeAccessibilityPredicate)178 private TypeMirror accessibleType( 179 TypeMirror type, 180 Predicate<TypeMirror> accessibilityPredicate, 181 Predicate<TypeMirror> rawTypeAccessibilityPredicate) { 182 if (accessibilityPredicate.test(type)) { 183 return type; 184 } else if (type.getKind().equals(TypeKind.DECLARED) 185 && rawTypeAccessibilityPredicate.test(type)) { 186 return getDeclaredType(MoreTypes.asTypeElement(type)); 187 } else { 188 return elements.getTypeElement(Object.class).asType(); 189 } 190 } 191 192 /** 193 * Throws {@link TypeNotPresentException} if {@code type} is an {@link 194 * javax.lang.model.type.ErrorType}. 195 */ checkTypePresent(TypeMirror type)196 public static void checkTypePresent(TypeMirror type) { 197 type.accept( 198 // TODO(ronshapiro): Extract a base class that visits all components of a complex type 199 // and put it in auto.common 200 new SimpleTypeVisitor8<Void, Void>() { 201 @Override 202 public Void visitArray(ArrayType arrayType, Void p) { 203 return arrayType.getComponentType().accept(this, p); 204 } 205 206 @Override 207 public Void visitDeclared(DeclaredType declaredType, Void p) { 208 declaredType.getTypeArguments().forEach(t -> t.accept(this, p)); 209 return null; 210 } 211 212 @Override 213 public Void visitError(ErrorType errorType, Void p) { 214 throw new TypeNotPresentException(type.toString(), null); 215 } 216 }, 217 null); 218 } 219 220 private static final ImmutableSet<Class<?>> FUTURE_TYPES = 221 ImmutableSet.of(ListenableFuture.class, FluentFuture.class); 222 isFutureType(TypeMirror type)223 public static boolean isFutureType(TypeMirror type) { 224 return FUTURE_TYPES.stream().anyMatch(t -> MoreTypes.isTypeOf(t, type)); 225 } 226 hasTypeVariable(TypeMirror type)227 public static boolean hasTypeVariable(TypeMirror type) { 228 return type.accept( 229 new SimpleTypeVisitor8<Boolean, Void>() { 230 @Override 231 public Boolean visitArray(ArrayType arrayType, Void p) { 232 return arrayType.getComponentType().accept(this, p); 233 } 234 235 @Override 236 public Boolean visitDeclared(DeclaredType declaredType, Void p) { 237 return declaredType.getTypeArguments().stream().anyMatch(type -> type.accept(this, p)); 238 } 239 240 @Override 241 public Boolean visitTypeVariable(TypeVariable t, Void aVoid) { 242 return true; 243 } 244 245 @Override 246 protected Boolean defaultAction(TypeMirror e, Void aVoid) { 247 return false; 248 } 249 }, 250 null); 251 } 252 253 /** 254 * Resolves the type of the given executable element as a member of the given type. This may 255 * resolve type variables to concrete types, etc. 256 */ 257 public ExecutableType resolveExecutableType(ExecutableElement element, TypeMirror containerType) { 258 return MoreTypes.asExecutable(asMemberOf(MoreTypes.asDeclared(containerType), element)); 259 } 260 261 // Implementation of Types methods, delegating to types. 262 263 @Override 264 public Element asElement(TypeMirror t) { 265 return types.asElement(t); 266 } 267 268 @Override 269 public boolean isSameType(TypeMirror t1, TypeMirror t2) { 270 return types.isSameType(t1, t2); 271 } 272 273 @Override 274 public boolean isSubtype(TypeMirror t1, TypeMirror t2) { 275 return types.isSubtype(t1, t2); 276 } 277 278 @Override 279 public boolean isAssignable(TypeMirror t1, TypeMirror t2) { 280 return types.isAssignable(t1, t2); 281 } 282 283 @Override 284 public boolean contains(TypeMirror t1, TypeMirror t2) { 285 return types.contains(t1, t2); 286 } 287 288 @Override 289 public boolean isSubsignature(ExecutableType m1, ExecutableType m2) { 290 return types.isSubsignature(m1, m2); 291 } 292 293 @Override 294 public List<? extends TypeMirror> directSupertypes(TypeMirror t) { 295 return types.directSupertypes(t); 296 } 297 298 @Override 299 public TypeMirror erasure(TypeMirror t) { 300 return types.erasure(t); 301 } 302 303 @Override 304 public TypeElement boxedClass(PrimitiveType p) { 305 return types.boxedClass(p); 306 } 307 308 @Override 309 public PrimitiveType unboxedType(TypeMirror t) { 310 return types.unboxedType(t); 311 } 312 313 @Override 314 public TypeMirror capture(TypeMirror t) { 315 return types.capture(t); 316 } 317 318 @Override 319 public PrimitiveType getPrimitiveType(TypeKind kind) { 320 return types.getPrimitiveType(kind); 321 } 322 323 @Override 324 public NullType getNullType() { 325 return types.getNullType(); 326 } 327 328 @Override 329 public NoType getNoType(TypeKind kind) { 330 return types.getNoType(kind); 331 } 332 333 @Override 334 public ArrayType getArrayType(TypeMirror componentType) { 335 return types.getArrayType(componentType); 336 } 337 338 @Override 339 public WildcardType getWildcardType(TypeMirror extendsBound, TypeMirror superBound) { 340 return types.getWildcardType(extendsBound, superBound); 341 } 342 343 @Override 344 public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { 345 return types.getDeclaredType(typeElem, typeArgs); 346 } 347 348 @Override 349 public DeclaredType getDeclaredType( 350 DeclaredType containing, TypeElement typeElem, TypeMirror... typeArgs) { 351 return types.getDeclaredType(containing, typeElem, typeArgs); 352 } 353 354 @Override 355 public TypeMirror asMemberOf(DeclaredType containing, Element element) { 356 return types.asMemberOf(containing, element); 357 } 358 } 359