xref: /aosp_15_r20/tools/metalava/metalava-model/src/main/java/com/android/tools/metalava/model/ModifierList.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
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 
17 package com.android.tools.metalava.model
18 
19 interface BaseModifierList {
annotationsnull20     fun annotations(): List<AnnotationItem>
21 
22     fun getVisibilityLevel(): VisibilityLevel
23 
24     fun isPublic(): Boolean
25 
26     fun isProtected(): Boolean
27 
28     fun isPrivate(): Boolean
29 
30     @MetalavaApi fun isStatic(): Boolean
31 
32     fun isAbstract(): Boolean
33 
34     fun isFinal(): Boolean
35 
36     fun isNative(): Boolean
37 
38     fun isSynchronized(): Boolean
39 
40     fun isStrictFp(): Boolean
41 
42     fun isTransient(): Boolean
43 
44     fun isVolatile(): Boolean
45 
46     fun isDefault(): Boolean
47 
48     fun isDeprecated(): Boolean
49 
50     // Modifier in Kotlin, separate syntax (...) in Java but modeled as modifier here
51     fun isVarArg(): Boolean = false
52 
53     // Kotlin
54     fun isSealed(): Boolean = false
55 
56     fun isFunctional(): Boolean = false
57 
58     fun isCompanion(): Boolean = false
59 
60     fun isInfix(): Boolean = false
61 
62     fun isConst(): Boolean = false
63 
64     fun isSuspend(): Boolean = false
65 
66     fun isOperator(): Boolean = false
67 
68     fun isInline(): Boolean = false
69 
70     fun isValue(): Boolean = false
71 
72     fun isData(): Boolean = false
73 
74     fun isExpect(): Boolean = false
75 
76     fun isActual(): Boolean = false
77 
78     fun isPackagePrivate() = !(isPublic() || isProtected() || isPrivate())
79 
80     fun isPublicOrProtected() = isPublic() || isProtected()
81 
82     /**
83      * Check whether this [ModifierList]'s modifiers are equivalent to the [other] [ModifierList]'s
84      * modifiers.
85      *
86      * Modifier meaning does depend on the [Item] to which they belong, e.g. just because `final`
87      * and `deprecated` are `false` does not mean that the [Item] is not final or deprecated as the
88      * containing class may be final or deprecated.
89      *
90      * It is used for:
91      * * Checking method overrides.
92      * * Checking consistent of classes whose definition is split across multiple signature files.
93      * * Testing the [InheritableItem.duplicate] works correctly.
94      *
95      * @param owner the optional [Item] that owns this [ModifierList] and which is used to tweak the
96      *   check to make it take into account the content within which they are being used. If it is
97      *   not provided then this will just compare modifiers like for like.
98      *
99      * TODO(b/356548977): Currently, [owner] only has an effect if it is a [MethodItem]. That is due
100      *   to it historically only being used for method overrides. However, as the previous list
101      *   shows that is no longer true so it will need to be updated to correctly handle the other
102      *   cases.
103      */
104     fun equivalentTo(owner: Item?, other: BaseModifierList): Boolean
105 
106     /** Returns true if this modifier list contains the `@JvmSynthetic` annotation */
107     fun hasJvmSyntheticAnnotation(): Boolean = hasAnnotation(AnnotationItem::isJvmSynthetic)
108 
109     /** Returns true if this modifier list contains the given annotation */
110     fun isAnnotatedWith(qualifiedName: String): Boolean {
111         return findAnnotation(qualifiedName) != null
112     }
113 
114     /**
115      * Returns the annotation of the given qualified name (or equivalent) if found in this modifier
116      * list
117      */
findAnnotationnull118     fun findAnnotation(qualifiedName: String): AnnotationItem? {
119         return findAnnotation { qualifiedName == it.qualifiedName }
120     }
121 
122     /**
123      * Returns true if the visibility modifiers in this modifier list is as least as visible as the
124      * ones in the given [other] modifier list
125      */
asAccessibleAsnull126     fun asAccessibleAs(other: BaseModifierList): Boolean {
127         val otherLevel = other.getVisibilityLevel()
128         val thisLevel = getVisibilityLevel()
129         // Generally the access level enum order determines relative visibility. However, there is
130         // an exception because
131         // package private and internal are not directly comparable.
132         val result = thisLevel >= otherLevel
133         return when (otherLevel) {
134             VisibilityLevel.PACKAGE_PRIVATE -> result && thisLevel != VisibilityLevel.INTERNAL
135             VisibilityLevel.INTERNAL -> result && thisLevel != VisibilityLevel.PACKAGE_PRIVATE
136             else -> result
137         }
138     }
139 
140     /** User visible description of the visibility in this modifier list */
getVisibilityStringnull141     fun getVisibilityString(): String {
142         return getVisibilityLevel().userVisibleDescription
143     }
144 
145     /**
146      * Like [getVisibilityString], but package private has no modifiers; this typically corresponds
147      * to the source code for the visibility modifiers in the modifier list
148      */
getVisibilityModifiersnull149     fun getVisibilityModifiers(): String {
150         return getVisibilityLevel().javaSourceCodeModifier
151     }
152 
153     /**
154      * Get a [MutableModifierList] from this.
155      *
156      * This will return the object on which it is called if that is already mutable, otherwise it
157      * will create a separate mutable copy of this.
158      */
toMutablenull159     fun toMutable(): MutableModifierList
160 
161     /**
162      * Get an immutable [ModifierList] from this.
163      *
164      * This will return the object on which it is called if that is already immutable, otherwise it
165      * will create a separate immutable copy of this.
166      */
167     fun toImmutable(): ModifierList
168 }
169 
170 /**
171  * Returns the first annotation in the modifier list that matches the supplied predicate, or null
172  * otherwise.
173  */
174 inline fun BaseModifierList.findAnnotation(
175     predicate: (AnnotationItem) -> Boolean
176 ): AnnotationItem? {
177     return annotations().firstOrNull(predicate)
178 }
179 
180 /**
181  * Returns true iff the modifier list contains any annotation that matches the supplied predicate.
182  */
hasAnnotationnull183 inline fun BaseModifierList.hasAnnotation(predicate: (AnnotationItem) -> Boolean): Boolean {
184     return annotations().any(predicate)
185 }
186 
187 interface ModifierList : BaseModifierList {
188     /**
189      * Take a snapshot of this for use in [targetCodebase].
190      *
191      * Creates a deep snapshot, including snapshots of each annotation for use in [targetCodebase].
192      *
193      * @param targetCodebase The [Codebase] of which the snapshot will be part.
194      */
snapshotnull195     fun snapshot(targetCodebase: Codebase): ModifierList
196 }
197