Home | History | Annotate | Download | only in ext
      1 /*
      2  * 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 
     44 fun Element.hasAnnotation(klass: KClass<out Annotation>): Boolean {
     45     return MoreElements.isAnnotationPresent(this, klass.java)
     46 }
     47 
     48 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?>() {
     76     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 
     83     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 
     90     override fun visitType(t: TypeMirror, p: Void?): TypeMirror {
     91         return t
     92     }
     93 
     94     override fun defaultAction(o: Any?, p: Void?): TypeMirror {
     95         throw TypeNotPresentException(o!!.toString(), null)
     96     }
     97 }
     98 
     99 fun AnnotationValue.toListOfClassTypes(): List<TypeMirror> {
    100     return TO_LIST_OF_TYPES.visit(this)
    101 }
    102 
    103 fun AnnotationValue.toType(): TypeMirror {
    104     return TO_TYPE.visit(this)
    105 }
    106 
    107 fun AnnotationValue.toClassType(): TypeMirror? {
    108     return TO_TYPE.visit(this)
    109 }
    110 
    111 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 
    117 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>() {
    125     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>() {
    132     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>() {
    139     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>() {
    146     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 
    153 fun AnnotationValue.getAsInt(def: Int? = null): Int? {
    154     return ANNOTATION_VALUE_TO_INT_VISITOR.visit(this) ?: def
    155 }
    156 
    157 fun AnnotationValue.getAsString(def: String? = null): String? {
    158     return ANNOTATION_VALUE_TO_STRING_VISITOR.visit(this) ?: def
    159 }
    160 
    161 fun AnnotationValue.getAsBoolean(def: Boolean): Boolean {
    162     return ANNOTATION_VALUE_TO_BOOLEAN_VISITOR.visit(this) ?: def
    163 }
    164 
    165 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.
    170 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
    208 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  */
    220 fun TypeMirror.extendsBoundOrSelf(): TypeMirror {
    221     return extendsBound() ?: this
    222 }
    223 
    224 /**
    225  * Finds the default implementation method corresponding to this Kotlin interface method.
    226  */
    227 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