1 /* 2 * Copyright (C) 2017 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 package com.android.tools.metalava 17 18 import com.android.sdklib.SdkVersionInfo 19 import java.util.ArrayList 20 import java.util.HashMap 21 import java.util.Locale 22 import kotlin.reflect.full.declaredMemberProperties 23 24 object Issues { 25 private val allIssues: MutableList<Issue> = ArrayList(300) 26 private val nameToIssue: MutableMap<String, Issue> = HashMap(300) 27 28 val PARSE_ERROR = Issue(Severity.ERROR) 29 // Compatibility issues 30 val ADDED_PACKAGE = Issue(Severity.WARNING, Category.COMPATIBILITY) 31 val ADDED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY) 32 val ADDED_METHOD = Issue(Severity.WARNING, Category.COMPATIBILITY) 33 val ADDED_FIELD = Issue(Severity.WARNING, Category.COMPATIBILITY) 34 val ADDED_INTERFACE = Issue(Severity.WARNING, Category.COMPATIBILITY) 35 val REMOVED_PACKAGE = Issue(Severity.WARNING, Category.COMPATIBILITY) 36 val REMOVED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY) 37 val REMOVED_METHOD = Issue(Severity.WARNING, Category.COMPATIBILITY) 38 val REMOVED_FIELD = Issue(Severity.WARNING, Category.COMPATIBILITY) 39 val REMOVED_INTERFACE = Issue(Severity.WARNING, Category.COMPATIBILITY) 40 val CHANGED_STATIC = Issue(Severity.WARNING, Category.COMPATIBILITY) 41 val ADDED_FINAL = Issue(Severity.WARNING, Category.COMPATIBILITY) 42 val CHANGED_TRANSIENT = Issue(Severity.WARNING, Category.COMPATIBILITY) 43 val CHANGED_VOLATILE = Issue(Severity.WARNING, Category.COMPATIBILITY) 44 val CHANGED_TYPE = Issue(Severity.WARNING, Category.COMPATIBILITY) 45 val CHANGED_VALUE = Issue(Severity.WARNING, Category.COMPATIBILITY) 46 val CHANGED_SUPERCLASS = Issue(Severity.WARNING, Category.COMPATIBILITY) 47 val CHANGED_SCOPE = Issue(Severity.WARNING, Category.COMPATIBILITY) 48 val CHANGED_ABSTRACT = Issue(Severity.WARNING, Category.COMPATIBILITY) 49 val CHANGED_THROWS = Issue(Severity.WARNING, Category.COMPATIBILITY) 50 val CHANGED_NATIVE = Issue(Severity.HIDDEN, Category.COMPATIBILITY) 51 val CHANGED_CLASS = Issue(Severity.WARNING, Category.COMPATIBILITY) 52 val CHANGED_DEPRECATED = Issue(Severity.WARNING, Category.COMPATIBILITY) 53 val CHANGED_SYNCHRONIZED = Issue(Severity.WARNING, Category.COMPATIBILITY) 54 val ADDED_FINAL_UNINSTANTIABLE = Issue(Severity.WARNING, Category.COMPATIBILITY) 55 val REMOVED_FINAL = Issue(Severity.WARNING, Category.COMPATIBILITY) 56 val REMOVED_DEPRECATED_CLASS = Issue(REMOVED_CLASS, Category.COMPATIBILITY) 57 val REMOVED_DEPRECATED_METHOD = Issue(REMOVED_METHOD, Category.COMPATIBILITY) 58 val REMOVED_DEPRECATED_FIELD = Issue(REMOVED_FIELD, Category.COMPATIBILITY) 59 val ADDED_ABSTRACT_METHOD = Issue(ADDED_METHOD, Category.COMPATIBILITY) 60 val ADDED_REIFIED = Issue(Severity.WARNING, Category.COMPATIBILITY) 61 62 // Issues in javadoc generation 63 val UNRESOLVED_LINK = Issue(Severity.LINT, Category.DOCUMENTATION) 64 val BAD_INCLUDE_TAG = Issue(Severity.LINT, Category.DOCUMENTATION) 65 val UNKNOWN_TAG = Issue(Severity.LINT, Category.DOCUMENTATION) 66 val UNKNOWN_PARAM_TAG_NAME = Issue(Severity.LINT, Category.DOCUMENTATION) 67 val UNDOCUMENTED_PARAMETER = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 68 val BAD_ATTR_TAG = Issue(Severity.LINT, Category.DOCUMENTATION) 69 val BAD_INHERITDOC = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 70 val HIDDEN_LINK = Issue(Severity.LINT, Category.DOCUMENTATION) 71 val HIDDEN_CONSTRUCTOR = Issue(Severity.WARNING, Category.DOCUMENTATION) 72 val UNAVAILABLE_SYMBOL = Issue(Severity.WARNING, Category.DOCUMENTATION) 73 val HIDDEN_SUPERCLASS = Issue(Severity.WARNING, Category.DOCUMENTATION) 74 val DEPRECATED = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 75 val DEPRECATION_MISMATCH = Issue(Severity.ERROR, Category.DOCUMENTATION) 76 val MISSING_COMMENT = Issue(Severity.LINT, Category.DOCUMENTATION) 77 val IO_ERROR = Issue(Severity.ERROR) 78 val NO_SINCE_DATA = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 79 val NO_FEDERATION_DATA = Issue(Severity.WARNING, Category.DOCUMENTATION) 80 val BROKEN_SINCE_FILE = Issue(Severity.ERROR, Category.DOCUMENTATION) 81 val INVALID_CONTENT_TYPE = Issue(Severity.ERROR, Category.DOCUMENTATION) 82 val INVALID_SAMPLE_INDEX = Issue(Severity.ERROR, Category.DOCUMENTATION) 83 val HIDDEN_TYPE_PARAMETER = Issue(Severity.WARNING, Category.DOCUMENTATION) 84 val PRIVATE_SUPERCLASS = Issue(Severity.WARNING, Category.DOCUMENTATION) 85 val NULLABLE = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 86 val INT_DEF = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 87 val REQUIRES_PERMISSION = Issue(Severity.LINT, Category.DOCUMENTATION) 88 val BROADCAST_BEHAVIOR = Issue(Severity.LINT, Category.DOCUMENTATION) 89 val SDK_CONSTANT = Issue(Severity.LINT, Category.DOCUMENTATION) 90 val TODO = Issue(Severity.LINT, Category.DOCUMENTATION) 91 val NO_ARTIFACT_DATA = Issue(Severity.HIDDEN, Category.DOCUMENTATION) 92 val BROKEN_ARTIFACT_FILE = Issue(Severity.ERROR, Category.DOCUMENTATION) 93 94 // Metalava warnings (not from doclava) 95 96 val TYPO = Issue(Severity.WARNING, Category.DOCUMENTATION) 97 val MISSING_PERMISSION = Issue(Severity.LINT, Category.DOCUMENTATION) 98 val MULTIPLE_THREAD_ANNOTATIONS = Issue(Severity.LINT, Category.DOCUMENTATION) 99 val UNRESOLVED_CLASS = Issue(Severity.LINT, Category.DOCUMENTATION) 100 val INVALID_NULL_CONVERSION = Issue(Severity.ERROR, Category.COMPATIBILITY) 101 val PARAMETER_NAME_CHANGE = Issue(Severity.ERROR, Category.COMPATIBILITY) 102 val OPERATOR_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY) 103 val INFIX_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY) 104 val VARARG_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY) 105 val ADD_SEALED = Issue(Severity.ERROR, Category.COMPATIBILITY) 106 val FUN_REMOVAL = Issue(Severity.ERROR, Category.COMPATIBILITY) 107 val ANNOTATION_EXTRACTION = Issue(Severity.ERROR) 108 val SUPERFLUOUS_PREFIX = Issue(Severity.WARNING) 109 val HIDDEN_TYPEDEF_CONSTANT = Issue(Severity.ERROR) 110 val EXPECTED_PLATFORM_TYPE = Issue(Severity.HIDDEN) 111 val INTERNAL_ERROR = Issue(Severity.ERROR) 112 val RETURNING_UNEXPECTED_CONSTANT = Issue(Severity.WARNING) 113 val DEPRECATED_OPTION = Issue(Severity.WARNING) 114 val BOTH_PACKAGE_INFO_AND_HTML = Issue(Severity.WARNING, Category.DOCUMENTATION) 115 val UNMATCHED_MERGE_ANNOTATION = Issue(Severity.WARNING) 116 // The plan is for this to be set as an error once (1) existing code is marked as @deprecated 117 // and (2) the principle is adopted by the API council 118 val REFERENCES_DEPRECATED = Issue(Severity.HIDDEN) 119 val UNHIDDEN_SYSTEM_API = Issue(Severity.ERROR) 120 val SHOWING_MEMBER_IN_HIDDEN_CLASS = Issue(Severity.ERROR) 121 val INVALID_NULLABILITY_ANNOTATION = Issue(Severity.ERROR) 122 val REFERENCES_HIDDEN = Issue(Severity.ERROR) 123 val IGNORING_SYMLINK = Issue(Severity.INFO) 124 val INVALID_NULLABILITY_ANNOTATION_WARNING = Issue(Severity.WARNING) 125 // The plan is for this to be set as an error once (1) existing code is marked as @deprecated 126 // and (2) the principle is adopted by the API council 127 val EXTENDS_DEPRECATED = Issue(Severity.HIDDEN) 128 val FORBIDDEN_TAG = Issue(Severity.ERROR) 129 val MISSING_COLUMN = Issue(Severity.WARNING, Category.DOCUMENTATION) 130 val INVALID_SYNTAX = Issue(Severity.ERROR) 131 val UNRESOLVED_IMPORT = Issue(Severity.INFO) 132 val HIDDEN_ABSTRACT_METHOD = Issue(Severity.ERROR) 133 134 // API lint 135 val START_WITH_LOWER = Issue(Severity.ERROR, Category.API_LINT, "style-conventions") 136 val START_WITH_UPPER = Issue(Severity.ERROR, Category.API_LINT, "style-conventions") 137 val ALL_UPPER = Issue(Severity.ERROR, Category.API_LINT, "constant-naming") 138 val ACRONYM_NAME = Issue(Severity.WARNING, Category.API_LINT, "acronyms-in-method-name") 139 val ENUM = Issue(Severity.ERROR, Category.API_LINT, "avoid-enum") 140 val ENDS_WITH_IMPL = Issue(Severity.ERROR, Category.API_LINT, "dont-end-with-impl") 141 val MIN_MAX_CONSTANT = Issue(Severity.WARNING, Category.API_LINT, "min-max-constants") 142 val COMPILE_TIME_CONSTANT = Issue(Severity.ERROR, Category.API_LINT) 143 val SINGULAR_CALLBACK = Issue(Severity.ERROR, Category.API_LINT, "callback-class-singular") 144 val CALLBACK_NAME = Issue(Severity.WARNING, Category.API_LINT, "observer-should-be-callback") 145 val CALLBACK_INTERFACE = 146 Issue(Severity.ERROR, Category.API_LINT, "callback-abstract-instead-of-interface") 147 val CALLBACK_METHOD_NAME = Issue(Severity.ERROR, Category.API_LINT, "callback-method-naming") 148 val LISTENER_INTERFACE = Issue(Severity.ERROR, Category.API_LINT, "callbacks-listener") 149 val SINGLE_METHOD_INTERFACE = Issue(Severity.ERROR, Category.API_LINT, "callbacks-listener") 150 val INTENT_NAME = 151 Issue(Severity.ERROR, Category.API_LINT, "use-standard-prefixes-for-constants") 152 val ACTION_VALUE = Issue(Severity.ERROR, Category.API_LINT) 153 val EQUALS_AND_HASH_CODE = Issue(Severity.ERROR, Category.API_LINT, "equals-and-hashcode") 154 val PARCEL_CREATOR = Issue(Severity.ERROR, Category.API_LINT, "parcelable-creator") 155 val PARCEL_NOT_FINAL = Issue(Severity.ERROR, Category.API_LINT, "parcelable-final") 156 val PARCEL_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT, "parcelable-creator") 157 val PROTECTED_MEMBER = Issue(Severity.ERROR, Category.API_LINT, "avoid-protected") 158 val PAIRED_REGISTRATION = Issue(Severity.ERROR, Category.API_LINT, "callbacks-symmetry") 159 val REGISTRATION_NAME = Issue(Severity.ERROR, Category.API_LINT, "callbacks-accessors") 160 val VISIBLY_SYNCHRONIZED = Issue(Severity.ERROR, Category.API_LINT, "avoid-synchronized") 161 val INTENT_BUILDER_NAME = 162 Issue(Severity.WARNING, Category.API_LINT, "intent-builder-createintent") 163 val CONTEXT_NAME_SUFFIX = Issue(Severity.ERROR, Category.API_LINT, "classes-subclass-naming") 164 val INTERFACE_CONSTANT = Issue(Severity.ERROR, Category.API_LINT, "services-intents") 165 val ON_NAME_EXPECTED = Issue(Severity.WARNING, Category.API_LINT, "callback-method-naming") 166 val TOP_LEVEL_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "builders-static-inner") 167 val MISSING_BUILD_METHOD = 168 Issue(Severity.WARNING, Category.API_LINT, "builder-must-declare-build") 169 val BUILDER_SET_STYLE = Issue(Severity.WARNING, Category.API_LINT, "builder-method-naming") 170 val SETTER_RETURNS_THIS = Issue(Severity.WARNING, Category.API_LINT) 171 val RAW_AIDL = Issue(Severity.ERROR, Category.API_LINT, "no-public-binder") 172 val INTERNAL_CLASSES = Issue(Severity.ERROR, Category.API_LINT) 173 val PACKAGE_LAYERING = Issue(Severity.WARNING, Category.API_LINT) 174 val GETTER_SETTER_NAMES = Issue(Severity.ERROR, Category.API_LINT) 175 val CONCRETE_COLLECTION = Issue(Severity.ERROR, Category.API_LINT, "classes-collections") 176 val OVERLAPPING_CONSTANTS = Issue(Severity.WARNING, Category.API_LINT, "overlapping-constants") 177 val GENERIC_EXCEPTION = Issue(Severity.ERROR, Category.API_LINT, "appropriate-exception") 178 val ILLEGAL_STATE_EXCEPTION = 179 Issue(Severity.WARNING, Category.API_LINT, "appropriate-exception") 180 val RETHROW_REMOTE_EXCEPTION = Issue(Severity.ERROR, Category.API_LINT, "appropriate-exception") 181 val MENTIONS_GOOGLE = Issue(Severity.ERROR, Category.API_LINT, "mentions-google") 182 val HEAVY_BIT_SET = Issue(Severity.ERROR, Category.API_LINT, "avoid-bitset") 183 val MANAGER_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT) 184 val MANAGER_LOOKUP = Issue(Severity.ERROR, Category.API_LINT) 185 val AUTO_BOXING = Issue(Severity.ERROR, Category.API_LINT, "auto-boxing") 186 val STATIC_UTILS = Issue(Severity.ERROR, Category.API_LINT) 187 val CONTEXT_FIRST = Issue(Severity.ERROR, Category.API_LINT) 188 val LISTENER_LAST = Issue(Severity.WARNING, Category.API_LINT, "placement-of-sam-parameters") 189 val EXECUTOR_REGISTRATION = Issue(Severity.WARNING, Category.API_LINT, "callbacks-listener") 190 val CONFIG_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT) 191 val RESOURCE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT) 192 val RESOURCE_VALUE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT) 193 val RESOURCE_STYLE_FIELD_NAME = Issue(Severity.ERROR, Category.API_LINT) 194 val STREAM_FILES = Issue(Severity.WARNING, Category.API_LINT) 195 val PARCELABLE_LIST = Issue(Severity.WARNING, Category.API_LINT) 196 val ABSTRACT_INNER = Issue(Severity.WARNING, Category.API_LINT) 197 val BANNED_THROW = Issue(Severity.ERROR, Category.API_LINT) 198 val EXTENDS_ERROR = Issue(Severity.ERROR, Category.API_LINT) 199 val EXCEPTION_NAME = Issue(Severity.ERROR, Category.API_LINT) 200 val METHOD_NAME_UNITS = Issue(Severity.ERROR, Category.API_LINT, "unit-names") 201 val FRACTION_FLOAT = Issue(Severity.ERROR, Category.API_LINT) 202 val PERCENTAGE_INT = Issue(Severity.ERROR, Category.API_LINT) 203 val NOT_CLOSEABLE = Issue(Severity.WARNING, Category.API_LINT) 204 val KOTLIN_OPERATOR = Issue(Severity.INFO, Category.API_LINT) 205 val ARRAY_RETURN = 206 Issue(Severity.WARNING, Category.API_LINT, "methods-prefer-collection-over-array") 207 val USER_HANDLE = Issue(Severity.WARNING, Category.API_LINT) 208 val USER_HANDLE_NAME = Issue(Severity.WARNING, Category.API_LINT) 209 val SERVICE_NAME = Issue(Severity.ERROR, Category.API_LINT) 210 val METHOD_NAME_TENSE = Issue(Severity.WARNING, Category.API_LINT) 211 val NO_CLONE = Issue(Severity.ERROR, Category.API_LINT, "avoid-clone") 212 val USE_ICU = Issue(Severity.WARNING, Category.API_LINT) 213 val USE_PARCEL_FILE_DESCRIPTOR = 214 Issue(Severity.ERROR, Category.API_LINT, "prefer-parcelfiledescriptor") 215 val NO_BYTE_OR_SHORT = Issue(Severity.WARNING, Category.API_LINT, "avoid-short-byte") 216 val SINGLETON_CONSTRUCTOR = Issue(Severity.ERROR, Category.API_LINT, "singleton-class") 217 val COMMON_ARGS_FIRST = Issue(Severity.WARNING, Category.API_LINT, "optional-params-last") 218 val CONSISTENT_ARGUMENT_ORDER = Issue(Severity.ERROR, Category.API_LINT, "optional-params-last") 219 val KOTLIN_KEYWORD = Issue(Severity.ERROR, Category.API_LINT) 220 val UNIQUE_KOTLIN_OPERATOR = Issue(Severity.ERROR, Category.API_LINT) 221 val SAM_SHOULD_BE_LAST = 222 Issue(Severity.WARNING, Category.API_LINT, "placement-of-sam-parameters") 223 val MISSING_JVMSTATIC = Issue(Severity.WARNING, Category.API_LINT) 224 val DEFAULT_VALUE_CHANGE = Issue(Severity.ERROR, Category.API_LINT, "default-value-removal") 225 val DOCUMENT_EXCEPTIONS = Issue(Severity.ERROR, Category.API_LINT, "docs-throws") 226 val FORBIDDEN_SUPER_CLASS = Issue(Severity.ERROR, Category.API_LINT) 227 val MISSING_NULLABILITY = Issue(Severity.ERROR, Category.API_LINT, "annotations") 228 val MUTABLE_BARE_FIELD = Issue(Severity.ERROR, Category.API_LINT, "mutable-bare-field") 229 val INTERNAL_FIELD = Issue(Severity.ERROR, Category.API_LINT, "internal-fields") 230 val PUBLIC_TYPEDEF = Issue(Severity.ERROR, Category.API_LINT, "no-public-typedefs") 231 val ANDROID_URI = Issue(Severity.ERROR, Category.API_LINT, "android-uri") 232 val BAD_FUTURE = Issue(Severity.ERROR, Category.API_LINT, "bad-future") 233 val STATIC_FINAL_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "builders-static-inner") 234 val GETTER_ON_BUILDER = Issue(Severity.WARNING, Category.API_LINT, "getter-on-builder") 235 val MISSING_GETTER_MATCHING_BUILDER = 236 Issue(Severity.WARNING, Category.API_LINT, "builders-symmetric-setters") 237 val OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT = 238 Issue(Severity.WARNING, Category.API_LINT, "builders-nonnull-constructors") 239 val NO_SETTINGS_PROVIDER = Issue(Severity.HIDDEN, Category.API_LINT, "no-settings-provider") 240 val NULLABLE_COLLECTION = Issue(Severity.WARNING, Category.API_LINT, "methods-prefer-non-null-collections") 241 findIssueByIdnull242 fun findIssueById(id: String?): Issue? { 243 return nameToIssue[id] 244 } 245 findIssueByIdIgnoringCasenull246 fun findIssueByIdIgnoringCase(id: String): Issue? { 247 for (e in allIssues) { 248 if (id.equals(e.name, ignoreCase = true)) { 249 return e 250 } 251 } 252 return null 253 } 254 255 class Issue private constructor( 256 val defaultLevel: Severity, 257 /** 258 * When `level` is set to [Severity.INHERIT], this is the parent from 259 * which the issue will inherit its level. 260 */ 261 val parent: Issue?, 262 /** Applicable category */ 263 val category: Category, 264 /** Related rule, if any */ 265 val rule: String? 266 ) { 267 /** 268 * The name of this issue 269 */ 270 lateinit var name: String 271 internal set 272 273 internal constructor( 274 defaultLevel: Severity, 275 category: Category = Category.UNKNOWN 276 ) : this(defaultLevel, null, category, null) 277 278 internal constructor( 279 defaultLevel: Severity, 280 category: Category, 281 rule: String 282 ) : this(defaultLevel, null, category, rule) 283 284 internal constructor( 285 parent: Issue, 286 category: Category 287 ) : this(Severity.INHERIT, parent, category, null) 288 toStringnull289 override fun toString(): String { 290 return "Issue $name" 291 } 292 293 init { 294 allIssues.add(this) 295 } 296 } 297 298 enum class Category(val description: String, val ruleLink: String?) { 299 COMPATIBILITY("Compatibility", null), 300 DOCUMENTATION("Documentation", null), 301 API_LINT("API Lint", "https://s.android.com/api-guidelines#"), 302 UNKNOWN("Default", null) 303 } 304 305 init { // Initialize issue names based on the field names 306 for (property in Issues::class.declaredMemberProperties) { 307 if (property.returnType.classifier != Issue::class) continue 308 val issue = property.getter.call(Issues) as Issue 309 310 issue.name = SdkVersionInfo.underlinesToCamelCase(property.name.toLowerCase(Locale.US)) 311 nameToIssue[issue.name] = issue 312 } 313 for (issue in allIssues) { 314 check(issue.name != "") 315 } 316 } 317 } 318