PojoProcessor.kt revision a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252
113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar/* 213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * Copyright (C) 2017 The Android Open Source Project 313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * 413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * you may not use this file except in compliance with the License. 613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * You may obtain a copy of the License at 713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * 813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * 1013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * Unless required by applicable law or agreed to in writing, software 1113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 1213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * See the License for the specific language governing permissions and 1413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * limitations under the License. 1513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar */ 1613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 1764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarpackage android.arch.persistence.room.processor 1813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 1964db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Relation 2064db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ColumnInfo 214d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyarimport android.arch.persistence.room.Embedded 2264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Ignore 2364db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.getAllFieldsIncludingPrivateSupers 2464db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.getAnnotationValue 2564db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.getAsString 2664db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.getAsStringList 2764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.hasAnnotation 2864db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.hasAnyOf 2964db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.isCollection 3064db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ext.toClassType 3164db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.processor.ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD 3264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.processor.ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD 3364db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.processor.ProcessorErrors.CANNOT_FIND_TYPE 3464db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.processor.ProcessorErrors.POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME 3564db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.processor.cache.Cache 3664db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.CallType 3764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.Constructor 3864db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.Field 3964db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.FieldGetter 404d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyarimport android.arch.persistence.room.vo.EmbeddedField 4164db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.Entity 4264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.FieldSetter 4364db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.vo.Pojo 44092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyarimport com.google.auto.common.AnnotationMirrors 4513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport com.google.auto.common.MoreElements 4613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport com.google.auto.common.MoreTypes 4796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyarimport javax.lang.model.element.Element 4813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.ExecutableElement 4913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.Modifier 5013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.Modifier.ABSTRACT 5113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.Modifier.PRIVATE 525bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyarimport javax.lang.model.element.Modifier.PROTECTED 535bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyarimport javax.lang.model.element.Modifier.PUBLIC 5413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.Modifier.STATIC 55a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyarimport javax.lang.model.element.Modifier.TRANSIENT 5613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.TypeElement 57092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyarimport javax.lang.model.element.VariableElement 5896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyarimport javax.lang.model.type.DeclaredType 5913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.type.TypeKind 605bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyarimport javax.lang.model.type.TypeMirror 61f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyarimport javax.lang.model.util.ElementFilter 6213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 6313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar/** 6413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * Processes any class as if it is a Pojo. 6513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar */ 6696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyarclass PojoProcessor(baseContext: Context, val element: TypeElement, 6796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val bindingScope: FieldProcessor.BindingScope, 684d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val parent: EmbeddedField?) { 69aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar val context = baseContext.fork(element) 70092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar companion object { 714d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val PROCESSED_ANNOTATIONS = listOf(ColumnInfo::class, Embedded::class, 72092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar Relation::class) 73092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 745124503104860e68981cc3e3092b95932586f66fYigit Boyar fun process() : Pojo { 755124503104860e68981cc3e3092b95932586f66fYigit Boyar return context.cache.pojos.get(Cache.PojoKey(element, bindingScope, parent), { 765124503104860e68981cc3e3092b95932586f66fYigit Boyar doProcess() 775124503104860e68981cc3e3092b95932586f66fYigit Boyar }) 785124503104860e68981cc3e3092b95932586f66fYigit Boyar } 795124503104860e68981cc3e3092b95932586f66fYigit Boyar 805124503104860e68981cc3e3092b95932586f66fYigit Boyar private fun doProcess(): Pojo { 81092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // TODO handle recursion: b/35980205 8213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val declaredType = MoreTypes.asDeclared(element.asType()) 8396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar // TODO handle conflicts with super: b/35568142 8496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val allFields = element.getAllFieldsIncludingPrivateSupers(context.processingEnv) 8513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .filter { 86a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar !it.hasAnnotation(Ignore::class) 87a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar && !it.hasAnyOf(STATIC) 88a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar && (!it.hasAnyOf(TRANSIENT) 89a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar || it.hasAnnotation(ColumnInfo::class) 90a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar || it.hasAnnotation(Embedded::class) 91a3a639f77c2d82b09b5cbcd4125b1d3b2a8ed252Yigit Boyar || it.hasAnnotation(Relation::class)) 9296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 93092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .groupBy { field -> 94092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check( 95092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar PROCESSED_ANNOTATIONS.count { field.hasAnnotation(it) } < 2, field, 96092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION 97092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ) 984d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (field.hasAnnotation(Embedded::class)) { 994d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar Embedded::class 100092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else if (field.hasAnnotation(Relation::class)) { 101092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar Relation::class 102092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else { 103092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar null 104092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 105092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 106092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val myFields = allFields[null] 107092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 10896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar FieldProcessor( 10996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar baseContext = context, 11096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar containing = declaredType, 11196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar element = it, 11296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar bindingScope = bindingScope, 11396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fieldParent = parent).process() 114092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } ?: emptyList() 115092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1164d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedFields = allFields[Embedded::class] 117092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 1184d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar processEmbeddedField(declaredType, it) 119092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } ?: emptyList() 1204d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subFields = embeddedFields.flatMap { it.pojo.fields } 12113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 12296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val fields = myFields + subFields 123092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 124092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val myRelationsList = allFields[Relation::class] 125092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 126092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar processRelationField(fields, declaredType, it) 127092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 128092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.filterNotNull() ?: emptyList() 129092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1304d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subRelations = embeddedFields.flatMap { it.pojo.relations } 131092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 132092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val relations = myRelationsList + subRelations 133092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 13496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fields.groupBy { it.columnName } 13596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar .filter { it.value.size > 1 } 13696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar .forEach { 13796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.logger.e(element, ProcessorErrors.pojoDuplicateFieldNames( 13896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.key, it.value.map(Field::getPath) 13996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar )) 14096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.value.forEach { 14196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.logger.e(it.element, POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME) 14296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 14396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 14496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val methods = MoreElements.getLocalAndInheritedMethods(element, 14596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.processingEnv.elementUtils) 14613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .filter { 14796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar !it.hasAnyOf(PRIVATE, ABSTRACT, STATIC) 14813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar && !it.hasAnnotation(Ignore::class) 14913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 15013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .map { MoreElements.asExecutable(it) } 15113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 15213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val getterCandidates = methods.filter { 15313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar it.parameters.size == 0 && it.returnType.kind != TypeKind.VOID 15413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 15513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 15613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val setterCandidates = methods.filter { 15713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar it.parameters.size == 1 && it.returnType.kind == TypeKind.VOID 15813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 159f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar // don't try to find a constructor for binding to statement. 160f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val constructor = if (bindingScope == FieldProcessor.BindingScope.BIND_TO_STMT) { 161f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar // we don't need to construct this POJO. 162f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 163f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 1644d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar chooseConstructor(myFields, embeddedFields) 165f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 16613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 16796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar assignGetters(myFields, getterCandidates) 168f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetters(myFields, setterCandidates, constructor) 169092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1704d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar embeddedFields.forEach { 171092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(it.field, getterCandidates) 172f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(it.field, setterCandidates, constructor) 173092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 174092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 175092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar myRelationsList.forEach { 176092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(it.field, getterCandidates) 177f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(it.field, setterCandidates, constructor) 178092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 179092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 18096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val pojo = Pojo(element = element, 18196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar type = declaredType, 18296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fields = fields, 1834d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar embeddedFields = embeddedFields, 184f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar relations = relations, 185f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor = constructor) 18613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar return pojo 18713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 18813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 1894d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar private fun chooseConstructor(myFields: List<Field>, embedded: List<EmbeddedField>) 190f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar : Constructor? { 191f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val constructors = ElementFilter.constructorsIn(element.enclosedElements) 192f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar .filterNot { it.hasAnnotation(Ignore::class) || it.hasAnyOf(PRIVATE) } 193f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val fieldMap = myFields.associateBy { it.name } 1944d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedMap = embedded.associateBy { it.field.name } 195f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val typeUtils = context.processingEnv.typeUtils 196f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val failedConstructors = mutableMapOf<ExecutableElement, List<Constructor.Param?>>() 197f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val goodConstructors = constructors.map { constructor -> 198f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val params = constructor.parameters.map param@ { param -> 199f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramName = param.simpleName.toString() 200f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramType = param.asType() 201f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 202f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val matches = fun(field: Field?): Boolean { 203f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return if (field == null) { 204f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar false 205f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else if (!field.nameWithVariations.contains(paramName)) { 206f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar false 207f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 208f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar typeUtils.isAssignable(paramType, field.type) 209f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 210f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 211f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 212f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val exactFieldMatch = fieldMap[paramName] 213f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 214f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (matches(exactFieldMatch)) { 215f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return@param Constructor.FieldParam(exactFieldMatch!!) 216f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2174d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val exactEmbeddedMatch = embeddedMap[paramName] 2184d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (matches(exactEmbeddedMatch?.field)) { 2194d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar return@param Constructor.EmbeddedParam(exactEmbeddedMatch!!) 220f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 221f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 222f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val matchingFields = myFields.filter { 223f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matches(it) 224f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2254d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedMatches = embedded.filter { 226f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matches(it.field) 227f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2284d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (matchingFields.isEmpty() && embeddedMatches.isEmpty()) { 229f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 2304d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar } else if (matchingFields.size + embeddedMatches.size == 1) { 231f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (matchingFields.isNotEmpty()) { 232f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar Constructor.FieldParam(matchingFields.first()) 233f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 2344d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar Constructor.EmbeddedParam(embeddedMatches.first()) 235f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 236f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 237f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(param, ProcessorErrors.ambigiousConstructor( 238f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar pojo = element.qualifiedName.toString(), 239f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar paramName = param.simpleName.toString(), 240f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matchingFields = matchingFields.map { it.getPath() } 2414d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar + embedded.map { it.field.getPath() } 242f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar )) 243f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 244f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 245f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 246f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (params.any { it == null }) { 247f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar failedConstructors.put(constructor, params) 248f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 249f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 250f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar @Suppress("UNCHECKED_CAST") 251f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar Constructor(constructor, params as List<Constructor.Param>) 252f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 253f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar }.filterNotNull() 254f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (goodConstructors.isEmpty()) { 255f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (failedConstructors.isNotEmpty()) { 256f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val failureMsg = failedConstructors.entries.joinToString("\n") { entry -> 257f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramsMatching = entry.key.parameters.withIndex().joinToString(", ") { 258f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "${it.value.simpleName} : ${entry.value[it.index]?.log()}" 259f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 260f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "${entry.key} : [$paramsMatching]" 261f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 262f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR + 263f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "\nTried the following constructors but they failed to match:\n$failureMsg") 264f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 265f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR) 266f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return null 267f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 268f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (goodConstructors.size > 1) { 269f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar goodConstructors.forEach { 270f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(it.element, ProcessorErrors.TOO_MANY_POJO_CONSTRUCTORS) 271f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 272f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return null 273f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 274f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return goodConstructors.first() 275f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 276f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 2774d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar private fun processEmbeddedField(declaredType: DeclaredType?, it: Element): EmbeddedField { 2784d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val fieldPrefix = it.getAnnotationValue(Embedded::class.java, "prefix") 27996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar ?.toString() ?: "" 28096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val inheritedPrefix = parent?.prefix ?: "" 2814d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedField = Field( 28296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it, 28396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.simpleName.toString(), 28496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar type = context.processingEnv.typeUtils.asMemberOf(declaredType, it), 28596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar affinity = null, 2862c6462f129bf43965ed8b054b026f6a28fe6fd8fYigit Boyar parent = parent) 2874d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subParent = EmbeddedField( 2884d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar field = embeddedField, 28996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar prefix = inheritedPrefix + fieldPrefix, 29096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar parent = parent) 29196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val asVariable = MoreElements.asVariable(it) 29296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar subParent.pojo = PojoProcessor(baseContext = context.fork(it), 29396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar element = MoreTypes.asTypeElement(asVariable.asType()), 29496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar bindingScope = bindingScope, 29596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar parent = subParent).process() 29696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar return subParent 29796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 29896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar 299092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar private fun processRelationField(myFields : List<Field>, container: DeclaredType?, 300092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar relationElement: VariableElement) 30164db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar : android.arch.persistence.room.vo.Relation? { 302092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val annotation = MoreElements.getAnnotationMirror(relationElement, Relation::class.java) 303092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .orNull()!! 304f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar val parentColumnInput = AnnotationMirrors.getAnnotationValue(annotation, "parentColumn") 305092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsString("") ?: "" 306092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 307092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val parentField = myFields.firstOrNull { 308f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar it.columnName == parentColumnInput 309092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 310092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (parentField == null) { 311092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 312092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationCannotFindParentEntityField( 313092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityName = element.qualifiedName.toString(), 314f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar columnName = parentColumnInput, 315f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar availableColumns = myFields.map { it.columnName })) 316092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 317092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 318092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // parse it as an entity. 319092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val asMember = MoreTypes 320092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .asMemberOf(context.processingEnv.typeUtils, container, relationElement) 321092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (asMember.kind == TypeKind.ERROR) { 322092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(ProcessorErrors.CANNOT_FIND_TYPE, element) 323092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 324092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 325092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val declared = MoreTypes.asDeclared(asMember) 326092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (!declared.isCollection()) { 327092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, ProcessorErrors.RELATION_NOT_COLLECTION) 328092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 329092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 330092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val typeArg = declared.typeArguments.first() 331092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (typeArg.kind == TypeKind.ERROR) { 332092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(MoreTypes.asTypeElement(typeArg), CANNOT_FIND_TYPE) 333092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 334092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 335092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val typeArgElement = MoreTypes.asTypeElement(typeArg) 336092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entityClassInput = AnnotationMirrors 337092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAnnotationValue(annotation, "entity").toClassType() 338092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val pojo : Pojo 339092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entity : Entity 340092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (entityClassInput == null 341092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar || MoreTypes.isTypeOf(Any::class.java, entityClassInput)) { 342092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = EntityProcessor(context, typeArgElement).process() 343092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = entity 344092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else { 345092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = EntityProcessor(context, MoreTypes.asTypeElement(entityClassInput)).process() 346092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = PojoProcessor(baseContext = context, 347092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar element = typeArgElement, 348092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR, 349092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parent = parent).process() 350092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 351092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // now find the field in the entity. 352f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar val entityColumnInput = AnnotationMirrors.getAnnotationValue(annotation, "entityColumn") 353092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsString() ?: "" 354092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entityField = entity.fields.firstOrNull { 355f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar it.columnName == entityColumnInput 356092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 357092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 358092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (entityField == null) { 359092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 360092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationCannotFindEntityField( 361092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityName = entity.typeName.toString(), 362f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar columnName = entityColumnInput, 363f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar availableColumns = entity.fields.map { it.columnName })) 364092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 365092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 366092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 367092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val field = Field( 368092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar element = relationElement, 369092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = relationElement.simpleName.toString(), 370092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = context.processingEnv.typeUtils.asMemberOf(container, relationElement), 371092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar affinity = null, 372092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parent = parent) 373092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 374092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val projection = AnnotationMirrors.getAnnotationValue(annotation, "projection") 375092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsStringList() 376092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if(projection.isNotEmpty()) { 377092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val missingColumns = projection.filterNot { columnName -> 378092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity.fields.any { columnName == it.columnName } 379092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 380092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (missingColumns.isNotEmpty()) { 381092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 382092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationBadProject(entity.typeName.toString(), 383092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar missingColumns, entity.fields.map { it.columnName })) 384092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 385092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 386092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 387092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // if types don't match, row adapter prints a warning 38864db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar return android.arch.persistence.room.vo.Relation( 389092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = entity, 390092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = pojo, 391092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field = field, 392092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parentField = parentField, 393092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityField = entityField, 394092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar projection = projection 395092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ) 396092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 397092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 39813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar private fun assignGetters(fields: List<Field>, getterCandidates: List<ExecutableElement>) { 39913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar fields.forEach { field -> 400092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(field, getterCandidates) 40113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 40213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 40313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 404092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar private fun assignGetter(field: Field, getterCandidates: List<ExecutableElement>) { 405092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val success = chooseAssignment(field = field, 406092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar candidates = getterCandidates, 407092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar nameVariations = field.getterNameWithVariations, 408092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar getType = { method -> 409092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar method.returnType 410092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 411092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromField = { 412092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.getter = FieldGetter( 413092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = field.name, 414092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = field.type, 415092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.FIELD) 416092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 417092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromMethod = { match -> 418092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.getter = FieldGetter( 419092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = match.simpleName.toString(), 420092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = match.returnType, 421092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.METHOD) 422092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 423092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar reportAmbiguity = { matching -> 424092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(field.element, 425092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.tooManyMatchingGetters(field, matching)) 426092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }) 427092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check(success, field.element, CANNOT_FIND_GETTER_FOR_FIELD) 428092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 429092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 430f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar private fun assignSetters(fields: List<Field>, setterCandidates: List<ExecutableElement>, 431f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor : Constructor?) { 43213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar fields.forEach { field -> 433f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(field, setterCandidates, constructor) 4345bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4355bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4365bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar 437f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar private fun assignSetter(field: Field, setterCandidates: List<ExecutableElement>, 438f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor: Constructor?) { 439f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (constructor != null && constructor.hasField(field)) { 440f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar field.setter = FieldSetter(field.name, field.type, CallType.CONSTRUCTOR) 441f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return 442f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 443092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val success = chooseAssignment(field = field, 444092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar candidates = setterCandidates, 445092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar nameVariations = field.setterNameWithVariations, 446092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar getType = { method -> 447092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar method.parameters.first().asType() 448092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 449092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromField = { 450092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.setter = FieldSetter( 451092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = field.name, 452092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = field.type, 453092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.FIELD) 454092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 455092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromMethod = { match -> 456092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val paramType = match.parameters.first().asType() 457092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.setter = FieldSetter( 458092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = match.simpleName.toString(), 459092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = paramType, 460092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.METHOD) 461092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 462092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar reportAmbiguity = { matching -> 463092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(field.element, 464092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.tooManyMatchingSetter(field, matching)) 465092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }) 466092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check(success, field.element, CANNOT_FIND_SETTER_FOR_FIELD) 467092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 468092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 4695bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar /** 4705bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * Finds a setter/getter from available list of methods. 4715bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * It returns true if assignment is successful, false otherwise. 4725bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * At worst case, it sets to the field as if it is accessible so that the rest of the 4735bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * compilation can continue. 4745bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar */ 4755bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar private fun chooseAssignment(field: Field, candidates: List<ExecutableElement>, 47696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar nameVariations: List<String>, 47796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar getType: (ExecutableElement) -> TypeMirror, 4785bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField: () -> Unit, 4795bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromMethod: (ExecutableElement) -> Unit, 4805bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity: (List<String>) -> Unit): Boolean { 4815bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (field.element.hasAnyOf(PUBLIC)) { 4825bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 4835bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return true 4845bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4855bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val types = context.processingEnv.typeUtils 4866d6fe7fde68c1285107cedd5fc18d4c02232a4a6Yigit Boyar 4875bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val matching = candidates 4885bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar .filter { 4896d6fe7fde68c1285107cedd5fc18d4c02232a4a6Yigit Boyar types.isAssignable(getType(it), field.element.asType()) 4906d6fe7fde68c1285107cedd5fc18d4c02232a4a6Yigit Boyar && (field.nameWithVariations.contains(it.simpleName.toString()) 4916d6fe7fde68c1285107cedd5fc18d4c02232a4a6Yigit Boyar || nameVariations.contains(it.simpleName.toString())) 49213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 4935bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar .groupBy { 4945bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (it.hasAnyOf(PUBLIC)) PUBLIC else PROTECTED 4955bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4965bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (matching.isEmpty()) { 4975bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // we always assign to avoid NPEs in the rest of the compilation. 4985bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 4995bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // if field is not private, assume it works (if we are on the same package). 5005bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // if not, compiler will tell, we didn't have any better alternative anyways. 5015bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return !field.element.hasAnyOf(PRIVATE) 5025bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5035bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val match = verifyAndChooseOneFrom(matching[PUBLIC], reportAmbiguity) ?: 5045bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar verifyAndChooseOneFrom(matching[PROTECTED], reportAmbiguity) 5055bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (match == null) { 5065bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 5075bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return false 5085bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } else { 5095bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromMethod(match) 5105bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return true 5115bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5125bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5135bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar 5145bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar private fun verifyAndChooseOneFrom(candidates: List<ExecutableElement>?, 5155bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity: (List<String>) -> Unit) 5165bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar : ExecutableElement? { 5175bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (candidates == null) { 5185bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return null 5195bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5205bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (candidates.size > 1) { 5215bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity(candidates.map { it.simpleName.toString() }) 52213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 5235bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return candidates.first() 52413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 52513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar} 526