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.psi
18 
19 import com.android.tools.metalava.model.ArrayTypeItem
20 import com.android.tools.metalava.model.ClassTypeItem
21 import com.android.tools.metalava.model.Codebase
22 import com.android.tools.metalava.model.DefaultTypeItem
23 import com.android.tools.metalava.model.LambdaTypeItem
24 import com.android.tools.metalava.model.PrimitiveTypeItem
25 import com.android.tools.metalava.model.ReferenceTypeItem
26 import com.android.tools.metalava.model.TypeArgumentTypeItem
27 import com.android.tools.metalava.model.TypeItem
28 import com.android.tools.metalava.model.TypeModifiers
29 import com.android.tools.metalava.model.TypeParameterItem
30 import com.android.tools.metalava.model.VariableTypeItem
31 import com.android.tools.metalava.model.WildcardTypeItem
32 import com.intellij.psi.PsiArrayType
33 import com.intellij.psi.PsiClassType
34 import com.intellij.psi.PsiPrimitiveType
35 import com.intellij.psi.PsiType
36 import com.intellij.psi.PsiWildcardType
37 import com.intellij.psi.util.TypeConversionUtil
38 
39 /** Represents a type backed by PSI */
40 internal sealed class PsiTypeItem(
41     val psiType: PsiType,
42     modifiers: TypeModifiers,
43 ) : DefaultTypeItem(modifiers) {
44 
45     /** Returns `true` if `this` type can be assigned from `other` without unboxing the other. */
isAssignableFromWithoutUnboxingnull46     override fun isAssignableFromWithoutUnboxing(other: TypeItem): Boolean {
47         if (other !is PsiTypeItem) return super.isAssignableFromWithoutUnboxing(other)
48         if (this is PrimitiveTypeItem && other !is PrimitiveTypeItem) {
49             return false
50         }
51         return TypeConversionUtil.isAssignable(psiType, other.psiType)
52     }
53 }
54 
55 /** A [PsiTypeItem] backed by a [PsiPrimitiveType]. */
56 internal class PsiPrimitiveTypeItem(
57     psiType: PsiType,
58     override val kind: PrimitiveTypeItem.Primitive,
59     modifiers: TypeModifiers,
60 ) : PrimitiveTypeItem, PsiTypeItem(psiType, modifiers) {
duplicatenull61     override fun duplicate(): PsiPrimitiveTypeItem =
62         PsiPrimitiveTypeItem(psiType = psiType, kind = kind, modifiers = modifiers.duplicate())
63 }
64 
65 /** A [PsiTypeItem] backed by a [PsiArrayType]. */
66 internal class PsiArrayTypeItem(
67     psiType: PsiType,
68     override val componentType: PsiTypeItem,
69     override val isVarargs: Boolean,
70     modifiers: TypeModifiers,
71 ) : ArrayTypeItem, PsiTypeItem(psiType, modifiers) {
72     override fun duplicate(componentType: TypeItem): ArrayTypeItem =
73         PsiArrayTypeItem(
74             psiType = psiType,
75             componentType = componentType as PsiTypeItem,
76             isVarargs = isVarargs,
77             modifiers = modifiers.duplicate()
78         )
79 }
80 
81 /** A [PsiTypeItem] backed by a [PsiClassType] that does not represent a type variable. */
82 internal open class PsiClassTypeItem(
83     protected val codebase: Codebase,
84     psiType: PsiType,
85     final override val qualifiedName: String,
86     final override val arguments: List<TypeArgumentTypeItem>,
87     final override val outerClassType: PsiClassTypeItem?,
88     final override val className: String,
89     modifiers: TypeModifiers,
90 ) : ClassTypeItem, PsiTypeItem(psiType, modifiers) {
91 
92     private val asClassCache by
<lambda>null93         lazy(LazyThreadSafetyMode.NONE) { codebase.resolveClass(qualifiedName) }
94 
asClassnull95     override fun asClass() = asClassCache
96 
97     override fun duplicate(
98         outerClass: ClassTypeItem?,
99         arguments: List<TypeArgumentTypeItem>
100     ): ClassTypeItem =
101         PsiClassTypeItem(
102             codebase = codebase,
103             psiType = psiType,
104             qualifiedName = qualifiedName,
105             arguments = arguments,
106             outerClassType = outerClass as? PsiClassTypeItem,
107             className = className,
108             modifiers = modifiers.duplicate()
109         )
110 }
111 
112 internal class PsiLambdaTypeItem(
113     codebase: Codebase,
114     psiType: PsiType,
115     qualifiedName: String,
116     arguments: List<TypeArgumentTypeItem>,
117     outerClassType: PsiClassTypeItem?,
118     className: String,
119     modifiers: TypeModifiers,
120     override val isSuspend: Boolean,
121     override val receiverType: TypeItem?,
122     override val parameterTypes: List<TypeItem>,
123     override val returnType: TypeItem,
124 ) :
125     PsiClassTypeItem(
126         codebase = codebase,
127         psiType = psiType,
128         qualifiedName = qualifiedName,
129         arguments = arguments,
130         outerClassType = outerClassType,
131         className = className,
132         modifiers = modifiers,
133     ),
134     LambdaTypeItem {
135 
136     override fun duplicate(
137         outerClass: ClassTypeItem?,
138         arguments: List<TypeArgumentTypeItem>
139     ): LambdaTypeItem {
140         return PsiLambdaTypeItem(
141             codebase = codebase,
142             psiType = psiType,
143             qualifiedName = qualifiedName,
144             arguments = arguments,
145             outerClassType = outerClass as? PsiClassTypeItem,
146             className = className,
147             modifiers = modifiers.duplicate(),
148             isSuspend = isSuspend,
149             receiverType = receiverType,
150             parameterTypes = parameterTypes,
151             returnType = returnType,
152         )
153     }
154 }
155 
156 /** A [PsiTypeItem] backed by a [PsiClassType] that represents a type variable.e */
157 internal class PsiVariableTypeItem(
158     psiType: PsiType,
159     modifiers: TypeModifiers,
160     override val asTypeParameter: TypeParameterItem,
161 ) : VariableTypeItem, PsiTypeItem(psiType, modifiers) {
162 
163     override val name: String = asTypeParameter.name()
164 
duplicatenull165     override fun duplicate(): PsiVariableTypeItem =
166         PsiVariableTypeItem(
167             psiType = psiType,
168             modifiers = modifiers.duplicate(),
169             asTypeParameter = asTypeParameter,
170         )
171 }
172 
173 /** A [PsiTypeItem] backed by a [PsiWildcardType]. */
174 internal class PsiWildcardTypeItem(
175     psiType: PsiType,
176     override val extendsBound: ReferenceTypeItem?,
177     override val superBound: ReferenceTypeItem?,
178     modifiers: TypeModifiers,
179 ) : WildcardTypeItem, PsiTypeItem(psiType, modifiers) {
180     override fun duplicate(
181         extendsBound: ReferenceTypeItem?,
182         superBound: ReferenceTypeItem?
183     ): WildcardTypeItem =
184         PsiWildcardTypeItem(
185             psiType = psiType,
186             extendsBound = extendsBound,
187             superBound = superBound,
188             modifiers = modifiers.duplicate()
189         )
190 }
191