PojoProcessor.kt revision 4d4bae3f216e55f824d7d7fbfe2f8861906ee3e2
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 5513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.element.TypeElement 56092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyarimport javax.lang.model.element.VariableElement 5796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyarimport javax.lang.model.type.DeclaredType 5813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyarimport javax.lang.model.type.TypeKind 595bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyarimport javax.lang.model.type.TypeMirror 60f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyarimport javax.lang.model.util.ElementFilter 6113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 6213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar/** 6313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar * Processes any class as if it is a Pojo. 6413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar */ 6596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyarclass PojoProcessor(baseContext: Context, val element: TypeElement, 6696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val bindingScope: FieldProcessor.BindingScope, 674d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val parent: EmbeddedField?) { 68aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar val context = baseContext.fork(element) 69092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar companion object { 704d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val PROCESSED_ANNOTATIONS = listOf(ColumnInfo::class, Embedded::class, 71092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar Relation::class) 72092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 735124503104860e68981cc3e3092b95932586f66fYigit Boyar fun process() : Pojo { 745124503104860e68981cc3e3092b95932586f66fYigit Boyar return context.cache.pojos.get(Cache.PojoKey(element, bindingScope, parent), { 755124503104860e68981cc3e3092b95932586f66fYigit Boyar doProcess() 765124503104860e68981cc3e3092b95932586f66fYigit Boyar }) 775124503104860e68981cc3e3092b95932586f66fYigit Boyar } 785124503104860e68981cc3e3092b95932586f66fYigit Boyar 795124503104860e68981cc3e3092b95932586f66fYigit Boyar private fun doProcess(): Pojo { 80092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // TODO handle recursion: b/35980205 8113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val declaredType = MoreTypes.asDeclared(element.asType()) 8296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar // TODO handle conflicts with super: b/35568142 8396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val allFields = element.getAllFieldsIncludingPrivateSupers(context.processingEnv) 8413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .filter { 8596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar !it.hasAnnotation(Ignore::class) && !it.hasAnyOf(Modifier.STATIC) 8696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 87092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .groupBy { field -> 88092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check( 89092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar PROCESSED_ANNOTATIONS.count { field.hasAnnotation(it) } < 2, field, 90092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.CANNOT_USE_MORE_THAN_ONE_POJO_FIELD_ANNOTATION 91092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ) 924d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (field.hasAnnotation(Embedded::class)) { 934d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar Embedded::class 94092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else if (field.hasAnnotation(Relation::class)) { 95092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar Relation::class 96092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else { 97092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar null 98092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 99092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 100092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val myFields = allFields[null] 101092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 10296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar FieldProcessor( 10396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar baseContext = context, 10496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar containing = declaredType, 10596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar element = it, 10696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar bindingScope = bindingScope, 10796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fieldParent = parent).process() 108092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } ?: emptyList() 109092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1104d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedFields = allFields[Embedded::class] 111092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 1124d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar processEmbeddedField(declaredType, it) 113092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } ?: emptyList() 1144d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subFields = embeddedFields.flatMap { it.pojo.fields } 11513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 11696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val fields = myFields + subFields 117092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 118092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val myRelationsList = allFields[Relation::class] 119092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.map { 120092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar processRelationField(fields, declaredType, it) 121092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 122092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ?.filterNotNull() ?: emptyList() 123092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1244d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subRelations = embeddedFields.flatMap { it.pojo.relations } 125092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 126092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val relations = myRelationsList + subRelations 127092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 12896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fields.groupBy { it.columnName } 12996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar .filter { it.value.size > 1 } 13096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar .forEach { 13196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.logger.e(element, ProcessorErrors.pojoDuplicateFieldNames( 13296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.key, it.value.map(Field::getPath) 13396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar )) 13496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.value.forEach { 13596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.logger.e(it.element, POJO_FIELD_HAS_DUPLICATE_COLUMN_NAME) 13696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 13796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 13896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val methods = MoreElements.getLocalAndInheritedMethods(element, 13996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar context.processingEnv.elementUtils) 14013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .filter { 14196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar !it.hasAnyOf(PRIVATE, ABSTRACT, STATIC) 14213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar && !it.hasAnnotation(Ignore::class) 14313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 14413a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar .map { MoreElements.asExecutable(it) } 14513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 14613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val getterCandidates = methods.filter { 14713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar it.parameters.size == 0 && it.returnType.kind != TypeKind.VOID 14813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 14913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 15013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar val setterCandidates = methods.filter { 15113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar it.parameters.size == 1 && it.returnType.kind == TypeKind.VOID 15213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 153f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar // don't try to find a constructor for binding to statement. 154f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val constructor = if (bindingScope == FieldProcessor.BindingScope.BIND_TO_STMT) { 155f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar // we don't need to construct this POJO. 156f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 157f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 1584d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar chooseConstructor(myFields, embeddedFields) 159f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 16013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 16196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar assignGetters(myFields, getterCandidates) 162f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetters(myFields, setterCandidates, constructor) 163092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 1644d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar embeddedFields.forEach { 165092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(it.field, getterCandidates) 166f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(it.field, setterCandidates, constructor) 167092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 168092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 169092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar myRelationsList.forEach { 170092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(it.field, getterCandidates) 171f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(it.field, setterCandidates, constructor) 172092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 173092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 17496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val pojo = Pojo(element = element, 17596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar type = declaredType, 17696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar fields = fields, 1774d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar embeddedFields = embeddedFields, 178f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar relations = relations, 179f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor = constructor) 18013a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar return pojo 18113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 18213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 1834d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar private fun chooseConstructor(myFields: List<Field>, embedded: List<EmbeddedField>) 184f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar : Constructor? { 185f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val constructors = ElementFilter.constructorsIn(element.enclosedElements) 186f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar .filterNot { it.hasAnnotation(Ignore::class) || it.hasAnyOf(PRIVATE) } 187f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val fieldMap = myFields.associateBy { it.name } 1884d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedMap = embedded.associateBy { it.field.name } 189f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val typeUtils = context.processingEnv.typeUtils 190f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val failedConstructors = mutableMapOf<ExecutableElement, List<Constructor.Param?>>() 191f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val goodConstructors = constructors.map { constructor -> 192f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val params = constructor.parameters.map param@ { param -> 193f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramName = param.simpleName.toString() 194f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramType = param.asType() 195f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 196f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val matches = fun(field: Field?): Boolean { 197f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return if (field == null) { 198f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar false 199f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else if (!field.nameWithVariations.contains(paramName)) { 200f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar false 201f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 202f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar typeUtils.isAssignable(paramType, field.type) 203f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 204f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 205f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 206f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val exactFieldMatch = fieldMap[paramName] 207f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 208f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (matches(exactFieldMatch)) { 209f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return@param Constructor.FieldParam(exactFieldMatch!!) 210f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2114d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val exactEmbeddedMatch = embeddedMap[paramName] 2124d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (matches(exactEmbeddedMatch?.field)) { 2134d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar return@param Constructor.EmbeddedParam(exactEmbeddedMatch!!) 214f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 215f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 216f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val matchingFields = myFields.filter { 217f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matches(it) 218f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2194d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedMatches = embedded.filter { 220f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matches(it.field) 221f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 2224d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar if (matchingFields.isEmpty() && embeddedMatches.isEmpty()) { 223f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 2244d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar } else if (matchingFields.size + embeddedMatches.size == 1) { 225f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (matchingFields.isNotEmpty()) { 226f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar Constructor.FieldParam(matchingFields.first()) 227f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 2284d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar Constructor.EmbeddedParam(embeddedMatches.first()) 229f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 230f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 231f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(param, ProcessorErrors.ambigiousConstructor( 232f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar pojo = element.qualifiedName.toString(), 233f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar paramName = param.simpleName.toString(), 234f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar matchingFields = matchingFields.map { it.getPath() } 2354d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar + embedded.map { it.field.getPath() } 236f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar )) 237f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 238f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 239f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 240f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (params.any { it == null }) { 241f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar failedConstructors.put(constructor, params) 242f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar null 243f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } else { 244f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar @Suppress("UNCHECKED_CAST") 245f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar Constructor(constructor, params as List<Constructor.Param>) 246f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 247f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar }.filterNotNull() 248f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (goodConstructors.isEmpty()) { 249f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (failedConstructors.isNotEmpty()) { 250f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val failureMsg = failedConstructors.entries.joinToString("\n") { entry -> 251f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar val paramsMatching = entry.key.parameters.withIndex().joinToString(", ") { 252f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "${it.value.simpleName} : ${entry.value[it.index]?.log()}" 253f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 254f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "${entry.key} : [$paramsMatching]" 255f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 256f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR + 257f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar "\nTried the following constructors but they failed to match:\n$failureMsg") 258f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 259f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(element, ProcessorErrors.MISSING_POJO_CONSTRUCTOR) 260f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return null 261f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 262f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (goodConstructors.size > 1) { 263f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar goodConstructors.forEach { 264f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar context.logger.e(it.element, ProcessorErrors.TOO_MANY_POJO_CONSTRUCTORS) 265f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 266f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return null 267f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 268f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return goodConstructors.first() 269f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 270f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar 2714d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar private fun processEmbeddedField(declaredType: DeclaredType?, it: Element): EmbeddedField { 2724d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val fieldPrefix = it.getAnnotationValue(Embedded::class.java, "prefix") 27396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar ?.toString() ?: "" 27496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val inheritedPrefix = parent?.prefix ?: "" 2754d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val embeddedField = Field( 27696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it, 27796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar it.simpleName.toString(), 27896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar type = context.processingEnv.typeUtils.asMemberOf(declaredType, it), 27996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar affinity = null, 2802c6462f129bf43965ed8b054b026f6a28fe6fd8fYigit Boyar parent = parent) 2814d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar val subParent = EmbeddedField( 2824d4bae3f216e55f824d7d7fbfe2f8861906ee3e2Yigit Boyar field = embeddedField, 28396cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar prefix = inheritedPrefix + fieldPrefix, 28496cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar parent = parent) 28596cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar val asVariable = MoreElements.asVariable(it) 28696cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar subParent.pojo = PojoProcessor(baseContext = context.fork(it), 28796cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar element = MoreTypes.asTypeElement(asVariable.asType()), 28896cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar bindingScope = bindingScope, 28996cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar parent = subParent).process() 29096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar return subParent 29196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar } 29296cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar 293092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar private fun processRelationField(myFields : List<Field>, container: DeclaredType?, 294092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar relationElement: VariableElement) 29564db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar : android.arch.persistence.room.vo.Relation? { 296092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val annotation = MoreElements.getAnnotationMirror(relationElement, Relation::class.java) 297092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .orNull()!! 298f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar val parentColumnInput = AnnotationMirrors.getAnnotationValue(annotation, "parentColumn") 299092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsString("") ?: "" 300092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 301092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val parentField = myFields.firstOrNull { 302f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar it.columnName == parentColumnInput 303092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 304092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (parentField == null) { 305092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 306092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationCannotFindParentEntityField( 307092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityName = element.qualifiedName.toString(), 308f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar columnName = parentColumnInput, 309f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar availableColumns = myFields.map { it.columnName })) 310092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 311092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 312092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // parse it as an entity. 313092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val asMember = MoreTypes 314092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .asMemberOf(context.processingEnv.typeUtils, container, relationElement) 315092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (asMember.kind == TypeKind.ERROR) { 316092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(ProcessorErrors.CANNOT_FIND_TYPE, element) 317092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 318092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 319092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val declared = MoreTypes.asDeclared(asMember) 320092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (!declared.isCollection()) { 321092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, ProcessorErrors.RELATION_NOT_COLLECTION) 322092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 323092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 324092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val typeArg = declared.typeArguments.first() 325092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (typeArg.kind == TypeKind.ERROR) { 326092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(MoreTypes.asTypeElement(typeArg), CANNOT_FIND_TYPE) 327092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 328092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 329092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val typeArgElement = MoreTypes.asTypeElement(typeArg) 330092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entityClassInput = AnnotationMirrors 331092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAnnotationValue(annotation, "entity").toClassType() 332092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val pojo : Pojo 333092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entity : Entity 334092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (entityClassInput == null 335092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar || MoreTypes.isTypeOf(Any::class.java, entityClassInput)) { 336092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = EntityProcessor(context, typeArgElement).process() 337092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = entity 338092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } else { 339092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = EntityProcessor(context, MoreTypes.asTypeElement(entityClassInput)).process() 340092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = PojoProcessor(baseContext = context, 341092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar element = typeArgElement, 342092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar bindingScope = FieldProcessor.BindingScope.READ_FROM_CURSOR, 343092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parent = parent).process() 344092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 345092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // now find the field in the entity. 346f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar val entityColumnInput = AnnotationMirrors.getAnnotationValue(annotation, "entityColumn") 347092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsString() ?: "" 348092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val entityField = entity.fields.firstOrNull { 349f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar it.columnName == entityColumnInput 350092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 351092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 352092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (entityField == null) { 353092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 354092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationCannotFindEntityField( 355092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityName = entity.typeName.toString(), 356f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar columnName = entityColumnInput, 357f385ca501bbfd3ccaf6b412f8f09c64d9ee742f2Yigit Boyar availableColumns = entity.fields.map { it.columnName })) 358092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar return null 359092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 360092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 361092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val field = Field( 362092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar element = relationElement, 363092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = relationElement.simpleName.toString(), 364092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = context.processingEnv.typeUtils.asMemberOf(container, relationElement), 365092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar affinity = null, 366092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parent = parent) 367092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 368092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val projection = AnnotationMirrors.getAnnotationValue(annotation, "projection") 369092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar .getAsStringList() 370092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if(projection.isNotEmpty()) { 371092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val missingColumns = projection.filterNot { columnName -> 372092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity.fields.any { columnName == it.columnName } 373092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 374092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar if (missingColumns.isNotEmpty()) { 375092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(relationElement, 376092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.relationBadProject(entity.typeName.toString(), 377092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar missingColumns, entity.fields.map { it.columnName })) 378092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 379092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 380092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 381092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar // if types don't match, row adapter prints a warning 38264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar return android.arch.persistence.room.vo.Relation( 383092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entity = entity, 384092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar pojo = pojo, 385092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field = field, 386092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar parentField = parentField, 387092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar entityField = entityField, 388092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar projection = projection 389092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ) 390092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 391092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 39213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar private fun assignGetters(fields: List<Field>, getterCandidates: List<ExecutableElement>) { 39313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar fields.forEach { field -> 394092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignGetter(field, getterCandidates) 39513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 39613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 39713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar 398092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar private fun assignGetter(field: Field, getterCandidates: List<ExecutableElement>) { 399092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val success = chooseAssignment(field = field, 400092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar candidates = getterCandidates, 401092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar nameVariations = field.getterNameWithVariations, 402092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar getType = { method -> 403092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar method.returnType 404092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 405092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromField = { 406092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.getter = FieldGetter( 407092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = field.name, 408092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = field.type, 409092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.FIELD) 410092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 411092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromMethod = { match -> 412092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.getter = FieldGetter( 413092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = match.simpleName.toString(), 414092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = match.returnType, 415092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.METHOD) 416092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 417092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar reportAmbiguity = { matching -> 418092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(field.element, 419092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.tooManyMatchingGetters(field, matching)) 420092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }) 421092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check(success, field.element, CANNOT_FIND_GETTER_FOR_FIELD) 422092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 423092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 424f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar private fun assignSetters(fields: List<Field>, setterCandidates: List<ExecutableElement>, 425f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor : Constructor?) { 42613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar fields.forEach { field -> 427f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar assignSetter(field, setterCandidates, constructor) 4285bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4295bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4305bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar 431f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar private fun assignSetter(field: Field, setterCandidates: List<ExecutableElement>, 432f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar constructor: Constructor?) { 433f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar if (constructor != null && constructor.hasField(field)) { 434f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar field.setter = FieldSetter(field.name, field.type, CallType.CONSTRUCTOR) 435f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar return 436f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar } 437092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val success = chooseAssignment(field = field, 438092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar candidates = setterCandidates, 439092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar nameVariations = field.setterNameWithVariations, 440092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar getType = { method -> 441092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar method.parameters.first().asType() 442092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 443092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromField = { 444092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.setter = FieldSetter( 445092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = field.name, 446092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = field.type, 447092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.FIELD) 448092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 449092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar assignFromMethod = { match -> 450092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar val paramType = match.parameters.first().asType() 451092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar field.setter = FieldSetter( 452092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar name = match.simpleName.toString(), 453092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar type = paramType, 454092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar callType = CallType.METHOD) 455092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }, 456092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar reportAmbiguity = { matching -> 457092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.logger.e(field.element, 458092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar ProcessorErrors.tooManyMatchingSetter(field, matching)) 459092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar }) 460092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar context.checker.check(success, field.element, CANNOT_FIND_SETTER_FOR_FIELD) 461092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar } 462092164e5501d0a254001225acd9dca42e5fa57e9Yigit Boyar 4635bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar /** 4645bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * Finds a setter/getter from available list of methods. 4655bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * It returns true if assignment is successful, false otherwise. 4665bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * At worst case, it sets to the field as if it is accessible so that the rest of the 4675bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar * compilation can continue. 4685bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar */ 4695bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar private fun chooseAssignment(field: Field, candidates: List<ExecutableElement>, 47096cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar nameVariations: List<String>, 47196cc740203eaa752fc85ca7ca722a8de550ae88cYigit Boyar getType: (ExecutableElement) -> TypeMirror, 4725bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField: () -> Unit, 4735bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromMethod: (ExecutableElement) -> Unit, 4745bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity: (List<String>) -> Unit): Boolean { 4755bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (field.element.hasAnyOf(PUBLIC)) { 4765bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 4775bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return true 4785bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4795bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val types = context.processingEnv.typeUtils 4805bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val matching = candidates 4815bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar .filter { 4825bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar types.isSameType(field.element.asType(), getType(it)) 4835bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar && field.nameWithVariations.contains(it.simpleName.toString()) 4845bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar || nameVariations.contains(it.simpleName.toString()) 48513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 4865bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar .groupBy { 4875bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (it.hasAnyOf(PUBLIC)) PUBLIC else PROTECTED 4885bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4895bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (matching.isEmpty()) { 4905bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // we always assign to avoid NPEs in the rest of the compilation. 4915bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 4925bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // if field is not private, assume it works (if we are on the same package). 4935bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar // if not, compiler will tell, we didn't have any better alternative anyways. 4945bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return !field.element.hasAnyOf(PRIVATE) 4955bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 4965bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar val match = verifyAndChooseOneFrom(matching[PUBLIC], reportAmbiguity) ?: 4975bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar verifyAndChooseOneFrom(matching[PROTECTED], reportAmbiguity) 4985bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (match == null) { 4995bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromField() 5005bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return false 5015bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } else { 5025bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar assignFromMethod(match) 5035bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return true 5045bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5055bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5065bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar 5075bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar private fun verifyAndChooseOneFrom(candidates: List<ExecutableElement>?, 5085bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity: (List<String>) -> Unit) 5095bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar : ExecutableElement? { 5105bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (candidates == null) { 5115bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return null 5125bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar } 5135bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar if (candidates.size > 1) { 5145bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar reportAmbiguity(candidates.map { it.simpleName.toString() }) 51513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 5165bd1d1b032b37561f015985ca8854b89214bbcb3Yigit Boyar return candidates.first() 51713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar } 51813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar} 519