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.doclava1 17 18 import com.android.sdklib.SdkVersionInfo 19 import com.android.tools.metalava.Severity 20 import java.util.ArrayList 21 import java.util.HashMap 22 import java.util.Locale 23 import kotlin.reflect.full.declaredMemberProperties 24 25 // Copied from doclava1 (and a bunch of stuff left alone preserving to have same error id's) 26 object Issues { 27 private val allIssues: MutableList<Issue> = ArrayList(200) 28 private val nameToIssue: MutableMap<String, Issue> = HashMap(200) 29 private val idToIssue: MutableMap<Int, Issue> = HashMap(200) 30 31 val PARSE_ERROR = Issue(1, Severity.ERROR) 32 val ADDED_PACKAGE = Issue(2, Severity.WARNING, Category.COMPATIBILITY) 33 val ADDED_CLASS = Issue(3, Severity.WARNING, Category.COMPATIBILITY) 34 val ADDED_METHOD = Issue(4, Severity.WARNING, Category.COMPATIBILITY) 35 val ADDED_FIELD = Issue(5, Severity.WARNING, Category.COMPATIBILITY) 36 val ADDED_INTERFACE = Issue(6, Severity.WARNING, Category.COMPATIBILITY) 37 val REMOVED_PACKAGE = Issue(7, Severity.WARNING, Category.COMPATIBILITY) 38 val REMOVED_CLASS = Issue(8, Severity.WARNING, Category.COMPATIBILITY) 39 val REMOVED_METHOD = Issue(9, Severity.WARNING, Category.COMPATIBILITY) 40 val REMOVED_FIELD = Issue(10, Severity.WARNING, Category.COMPATIBILITY) 41 val REMOVED_INTERFACE = Issue(11, Severity.WARNING, Category.COMPATIBILITY) 42 val CHANGED_STATIC = Issue(12, Severity.WARNING, Category.COMPATIBILITY) 43 val ADDED_FINAL = Issue(13, Severity.WARNING, Category.COMPATIBILITY) 44 val CHANGED_TRANSIENT = Issue(14, Severity.WARNING, Category.COMPATIBILITY) 45 val CHANGED_VOLATILE = Issue(15, Severity.WARNING, Category.COMPATIBILITY) 46 val CHANGED_TYPE = Issue(16, Severity.WARNING, Category.COMPATIBILITY) 47 val CHANGED_VALUE = Issue(17, Severity.WARNING, Category.COMPATIBILITY) 48 val CHANGED_SUPERCLASS = Issue(18, Severity.WARNING, Category.COMPATIBILITY) 49 val CHANGED_SCOPE = Issue(19, Severity.WARNING, Category.COMPATIBILITY) 50 val CHANGED_ABSTRACT = Issue(20, Severity.WARNING, Category.COMPATIBILITY) 51 val CHANGED_THROWS = Issue(21, Severity.WARNING, Category.COMPATIBILITY) 52 val CHANGED_NATIVE = Issue(22, Severity.HIDDEN, Category.COMPATIBILITY) 53 val CHANGED_CLASS = Issue(23, Severity.WARNING, Category.COMPATIBILITY) 54 val CHANGED_DEPRECATED = Issue(24, Severity.WARNING, Category.COMPATIBILITY) 55 val CHANGED_SYNCHRONIZED = Issue(25, Severity.WARNING, Category.COMPATIBILITY) 56 val ADDED_FINAL_UNINSTANTIABLE = Issue(26, Severity.WARNING, Category.COMPATIBILITY) 57 val REMOVED_FINAL = Issue(27, Severity.WARNING, Category.COMPATIBILITY) 58 val REMOVED_DEPRECATED_CLASS = Issue(28, REMOVED_CLASS, Category.COMPATIBILITY) 59 val REMOVED_DEPRECATED_METHOD = Issue(29, REMOVED_METHOD, Category.COMPATIBILITY) 60 val REMOVED_DEPRECATED_FIELD = Issue(30, REMOVED_FIELD, Category.COMPATIBILITY) 61 val ADDED_ABSTRACT_METHOD = Issue(31, ADDED_METHOD, Category.COMPATIBILITY) 62 val ADDED_REIFIED = Issue(32, Severity.WARNING, Category.COMPATIBILITY) 63 64 // Issues in javadoc generation 65 val UNRESOLVED_LINK = Issue(101, Severity.LINT, Category.DOCUMENTATION) 66 val BAD_INCLUDE_TAG = Issue(102, Severity.LINT, Category.DOCUMENTATION) 67 val UNKNOWN_TAG = Issue(103, Severity.LINT, Category.DOCUMENTATION) 68 val UNKNOWN_PARAM_TAG_NAME = Issue(104, Severity.LINT, Category.DOCUMENTATION) 69 val UNDOCUMENTED_PARAMETER = Issue(105, Severity.HIDDEN, Category.DOCUMENTATION) 70 val BAD_ATTR_TAG = Issue(106, Severity.LINT, Category.DOCUMENTATION) 71 val BAD_INHERITDOC = Issue(107, Severity.HIDDEN, Category.DOCUMENTATION) 72 val HIDDEN_LINK = Issue(108, Severity.LINT, Category.DOCUMENTATION) 73 val HIDDEN_CONSTRUCTOR = Issue(109, Severity.WARNING, Category.DOCUMENTATION) 74 val UNAVAILABLE_SYMBOL = Issue(110, Severity.WARNING, Category.DOCUMENTATION) 75 val HIDDEN_SUPERCLASS = Issue(111, Severity.WARNING, Category.DOCUMENTATION) 76 val DEPRECATED = Issue(112, Severity.HIDDEN, Category.DOCUMENTATION) 77 val DEPRECATION_MISMATCH = Issue(113, Severity.ERROR, Category.DOCUMENTATION) 78 val MISSING_COMMENT = Issue(114, Severity.LINT, Category.DOCUMENTATION) 79 val IO_ERROR = Issue(115, Severity.ERROR) 80 val NO_SINCE_DATA = Issue(116, Severity.HIDDEN, Category.DOCUMENTATION) 81 val NO_FEDERATION_DATA = Issue(117, Severity.WARNING, Category.DOCUMENTATION) 82 val BROKEN_SINCE_FILE = Issue(118, Severity.ERROR, Category.DOCUMENTATION) 83 val INVALID_CONTENT_TYPE = Issue(119, Severity.ERROR, Category.DOCUMENTATION) 84 val INVALID_SAMPLE_INDEX = Issue(120, Severity.ERROR, Category.DOCUMENTATION) 85 val HIDDEN_TYPE_PARAMETER = Issue(121, Severity.WARNING, Category.DOCUMENTATION) 86 val PRIVATE_SUPERCLASS = Issue(122, Severity.WARNING, Category.DOCUMENTATION) 87 val NULLABLE = Issue(123, Severity.HIDDEN, Category.DOCUMENTATION) 88 val INT_DEF = Issue(124, Severity.HIDDEN, Category.DOCUMENTATION) 89 val REQUIRES_PERMISSION = Issue(125, Severity.LINT, Category.DOCUMENTATION) 90 val BROADCAST_BEHAVIOR = Issue(126, Severity.LINT, Category.DOCUMENTATION) 91 val SDK_CONSTANT = Issue(127, Severity.LINT, Category.DOCUMENTATION) 92 val TODO = Issue(128, Severity.LINT, Category.DOCUMENTATION) 93 val NO_ARTIFACT_DATA = Issue(129, Severity.HIDDEN, Category.DOCUMENTATION) 94 val BROKEN_ARTIFACT_FILE = Issue(130, Severity.ERROR, Category.DOCUMENTATION) 95 96 // Metalava warnings (not from doclava) 97 98 val TYPO = Issue(131, Severity.WARNING, Category.DOCUMENTATION) 99 val MISSING_PERMISSION = Issue(132, Severity.LINT, Category.DOCUMENTATION) 100 val MULTIPLE_THREAD_ANNOTATIONS = Issue(133, Severity.LINT, Category.DOCUMENTATION) 101 val UNRESOLVED_CLASS = Issue(134, Severity.LINT, Category.DOCUMENTATION) 102 val INVALID_NULL_CONVERSION = Issue(135, Severity.ERROR, Category.COMPATIBILITY) 103 val PARAMETER_NAME_CHANGE = Issue(136, Severity.ERROR, Category.COMPATIBILITY) 104 val OPERATOR_REMOVAL = Issue(137, Severity.ERROR, Category.COMPATIBILITY) 105 val INFIX_REMOVAL = Issue(138, Severity.ERROR, Category.COMPATIBILITY) 106 val VARARG_REMOVAL = Issue(139, Severity.ERROR, Category.COMPATIBILITY) 107 val ADD_SEALED = Issue(140, Severity.ERROR, Category.COMPATIBILITY) 108 val ANNOTATION_EXTRACTION = Issue(146, Severity.ERROR) 109 val SUPERFLUOUS_PREFIX = Issue(147, Severity.WARNING) 110 val HIDDEN_TYPEDEF_CONSTANT = Issue(148, Severity.ERROR) 111 val EXPECTED_PLATFORM_TYPE = Issue(149, Severity.HIDDEN) 112 val INTERNAL_ERROR = Issue(150, Severity.ERROR) 113 val RETURNING_UNEXPECTED_CONSTANT = Issue(151, Severity.WARNING) 114 val DEPRECATED_OPTION = Issue(152, Severity.WARNING) 115 val BOTH_PACKAGE_INFO_AND_HTML = Issue(153, Severity.WARNING, Category.DOCUMENTATION) 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(154, Severity.HIDDEN) 119 val UNHIDDEN_SYSTEM_API = Issue(155, Severity.ERROR) 120 val SHOWING_MEMBER_IN_HIDDEN_CLASS = Issue(156, Severity.ERROR) 121 val INVALID_NULLABILITY_ANNOTATION = Issue(157, Severity.ERROR) 122 val REFERENCES_HIDDEN = Issue(158, Severity.ERROR) 123 val IGNORING_SYMLINK = Issue(159, Severity.INFO) 124 val INVALID_NULLABILITY_ANNOTATION_WARNING = Issue(160, 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(161, Severity.HIDDEN) 128 val FORBIDDEN_TAG = Issue(162, Severity.ERROR) 129 val MISSING_COLUMN = Issue(163, Severity.WARNING, Category.DOCUMENTATION) 130 val INVALID_SYNTAX = Issue(164, Severity.ERROR) 131 val UNRESOLVED_IMPORT = Issue(165, Severity.INFO) 132 133 // API lint 134 val START_WITH_LOWER = Issue(300, Severity.ERROR, Category.API_LINT, "S1") 135 val START_WITH_UPPER = Issue(301, Severity.ERROR, Category.API_LINT, "S1") 136 val ALL_UPPER = Issue(302, Severity.ERROR, Category.API_LINT, "C2") 137 val ACRONYM_NAME = Issue(303, Severity.WARNING, Category.API_LINT, "S1") 138 val ENUM = Issue(304, Severity.ERROR, Category.API_LINT, "F5") 139 val ENDS_WITH_IMPL = Issue(305, Severity.ERROR, Category.API_LINT) 140 val MIN_MAX_CONSTANT = Issue(306, Severity.WARNING, Category.API_LINT, "C8") 141 val COMPILE_TIME_CONSTANT = Issue(307, Severity.ERROR, Category.API_LINT) 142 val SINGULAR_CALLBACK = Issue(308, Severity.ERROR, Category.API_LINT, "L1") 143 val CALLBACK_NAME = Issue(309, Severity.WARNING, Category.API_LINT, "L1") 144 val CALLBACK_INTERFACE = Issue(310, Severity.ERROR, Category.API_LINT, "CL3") 145 val CALLBACK_METHOD_NAME = Issue(311, Severity.ERROR, Category.API_LINT, "L1") 146 val LISTENER_INTERFACE = Issue(312, Severity.ERROR, Category.API_LINT, "L1") 147 val SINGLE_METHOD_INTERFACE = Issue(313, Severity.ERROR, Category.API_LINT, "L1") 148 val INTENT_NAME = Issue(314, Severity.ERROR, Category.API_LINT, "C3") 149 val ACTION_VALUE = Issue(315, Severity.ERROR, Category.API_LINT, "C4") 150 val EQUALS_AND_HASH_CODE = Issue(316, Severity.ERROR, Category.API_LINT, "M8") 151 val PARCEL_CREATOR = Issue(317, Severity.ERROR, Category.API_LINT, "FW3") 152 val PARCEL_NOT_FINAL = Issue(318, Severity.ERROR, Category.API_LINT, "FW8") 153 val PARCEL_CONSTRUCTOR = Issue(319, Severity.ERROR, Category.API_LINT, "FW3") 154 val PROTECTED_MEMBER = Issue(320, Severity.ERROR, Category.API_LINT, "M7") 155 val PAIRED_REGISTRATION = Issue(321, Severity.ERROR, Category.API_LINT, "L2") 156 val REGISTRATION_NAME = Issue(322, Severity.ERROR, Category.API_LINT, "L3") 157 val VISIBLY_SYNCHRONIZED = Issue(323, Severity.ERROR, Category.API_LINT, "M5") 158 val INTENT_BUILDER_NAME = Issue(324, Severity.WARNING, Category.API_LINT, "FW1") 159 val CONTEXT_NAME_SUFFIX = Issue(325, Severity.ERROR, Category.API_LINT, "C4") 160 val INTERFACE_CONSTANT = Issue(326, Severity.ERROR, Category.API_LINT, "C4") 161 val ON_NAME_EXPECTED = Issue(327, Severity.WARNING, Category.API_LINT) 162 val TOP_LEVEL_BUILDER = Issue(328, Severity.WARNING, Category.API_LINT) 163 val MISSING_BUILD_METHOD = Issue(329, Severity.WARNING, Category.API_LINT) 164 val BUILDER_SET_STYLE = Issue(330, Severity.WARNING, Category.API_LINT) 165 val SETTER_RETURNS_THIS = Issue(331, Severity.WARNING, Category.API_LINT, "M4") 166 val RAW_AIDL = Issue(332, Severity.ERROR, Category.API_LINT) 167 val INTERNAL_CLASSES = Issue(333, Severity.ERROR, Category.API_LINT) 168 val PACKAGE_LAYERING = Issue(334, Severity.WARNING, Category.API_LINT, "FW6") 169 val GETTER_SETTER_NAMES = Issue(335, Severity.ERROR, Category.API_LINT, "M6") 170 val CONCRETE_COLLECTION = Issue(336, Severity.ERROR, Category.API_LINT, "CL2") 171 val OVERLAPPING_CONSTANTS = Issue(337, Severity.WARNING, Category.API_LINT, "C1") 172 val GENERIC_EXCEPTION = Issue(338, Severity.ERROR, Category.API_LINT, "S1") 173 val ILLEGAL_STATE_EXCEPTION = Issue(339, Severity.WARNING, Category.API_LINT, "S1") 174 val RETHROW_REMOTE_EXCEPTION = Issue(340, Severity.ERROR, Category.API_LINT, "FW9") 175 val MENTIONS_GOOGLE = Issue(341, Severity.ERROR, Category.API_LINT) 176 val HEAVY_BIT_SET = Issue(342, Severity.ERROR, Category.API_LINT) 177 val MANAGER_CONSTRUCTOR = Issue(343, Severity.ERROR, Category.API_LINT) 178 val MANAGER_LOOKUP = Issue(344, Severity.ERROR, Category.API_LINT) 179 val AUTO_BOXING = Issue(345, Severity.ERROR, Category.API_LINT, "M11") 180 val STATIC_UTILS = Issue(346, Severity.ERROR, Category.API_LINT) 181 val CONTEXT_FIRST = Issue(347, Severity.ERROR, Category.API_LINT, "M3") 182 val LISTENER_LAST = Issue(348, Severity.WARNING, Category.API_LINT, "M3") 183 val EXECUTOR_REGISTRATION = Issue(349, Severity.WARNING, Category.API_LINT, "L1") 184 val CONFIG_FIELD_NAME = Issue(350, Severity.ERROR, Category.API_LINT) 185 val RESOURCE_FIELD_NAME = Issue(351, Severity.ERROR, Category.API_LINT) 186 val RESOURCE_VALUE_FIELD_NAME = Issue(352, Severity.ERROR, Category.API_LINT, "C7") 187 val RESOURCE_STYLE_FIELD_NAME = Issue(353, Severity.ERROR, Category.API_LINT, "C7") 188 val STREAM_FILES = Issue(354, Severity.WARNING, Category.API_LINT, "M10") 189 val PARCELABLE_LIST = Issue(355, Severity.WARNING, Category.API_LINT) 190 val ABSTRACT_INNER = Issue(356, Severity.WARNING, Category.API_LINT) 191 val BANNED_THROW = Issue(358, Severity.ERROR, Category.API_LINT) 192 val EXTENDS_ERROR = Issue(359, Severity.ERROR, Category.API_LINT) 193 val EXCEPTION_NAME = Issue(360, Severity.ERROR, Category.API_LINT) 194 val METHOD_NAME_UNITS = Issue(361, Severity.ERROR, Category.API_LINT) 195 val FRACTION_FLOAT = Issue(362, Severity.ERROR, Category.API_LINT) 196 val PERCENTAGE_INT = Issue(363, Severity.ERROR, Category.API_LINT) 197 val NOT_CLOSEABLE = Issue(364, Severity.WARNING, Category.API_LINT) 198 val KOTLIN_OPERATOR = Issue(365, Severity.INFO, Category.API_LINT) 199 val ARRAY_RETURN = Issue(366, Severity.WARNING, Category.API_LINT) 200 val USER_HANDLE = Issue(367, Severity.WARNING, Category.API_LINT) 201 val USER_HANDLE_NAME = Issue(368, Severity.WARNING, Category.API_LINT) 202 val SERVICE_NAME = Issue(369, Severity.ERROR, Category.API_LINT, "C4") 203 val METHOD_NAME_TENSE = Issue(370, Severity.WARNING, Category.API_LINT) 204 val NO_CLONE = Issue(371, Severity.ERROR, Category.API_LINT) 205 val USE_ICU = Issue(372, Severity.WARNING, Category.API_LINT) 206 val USE_PARCEL_FILE_DESCRIPTOR = Issue(373, Severity.ERROR, Category.API_LINT, "FW11") 207 val NO_BYTE_OR_SHORT = Issue(374, Severity.WARNING, Category.API_LINT, "FW12") 208 val SINGLETON_CONSTRUCTOR = Issue(375, Severity.ERROR, Category.API_LINT) 209 val COMMON_ARGS_FIRST = Issue(376, Severity.WARNING, Category.API_LINT, "M2") 210 val CONSISTENT_ARGUMENT_ORDER = Issue(377, Severity.ERROR, Category.API_LINT, "M2") 211 val KOTLIN_KEYWORD = Issue(378, Severity.ERROR, Category.API_LINT) // Formerly 141 212 val UNIQUE_KOTLIN_OPERATOR = Issue(379, Severity.ERROR, Category.API_LINT) 213 val SAM_SHOULD_BE_LAST = Issue(380, Severity.WARNING, Category.API_LINT) // Formerly 142 214 val MISSING_JVMSTATIC = Issue(381, Severity.WARNING, Category.API_LINT) // Formerly 143 215 val DEFAULT_VALUE_CHANGE = Issue(382, Severity.ERROR, Category.API_LINT) // Formerly 144 216 val DOCUMENT_EXCEPTIONS = Issue(383, Severity.ERROR, Category.API_LINT) // Formerly 145 217 val FORBIDDEN_SUPER_CLASS = Issue(384, Severity.ERROR, Category.API_LINT) 218 val MISSING_NULLABILITY = Issue(385, Severity.ERROR, Category.API_LINT) 219 val MUTABLE_BARE_FIELD = Issue(386, Severity.ERROR, Category.API_LINT, "F2") 220 val INTERNAL_FIELD = Issue(387, Severity.ERROR, Category.API_LINT, "F2") 221 val PUBLIC_TYPEDEF = Issue(388, Severity.ERROR, Category.API_LINT, "FW15") 222 val ANDROID_URI = Issue(389, Severity.ERROR, Category.API_LINT, "FW14") 223 val BAD_FUTURE = Issue(390, Severity.ERROR, Category.API_LINT) 224 val STATIC_FINAL_BUILDER = Issue(391, Severity.WARNING, Category.API_LINT) 225 val GETTER_ON_BUILDER = Issue(392, Severity.WARNING, Category.API_LINT) 226 val MISSING_GETTER_MATCHING_BUILDER = Issue(393, Severity.WARNING, Category.API_LINT) 227 val OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT = Issue(394, Severity.WARNING, Category.API_LINT) 228 val NO_SETTINGS_PROVIDER = Issue(395, Severity.HIDDEN, Category.API_LINT) 229 findIssueByIdnull230 fun findIssueById(id: Int): Issue? { 231 return idToIssue[id] 232 } 233 findIssueByIdnull234 fun findIssueById(id: String?): Issue? { 235 return nameToIssue[id] 236 } 237 findIssueByIdIgnoringCasenull238 fun findIssueByIdIgnoringCase(id: String): Issue? { 239 for (e in allIssues) { 240 if (id.equals(e.name, ignoreCase = true)) { 241 return e 242 } 243 } 244 return null 245 } 246 247 class Issue private constructor( 248 val code: Int, 249 val defaultLevel: Severity, 250 /** 251 * When `level` is set to [Severity.INHERIT], this is the parent from 252 * which the issue will inherit its level. 253 */ 254 val parent: Issue?, 255 /** Applicable category */ 256 val category: Category, 257 /** Related rule, if any */ 258 val rule: String?, 259 /** Related explanation, if any */ 260 val explanation: String? 261 ) { 262 /** 263 * The name of this issue 264 */ 265 lateinit var name: String 266 internal set 267 268 internal constructor( 269 code: Int, 270 defaultLevel: Severity, 271 category: Category = Category.UNKNOWN 272 ) : this(code, defaultLevel, null, category, null, null) 273 274 internal constructor( 275 code: Int, 276 defaultLevel: Severity, 277 category: Category, 278 rule: String 279 ) : this(code, defaultLevel, null, category, rule, null) 280 281 internal constructor( 282 code: Int, 283 parent: Issue, 284 category: Category 285 ) : this(code, Severity.INHERIT, parent, category, null, null) 286 toStringnull287 override fun toString(): String { 288 return "Issue #$code ($name)" 289 } 290 291 init { 292 allIssues.add(this) 293 } 294 } 295 296 enum class Category(val description: String, val ruleLink: String?) { 297 COMPATIBILITY("Compatibility", null), 298 DOCUMENTATION("Documentation", null), 299 API_LINT("API Lint", "go/android-api-guidelines"), 300 UNKNOWN("Default", null) 301 } 302 303 init { // Initialize issue names based on the field names 304 for (property in Issues::class.declaredMemberProperties) { 305 if (property.returnType.classifier != Issue::class) continue 306 val issue = property.getter.call(Issues) as Issue 307 308 issue.name = SdkVersionInfo.underlinesToCamelCase(property.name.toLowerCase(Locale.US)) 309 nameToIssue[issue.name] = issue 310 idToIssue[issue.code] = issue 311 } 312 for (issue in allIssues) { 313 check(issue.name != "") 314 } 315 } 316 } 317