1 /* 2 * Copyright (C) 2017 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 dagger.internal.codegen.base.ComponentAnnotation.allComponentAndCreatorAnnotations; 20 import static dagger.internal.codegen.xprocessing.XElements.hasAnyAnnotation; 21 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared; 22 import static dagger.internal.codegen.xprocessing.XTypes.isRawParameterizedType; 23 24 import androidx.room.compiler.processing.XAnnotation; 25 import androidx.room.compiler.processing.XType; 26 import androidx.room.compiler.processing.XTypeElement; 27 import dagger.internal.codegen.model.DaggerAnnotation; 28 import dagger.internal.codegen.model.Key; 29 import java.util.Optional; 30 31 /** Utility methods related to {@link Key}s. */ 32 public final class Keys { isValidMembersInjectionKey(Key key)33 public static boolean isValidMembersInjectionKey(Key key) { 34 return !key.qualifier().isPresent() 35 && !key.multibindingContributionIdentifier().isPresent() 36 && isDeclared(key.type().xprocessing()); 37 } 38 39 /** 40 * Returns {@code true} if this is valid as an implicit key (that is, if it's valid for a 41 * just-in-time binding by discovering an {@code @Inject} constructor). 42 */ isValidImplicitProvisionKey(Key key)43 public static boolean isValidImplicitProvisionKey(Key key) { 44 return isValidImplicitProvisionKey( 45 key.qualifier().map(DaggerAnnotation::xprocessing), key.type().xprocessing()); 46 } 47 48 /** 49 * Returns {@code true} if a key with {@code qualifier} and {@code type} is valid as an implicit 50 * key (that is, if it's valid for a just-in-time binding by discovering an {@code @Inject} 51 * constructor). 52 */ isValidImplicitProvisionKey(Optional<XAnnotation> qualifier, XType type)53 public static boolean isValidImplicitProvisionKey(Optional<XAnnotation> qualifier, XType type) { 54 // Qualifiers disqualify implicit provisioning. 55 if (qualifier.isPresent()) { 56 return false; 57 } 58 59 // A provision type must be a declared type 60 if (!isDeclared(type)) { 61 return false; 62 } 63 64 // Non-classes or abstract classes aren't allowed. 65 XTypeElement typeElement = type.getTypeElement(); 66 if (!typeElement.isClass() || typeElement.isAbstract()) { 67 return false; 68 } 69 70 // If the key has type arguments, validate that each type argument is declared. 71 // Otherwise the type argument may be a wildcard (or other type), and we can't 72 // resolve that to actual types. 73 for (XType arg : type.getTypeArguments()) { 74 if (!isDeclared(arg)) { 75 return false; 76 } 77 } 78 79 // Also validate that if the type represents a parameterized type the user didn't refer to its 80 // raw type, which we don't allow. (This is a judgement call -- we *could* allow it and 81 // instantiate the type bounds... but we don't.) 82 return !isRawParameterizedType(type); 83 } 84 85 /** 86 * Returns {@code true} if the given key is for a component/subcomponent or a creator of a 87 * component/subcomponent. 88 */ isComponentOrCreator(Key key)89 public static boolean isComponentOrCreator(Key key) { 90 return !key.qualifier().isPresent() 91 && isDeclared(key.type().xprocessing()) 92 && hasAnyAnnotation( 93 key.type().xprocessing().getTypeElement(), allComponentAndCreatorAnnotations()); 94 } 95 } 96