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