15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/* 25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2013 Google, Inc. 35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2013 Square, Inc. 45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * 55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * you may not use this file except in compliance with the License. 75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * You may obtain a copy of the License at 85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * 95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * 115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unless required by applicable law or agreed to in writing, software 125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * See the License for the specific language governing permissions and 155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * limitations under the License. 165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.internal.codegen; 185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.auto.common.MoreTypes; 205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Equivalence; 215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Equivalence.Wrapper; 225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.base.Optional; 235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.collect.ImmutableSet; 2487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport dagger.producers.Produced; 255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.Map; 265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.Set; 275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.inject.Provider; 285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.Element; 295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.ExecutableElement; 305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.Modifier; 315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.element.TypeElement; 325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.type.DeclaredType; 335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.type.TypeMirror; 345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport javax.lang.model.util.Elements; 355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.auto.common.MoreElements.getLocalAndInheritedMethods; 375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.auto.common.MoreTypes.asDeclared; 385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.common.base.Preconditions.checkState; 395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.element.ElementKind.CONSTRUCTOR; 405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.element.Modifier.ABSTRACT; 415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.element.Modifier.PRIVATE; 425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static javax.lang.model.element.Modifier.STATIC; 435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/** 455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Utilities for handling types in annotation processors 465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinfinal class Util { 485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 4987182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin * Returns the {@code V} type for a {@link Map} type like {@code Map<K, Provider<V>>} if the map 505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * includes such a construction 515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 5287182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin public static TypeMirror getProvidedValueTypeOfMap(DeclaredType mapType) { 535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin checkState(MoreTypes.isTypeOf(Map.class, mapType), "%s is not a Map.", mapType); 5487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin return asDeclared(mapType.getTypeArguments().get(1)).getTypeArguments().get(0); 555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin // TODO(cgruber): Consider an object that holds and exposes the various parts of a Map type. 585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * returns the value type for a {@link Map} type like Map<K, V>}. 605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 6187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin public static TypeMirror getValueTypeOfMap(DeclaredType mapType) { 625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin checkState(MoreTypes.isTypeOf(Map.class, mapType), "%s is not a Map.", mapType); 6387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin return mapType.getTypeArguments().get(1); 645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 675d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Returns the key type for a {@link Map} type like Map<K, Provider<V>>} 685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 6987182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin public static TypeMirror getKeyTypeOfMap(DeclaredType mapType) { 705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin checkState(MoreTypes.isTypeOf(Map.class, mapType), "%s is not a Map.", mapType); 7187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin return mapType.getTypeArguments().get(0); 725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Returns true if {@code type} is a {@link Map} whose value type is not a {@link Provider}. 765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin public static boolean isMapWithNonProvidedValues(TypeMirror type) { 785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return MoreTypes.isType(type) 795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && MoreTypes.isTypeOf(Map.class, type) 805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && !MoreTypes.isTypeOf(Provider.class, asDeclared(type).getTypeArguments().get(1)); 815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Returns true if {@code type} is a {@link Map} whose value type is a {@link Provider}. 855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin public static boolean isMapWithProvidedValues(TypeMirror type) { 875d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return MoreTypes.isType(type) 885d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && MoreTypes.isTypeOf(Map.class, type) 895d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && MoreTypes.isTypeOf(Provider.class, asDeclared(type).getTypeArguments().get(1)); 905d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 915d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 9287182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin /** Returns true if {@code type} is a {@code Set<Produced<T>>}. */ 9387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin static boolean isSetOfProduced(TypeMirror type) { 9487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin return MoreTypes.isType(type) 9587182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin && MoreTypes.isTypeOf(Set.class, type) 9687182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin && MoreTypes.isTypeOf(Produced.class, MoreTypes.asDeclared(type).getTypeArguments().get(0)); 9787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin } 9887182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin 995d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 1005d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Wraps an {@link Optional} of a type in an {@code Optional} of a {@link Wrapper} for that type. 1015d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 1025d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin static <T> Optional<Equivalence.Wrapper<T>> wrapOptionalInEquivalence( 1035d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin Equivalence<T> equivalence, Optional<T> optional) { 1045d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return optional.isPresent() 1055d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin ? Optional.of(equivalence.wrap(optional.get())) 1065d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin : Optional.<Equivalence.Wrapper<T>>absent(); 1075d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1085d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1095d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 1105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unwraps an {@link Optional} of a {@link Wrapper} into an {@code Optional} of the underlying 1115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * type. 1125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 1135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin static <T> Optional<T> unwrapOptionalEquivalence( 1145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin Optional<Equivalence.Wrapper<T>> wrappedOptional) { 1155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return wrappedOptional.isPresent() 1165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin ? Optional.of(wrappedOptional.get().get()) 1175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin : Optional.<T>absent(); 1185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin private static boolean requiresEnclosingInstance(TypeElement typeElement) { 1215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin switch (typeElement.getNestingKind()) { 1225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case TOP_LEVEL: 1235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return false; 1245d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case MEMBER: 1255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return !typeElement.getModifiers().contains(STATIC); 1265d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case ANONYMOUS: 1275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case LOCAL: 1285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return true; 1295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin default: 1305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin throw new AssertionError("TypeElement cannot have nesting kind: " 1315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin + typeElement.getNestingKind()); 1325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin /** 1365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Returns true if and only if a component can instantiate new instances (typically of a module) 1375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * rather than requiring that they be passed. 1385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */ 1395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin static boolean componentCanMakeNewInstances(TypeElement typeElement) { 1405d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin switch (typeElement.getKind()) { 1415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case CLASS: 1425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin break; 1435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case ENUM: 1445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case ANNOTATION_TYPE: 1455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin case INTERFACE: 1465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return false; 1475d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin default: 1485d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin throw new AssertionError("TypeElement cannot have kind: " + typeElement.getKind()); 1495d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin if (typeElement.getModifiers().contains(ABSTRACT)) { 1525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return false; 1535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1545d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1555d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin if (requiresEnclosingInstance(typeElement)) { 1565d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return false; 1575d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1585d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1595d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin for (Element enclosed : typeElement.getEnclosedElements()) { 1605d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin if (enclosed.getKind().equals(CONSTRUCTOR) 1615d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && ((ExecutableElement) enclosed).getParameters().isEmpty() 1625d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin && !enclosed.getModifiers().contains(PRIVATE)) { 1635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return true; 1645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1675d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin // TODO(gak): still need checks for visibility 1685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return false; 1705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin static ImmutableSet<ExecutableElement> getUnimplementedMethods( 1735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin Elements elements, TypeElement type) { 1745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin ImmutableSet.Builder<ExecutableElement> unimplementedMethods = ImmutableSet.builder(); 1755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin Set<ExecutableElement> methods = getLocalAndInheritedMethods(type, elements); 1765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin for (ExecutableElement method : methods) { 1775d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin if (method.getModifiers().contains(Modifier.ABSTRACT)) { 1785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin unimplementedMethods.add(method); 1795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1815d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin return unimplementedMethods.build(); 1825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin } 1835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin 1845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin private Util() {} 1855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin} 186