ProcessorErrors.kt revision 13a2048db98b1cc2dbd1692b73b794527975a446
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.support.room.processor 18 19import com.android.support.room.Delete 20import com.android.support.room.Insert 21import com.android.support.room.Query 22import com.android.support.room.ext.RoomTypeNames 23import com.android.support.room.vo.Field 24import com.android.support.room.vo.Pojo 25import com.squareup.javapoet.TypeName 26import javax.lang.model.type.TypeMirror 27 28object ProcessorErrors { 29 val MISSING_QUERY_ANNOTATION = "Query methods must be annotated with ${Query::class.java}" 30 val MISSING_INSERT_ANNOTATION = "Insertion methods must be annotated with ${Insert::class.java}" 31 val MISSING_DELETE_ANNOTATION = "Deletion methods must be annotated with ${Delete::class.java}" 32 val INVALID_ON_CONFLICT_VALUE = "On conflict value must be one of Insert.OnConflict values." 33 val INVALID_INSERTION_METHOD_RETURN_TYPE = "Methods annotated with @Insert can return either" + 34 " void, long, long[] or List<Long>." 35 val ABSTRACT_METHOD_IN_DAO_MISSING_ANY_ANNOTATION = "Abstract method in DAO must be annotated" + 36 " with ${Query::class.java} AND ${Insert::class.java}" 37 val CANNOT_USE_MORE_THAN_ONE_DAO_METHOD_ANNOTATION = "A DAO method can be annotated with only" + 38 " one of the following:" + DaoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") { 39 it.java.simpleName 40 } 41 val CANNOT_RESOLVE_RETURN_TYPE = "Cannot resolve return type for %s" 42 val CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS = "Cannot use unbound generics in query" + 43 " methods. It must be bound to a type through base Dao class." 44 val CANNOT_USE_UNBOUND_GENERICS_IN_INSERTION_METHODS = "Cannot use unbound generics in" + 45 " insertion methods. It must be bound to a type through base Dao class." 46 val CANNOT_USE_UNBOUND_GENERICS_IN_ENTITY_FIELDS = "Cannot use unbound fields in entities." 47 val CANNOT_USE_UNBOUND_GENERICS_IN_DAO_CLASSES = "Cannot use unbound generics in Dao classes." + 48 " If you are trying to create a base DAO, create a normal class, extend it with type" + 49 " params then mark the subclass with @Dao." 50 val CANNOT_FIND_GETTER_FOR_FIELD = "Cannot find getter for field." 51 val CANNOT_FIND_SETTER_FOR_FIELD = "Cannot find setter for field." 52 val MISSING_PRIMARY_KEY = "An entity must have at least 1 field annotated with @PrimaryKey" 53 val DAO_MUST_BE_AN_ABSTRACT_CLASS_OR_AN_INTERFACE = "Dao class must be an abstract class or" + 54 " an interface" 55 val DATABASE_MUST_BE_ANNOTATED_WITH_DATABASE = "Database must be annotated with @Database" 56 val DAO_MUST_BE_ANNOTATED_WITH_DAO = "Dao class must be annotated with @Dao" 57 val ENTITY_MUST_BE_ANNOTATED_WITH_ENTITY = "Entity class must be annotated with @Entity" 58 val DATABASE_ANNOTATION_MUST_HAVE_LIST_OF_ENTITIES = "@Database annotation must specify list" + 59 " of entities" 60 val COLUMN_NAME_CANNOT_BE_EMPTY = "Column name cannot be blank. If you don't want to set it" + 61 ", just remove the @ColumnName annotation." 62 63 val ENTITY_TABLE_NAME_CANNOT_BE_EMPTY = "Entity table name cannot be blank. If you don't want" + 64 " to set it, just remove the tableName property." 65 66 val CANNOT_CONVERT_QUERY_PARAMETER_TO_STRING = "Query method parameters should either be a" + 67 " type that can be converted into String or a List / Array that contains such type." 68 69 val QUERY_PARAMETERS_CANNOT_START_WITH_UNDERSCORE = "Query/Insert method parameters cannot " + 70 "start with underscore (_)." 71 72 val CANNOT_FIND_QUERY_RESULT_ADAPTER = "Not sure how to convert a Cursor to this method's " + 73 "return type" 74 75 val INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT = "Method annotated with" + 76 " @Insert but does not have any parameters to insert." 77 78 val INSERTION_METHOD_PARAMETERS_MUST_HAVE_THE_SAME_ENTITY_TYPE = "Parameter types in " + 79 "insertion methods must be the same type. If you want to insert entities from " + 80 "different types atomically, use a transaction." 81 82 val DELETION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_DELETE = "Method annotated with" + 83 " @Delete but does not have any parameters to delete." 84 85 val DELETION_METHOD_PARAMETERS_MUST_HAVE_THE_SAME_ENTITY_TYPE = "Parameter types in " + 86 "deletion methods must be the same type. If you want to delete entities from " + 87 "different types atomically, use a transaction." 88 89 val CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER = "Type of the parameter must be a class " + 90 "annotated with @Entity or a collection/array of it." 91 92 val DB_MUST_EXTEND_ROOM_DB = "Classes annotated with @Database should extend " + 93 RoomTypeNames.ROOM_DB 94 95 val LIVE_DATA_QUERY_WITHOUT_SELECT = "LiveData return type can only be used with SELECT" + 96 " queries." 97 98 private val TOO_MANY_MATCHING_GETTERS = "Ambiguous getter for %s. All of the following " + 99 "match: %s. You can @Ignore the ones that you don't want to match." 100 101 fun tooManyMatchingGetters(field: Field, methodNames: List<String>): String { 102 return TOO_MANY_MATCHING_GETTERS.format(field, methodNames.joinToString(", ")) 103 } 104 105 private val TOO_MANY_MATCHING_SETTERS = "Ambiguous setter for %s. All of the following " + 106 "match: %s. You can @Ignore the ones that you don't want to match." 107 108 fun tooManyMatchingSetter(field: Field, methodNames: List<String>): String { 109 return TOO_MANY_MATCHING_SETTERS.format(field, methodNames.joinToString(", ")) 110 } 111 112 private val MISSING_PARAMETER_FOR_BIND = "Each bind variable in the query must have a" + 113 " matching method parameter. Cannot find method parameters for %s." 114 115 fun missingParameterForBindVariable(bindVarName: List<String>): String { 116 return MISSING_PARAMETER_FOR_BIND.format(bindVarName.joinToString(", ")) 117 } 118 119 private val UNUSED_QUERY_METHOD_PARAMETER = "Unused parameter%s: %s" 120 fun unusedQueryMethodParameter(unusedParams: List<String>): String { 121 return UNUSED_QUERY_METHOD_PARAMETER.format( 122 if (unusedParams.size > 1) "s" else "", 123 unusedParams.joinToString(",")) 124 } 125 126 private val DUPLICATE_TABLES = "Table name \"%s\" is used by multiple entities: %s" 127 fun duplicateTableNames(tableName: String, entityNames: List<String>): String { 128 return DUPLICATE_TABLES.format(tableName, entityNames.joinToString(", ")) 129 } 130 131 val DELETION_METHODS_MUST_RETURN_VOID_OR_INT = "Deletion methods must either return void or" + 132 " return int (the number of deleted rows)." 133 134 val DAO_METHOD_CONFLICTS_WITH_OTHERS = "Dao method has conflicts." 135 136 fun duplicateDao(dao: TypeName, methodNames: List<String>): String { 137 return """ 138 All of these functions (${methodNames.joinToString(", ")}) return the same DAO 139 class ($dao). 140 A database can use a DAO only once so you should remove ${methodNames.size - 1} of 141 these conflicting DAO methods. If you are implementing any of these to fulfill an 142 interface, don't make it abstract, instead, implement the code that calls the 143 other one. 144 """.trimIndent().replace(System.lineSeparator(), " ") 145 } 146 147 fun cursorPojoMismatch(pojoTypeName: TypeName, 148 unusedColumns: List<String>, allColumns: List<String>, 149 unusedFields: List<Field>, allFields: List<Field>): String { 150 val unusedColumnsWarning = if (unusedColumns.isNotEmpty()) { """ 151 The query returns some columns (${unusedColumns.joinToString(", ")}) which are not 152 use by $pojoTypeName. You can use @ColumnName annotation on the fields to specify 153 the mapping. 154 """.trimIndent().replace(System.lineSeparator(), " ") 155 } else { 156 "" 157 } 158 val unusedFieldsWarning = if (unusedFields.isNotEmpty()) { """ 159 $pojoTypeName has some fields 160 (${unusedFields.joinToString(", ") { it.columnName }}) which are not returned by the 161 query. If they are not supposed to be read from the result, you can mark them with 162 @Ignore annotation. 163 """.trimIndent().replace(System.lineSeparator(), " ") 164 } else { 165 "" 166 } 167 return """ 168 $unusedColumnsWarning 169 $unusedFieldsWarning 170 You can suppress this warning by annotating the method with 171 @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). 172 Columns returned by the query: ${allColumns.joinToString(", ")}. 173 Fields in $pojoTypeName: ${allFields.joinToString(", ") { it.columnName }}. 174 """.trimIndent().replace(System.lineSeparator(), " ") 175 } 176 177} 178