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