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 android.arch.persistence.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 javax.annotation.processing.ProcessingEnvironment
25 import javax.lang.model.element.AnnotationValue
26 import javax.lang.model.element.Element
27 import javax.lang.model.element.ElementKind
28 import javax.lang.model.element.Modifier
29 import javax.lang.model.element.TypeElement
30 import javax.lang.model.element.VariableElement
31 import javax.lang.model.type.TypeKind
32 import javax.lang.model.type.TypeMirror
33 import javax.lang.model.util.SimpleAnnotationValueVisitor6
34 import kotlin.reflect.KClass
35
hasAnyOfnull36 fun Element.hasAnyOf(vararg modifiers: Modifier): Boolean {
37 return this.modifiers.any { modifiers.contains(it) }
38 }
39
hasAnnotationnull40 fun Element.hasAnnotation(klass: KClass<out Annotation>): Boolean {
41 return MoreElements.isAnnotationPresent(this, klass.java)
42 }
43
isNonNullnull44 fun Element.isNonNull() =
45 asType().kind.isPrimitive
46 || hasAnnotation(android.support.annotation.NonNull::class)
47 || hasAnnotation(org.jetbrains.annotations.NotNull::class)
48
49 /**
50 * gets all members including super privates. does not handle duplicate field names!!!
51 */
52 // TODO handle conflicts with super: b/35568142
53 fun TypeElement.getAllFieldsIncludingPrivateSupers(processingEnvironment: ProcessingEnvironment):
54 Set<VariableElement> {
55 val myMembers = processingEnvironment.elementUtils.getAllMembers(this)
56 .filter { it.kind == ElementKind.FIELD }
57 .filter { it is VariableElement }
58 .map { it as VariableElement }
59 .toSet()
60 if (superclass.kind != TypeKind.NONE) {
61 return myMembers + MoreTypes.asTypeElement(superclass)
62 .getAllFieldsIncludingPrivateSupers(processingEnvironment)
63 } else {
64 return myMembers
65 }
66 }
67
68 // code below taken from dagger2
69 // compiler/src/main/java/dagger/internal/codegen/ConfigurationAnnotations.java
70 private val TO_LIST_OF_TYPES = object
71 : SimpleAnnotationValueVisitor6<List<TypeMirror>, Void?>() {
visitArraynull72 override fun visitArray(values: MutableList<out AnnotationValue>?, p: Void?)
73 : List<TypeMirror> {
74 return values?.map {
75 val tmp = TO_TYPE.visit(it)
76 tmp
77 }?.filterNotNull() ?: emptyList()
78 }
79
80
defaultActionnull81 override fun defaultAction(o: Any?, p: Void?): List<TypeMirror>? {
82 return emptyList()
83 }
84 }
85
86 private val TO_TYPE = object : SimpleAnnotationValueVisitor6<TypeMirror, Void>() {
87
visitTypenull88 override fun visitType(t: TypeMirror, p: Void?): TypeMirror {
89 return t
90 }
91
defaultActionnull92 override fun defaultAction(o: Any?, p: Void?): TypeMirror {
93 throw TypeNotPresentException(o!!.toString(), null)
94 }
95 }
96
AnnotationValuenull97 fun AnnotationValue.toListOfClassTypes(): List<TypeMirror> {
98 return TO_LIST_OF_TYPES.visit(this)
99 }
100
toTypenull101 fun AnnotationValue.toType(): TypeMirror {
102 return TO_TYPE.visit(this)
103 }
104
toClassTypenull105 fun AnnotationValue.toClassType(): TypeMirror? {
106 return TO_TYPE.visit(this)
107 }
108
TypeMirrornull109 fun TypeMirror.isCollection(): Boolean {
110 return MoreTypes.isType(this)
111 && (MoreTypes.isTypeOf(java.util.List::class.java, this)
112 || MoreTypes.isTypeOf(java.util.Set::class.java, this))
113 }
114
getAnnotationValuenull115 fun Element.getAnnotationValue(annotation: Class<out Annotation>, fieldName: String): Any? {
116 return MoreElements.getAnnotationMirror(this, annotation)
117 .orNull()?.let {
118 AnnotationMirrors.getAnnotationValue(it, fieldName)?.value
119 }
120 }
121
122 private val ANNOTATION_VALUE_TO_INT_VISITOR = object : SimpleAnnotationValueVisitor6<Int?, Void>() {
visitIntnull123 override fun visitInt(i: Int, p: Void?): Int? {
124 return i
125 }
126 }
127
128 private val ANNOTATION_VALUE_TO_BOOLEAN_VISITOR = object
129 : SimpleAnnotationValueVisitor6<Boolean?, Void>() {
visitBooleannull130 override fun visitBoolean(b: Boolean, p: Void?): Boolean? {
131 return b
132 }
133 }
134
135 private val ANNOTATION_VALUE_TO_STRING_VISITOR = object
136 : SimpleAnnotationValueVisitor6<String?, Void>() {
visitStringnull137 override fun visitString(s: String?, p: Void?): String? {
138 return s
139 }
140 }
141
142 private val ANNOTATION_VALUE_STRING_ARR_VISITOR = object
143 : SimpleAnnotationValueVisitor6<List<String>, Void>() {
visitArraynull144 override fun visitArray(vals: MutableList<out AnnotationValue>?, p: Void?): List<String> {
145 return vals?.map {
146 ANNOTATION_VALUE_TO_STRING_VISITOR.visit(it)
147 }?.filterNotNull() ?: emptyList()
148 }
149 }
150
AnnotationValuenull151 fun AnnotationValue.getAsInt(def: Int? = null): Int? {
152 return ANNOTATION_VALUE_TO_INT_VISITOR.visit(this) ?: def
153 }
154
AnnotationValuenull155 fun AnnotationValue.getAsString(def: String? = null): String? {
156 return ANNOTATION_VALUE_TO_STRING_VISITOR.visit(this) ?: def
157 }
158
getAsBooleannull159 fun AnnotationValue.getAsBoolean(def: Boolean): Boolean {
160 return ANNOTATION_VALUE_TO_BOOLEAN_VISITOR.visit(this) ?: def
161 }
162
AnnotationValuenull163 fun AnnotationValue.getAsStringList(): List<String> {
164 return ANNOTATION_VALUE_STRING_ARR_VISITOR.visit(this)
165 }
166