1 /*
2  * Copyright (C) 2018 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 
17 package com.android.tools.metalava.model
18 
19 import com.android.tools.metalava.compatibility
20 
21 open class DefaultModifierList(
22     override val codebase: Codebase,
23     protected var flags: Int = PACKAGE_PRIVATE,
24     protected open var annotations: MutableList<AnnotationItem>? = null
25 ) : MutableModifierList {
26     private lateinit var owner: Item
27 
setnull28     private operator fun set(mask: Int, set: Boolean) {
29         flags = if (set) {
30             flags or mask
31         } else {
32             flags and mask.inv()
33         }
34     }
35 
isSetnull36     private fun isSet(mask: Int): Boolean {
37         return flags and mask != 0
38     }
39 
annotationsnull40     override fun annotations(): List<AnnotationItem> {
41         return annotations ?: emptyList()
42     }
43 
ownernull44     override fun owner(): Item {
45         return owner
46     }
47 
setOwnernull48     fun setOwner(owner: Item) {
49         this.owner = owner
50     }
51 
getVisibilityLevelnull52     override fun getVisibilityLevel(): VisibilityLevel {
53         val visibilityFlags = flags and VISIBILITY_MASK
54         val levels = VISIBILITY_LEVEL_ENUMS
55         if (visibilityFlags >= levels.size) {
56             throw IllegalStateException(
57                 "Visibility flags are invalid, expected value in range [0, " + levels.size + ") got " + visibilityFlags)
58         }
59         return levels[visibilityFlags]
60     }
61 
isPublicnull62     override fun isPublic(): Boolean {
63         return getVisibilityLevel() == VisibilityLevel.PUBLIC
64     }
65 
isProtectednull66     override fun isProtected(): Boolean {
67         return getVisibilityLevel() == VisibilityLevel.PROTECTED
68     }
69 
isPrivatenull70     override fun isPrivate(): Boolean {
71         return getVisibilityLevel() == VisibilityLevel.PRIVATE
72     }
73 
isStaticnull74     override fun isStatic(): Boolean {
75         return isSet(STATIC)
76     }
77 
isAbstractnull78     override fun isAbstract(): Boolean {
79         return isSet(ABSTRACT)
80     }
81 
isFinalnull82     override fun isFinal(): Boolean {
83         return isSet(FINAL)
84     }
85 
isNativenull86     override fun isNative(): Boolean {
87         return isSet(NATIVE)
88     }
89 
isSynchronizednull90     override fun isSynchronized(): Boolean {
91         return isSet(SYNCHRONIZED)
92     }
93 
isStrictFpnull94     override fun isStrictFp(): Boolean {
95         return isSet(STRICT_FP)
96     }
97 
isTransientnull98     override fun isTransient(): Boolean {
99         return isSet(TRANSIENT)
100     }
101 
isVolatilenull102     override fun isVolatile(): Boolean {
103         return isSet(VOLATILE)
104     }
105 
isDefaultnull106     override fun isDefault(): Boolean {
107         return isSet(DEFAULT)
108     }
109 
isDeprecatednull110     fun isDeprecated(): Boolean {
111         return isSet(DEPRECATED)
112     }
113 
isVarArgnull114     override fun isVarArg(): Boolean {
115         return isSet(VARARG)
116     }
117 
isSealednull118     override fun isSealed(): Boolean {
119         return isSet(SEALED)
120     }
121 
isInfixnull122     override fun isInfix(): Boolean {
123         return isSet(INFIX)
124     }
125 
isConstnull126     override fun isConst(): Boolean {
127         return isSet(CONST)
128     }
129 
isSuspendnull130     override fun isSuspend(): Boolean {
131         return isSet(SUSPEND)
132     }
133 
isCompanionnull134     override fun isCompanion(): Boolean {
135         return isSet(COMPANION)
136     }
137 
isOperatornull138     override fun isOperator(): Boolean {
139         return isSet(OPERATOR)
140     }
141 
isInlinenull142     override fun isInline(): Boolean {
143         return isSet(INLINE)
144     }
145 
setVisibilityLevelnull146     override fun setVisibilityLevel(level: VisibilityLevel) {
147         flags = (flags and VISIBILITY_MASK.inv()) or level.visibilityFlagValue
148     }
149 
setStaticnull150     override fun setStatic(static: Boolean) {
151         set(STATIC, static)
152     }
153 
setAbstractnull154     override fun setAbstract(abstract: Boolean) {
155         set(ABSTRACT, abstract)
156     }
157 
setFinalnull158     override fun setFinal(final: Boolean) {
159         set(FINAL, final)
160     }
161 
setNativenull162     override fun setNative(native: Boolean) {
163         set(NATIVE, native)
164     }
165 
setSynchronizednull166     override fun setSynchronized(synchronized: Boolean) {
167         set(SYNCHRONIZED, synchronized)
168     }
169 
setStrictFpnull170     override fun setStrictFp(strictfp: Boolean) {
171         set(STRICT_FP, strictfp)
172     }
173 
setTransientnull174     override fun setTransient(transient: Boolean) {
175         set(TRANSIENT, transient)
176     }
177 
setVolatilenull178     override fun setVolatile(volatile: Boolean) {
179         set(VOLATILE, volatile)
180     }
181 
setDefaultnull182     override fun setDefault(default: Boolean) {
183         set(DEFAULT, default)
184     }
185 
setSealednull186     override fun setSealed(sealed: Boolean) {
187         set(SEALED, sealed)
188     }
189 
setInfixnull190     override fun setInfix(infix: Boolean) {
191         set(INFIX, infix)
192     }
193 
setOperatornull194     override fun setOperator(operator: Boolean) {
195         set(OPERATOR, operator)
196     }
197 
setInlinenull198     override fun setInline(inline: Boolean) {
199         set(INLINE, inline)
200     }
201 
202     override fun setVarArg(vararg: Boolean) {
203         set(VARARG, vararg)
204     }
205 
setDeprecatednull206     fun setDeprecated(deprecated: Boolean) {
207         set(DEPRECATED, deprecated)
208     }
209 
setSuspendnull210     fun setSuspend(suspend: Boolean) {
211         set(SUSPEND, suspend)
212     }
213 
setCompanionnull214     fun setCompanion(companion: Boolean) {
215         set(COMPANION, companion)
216     }
217 
addAnnotationnull218     override fun addAnnotation(annotation: AnnotationItem) {
219         if (annotations == null) {
220             annotations = mutableListOf()
221         }
222         annotations?.add(annotation)
223     }
224 
removeAnnotationnull225     override fun removeAnnotation(annotation: AnnotationItem) {
226         annotations?.remove(annotation)
227     }
228 
clearAnnotationsnull229     override fun clearAnnotations(annotation: AnnotationItem) {
230         annotations?.clear()
231     }
232 
isEmptynull233     override fun isEmpty(): Boolean {
234         return flags and DEPRECATED.inv() == 0 // deprecated isn't a real modifier
235     }
236 
isPackagePrivatenull237     override fun isPackagePrivate(): Boolean {
238         return flags and VISIBILITY_MASK == PACKAGE_PRIVATE
239     }
240 
241     // Rename? It's not a full equality, it's whether an override's modifier set is significant
equivalentTonull242     override fun equivalentTo(other: ModifierList): Boolean {
243         if (other is DefaultModifierList) {
244             val flags2 = other.flags
245             val mask = if (compatibility.includeSynchronized) COMPAT_EQUIVALENCE_MASK else EQUIVALENCE_MASK
246 
247             val masked1 = flags and mask
248             val masked2 = flags2 and mask
249             val same = masked1 xor masked2
250             if (same == 0) {
251                 return true
252             } else if (compatibility.hideDifferenceImplicit) {
253                 if (same == FINAL &&
254                     // Only differ in final: not significant if implied by containing class
255                     isFinal() && (owner as? MethodItem)?.containingClass()?.modifiers?.isFinal() == true) {
256                     return true
257                 } else if (same == DEPRECATED &&
258                     // Only differ in deprecated: not significant if implied by containing class
259                     isDeprecated() && (owner as? MethodItem)?.containingClass()?.deprecated == true) {
260                     return true
261                 }
262             }
263         }
264         return false
265     }
266 
267     companion object {
268         const val PRIVATE = 0
269         const val INTERNAL = 1
270         const val PACKAGE_PRIVATE = 2
271         const val PROTECTED = 3
272         const val PUBLIC = 4
273         const val VISIBILITY_MASK = 0b111
274 
275         /**
276          * An internal copy of VisibilityLevel.values() to avoid paying the cost of duplicating the array on every
277          * call.
278          */
279         private val VISIBILITY_LEVEL_ENUMS = VisibilityLevel.values()
280 
281         // Check that the constants above are consistent with the VisibilityLevel enum, i.e. the mask is large enough
282         // to include all allowable values and that each visibility level value is the same as the corresponding enum
283         // constant's ordinal.
<lambda>null284         init {
285             check(PRIVATE == VisibilityLevel.PRIVATE.ordinal)
286             check(INTERNAL == VisibilityLevel.INTERNAL.ordinal)
287             check(PACKAGE_PRIVATE == VisibilityLevel.PACKAGE_PRIVATE.ordinal)
288             check(PROTECTED == VisibilityLevel.PROTECTED.ordinal)
289             check(PUBLIC == VisibilityLevel.PUBLIC.ordinal)
290             // Calculate the mask required to hold as many different values as there are VisibilityLevel values.
291             // Given N visibility levels, the required mask is constructed by determining the MSB in the number N - 1
292             // and then setting all bits to the right.
293             // e.g. when N is 5 then N - 1 is 4, the MSB is bit 2, and so the mask is what you get when you set bits 2,
294             // 1 and 0, i.e. 0b111.
295             val expectedMask = (1 shl (32 - Integer.numberOfLeadingZeros(VISIBILITY_LEVEL_ENUMS.size - 1))) - 1
296             check(VISIBILITY_MASK == expectedMask)
297         }
298 
299         const val STATIC = 1 shl 3
300         const val ABSTRACT = 1 shl 4
301         const val FINAL = 1 shl 5
302         const val NATIVE = 1 shl 6
303         const val SYNCHRONIZED = 1 shl 7
304         const val STRICT_FP = 1 shl 8
305         const val TRANSIENT = 1 shl 9
306         const val VOLATILE = 1 shl 10
307         const val DEFAULT = 1 shl 11
308         const val DEPRECATED = 1 shl 12
309         const val VARARG = 1 shl 13
310         const val SEALED = 1 shl 14
311         // 15 currently unused
312         const val INFIX = 1 shl 16
313         const val OPERATOR = 1 shl 17
314         const val INLINE = 1 shl 18
315         const val SUSPEND = 1 shl 19
316         const val COMPANION = 1 shl 20
317         const val CONST = 1 shl 21
318 
319         /**
320          * Modifiers considered significant to include signature files (and similarly
321          * to consider whether an override of a method is different from its super implementation
322          */
323         private const val EQUIVALENCE_MASK = VISIBILITY_MASK or STATIC or ABSTRACT or
324             FINAL or TRANSIENT or VOLATILE or DEPRECATED or VARARG or
325             SEALED or INFIX or OPERATOR or SUSPEND or COMPANION
326 
327         private const val COMPAT_EQUIVALENCE_MASK = EQUIVALENCE_MASK or SYNCHRONIZED
328     }
329 }