• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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.model.ModifierFlags.Companion.ABSTRACT
20 import com.android.tools.metalava.model.ModifierFlags.Companion.ACTUAL
21 import com.android.tools.metalava.model.ModifierFlags.Companion.COMPANION
22 import com.android.tools.metalava.model.ModifierFlags.Companion.CONST
23 import com.android.tools.metalava.model.ModifierFlags.Companion.DATA
24 import com.android.tools.metalava.model.ModifierFlags.Companion.DEFAULT
25 import com.android.tools.metalava.model.ModifierFlags.Companion.DEPRECATED
26 import com.android.tools.metalava.model.ModifierFlags.Companion.EQUIVALENCE_MASK
27 import com.android.tools.metalava.model.ModifierFlags.Companion.EXPECT
28 import com.android.tools.metalava.model.ModifierFlags.Companion.FINAL
29 import com.android.tools.metalava.model.ModifierFlags.Companion.FUN
30 import com.android.tools.metalava.model.ModifierFlags.Companion.INFIX
31 import com.android.tools.metalava.model.ModifierFlags.Companion.INLINE
32 import com.android.tools.metalava.model.ModifierFlags.Companion.NATIVE
33 import com.android.tools.metalava.model.ModifierFlags.Companion.OPERATOR
34 import com.android.tools.metalava.model.ModifierFlags.Companion.PACKAGE_PRIVATE
35 import com.android.tools.metalava.model.ModifierFlags.Companion.PRIVATE
36 import com.android.tools.metalava.model.ModifierFlags.Companion.PROTECTED
37 import com.android.tools.metalava.model.ModifierFlags.Companion.SEALED
38 import com.android.tools.metalava.model.ModifierFlags.Companion.STATIC
39 import com.android.tools.metalava.model.ModifierFlags.Companion.STRICT_FP
40 import com.android.tools.metalava.model.ModifierFlags.Companion.SUSPEND
41 import com.android.tools.metalava.model.ModifierFlags.Companion.SYNCHRONIZED
42 import com.android.tools.metalava.model.ModifierFlags.Companion.TRANSIENT
43 import com.android.tools.metalava.model.ModifierFlags.Companion.VALUE
44 import com.android.tools.metalava.model.ModifierFlags.Companion.VARARG
45 import com.android.tools.metalava.model.ModifierFlags.Companion.VISIBILITY_LEVEL_ENUMS
46 import com.android.tools.metalava.model.ModifierFlags.Companion.VISIBILITY_MASK
47 import com.android.tools.metalava.model.ModifierFlags.Companion.VOLATILE
48 import java.lang.annotation.Retention
49 import java.lang.annotation.RetentionPolicy
50 
51 /** Default [BaseModifierList]. */
52 internal abstract class DefaultBaseModifierList
53 constructor(
54     protected var flags: Int,
55     protected var annotations: List<AnnotationItem> = emptyList(),
56 ) : BaseModifierList {
57 
58     protected operator fun set(mask: Int, set: Boolean) {
59         flags =
60             if (set) {
61                 flags or mask
62             } else {
63                 flags and mask.inv()
64             }
65     }
66 
67     private fun isSet(mask: Int): Boolean {
68         return flags and mask != 0
69     }
70 
71     override fun annotations(): List<AnnotationItem> {
72         return annotations
73     }
74 
75     override fun getVisibilityLevel(): VisibilityLevel {
76         val visibilityFlags = flags and VISIBILITY_MASK
77         val levels = VISIBILITY_LEVEL_ENUMS
78         if (visibilityFlags >= levels.size) {
79             throw IllegalStateException(
80                 "Visibility flags are invalid, expected value in range [0, " +
81                     levels.size +
82                     ") got " +
83                     visibilityFlags
84             )
85         }
86         return levels[visibilityFlags]
87     }
88 
89     override fun isPublic(): Boolean {
90         return getVisibilityLevel() == VisibilityLevel.PUBLIC
91     }
92 
93     override fun isProtected(): Boolean {
94         return getVisibilityLevel() == VisibilityLevel.PROTECTED
95     }
96 
97     override fun isPrivate(): Boolean {
98         return getVisibilityLevel() == VisibilityLevel.PRIVATE
99     }
100 
101     override fun isStatic(): Boolean {
102         return isSet(STATIC)
103     }
104 
105     override fun isAbstract(): Boolean {
106         return isSet(ABSTRACT)
107     }
108 
109     override fun isFinal(): Boolean {
110         return isSet(FINAL)
111     }
112 
113     override fun isNative(): Boolean {
114         return isSet(NATIVE)
115     }
116 
117     override fun isSynchronized(): Boolean {
118         return isSet(SYNCHRONIZED)
119     }
120 
121     override fun isStrictFp(): Boolean {
122         return isSet(STRICT_FP)
123     }
124 
125     override fun isTransient(): Boolean {
126         return isSet(TRANSIENT)
127     }
128 
129     override fun isVolatile(): Boolean {
130         return isSet(VOLATILE)
131     }
132 
133     override fun isDefault(): Boolean {
134         return isSet(DEFAULT)
135     }
136 
137     override fun isDeprecated(): Boolean {
138         return isSet(DEPRECATED)
139     }
140 
141     override fun isVarArg(): Boolean {
142         return isSet(VARARG)
143     }
144 
145     override fun isSealed(): Boolean {
146         return isSet(SEALED)
147     }
148 
149     override fun isFunctional(): Boolean {
150         return isSet(FUN)
151     }
152 
153     override fun isInfix(): Boolean {
154         return isSet(INFIX)
155     }
156 
157     override fun isConst(): Boolean {
158         return isSet(CONST)
159     }
160 
161     override fun isSuspend(): Boolean {
162         return isSet(SUSPEND)
163     }
164 
165     override fun isCompanion(): Boolean {
166         return isSet(COMPANION)
167     }
168 
169     override fun isOperator(): Boolean {
170         return isSet(OPERATOR)
171     }
172 
173     override fun isInline(): Boolean {
174         return isSet(INLINE)
175     }
176 
177     override fun isValue(): Boolean {
178         return isSet(VALUE)
179     }
180 
181     override fun isData(): Boolean {
182         return isSet(DATA)
183     }
184 
185     override fun isExpect(): Boolean {
186         return isSet(EXPECT)
187     }
188 
189     override fun isActual(): Boolean {
190         return isSet(ACTUAL)
191     }
192 
193     override fun isPackagePrivate(): Boolean {
194         return flags and VISIBILITY_MASK == PACKAGE_PRIVATE
195     }
196 
197     override fun equivalentTo(owner: Item?, other: BaseModifierList): Boolean {
198         other as DefaultBaseModifierList
199 
200         val flags2 = other.flags
201         val mask = EQUIVALENCE_MASK
202 
203         val masked1 = flags and mask
204         val masked2 = flags2 and mask
205         val same = masked1 xor masked2
206         if (same == 0) {
207             return true
208         } else {
209             if (
210                 same == FINAL &&
211                     // Only differ in final: not significant if implied by containing class
212                     isFinal() &&
213                     (owner as? MethodItem)?.containingClass()?.modifiers?.isFinal() == true
214             ) {
215                 return true
216             } else if (
217                 same == DEPRECATED &&
218                     // Only differ in deprecated: not significant if implied by containing class
219                     isDeprecated() &&
220                     (owner as? MethodItem)?.containingClass()?.effectivelyDeprecated == true
221             ) {
222                 return true
223             }
224         }
225 
226         return false
227     }
228 
229     override fun equals(other: Any?): Boolean {
230         if (this === other) return true
231         if (other !is DefaultBaseModifierList) return false
232 
233         if (flags != other.flags) return false
234         if (annotations != other.annotations) return false
235 
236         return true
237     }
238 
239     override fun hashCode(): Int {
240         var result = flags
241         result = 31 * result + annotations.hashCode()
242         return result
243     }
244 
245     override fun toString(): String {
246         val binaryFlags = Integer.toBinaryString(flags)
247         return "ModifierList(flags = 0b$binaryFlags, annotations = $annotations)"
248     }
249 }
250 
251 interface ModifierFlags {
252     companion object {
253 
254         /**
255          * 'PACKAGE_PRIVATE' is set to 0 to act as the default visibility when no other visibility
256          * flags are explicitly set.
257          */
258         const val PACKAGE_PRIVATE = 0
259         const val PRIVATE = 1
260         const val INTERNAL = 2
261         const val PROTECTED = 3
262         const val PUBLIC = 4
263         const val VISIBILITY_MASK = 0b111
264 
265         /**
266          * An internal copy of VisibilityLevel.values() to avoid paying the cost of duplicating the
267          * array on every call.
268          */
269         internal val VISIBILITY_LEVEL_ENUMS = VisibilityLevel.entries
270 
271         // Check that the constants above are consistent with the VisibilityLevel enum, i.e. the
272         // mask is large enough
273         // to include all allowable values and that each visibility level value is the same as the
274         // corresponding enum
275         // constant's ordinal.
276         init {
277             check(PACKAGE_PRIVATE == VisibilityLevel.PACKAGE_PRIVATE.ordinal)
278             check(PRIVATE == VisibilityLevel.PRIVATE.ordinal)
279             check(INTERNAL == VisibilityLevel.INTERNAL.ordinal)
280             check(PROTECTED == VisibilityLevel.PROTECTED.ordinal)
281             check(PUBLIC == VisibilityLevel.PUBLIC.ordinal)
282             // Calculate the mask required to hold as many different values as there are
283             // VisibilityLevel values.
284             // Given N visibility levels, the required mask is constructed by determining the MSB in
285             // the number N - 1
286             // and then setting all bits to the right.
287             // e.g. when N is 5 then N - 1 is 4, the MSB is bit 2, and so the mask is what you get
288             // when you set bits 2,
289             // 1 and 0, i.e. 0b111.
290             val expectedMask =
291                 (1 shl (32 - Integer.numberOfLeadingZeros(VISIBILITY_LEVEL_ENUMS.size - 1))) - 1
292             check(VISIBILITY_MASK == expectedMask)
293         }
294 
295         const val STATIC = 1 shl 3
296         const val ABSTRACT = 1 shl 4
297         const val FINAL = 1 shl 5
298         const val NATIVE = 1 shl 6
299         const val SYNCHRONIZED = 1 shl 7
300         const val STRICT_FP = 1 shl 8
301         const val TRANSIENT = 1 shl 9
302         const val VOLATILE = 1 shl 10
303         const val DEFAULT = 1 shl 11
304         const val DEPRECATED = 1 shl 12
305         const val VARARG = 1 shl 13
306         const val SEALED = 1 shl 14
307         const val FUN = 1 shl 15
308         const val INFIX = 1 shl 16
309         const val OPERATOR = 1 shl 17
310         const val INLINE = 1 shl 18
311         const val SUSPEND = 1 shl 19
312         const val COMPANION = 1 shl 20
313         const val CONST = 1 shl 21
314         const val DATA = 1 shl 22
315         const val VALUE = 1 shl 23
316         const val EXPECT = 1 shl 24
317         const val ACTUAL = 1 shl 25
318 
319         /**
320          * Modifiers considered significant to include signature files (and similarly to consider
321          * whether an override of a method is different from its super implementation)
322          */
323         internal const val EQUIVALENCE_MASK =
324             VISIBILITY_MASK or
325                 STATIC or
326                 ABSTRACT or
327                 FINAL or
328                 TRANSIENT or
329                 VOLATILE or
330                 DEPRECATED or
331                 VARARG or
332                 SEALED or
333                 FUN or
334                 INFIX or
335                 OPERATOR or
336                 SUSPEND or
337                 COMPANION
338     }
339 }
340 
341 /** Default [MutableModifierList]. */
342 internal class DefaultMutableModifierList(
343     flags: Int,
344     annotations: List<AnnotationItem> = emptyList(),
345 ) : DefaultBaseModifierList(flags, annotations), MutableModifierList {
346 
toMutablenull347     override fun toMutable(): MutableModifierList {
348         return this
349     }
350 
toImmutablenull351     override fun toImmutable(): ModifierList {
352         return DefaultModifierList.create(flags, annotations)
353     }
354 
setVisibilityLevelnull355     override fun setVisibilityLevel(level: VisibilityLevel) {
356         flags = (flags and VISIBILITY_MASK.inv()) or level.visibilityFlagValue
357     }
358 
setStaticnull359     override fun setStatic(static: Boolean) {
360         set(STATIC, static)
361     }
362 
setAbstractnull363     override fun setAbstract(abstract: Boolean) {
364         set(ABSTRACT, abstract)
365     }
366 
setFinalnull367     override fun setFinal(final: Boolean) {
368         set(FINAL, final)
369     }
370 
setNativenull371     override fun setNative(native: Boolean) {
372         set(NATIVE, native)
373     }
374 
setSynchronizednull375     override fun setSynchronized(synchronized: Boolean) {
376         set(SYNCHRONIZED, synchronized)
377     }
378 
setStrictFpnull379     override fun setStrictFp(strictfp: Boolean) {
380         set(STRICT_FP, strictfp)
381     }
382 
setTransientnull383     override fun setTransient(transient: Boolean) {
384         set(TRANSIENT, transient)
385     }
386 
setVolatilenull387     override fun setVolatile(volatile: Boolean) {
388         set(VOLATILE, volatile)
389     }
390 
setDefaultnull391     override fun setDefault(default: Boolean) {
392         set(DEFAULT, default)
393     }
394 
setSealednull395     override fun setSealed(sealed: Boolean) {
396         set(SEALED, sealed)
397     }
398 
setFunctionalnull399     override fun setFunctional(functional: Boolean) {
400         set(FUN, functional)
401     }
402 
setInfixnull403     override fun setInfix(infix: Boolean) {
404         set(INFIX, infix)
405     }
406 
setOperatornull407     override fun setOperator(operator: Boolean) {
408         set(OPERATOR, operator)
409     }
410 
setInlinenull411     override fun setInline(inline: Boolean) {
412         set(INLINE, inline)
413     }
414 
setValuenull415     override fun setValue(value: Boolean) {
416         set(VALUE, value)
417     }
418 
setDatanull419     override fun setData(data: Boolean) {
420         set(DATA, data)
421     }
422 
423     override fun setVarArg(vararg: Boolean) {
424         set(VARARG, vararg)
425     }
426 
setDeprecatednull427     override fun setDeprecated(deprecated: Boolean) {
428         set(DEPRECATED, deprecated)
429     }
430 
setSuspendnull431     override fun setSuspend(suspend: Boolean) {
432         set(SUSPEND, suspend)
433     }
434 
setCompanionnull435     override fun setCompanion(companion: Boolean) {
436         set(COMPANION, companion)
437     }
438 
setExpectnull439     override fun setExpect(expect: Boolean) {
440         set(EXPECT, expect)
441     }
442 
setActualnull443     override fun setActual(actual: Boolean) {
444         set(ACTUAL, actual)
445     }
446 
mutateAnnotationsnull447     override fun mutateAnnotations(mutator: MutableList<AnnotationItem>.() -> Unit) {
448         val mutable = annotations.toMutableList()
449         mutable.mutator()
450         annotations = mutable.toList()
451     }
452 }
453 
454 /** Default [ModifierList]. */
455 internal class DefaultModifierList
456 private constructor(
457     flags: Int,
458     annotations: List<AnnotationItem>,
459 ) : DefaultBaseModifierList(flags, annotations), ModifierList {
460 
toMutablenull461     override fun toMutable(): MutableModifierList {
462         return DefaultMutableModifierList(flags, annotations)
463     }
464 
toImmutablenull465     override fun toImmutable(): ModifierList {
466         return this
467     }
468 
snapshotnull469     override fun snapshot(targetCodebase: Codebase): ModifierList {
470         if (annotations.isEmpty()) return this
471 
472         val newAnnotations = annotations.map { it.snapshot(targetCodebase) }
473         return create(flags, newAnnotations)
474     }
475 
476     companion object {
477         private var cache = mutableMapOf<Int, DefaultModifierList>()
478 
479         /** Not thread-safe. */
createnull480         fun create(
481             flags: Int,
482             annotations: List<AnnotationItem> = emptyList(),
483         ): ModifierList {
484             if (annotations.isEmpty()) {
485                 return cache.computeIfAbsent(flags) { DefaultModifierList(it, emptyList()) }
486             }
487             return DefaultModifierList(flags, annotations)
488         }
489     }
490 }
491 
492 /**
493  * Add a [Retention] annotation with the default [RetentionPolicy] suitable for [codebase].
494  *
495  * The caller must ensure that the annotation does not already have a [Retention] annotation before
496  * calling this.
497  */
MutableModifierListnull498 fun MutableModifierList.addDefaultRetentionPolicyAnnotation(
499     codebase: Codebase,
500     isKotlin: Boolean,
501 ) {
502     // By policy, include explicit retention policy annotation if missing
503     val defaultRetentionPolicy = AnnotationRetention.getDefault(isKotlin)
504     addAnnotation(
505         codebase.createAnnotation(
506             buildString {
507                 append('@')
508                 append(Retention::class.qualifiedName)
509                 append('(')
510                 append(RetentionPolicy::class.qualifiedName)
511                 append('.')
512                 append(defaultRetentionPolicy.name)
513                 append(')')
514             },
515         )
516     )
517 }
518 
519 /**
520  * Create an immutable [ModifierList] with the [visibility] level and an optional list of
521  * [AnnotationItem]s.
522  */
createImmutableModifiersnull523 fun createImmutableModifiers(
524     visibility: VisibilityLevel,
525     annotations: List<AnnotationItem> = emptyList(),
526 ): ModifierList {
527     return DefaultModifierList.create(visibility.visibilityFlagValue, annotations)
528 }
529 
530 /**
531  * Create a [MutableModifierList] with the [visibility] level and an optional list of
532  * [AnnotationItem]s.
533  */
createMutableModifiersnull534 fun createMutableModifiers(
535     visibility: VisibilityLevel,
536     annotations: List<AnnotationItem> = emptyList(),
537 ): MutableModifierList {
538     return DefaultMutableModifierList(visibility.visibilityFlagValue, annotations)
539 }
540 
541 /**
542  * Modifies the modifier flags based on the `VisibleForTesting` annotation's `otherwise` value.
543  *
544  * @param otherwiseValue the value of the `otherwise` attribute, or `""` if no attribute is
545  *   provided.
546  */
useVisibilityFromVisibleForTestingnull547 private fun useVisibilityFromVisibleForTesting(otherwiseValue: String, flags: Int): Int {
548     /** Check to see if this matches [visibility] or numeric [value]. */
549     fun String.matchesVisibility(visibility: String, value: Int) =
550         endsWith(visibility) || equals(value.toString())
551 
552     val visibilityFlags =
553         when {
554             otherwiseValue.matchesVisibility("PROTECTED", VisibleForTesting.PROTECTED) -> {
555                 PROTECTED
556             }
557             otherwiseValue.matchesVisibility(
558                 "PACKAGE_PRIVATE",
559                 VisibleForTesting.PACKAGE_PRIVATE
560             ) -> {
561                 PACKAGE_PRIVATE
562             }
563             otherwiseValue.matchesVisibility("PRIVATE", VisibleForTesting.PRIVATE) ||
564                 otherwiseValue.matchesVisibility("NONE", VisibleForTesting.NONE) -> {
565                 PRIVATE
566             }
567             else -> {
568                 // Return the flags without changes.
569                 return flags
570             }
571         }
572 
573     return (flags and VISIBILITY_MASK.inv()) or visibilityFlags
574 }
575 
576 /**
577  * Create a [MutableModifierList] from a set of [flags] and an optional list of [AnnotationItem]s.
578  */
createMutableModifiersnull579 fun createMutableModifiers(
580     flags: Int,
581     annotations: List<AnnotationItem> = emptyList(),
582 ): MutableModifierList {
583     val actualFlags =
584         annotations
585             .find { it.qualifiedName == ANDROIDX_VISIBLE_FOR_TESTING }
586             ?.let { visibleForTesting ->
587                 visibleForTesting.findAttribute(ATTR_OTHERWISE)?.legacyValue?.let { otherwiseValue
588                     ->
589                     useVisibilityFromVisibleForTesting(otherwiseValue.toSource(), flags)
590                 }
591             }
592             ?: flags
593 
594     return DefaultMutableModifierList(actualFlags, annotations)
595 }
596 
597 private const val ANDROIDX_VISIBLE_FOR_TESTING = "androidx.annotation.VisibleForTesting"
598 private const val ATTR_OTHERWISE = "otherwise"
599 
600 /** Defines the numeric values of the symbols used in tests that use numbers instead of symbols. */
601 // TODO(b/387992791): Use a real VisibleForTesting annotation.
602 interface VisibleForTesting {
603     companion object {
604         const val PRIVATE = 2
605         const val PACKAGE_PRIVATE = 3
606         const val PROTECTED = 4
607         const val NONE = 5
608     }
609 }
610