1 /*
2 * Copyright (C) 2023 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.reporter
17
18 import java.util.Locale
19 import kotlin.properties.ReadOnlyProperty
20 import kotlin.reflect.KProperty
21
22 object Issues {
23 private val allIssues: MutableList<Issue> = ArrayList(300)
24
25 /** A list of all the issues. */
26 val all: List<Issue> by this::allIssues
27
28 private val nameToIssue: MutableMap<String, Issue> = HashMap(300)
29
30 val PARSE_ERROR by Issue(Severity.ERROR)
31 val DUPLICATE_SOURCE_CLASS by Issue(Severity.WARNING)
32
33 // Signature file parsing
34 val SIGNATURE_FILE_ERROR by Issue(Severity.ERROR)
35 // TODO(b/394789173): Hide until AndroidX has disabled it.
36 val UNQUALIFIED_TYPE_ERROR by Issue(Severity.HIDDEN)
37
38 // Compatibility issues
39 val ADDED_ANNOTATION by Issue(Severity.ERROR, Category.COMPATIBILITY)
40 val ADDED_PACKAGE by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
41 val ADDED_CLASS by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
42 val ADDED_METHOD by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
43 val ADDED_FIELD by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
44 val ADDED_INTERFACE by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
45 val REMOVED_ANNOTATION by Issue(Severity.ERROR, Category.COMPATIBILITY)
46 val REMOVED_PACKAGE by Issue(Severity.ERROR, Category.COMPATIBILITY)
47 val REMOVED_CLASS by Issue(Severity.ERROR, Category.COMPATIBILITY)
48 val REMOVED_METHOD by Issue(Severity.ERROR, Category.COMPATIBILITY)
49 val REMOVED_FIELD by Issue(Severity.ERROR, Category.COMPATIBILITY)
50 val REMOVED_INTERFACE by Issue(Severity.ERROR, Category.COMPATIBILITY)
51 val CHANGED_STATIC by Issue(Severity.ERROR, Category.COMPATIBILITY)
52 val ADDED_FINAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
53 val CHANGED_VOLATILE by Issue(Severity.ERROR, Category.COMPATIBILITY)
54 val CHANGED_TYPE by Issue(Severity.ERROR, Category.COMPATIBILITY)
55 val CHANGED_VALUE by Issue(Severity.ERROR, Category.COMPATIBILITY)
56 val CHANGED_SUPERCLASS by Issue(Severity.ERROR, Category.COMPATIBILITY)
57 val CHANGED_SCOPE by Issue(Severity.ERROR, Category.COMPATIBILITY)
58 val CHANGED_ABSTRACT by Issue(Severity.ERROR, Category.COMPATIBILITY)
59 val CHANGED_DEFAULT by Issue(Severity.ERROR, Category.COMPATIBILITY)
60 val CHANGED_THROWS by Issue(Severity.ERROR, Category.COMPATIBILITY)
61 val CHANGED_NATIVE by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
62 val CHANGED_CLASS by Issue(Severity.ERROR, Category.COMPATIBILITY)
63 val CHANGED_DEPRECATED by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
64 val ADDED_FINAL_UNINSTANTIABLE by Issue(Severity.HIDDEN, Category.COMPATIBILITY)
65 val REMOVED_FINAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
66 val REMOVED_FINAL_STRICT by Issue(Severity.ERROR, Category.COMPATIBILITY)
67 val REMOVED_DEPRECATED_CLASS by Issue(REMOVED_CLASS, Category.COMPATIBILITY)
68 val REMOVED_DEPRECATED_METHOD by Issue(REMOVED_METHOD, Category.COMPATIBILITY)
69 val REMOVED_DEPRECATED_FIELD by Issue(REMOVED_FIELD, Category.COMPATIBILITY)
70 val ADDED_ABSTRACT_METHOD by Issue(Severity.ERROR, Category.COMPATIBILITY)
71 val ADDED_REIFIED by Issue(Severity.ERROR, Category.COMPATIBILITY)
72 val REMOVED_JVM_DEFAULT_WITH_COMPATIBILITY by Issue(Severity.ERROR, Category.COMPATIBILITY)
73
74 // Issues in javadoc generation
75 val UNRESOLVED_LINK by Issue(Severity.ERROR, Category.DOCUMENTATION)
76 val UNAVAILABLE_SYMBOL by Issue(Severity.WARNING, Category.DOCUMENTATION)
77 val HIDDEN_SUPERCLASS by Issue(Severity.WARNING, Category.DOCUMENTATION)
78 val DEPRECATED by Issue(Severity.HIDDEN, Category.DOCUMENTATION)
79 val DEPRECATION_MISMATCH by Issue(Severity.ERROR, Category.DOCUMENTATION)
80 val IO_ERROR by Issue(Severity.ERROR)
81 val HIDDEN_TYPE_PARAMETER by Issue(Severity.WARNING, Category.DOCUMENTATION)
82 val PRIVATE_SUPERCLASS by Issue(Severity.WARNING, Category.DOCUMENTATION)
83 val NULLABLE by Issue(Severity.HIDDEN, Category.DOCUMENTATION)
84 val INT_DEF by Issue(Severity.HIDDEN, Category.DOCUMENTATION)
85 val REQUIRES_PERMISSION by Issue(Severity.ERROR, Category.DOCUMENTATION)
86 val BROADCAST_BEHAVIOR by Issue(Severity.ERROR, Category.DOCUMENTATION)
87 val SDK_CONSTANT by Issue(Severity.ERROR, Category.DOCUMENTATION)
88 val TODO by Issue(Severity.ERROR, Category.DOCUMENTATION)
89
90 // Metalava warnings (not from doclava)
91
92 val INVALID_FEATURE_ENFORCEMENT by Issue(Severity.ERROR, Category.DOCUMENTATION)
93
94 val MISSING_PERMISSION by Issue(Severity.ERROR, Category.DOCUMENTATION)
95 val MULTIPLE_THREAD_ANNOTATIONS by Issue(Severity.ERROR, Category.DOCUMENTATION)
96 val INVALID_NULL_CONVERSION by Issue(Severity.ERROR, Category.COMPATIBILITY)
97 val PARAMETER_NAME_CHANGE by Issue(Severity.ERROR, Category.COMPATIBILITY)
98 val OPERATOR_REMOVAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
99 val INFIX_REMOVAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
100 val VARARG_REMOVAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
101 val ADD_SEALED by Issue(Severity.ERROR, Category.COMPATIBILITY)
102 val FUN_REMOVAL by Issue(Severity.ERROR, Category.COMPATIBILITY)
103 val BECAME_UNCHECKED by Issue(Severity.ERROR, Category.COMPATIBILITY)
104 val ANNOTATION_EXTRACTION by Issue(Severity.ERROR)
105 val SUPERFLUOUS_PREFIX by Issue(Severity.WARNING)
106 val HIDDEN_TYPEDEF_CONSTANT by Issue(Severity.ERROR)
107 val INTERNAL_ERROR by Issue(Severity.ERROR)
108 val RETURNING_UNEXPECTED_CONSTANT by Issue(Severity.WARNING)
109 val BOTH_PACKAGE_INFO_AND_HTML by Issue(Severity.WARNING, Category.DOCUMENTATION)
110 val UNMATCHED_MERGE_ANNOTATION by Issue(Severity.ERROR, Category.API_LINT)
111 val INCONSISTENT_MERGE_ANNOTATION by Issue(Severity.WARNING_ERROR_WHEN_NEW, Category.API_LINT)
112 // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
113 // and (2) the principle is adopted by the API council
114 val REFERENCES_DEPRECATED by Issue(Severity.HIDDEN, Category.API_LINT)
115 val UNHIDDEN_SYSTEM_API by Issue(Severity.ERROR, Category.API_LINT)
116 val SHOWING_MEMBER_IN_HIDDEN_CLASS by Issue(Severity.ERROR, Category.API_LINT)
117 val INVALID_NULLABILITY_ANNOTATION by Issue(Severity.ERROR)
118 val REFERENCES_HIDDEN by Issue(Severity.ERROR, Category.API_LINT)
119 val IGNORING_SYMLINK by Issue(Severity.INFO)
120 val INVALID_NULLABILITY_ANNOTATION_WARNING by Issue(Severity.WARNING)
121 // The plan is for this to be set as an error once (1) existing code is marked as @deprecated
122 // and (2) the principle is adopted by the API council
123 val EXTENDS_DEPRECATED by Issue(Severity.HIDDEN, Category.API_LINT)
124 val FORBIDDEN_TAG by Issue(Severity.ERROR, Category.DOCUMENTATION)
125 val MISSING_COLUMN by Issue(Severity.WARNING, Category.DOCUMENTATION)
126 val INVALID_SYNTAX by Issue(Severity.ERROR)
127 val INVALID_PACKAGE by Issue(Severity.ERROR)
128 val UNRESOLVED_IMPORT by Issue(Severity.INFO)
129 val HIDDEN_ABSTRACT_METHOD by Issue(Severity.ERROR, Category.API_LINT)
130
131 // API lint
132 val START_WITH_LOWER by Issue(Severity.ERROR, Category.API_LINT)
133 val START_WITH_UPPER by Issue(Severity.ERROR, Category.API_LINT)
134 val ALL_UPPER by Issue(Severity.ERROR, Category.API_LINT)
135 val ACRONYM_NAME by Issue(Severity.WARNING, Category.API_LINT)
136 val ENUM by Issue(Severity.ERROR, Category.API_LINT)
137 val ENDS_WITH_IMPL by Issue(Severity.ERROR, Category.API_LINT)
138 val MIN_MAX_CONSTANT by Issue(Severity.WARNING, Category.API_LINT)
139 val COMPILE_TIME_CONSTANT by Issue(Severity.ERROR, Category.API_LINT)
140 val SINGULAR_CALLBACK by Issue(Severity.ERROR, Category.API_LINT)
141 val CALLBACK_NAME by Issue(Severity.WARNING, Category.API_LINT)
142 // Obsolete per https://s.android.com/api-guidelines.
143 val CALLBACK_INTERFACE by Issue(Severity.HIDDEN, Category.API_LINT)
144 val CALLBACK_METHOD_NAME by Issue(Severity.ERROR, Category.API_LINT)
145 val LISTENER_INTERFACE by Issue(Severity.ERROR, Category.API_LINT)
146 val SINGLE_METHOD_INTERFACE by Issue(Severity.ERROR, Category.API_LINT)
147 val INTENT_NAME by Issue(Severity.ERROR, Category.API_LINT)
148 val ACTION_VALUE by Issue(Severity.ERROR, Category.API_LINT)
149 val EQUALS_AND_HASH_CODE by Issue(Severity.ERROR, Category.API_LINT)
150 val PARCEL_CREATOR by Issue(Severity.ERROR, Category.API_LINT)
151 val PARCEL_NOT_FINAL by Issue(Severity.ERROR, Category.API_LINT)
152 val PARCEL_CONSTRUCTOR by Issue(Severity.ERROR, Category.API_LINT)
153 val PROTECTED_MEMBER by Issue(Severity.ERROR, Category.API_LINT)
154 val PAIRED_REGISTRATION by Issue(Severity.ERROR, Category.API_LINT)
155 val VISIBLY_SYNCHRONIZED by Issue(Severity.ERROR, Category.API_LINT)
156 val INTENT_BUILDER_NAME by Issue(Severity.WARNING, Category.API_LINT)
157 val CONTEXT_NAME_SUFFIX by Issue(Severity.ERROR, Category.API_LINT)
158 val INTERFACE_CONSTANT by Issue(Severity.ERROR, Category.API_LINT)
159 val ON_NAME_EXPECTED by Issue(Severity.WARNING, Category.API_LINT)
160 val TOP_LEVEL_BUILDER by Issue(Severity.WARNING, Category.API_LINT)
161 val MISSING_BUILD_METHOD by Issue(Severity.WARNING, Category.API_LINT)
162 val BUILDER_SET_STYLE by Issue(Severity.WARNING, Category.API_LINT)
163 val SETTER_RETURNS_THIS by Issue(Severity.WARNING, Category.API_LINT)
164 val RAW_AIDL by Issue(Severity.ERROR, Category.API_LINT)
165 val INTERNAL_CLASSES by Issue(Severity.ERROR, Category.API_LINT)
166 val PACKAGE_LAYERING by Issue(Severity.WARNING, Category.API_LINT)
167 val GETTER_SETTER_NAMES by Issue(Severity.ERROR, Category.API_LINT)
168 val CONCRETE_COLLECTION by Issue(Severity.ERROR, Category.API_LINT)
169 val OVERLAPPING_CONSTANTS by Issue(Severity.WARNING, Category.API_LINT)
170 val GENERIC_EXCEPTION by Issue(Severity.ERROR, Category.API_LINT)
171 val RETHROW_REMOTE_EXCEPTION by Issue(Severity.ERROR, Category.API_LINT)
172 val MENTIONS_GOOGLE by Issue(Severity.ERROR, Category.API_LINT)
173 val HEAVY_BIT_SET by Issue(Severity.ERROR, Category.API_LINT)
174 val MANAGER_CONSTRUCTOR by Issue(Severity.ERROR, Category.API_LINT)
175 val MANAGER_LOOKUP by Issue(Severity.ERROR, Category.API_LINT)
176 val AUTO_BOXING by Issue(Severity.ERROR, Category.API_LINT)
177 val STATIC_UTILS by Issue(Severity.ERROR, Category.API_LINT)
178 val CONTEXT_FIRST by Issue(Severity.ERROR, Category.API_LINT)
179 val LISTENER_LAST by Issue(Severity.WARNING, Category.API_LINT)
180 val EXECUTOR_REGISTRATION by Issue(Severity.WARNING, Category.API_LINT)
181 val CONFIG_FIELD_NAME by Issue(Severity.ERROR, Category.API_LINT)
182 val RESOURCE_FIELD_NAME by Issue(Severity.ERROR, Category.API_LINT)
183 val RESOURCE_VALUE_FIELD_NAME by Issue(Severity.ERROR, Category.API_LINT)
184 val RESOURCE_STYLE_FIELD_NAME by Issue(Severity.ERROR, Category.API_LINT)
185 val STREAM_FILES by Issue(Severity.WARNING, Category.API_LINT)
186 val PARCELABLE_LIST by Issue(Severity.WARNING, Category.API_LINT)
187 val ABSTRACT_INNER by Issue(Severity.WARNING, Category.API_LINT)
188 val BANNED_THROW by Issue(Severity.ERROR, Category.API_LINT)
189 val EXTENDS_ERROR by Issue(Severity.ERROR, Category.API_LINT)
190 val EXCEPTION_NAME by Issue(Severity.ERROR, Category.API_LINT)
191 val METHOD_NAME_UNITS by Issue(Severity.ERROR, Category.API_LINT)
192 val FRACTION_FLOAT by Issue(Severity.ERROR, Category.API_LINT)
193 val PERCENTAGE_INT by Issue(Severity.ERROR, Category.API_LINT)
194 val NOT_CLOSEABLE by Issue(Severity.WARNING, Category.API_LINT)
195 val KOTLIN_OPERATOR by Issue(Severity.INFO, Category.API_LINT)
196 val ARRAY_RETURN by Issue(Severity.WARNING, Category.API_LINT)
197 val USER_HANDLE by Issue(Severity.WARNING, Category.API_LINT)
198 val USER_HANDLE_NAME by Issue(Severity.WARNING, Category.API_LINT)
199 val SERVICE_NAME by Issue(Severity.ERROR, Category.API_LINT)
200 val METHOD_NAME_TENSE by Issue(Severity.WARNING, Category.API_LINT)
201 val NO_CLONE by Issue(Severity.ERROR, Category.API_LINT)
202 val USE_ICU by Issue(Severity.WARNING, Category.API_LINT)
203 val USE_PARCEL_FILE_DESCRIPTOR by Issue(Severity.ERROR, Category.API_LINT)
204 val NO_BYTE_OR_SHORT by Issue(Severity.WARNING, Category.API_LINT)
205 val SINGLETON_CONSTRUCTOR by Issue(Severity.ERROR, Category.API_LINT)
206 val KOTLIN_KEYWORD by Issue(Severity.ERROR, Category.API_LINT)
207 val UNIQUE_KOTLIN_OPERATOR by Issue(Severity.ERROR, Category.API_LINT)
208 val SAM_SHOULD_BE_LAST by Issue(Severity.WARNING, Category.API_LINT)
209 val MISSING_JVMSTATIC by Issue(Severity.WARNING, Category.API_LINT)
210 val DEFAULT_VALUE_CHANGE by Issue(Severity.ERROR, Category.COMPATIBILITY)
211 val DOCUMENT_EXCEPTIONS by Issue(Severity.ERROR, Category.API_LINT)
212 val FORBIDDEN_SUPER_CLASS by Issue(Severity.ERROR, Category.API_LINT)
213 val MISSING_NULLABILITY by Issue(Severity.ERROR, Category.API_LINT)
214 // This issue must be manually enabled
215 val MISSING_INNER_NULLABILITY by Issue(Severity.HIDDEN, Category.API_LINT)
216 val INVALID_NULLABILITY_OVERRIDE by Issue(Severity.ERROR, Category.API_LINT)
217 val MUTABLE_BARE_FIELD by Issue(Severity.ERROR, Category.API_LINT)
218 val INTERNAL_FIELD by Issue(Severity.ERROR, Category.API_LINT)
219 val PUBLIC_TYPEDEF by Issue(Severity.ERROR, Category.API_LINT)
220 val ANDROID_URI by Issue(Severity.ERROR, Category.API_LINT)
221 val BAD_FUTURE by Issue(Severity.ERROR, Category.API_LINT)
222 val STATIC_FINAL_BUILDER by Issue(Severity.WARNING, Category.API_LINT)
223 val GETTER_ON_BUILDER by Issue(Severity.WARNING, Category.API_LINT)
224 val MISSING_GETTER_MATCHING_BUILDER by Issue(Severity.WARNING, Category.API_LINT)
225 val OPTIONAL_BUILDER_CONSTRUCTOR_ARGUMENT by Issue(Severity.WARNING, Category.API_LINT)
226 val NO_SETTINGS_PROVIDER by Issue(Severity.HIDDEN, Category.API_LINT)
227 val NULLABLE_COLLECTION by Issue(Severity.WARNING, Category.API_LINT)
228 val NULLABLE_COLLECTION_ELEMENT by Issue(Severity.WARNING, Category.API_LINT)
229 val ASYNC_SUFFIX_FUTURE by Issue(Severity.ERROR, Category.API_LINT)
230 val GENERIC_CALLBACKS by Issue(Severity.ERROR, Category.API_LINT)
231 val KOTLIN_DEFAULT_PARAMETER_ORDER by Issue(Severity.ERROR, Category.API_LINT)
232 val UNFLAGGED_API by Issue(Severity.HIDDEN, Category.API_LINT)
233 val FLAGGED_API_LITERAL by Issue(Severity.WARNING_ERROR_WHEN_NEW, Category.API_LINT)
234 val GETTER_SETTER_NULLABILITY by Issue(Severity.WARNING_ERROR_WHEN_NEW, Category.API_LINT)
235 val CONDITIONAL_REQUIRES_PERMISSION_NOT_EXPLAINED by Issue(Severity.HIDDEN, Category.API_LINT)
236 val VALUE_CLASS_DEFINITION by Issue(Severity.ERROR, Category.API_LINT)
237 val INVALID_ENVIRONMENT_IN_RESTRICTED_FOR_ENVIRONMENT by
238 Issue(Severity.ERROR, Category.API_LINT)
239 val MISSING_FROM_VALUE by Issue(Severity.ERROR, Category.API_LINT)
240 val INHERIT_CHANGES_SIGNATURE by Issue(Severity.WARNING_ERROR_WHEN_NEW)
241 val DATA_CLASS_DEFINITION by Issue(Severity.HIDDEN, Category.API_LINT)
242
findIssueByIdnull243 fun findIssueById(id: String?): Issue? {
244 return nameToIssue[id]
245 }
246
findCategoryByIdnull247 fun findCategoryById(id: String?): Category =
248 Category.entries.find { it.id == id }
249 ?: error(
<lambda>null250 "Unknown category: '$id', expected one of ${Category.entries.joinToString { it.id }}"
251 )
252
253 fun findIssuesByCategory(category: Category?): List<Issue> =
254 allIssues.filter { it.category == category }
255
256 class Issue
257 private constructor(
258 val defaultLevel: Severity,
259 /**
260 * When `level` is set to [Severity.INHERIT], this is the parent from which the issue will
261 * inherit its level.
262 */
263 val parent: Issue?,
264 /** Applicable category */
265 val category: Category,
266 ) : ReadOnlyProperty<Issues, Issue> {
267 /** The name of this issue */
268 lateinit var name: String
269 internal set
270
271 internal constructor(
272 defaultLevel: Severity,
273 category: Category = Category.UNKNOWN
274 ) : this(defaultLevel, null, category)
275
276 internal constructor(
277 parent: Issue,
278 category: Category
279 ) : this(Severity.INHERIT, parent, category)
280
281 /**
282 * Called to get the value of the delegating property; as this is the value just return it.
283 */
getValuenull284 override fun getValue(thisRef: Issues, property: KProperty<*>): Issue {
285 return this
286 }
287
288 /**
289 * Called once on creation to retrieve the property delegate.
290 *
291 * Initializes the name and adds a mapping from the name to this and then just returns this
292 * as the delegate.
293 */
provideDelegatenull294 operator fun provideDelegate(thisRef: Issues, property: KProperty<*>): Issue {
295 // Initialize issue names based on the property names.
296 name = enumConstantToCamelCase(property.name)
297 nameToIssue[name] = this
298 return this
299 }
300
toStringnull301 override fun toString(): String {
302 return "Issue $name"
303 }
304
305 init {
306 allIssues.add(this)
307 }
308 }
309
310 enum class Category(val description: String) {
311 COMPATIBILITY("Compatibility"),
312 DOCUMENTATION("Documentation"),
313 API_LINT("API Lint"),
314 UNKNOWN("Default");
315
316 /** Identifier for use in command-line arguments and reporting. */
317 val id: String = enumConstantToCamelCase(name)
318 }
319
320 init {
321 // Make sure that every Issue was created as a property delegate using `by` and not just
322 // assigned to the field using `=`.
323 for (issue in allIssues) {
324 check(issue.name != "")
325 }
326 }
327 }
328
329 /**
330 * Convert enum constant name to camel case starting with an upper case letter.
331 *
332 * e.g. `ALPHA_BETA` becomes `AlphaBeta`.
333 */
enumConstantToCamelCasenull334 private fun enumConstantToCamelCase(name: String): String {
335 return name
336 .splitToSequence("_")
337 .map { "${it[0]}${it.substring(1).lowercase(Locale.US)}" }
338 .joinToString("")
339 }
340