1 /* 2 * Copyright (C) 2013 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; 18 19 import static javax.lang.model.element.ElementKind.CONSTRUCTOR; 20 import static javax.lang.model.element.Modifier.ABSTRACT; 21 import static javax.lang.model.element.Modifier.PRIVATE; 22 import static javax.lang.model.element.Modifier.STATIC; 23 24 import java.util.Map; 25 import java.util.function.Function; 26 import javax.lang.model.element.Element; 27 import javax.lang.model.element.ExecutableElement; 28 import javax.lang.model.element.TypeElement; 29 30 /** 31 * Utilities for handling types in annotation processors 32 */ 33 final class Util { 34 /** 35 * Returns true if and only if a component can instantiate new instances (typically of a module) 36 * rather than requiring that they be passed. 37 */ componentCanMakeNewInstances(TypeElement typeElement)38 static boolean componentCanMakeNewInstances(TypeElement typeElement) { 39 switch (typeElement.getKind()) { 40 case CLASS: 41 break; 42 case ENUM: 43 case ANNOTATION_TYPE: 44 case INTERFACE: 45 return false; 46 default: 47 throw new AssertionError("TypeElement cannot have kind: " + typeElement.getKind()); 48 } 49 50 if (typeElement.getModifiers().contains(ABSTRACT)) { 51 return false; 52 } 53 54 if (requiresEnclosingInstance(typeElement)) { 55 return false; 56 } 57 58 for (Element enclosed : typeElement.getEnclosedElements()) { 59 if (enclosed.getKind().equals(CONSTRUCTOR) 60 && ((ExecutableElement) enclosed).getParameters().isEmpty() 61 && !enclosed.getModifiers().contains(PRIVATE)) { 62 return true; 63 } 64 } 65 66 // TODO(gak): still need checks for visibility 67 68 return false; 69 } 70 requiresEnclosingInstance(TypeElement typeElement)71 private static boolean requiresEnclosingInstance(TypeElement typeElement) { 72 switch (typeElement.getNestingKind()) { 73 case TOP_LEVEL: 74 return false; 75 case MEMBER: 76 return !typeElement.getModifiers().contains(STATIC); 77 case ANONYMOUS: 78 case LOCAL: 79 return true; 80 } 81 throw new AssertionError( 82 "TypeElement cannot have nesting kind: " + typeElement.getNestingKind()); 83 } 84 85 /** 86 * A version of {@link Map#computeIfAbsent(Object, Function)} that allows {@code mappingFunction} 87 * to update {@code map}. 88 */ reentrantComputeIfAbsent( Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction)89 static <K, V> V reentrantComputeIfAbsent( 90 Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction) { 91 V value = map.get(key); 92 if (value == null) { 93 value = mappingFunction.apply(key); 94 if (value != null) { 95 map.put(key, value); 96 } 97 } 98 return value; 99 } 100 Util()101 private Util() {} 102 } 103