• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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