1 /*
<lambda>null2  * Copyright (C) 2016 The Android Open Source Project
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 @file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
18 
19 package androidx.room.ext
20 
21 import com.google.auto.common.AnnotationMirrors
22 import com.google.auto.common.MoreElements
23 import com.google.auto.common.MoreTypes
24 import me.eugeniomarletti.kotlin.metadata.shadow.load.java.JvmAbi
25 import javax.annotation.processing.ProcessingEnvironment
26 import javax.lang.model.element.AnnotationValue
27 import javax.lang.model.element.Element
28 import javax.lang.model.element.ElementKind
29 import javax.lang.model.element.Modifier
30 import javax.lang.model.element.TypeElement
31 import javax.lang.model.element.VariableElement
32 import javax.lang.model.type.TypeKind
33 import javax.lang.model.type.TypeMirror
34 import javax.lang.model.type.WildcardType
35 import javax.lang.model.util.SimpleAnnotationValueVisitor6
36 import javax.lang.model.util.SimpleTypeVisitor7
37 import javax.lang.model.util.Types
38 import kotlin.reflect.KClass
39 
40 fun Element.hasAnyOf(vararg modifiers: Modifier): Boolean {
41     return this.modifiers.any { modifiers.contains(it) }
42 }
43 
hasAnnotationnull44 fun Element.hasAnnotation(klass: KClass<out Annotation>): Boolean {
45     return MoreElements.isAnnotationPresent(this, klass.java)
46 }
47 
isNonNullnull48 fun Element.isNonNull() =
49         asType().kind.isPrimitive
50                 || hasAnnotation(androidx.annotation.NonNull::class)
51                 || hasAnnotation(org.jetbrains.annotations.NotNull::class)
52 
53 /**
54  * gets all members including super privates. does not handle duplicate field names!!!
55  */
56 // TODO handle conflicts with super: b/35568142
57 fun TypeElement.getAllFieldsIncludingPrivateSupers(processingEnvironment: ProcessingEnvironment):
58         Set<VariableElement> {
59     val myMembers = processingEnvironment.elementUtils.getAllMembers(this)
60             .filter { it.kind == ElementKind.FIELD }
61             .filter { it is VariableElement }
62             .map { it as VariableElement }
63             .toSet()
64     if (superclass.kind != TypeKind.NONE) {
65         return myMembers + MoreTypes.asTypeElement(superclass)
66                 .getAllFieldsIncludingPrivateSupers(processingEnvironment)
67     } else {
68         return myMembers
69     }
70 }
71 
72 // code below taken from dagger2
73 // compiler/src/main/java/dagger/internal/codegen/ConfigurationAnnotations.java
74 private val TO_LIST_OF_TYPES = object
75     : SimpleAnnotationValueVisitor6<List<TypeMirror>, Void?>() {
visitArraynull76     override fun visitArray(values: MutableList<out AnnotationValue>?, p: Void?): List<TypeMirror> {
77         return values?.mapNotNull {
78             val tmp = TO_TYPE.visit(it)
79             tmp
80         } ?: emptyList()
81     }
82 
defaultActionnull83     override fun defaultAction(o: Any?, p: Void?): List<TypeMirror>? {
84         return emptyList()
85     }
86 }
87 
88 private val TO_TYPE = object : SimpleAnnotationValueVisitor6<TypeMirror, Void>() {
89 
visitTypenull90     override fun visitType(t: TypeMirror, p: Void?): TypeMirror {
91         return t
92     }
93 
defaultActionnull94     override fun defaultAction(o: Any?, p: Void?): TypeMirror {
95         throw TypeNotPresentException(o!!.toString(), null)
96     }
97 }
98 
AnnotationValuenull99 fun AnnotationValue.toListOfClassTypes(): List<TypeMirror> {
100     return TO_LIST_OF_TYPES.visit(this)
101 }
102 
toTypenull103 fun AnnotationValue.toType(): TypeMirror {
104     return TO_TYPE.visit(this)
105 }
106 
toClassTypenull107 fun AnnotationValue.toClassType(): TypeMirror? {
108     return TO_TYPE.visit(this)
109 }
110 
TypeMirrornull111 fun TypeMirror.isCollection(): Boolean {
112     return MoreTypes.isType(this)
113             && (MoreTypes.isTypeOf(java.util.List::class.java, this)
114             || MoreTypes.isTypeOf(java.util.Set::class.java, this))
115 }
116 
getAnnotationValuenull117 fun Element.getAnnotationValue(annotation: Class<out Annotation>, fieldName: String): Any? {
118     return MoreElements.getAnnotationMirror(this, annotation)
119             .orNull()?.let {
120         AnnotationMirrors.getAnnotationValue(it, fieldName)?.value
121     }
122 }
123 
124 private val ANNOTATION_VALUE_TO_INT_VISITOR = object : SimpleAnnotationValueVisitor6<Int?, Void>() {
visitIntnull125     override fun visitInt(i: Int, p: Void?): Int? {
126         return i
127     }
128 }
129 
130 private val ANNOTATION_VALUE_TO_BOOLEAN_VISITOR = object
131     : SimpleAnnotationValueVisitor6<Boolean?, Void>() {
visitBooleannull132     override fun visitBoolean(b: Boolean, p: Void?): Boolean? {
133         return b
134     }
135 }
136 
137 private val ANNOTATION_VALUE_TO_STRING_VISITOR = object
138     : SimpleAnnotationValueVisitor6<String?, Void>() {
visitStringnull139     override fun visitString(s: String?, p: Void?): String? {
140         return s
141     }
142 }
143 
144 private val ANNOTATION_VALUE_STRING_ARR_VISITOR = object
145     : SimpleAnnotationValueVisitor6<List<String>, Void>() {
visitArraynull146     override fun visitArray(vals: MutableList<out AnnotationValue>?, p: Void?): List<String> {
147         return vals?.mapNotNull {
148             ANNOTATION_VALUE_TO_STRING_VISITOR.visit(it)
149         } ?: emptyList()
150     }
151 }
152 
AnnotationValuenull153 fun AnnotationValue.getAsInt(def: Int? = null): Int? {
154     return ANNOTATION_VALUE_TO_INT_VISITOR.visit(this) ?: def
155 }
156 
AnnotationValuenull157 fun AnnotationValue.getAsString(def: String? = null): String? {
158     return ANNOTATION_VALUE_TO_STRING_VISITOR.visit(this) ?: def
159 }
160 
getAsBooleannull161 fun AnnotationValue.getAsBoolean(def: Boolean): Boolean {
162     return ANNOTATION_VALUE_TO_BOOLEAN_VISITOR.visit(this) ?: def
163 }
164 
AnnotationValuenull165 fun AnnotationValue.getAsStringList(): List<String> {
166     return ANNOTATION_VALUE_STRING_ARR_VISITOR.visit(this)
167 }
168 
169 // a variant of Types.isAssignable that ignores variance.
Typesnull170 fun Types.isAssignableWithoutVariance(from: TypeMirror, to: TypeMirror): Boolean {
171     val assignable = isAssignable(from, to)
172     if (assignable) {
173         return true
174     }
175     if (from.kind != TypeKind.DECLARED || to.kind != TypeKind.DECLARED) {
176         return false
177     }
178     val declaredFrom = MoreTypes.asDeclared(from)
179     val declaredTo = MoreTypes.asDeclared(to)
180     val fromTypeArgs = declaredFrom.typeArguments
181     val toTypeArgs = declaredTo.typeArguments
182     // no type arguments, we don't need extra checks
183     if (fromTypeArgs.isEmpty() || fromTypeArgs.size != toTypeArgs.size) {
184         return false
185     }
186     // check erasure version first, if it does not match, no reason to proceed
187     if (!isAssignable(erasure(from), erasure(to))) {
188         return false
189     }
190     // convert from args to their upper bounds if it exists
191     val fromExtendsBounds = fromTypeArgs.map {
192         it.extendsBound()
193     }
194     // if there are no upper bound conversions, return.
195     if (fromExtendsBounds.all { it == null }) {
196         return false
197     }
198     // try to move the types of the from to their upper bounds. It does not matter for the "to"
199     // because Types.isAssignable handles it as it is valid java
200     return (0 until fromTypeArgs.size).all { index ->
201         isAssignableWithoutVariance(
202                 from = fromExtendsBounds[index] ?: fromTypeArgs[index],
203                 to = toTypeArgs[index])
204     }
205 }
206 
207 // converts ? in Set< ? extends Foo> to Foo
extendsBoundnull208 fun TypeMirror.extendsBound(): TypeMirror? {
209     return this.accept(object : SimpleTypeVisitor7<TypeMirror?, Void?>() {
210         override fun visitWildcard(type: WildcardType, ignored: Void?): TypeMirror? {
211             return type.extendsBound
212         }
213     }, null)
214 }
215 
216 /**
217  * If the type mirror is in form of ? extends Foo, it returns Foo; otherwise, returns the TypeMirror
218  * itself.
219  */
TypeMirrornull220 fun TypeMirror.extendsBoundOrSelf(): TypeMirror {
221     return extendsBound() ?: this
222 }
223 
224 /**
225  * Finds the default implementation method corresponding to this Kotlin interface method.
226  */
findKotlinDefaultImplnull227 fun Element.findKotlinDefaultImpl(typeUtils: Types): Element? {
228     fun paramsMatch(ourParams: List<VariableElement>, theirParams: List<VariableElement>): Boolean {
229         if (ourParams.size != theirParams.size - 1) {
230             return false
231         }
232         ourParams.forEachIndexed { i, variableElement ->
233             // Plus 1 to their index because their first param is a self object.
234             if (!typeUtils.isSameType(theirParams[i + 1].asType(), variableElement.asType())) {
235                 return false
236             }
237         }
238         return true
239     }
240 
241     val parent = this.enclosingElement as TypeElement
242     val innerClass = parent.enclosedElements.find {
243         it.kind == ElementKind.CLASS && it.simpleName.contentEquals(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)
244     } ?: return null
245     return innerClass.enclosedElements.find {
246         it.kind == ElementKind.METHOD && it.simpleName == this.simpleName
247                 && paramsMatch(MoreElements.asExecutable(this).parameters,
248                 MoreElements.asExecutable(it).parameters)
249     }
250 }
251