EntityProcessor.kt revision 8bad027c789d3fb3da8e68fa0154f2a24ccc2865
11600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar/* 21600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * Copyright (C) 2016 The Android Open Source Project 31600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * 41600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 51600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * you may not use this file except in compliance with the License. 61600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * You may obtain a copy of the License at 71600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * 81600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 91600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * 101600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * Unless required by applicable law or agreed to in writing, software 111600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 121600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * See the License for the specific language governing permissions and 141600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar * limitations under the License. 151600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar */ 161600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 171600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarpackage com.android.support.room.processor 181600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 191600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.android.support.room.Ignore 201600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.android.support.room.errors.ElementBoundException 211600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.android.support.room.ext.hasAnnotation 221600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.android.support.room.ext.hasAnyOf 23e6325fbeaa2e6759496ea2ca9a4d3d958df690d7Yigit Boyarimport com.android.support.room.preconditions.Checks 241600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.android.support.room.vo.* 251600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.google.auto.common.MoreElements 261600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.google.auto.common.MoreTypes 271600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport com.squareup.javapoet.TypeName 281600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.annotation.processing.ProcessingEnvironment 291600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.annotation.processing.RoundEnvironment 301600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.element.ElementKind 311600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.element.ExecutableElement 321600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.element.Modifier 331600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.element.Modifier.* 341600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.element.TypeElement 351600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyarimport javax.lang.model.type.TypeKind 361600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 378bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarclass EntityProcessor(val roundEnv: RoundEnvironment, 388bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar val processingEnvironment: ProcessingEnvironment) { 398bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar val fieldParser = FieldProcessor(roundEnv, processingEnvironment) 401600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 411600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar fun parse(element: TypeElement): Entity { 428bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar Checks.hasAnnotation(element, com.android.support.room.Entity::class, 438bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar ProcessorErrors.ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY) 441600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val declaredType = MoreTypes.asDeclared(element.asType()) 451600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val allMembers = processingEnvironment.elementUtils.getAllMembers(element) 461600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val fields = allMembers 471600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .filter { 481600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar it.kind == ElementKind.FIELD 491600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && !it.hasAnnotation(Ignore::class) 501600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && !it.hasAnyOf(Modifier.STATIC) 511600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 521600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .map { fieldParser.parse(declaredType, it) } 531600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 541600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val methods = allMembers 551600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .filter { 561600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar it.kind == ElementKind.METHOD 571600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && !it.hasAnyOf(PRIVATE, ABSTRACT, STATIC) 581600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && !it.hasAnnotation(Ignore::class) 591600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 601600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .map { MoreElements.asExecutable(it) } 611600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 621600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val getterCandidates = methods.filter { 631600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar it.parameters.size == 0 && it.returnType.kind != TypeKind.VOID 641600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 651600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 661600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val setterCandidates = methods.filter { 671600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar it.parameters.size == 1 && it.returnType.kind == TypeKind.VOID 681600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 691600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 701600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar assignGetters(fields, getterCandidates) 711600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar assignSetters(fields, setterCandidates) 72e6325fbeaa2e6759496ea2ca9a4d3d958df690d7Yigit Boyar val entity = Entity(TypeName.get(declaredType), fields) 73e6325fbeaa2e6759496ea2ca9a4d3d958df690d7Yigit Boyar Checks.check(entity.primaryKeys.isNotEmpty(), element, ProcessorErrors.MISSING_PRIMARY_KEY) 74e6325fbeaa2e6759496ea2ca9a4d3d958df690d7Yigit Boyar return entity 751600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 761600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 771600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar private fun assignGetters(fields: List<Field>, getterCandidates: List<ExecutableElement>) { 781600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val types = processingEnvironment.typeUtils 791600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 801600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar fields.forEach { field -> 811600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (!field.element.hasAnyOf(PRIVATE)) { 821600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar field.getter = FieldGetter(field.name, CallType.FIELD) 831600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } else { 841600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val matching = getterCandidates 851600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .filter { 861600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar types.isSameType(field.element.asType(), it.returnType) 871600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && field.nameWithVariations.contains(it.simpleName.toString()) 881600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar || field.getterNameWithVariations 891600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .contains(it.simpleName.toString()) 901600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 911600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (matching.isEmpty()) { 921600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar throw ElementBoundException(field.element, 931600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar ProcessorErrors.CANNOT_FIND_GETTER_FOR_FIELD) 941600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 951600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (matching.size > 1) { 961600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar throw ElementBoundException(field.element, 971600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar ProcessorErrors.tooManyMatchingGetters(field, 981600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar matching.map { it.simpleName.toString() })) 991600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1001600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val match = matching.first() 1011600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar field.getter = FieldGetter(match.simpleName.toString(), CallType.METHOD) 1021600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1031600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1041600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1051600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 1061600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar private fun assignSetters(fields: List<Field>, setterCandidates: List<ExecutableElement>) { 1071600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val types = processingEnvironment.typeUtils 1081600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar 1091600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar fields.forEach { field -> 1101600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (!field.element.hasAnyOf(PRIVATE)) { 1111600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar field.setter = FieldSetter(field.name, CallType.FIELD) 1121600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } else { 1131600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val matching = setterCandidates 1141600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .filter { 1151600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar types.isSameType(field.element.asType(), it.parameters.first().asType()) 1161600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar && field.nameWithVariations.contains(it.simpleName.toString()) 1171600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar || field.setterNameWithVariations 1181600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar .contains(it.simpleName.toString()) 1191600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1201600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (matching.isEmpty()) { 1211600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar throw ElementBoundException(field.element, 1221600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar ProcessorErrors.CANNOT_FIND_SETTER_FOR_FIELD) 1231600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1241600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar if (matching.size > 1) { 1251600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar throw ElementBoundException(field.element, 1261600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar ProcessorErrors.tooManyMatchingSetter(field, 1271600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar matching.map { it.simpleName.toString() })) 1281600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1291600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar val match = matching.first() 1301600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar field.setter = FieldSetter(match.simpleName.toString(), CallType.METHOD) 1311600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1321600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1331600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar } 1341600cc11df868b62b6ae3995d94a3ec0b86559adYigit Boyar} 135