1 /*
<lambda>null2  * Copyright (C) 2023 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.turbine
18 
19 import com.android.tools.metalava.model.AnnotationRetention
20 import com.android.tools.metalava.model.ClassItem
21 import com.android.tools.metalava.model.ClassKind
22 import com.android.tools.metalava.model.ClassTypeItem
23 import com.android.tools.metalava.model.ConstructorItem
24 import com.android.tools.metalava.model.DefaultModifierList
25 import com.android.tools.metalava.model.FieldItem
26 import com.android.tools.metalava.model.MethodItem
27 import com.android.tools.metalava.model.PackageItem
28 import com.android.tools.metalava.model.PropertyItem
29 import com.android.tools.metalava.model.SourceFile
30 import com.android.tools.metalava.model.TypeParameterList
31 import com.android.tools.metalava.model.VariableTypeItem
32 import com.android.tools.metalava.model.type.DefaultResolvedClassTypeItem
33 import com.android.tools.metalava.model.type.DefaultTypeModifiers
34 import com.android.tools.metalava.model.type.DefaultVariableTypeItem
35 import com.android.tools.metalava.model.updateCopiedMethodState
36 import com.android.tools.metalava.reporter.FileLocation
37 import com.google.turbine.binder.sym.ClassSymbol
38 import com.google.turbine.binder.sym.MethodSymbol
39 
40 internal open class TurbineClassItem(
41     codebase: TurbineBasedCodebase,
42     fileLocation: FileLocation,
43     private val name: String,
44     private val fullName: String,
45     private val qualifiedName: String,
46     private val classSymbol: ClassSymbol,
47     modifiers: DefaultModifierList,
48     override val classKind: ClassKind,
49     override val typeParameterList: TypeParameterList,
50     documentation: String,
51     private val source: SourceFile?
52 ) : TurbineItem(codebase, fileLocation, modifiers, documentation), ClassItem {
53 
54     override var artifact: String? = null
55 
56     override var hasPrivateConstructor: Boolean = false
57 
58     override var stubConstructor: ConstructorItem? = null
59 
60     internal lateinit var innerClasses: List<TurbineClassItem>
61 
62     private var superClassType: ClassTypeItem? = null
63 
64     private var allInterfaces: List<ClassItem>? = null
65 
66     internal lateinit var containingPackage: TurbinePackageItem
67 
68     internal lateinit var fields: List<TurbineFieldItem>
69 
70     internal lateinit var methods: MutableList<TurbineMethodItem>
71 
72     internal lateinit var constructors: List<TurbineConstructorItem>
73 
74     internal var containingClass: TurbineClassItem? = null
75 
76     private lateinit var interfaceTypesList: List<ClassTypeItem>
77 
78     internal var hasImplicitDefaultConstructor = false
79 
80     private var retention: AnnotationRetention? = null
81 
82     override fun allInterfaces(): Sequence<ClassItem> {
83         if (allInterfaces == null) {
84             val interfaces = mutableSetOf<ClassItem>()
85 
86             // Add self as interface if applicable
87             if (isInterface()) {
88                 interfaces.add(this)
89             }
90 
91             // Add all the interfaces of super class
92             superClass()?.let { supClass ->
93                 supClass.allInterfaces().forEach { interfaces.add(it) }
94             }
95 
96             // Add all the interfaces of direct interfaces
97             interfaceTypesList.forEach { interfaceType ->
98                 val itf = interfaceType.asClass()
99                 itf?.allInterfaces()?.forEach { interfaces.add(it) }
100             }
101 
102             allInterfaces = interfaces.toList()
103         }
104 
105         return allInterfaces!!.asSequence()
106     }
107 
108     override fun constructors(): List<ConstructorItem> = constructors
109 
110     override fun containingClass(): TurbineClassItem? = containingClass
111 
112     override fun containingPackage(): PackageItem =
113         containingClass?.containingPackage() ?: containingPackage
114 
115     override fun fields(): List<FieldItem> = fields
116 
117     override fun getRetention(): AnnotationRetention {
118         retention?.let {
119             return it
120         }
121 
122         if (!isAnnotationType()) {
123             error("getRetention() should only be called on annotation classes")
124         }
125 
126         retention = ClassItem.findRetention(this)
127         return retention!!
128     }
129 
130     override fun hasImplicitDefaultConstructor(): Boolean = hasImplicitDefaultConstructor
131 
132     override fun createDefaultConstructor(): ConstructorItem {
133         val sym = MethodSymbol(0, classSymbol, name)
134         return TurbineConstructorItem.createDefaultConstructor(codebase, this, sym)
135     }
136 
137     override fun hasTypeVariables(): Boolean = typeParameterList.isNotEmpty()
138 
139     override fun innerClasses(): List<ClassItem> = innerClasses
140 
141     override fun interfaceTypes(): List<ClassTypeItem> = interfaceTypesList
142 
143     override fun methods(): List<MethodItem> = methods
144 
145     /**
146      * [PropertyItem]s are kotlin specific and it is unlikely that Turbine will ever support Kotlin
147      * so just return an empty list.
148      */
149     override fun properties(): List<PropertyItem> = emptyList()
150 
151     override fun simpleName(): String = name
152 
153     override fun qualifiedName(): String = qualifiedName
154 
155     override fun fullName(): String = fullName
156 
157     override fun setInterfaceTypes(interfaceTypes: List<ClassTypeItem>) {
158         interfaceTypesList = interfaceTypes
159     }
160 
161     internal fun setSuperClassType(superClassType: ClassTypeItem?) {
162         this.superClassType = superClassType
163     }
164 
165     override fun superClass(): ClassItem? = superClassType?.asClass()
166 
167     override fun superClassType(): ClassTypeItem? = superClassType
168 
169     /** Must only be used by [type] to cache its result. */
170     private lateinit var cachedType: ClassTypeItem
171 
172     override fun type(): ClassTypeItem {
173         if (!::cachedType.isInitialized) {
174             cachedType = DefaultResolvedClassTypeItem.createForClass(this)
175         }
176         return cachedType
177     }
178 
179     private fun createVariableType(typeParam: TurbineTypeParameterItem): VariableTypeItem {
180         val mods = DefaultTypeModifiers.create(typeParam.modifiers.annotations())
181         return DefaultVariableTypeItem(mods, typeParam)
182     }
183 
184     override fun hashCode(): Int = qualifiedName.hashCode()
185 
186     override fun equals(other: Any?): Boolean {
187         if (this === other) {
188             return true
189         }
190         return other is ClassItem && qualifiedName() == other.qualifiedName()
191     }
192 
193     override fun getSourceFile(): SourceFile? = source
194 
195     override fun inheritMethodFromNonApiAncestor(template: MethodItem): MethodItem {
196         val method = template as TurbineMethodItem
197         val replacementMap = mapTypeVariables(method.containingClass())
198         val retType = method.returnType().convertType(replacementMap)
199         val mods = method.modifiers.duplicate()
200 
201         val duplicateMethod =
202             TurbineMethodItem(
203                 codebase,
204                 FileLocation.UNKNOWN,
205                 method.getSymbol(),
206                 this,
207                 retType,
208                 mods,
209                 method.typeParameterList,
210                 method.documentation,
211                 method.defaultValue(),
212             )
213 
214         val params =
215             method.parameters().map {
216                 TurbineParameterItem.duplicate(codebase, duplicateMethod, it, replacementMap)
217             }
218         duplicateMethod.parameters = params
219         duplicateMethod.inheritedFrom = method.containingClass()
220         duplicateMethod.throwableTypes = method.throwableTypes
221 
222         duplicateMethod.updateCopiedMethodState()
223 
224         return duplicateMethod
225     }
226 
227     override fun addMethod(method: MethodItem) {
228         methods.add(method as TurbineMethodItem)
229     }
230 }
231