• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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