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.text
18 
19 import com.android.tools.metalava.model.AnnotationItem
20 import com.android.tools.metalava.model.AnnotationRetention
21 import com.android.tools.metalava.model.ClassItem
22 import com.android.tools.metalava.model.ClassKind
23 import com.android.tools.metalava.model.ClassTypeItem
24 import com.android.tools.metalava.model.ConstructorItem
25 import com.android.tools.metalava.model.DefaultModifierList
26 import com.android.tools.metalava.model.FieldItem
27 import com.android.tools.metalava.model.Item
28 import com.android.tools.metalava.model.MethodItem
29 import com.android.tools.metalava.model.PackageItem
30 import com.android.tools.metalava.model.PropertyItem
31 import com.android.tools.metalava.model.TypeItem
32 import com.android.tools.metalava.model.TypeParameterList
33 import com.android.tools.metalava.model.type.DefaultResolvedClassTypeItem
34 import com.android.tools.metalava.reporter.FileLocation
35 import java.util.function.Predicate
36 
37 internal open class TextClassItem(
38     override val codebase: TextCodebase,
39     fileLocation: FileLocation = FileLocation.UNKNOWN,
40     modifiers: DefaultModifierList,
41     override val classKind: ClassKind = ClassKind.CLASS,
42     val qualifiedName: String = "",
43     var simpleName: String = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1),
44     val fullName: String = simpleName,
45     override val typeParameterList: TypeParameterList = TypeParameterList.NONE
46 ) : TextItem(codebase = codebase, fileLocation = fileLocation, modifiers = modifiers), ClassItem {
47 
48     override var artifact: String? = null
49 
equalsnull50     override fun equals(other: Any?): Boolean {
51         if (this === other) return true
52         if (javaClass != other?.javaClass) return false
53 
54         other as TextClassItem
55 
56         return qualifiedName == other.qualifiedName()
57     }
58 
hashCodenull59     override fun hashCode(): Int {
60         return qualifiedName.hashCode()
61     }
62 
interfaceTypesnull63     override fun interfaceTypes(): List<ClassTypeItem> = interfaceTypes
64 
65     override fun allInterfaces(): Sequence<ClassItem> {
66         return sequenceOf(
67                 // Add this if and only if it is an interface.
68                 if (classKind == ClassKind.INTERFACE) sequenceOf(this) else emptySequence(),
69                 interfaceTypes.asSequence().map { it.asClass() }.filterNotNull(),
70             )
71             .flatten()
72     }
73 
74     private var innerClasses: MutableList<ClassItem> = mutableListOf()
75 
76     override var stubConstructor: ConstructorItem? = null
77 
78     override var hasPrivateConstructor: Boolean = false
79 
innerClassesnull80     override fun innerClasses(): List<ClassItem> = innerClasses
81 
82     override fun hasImplicitDefaultConstructor(): Boolean {
83         return false
84     }
85 
86     var containingClass: ClassItem? = null
87 
containingClassnull88     override fun containingClass(): ClassItem? = containingClass
89 
90     private var containingPackage: PackageItem? = null
91 
92     fun setContainingPackage(containingPackage: TextPackageItem) {
93         this.containingPackage = containingPackage
94     }
95 
containingPackagenull96     override fun containingPackage(): PackageItem =
97         containingClass?.containingPackage() ?: containingPackage ?: error(this)
98 
99     override fun hasTypeVariables(): Boolean = typeParameterList.isNotEmpty()
100 
101     private var superClassType: ClassTypeItem? = null
102 
103     override fun superClass(): ClassItem? = superClassType?.asClass()
104 
105     override fun superClassType(): ClassTypeItem? = superClassType
106 
107     internal fun setSuperClassType(superClassType: ClassTypeItem?) {
108         this.superClassType = superClassType
109     }
110 
setInterfaceTypesnull111     override fun setInterfaceTypes(interfaceTypes: List<ClassTypeItem>) {
112         this.interfaceTypes = interfaceTypes
113     }
114 
115     /** Must only be used by [type] to cache its result. */
116     private lateinit var cachedType: ClassTypeItem
117 
typenull118     override fun type(): ClassTypeItem {
119         if (!::cachedType.isInitialized) {
120             cachedType = DefaultResolvedClassTypeItem.createForClass(this)
121         }
122         return cachedType
123     }
124 
125     private var interfaceTypes = emptyList<ClassTypeItem>()
126     private val constructors = mutableListOf<ConstructorItem>()
127     private val methods = mutableListOf<MethodItem>()
128     private val fields = mutableListOf<FieldItem>()
129     private val properties = mutableListOf<PropertyItem>()
130 
constructorsnull131     override fun constructors(): List<ConstructorItem> = constructors
132 
133     override fun methods(): List<MethodItem> = methods
134 
135     override fun fields(): List<FieldItem> = fields
136 
137     override fun properties(): List<PropertyItem> = properties
138 
139     fun addConstructor(constructor: TextConstructorItem) {
140         constructors += constructor
141     }
142 
addMethodnull143     fun addMethod(method: TextMethodItem) {
144         methods += method
145     }
146 
addFieldnull147     fun addField(field: TextFieldItem) {
148         fields += field
149     }
150 
addPropertynull151     fun addProperty(property: TextPropertyItem) {
152         properties += property
153     }
154 
addEnumConstantnull155     fun addEnumConstant(field: TextFieldItem) {
156         field.setEnumConstant(true)
157         fields += field
158     }
159 
addInnerClassnull160     override fun addInnerClass(cls: ClassItem) {
161         innerClasses.add(cls)
162     }
163 
addAnnotationnull164     fun addAnnotation(annotation: AnnotationItem) {
165         modifiers.addAnnotation(annotation)
166     }
167 
filteredSuperClassTypenull168     override fun filteredSuperClassType(predicate: Predicate<Item>): TypeItem? {
169         // No filtering in signature files: we assume signature APIs
170         // have already been filtered and all items should match.
171         // This lets us load signature files and rewrite them using updated
172         // output formats etc.
173         return superClassType
174     }
175 
176     private var retention: AnnotationRetention? = null
177 
getRetentionnull178     override fun getRetention(): AnnotationRetention {
179         retention?.let {
180             return it
181         }
182 
183         if (!isAnnotationType()) {
184             error("getRetention() should only be called on annotation classes")
185         }
186 
187         retention = ClassItem.findRetention(this)
188         return retention!!
189     }
190 
simpleNamenull191     override fun simpleName(): String = simpleName
192 
193     override fun fullName(): String = fullName
194 
195     override fun qualifiedName(): String = qualifiedName
196 
197     override fun createDefaultConstructor(): ConstructorItem {
198         return TextConstructorItem.createDefaultConstructor(codebase, this, fileLocation)
199     }
200 }
201