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