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.LambdaUtil 33 import com.intellij.psi.PsiArrayType 34 import com.intellij.psi.PsiClassType 35 import com.intellij.psi.PsiPrimitiveType 36 import com.intellij.psi.PsiType 37 import com.intellij.psi.PsiWildcardType 38 import com.intellij.psi.util.TypeConversionUtil 39 40 /** Represents a type backed by PSI */ 41 internal sealed class PsiTypeItem( 42 val psiType: PsiType, 43 modifiers: TypeModifiers, 44 val kotlinTypeInfo: KotlinTypeInfo?, 45 ) : DefaultTypeItem(modifiers) { 46 /** Whether the [psiType] is originally a value class type. */ isValueClassTypenull47 override fun isValueClassType(): Boolean = kotlinTypeInfo?.isValueClassType() ?: false 48 49 /** Returns `true` if `this` type can be assigned from `other` without unboxing the other. */ 50 override fun isAssignableFromWithoutUnboxing(other: TypeItem): Boolean { 51 if (other !is PsiTypeItem) return super.isAssignableFromWithoutUnboxing(other) 52 if (this is PrimitiveTypeItem && other !is PrimitiveTypeItem) { 53 return false 54 } 55 return TypeConversionUtil.isAssignable(psiType, other.psiType) 56 } 57 } 58 59 /** A [PsiTypeItem] backed by a [PsiPrimitiveType]. */ 60 internal class PsiPrimitiveTypeItem( 61 psiType: PsiType, 62 override val kind: PrimitiveTypeItem.Primitive, 63 modifiers: TypeModifiers, 64 kotlinTypeInfo: KotlinTypeInfo?, 65 ) : PrimitiveTypeItem, PsiTypeItem(psiType, modifiers, kotlinTypeInfo) { 66 @Deprecated( 67 "implementation detail of this class", 68 replaceWith = ReplaceWith("substitute(modifiers)"), 69 ) duplicatenull70 override fun duplicate(modifiers: TypeModifiers): PsiPrimitiveTypeItem = 71 PsiPrimitiveTypeItem( 72 psiType = psiType, 73 kind = kind, 74 modifiers = modifiers, 75 kotlinTypeInfo = kotlinTypeInfo, 76 ) 77 } 78 79 /** A [PsiTypeItem] backed by a [PsiArrayType]. */ 80 internal class PsiArrayTypeItem( 81 psiType: PsiType, 82 override val componentType: TypeItem, 83 override val isVarargs: Boolean, 84 modifiers: TypeModifiers, 85 kotlinTypeInfo: KotlinTypeInfo?, 86 ) : ArrayTypeItem, PsiTypeItem(psiType, modifiers, kotlinTypeInfo) { 87 @Deprecated( 88 "implementation detail of this class", 89 replaceWith = ReplaceWith("substitute(modifiers, componentType)"), 90 ) 91 override fun duplicate(modifiers: TypeModifiers, componentType: TypeItem): ArrayTypeItem = 92 PsiArrayTypeItem( 93 psiType = psiType, 94 componentType = componentType, 95 isVarargs = isVarargs, 96 modifiers = modifiers, 97 kotlinTypeInfo = kotlinTypeInfo, 98 ) 99 } 100 101 /** A [PsiTypeItem] backed by a [PsiClassType] that does not represent a type variable. */ 102 internal open class PsiClassTypeItem( 103 protected val codebase: Codebase, 104 psiType: PsiType, 105 final override val qualifiedName: String, 106 final override val arguments: List<TypeArgumentTypeItem>, 107 final override val outerClassType: ClassTypeItem?, 108 modifiers: TypeModifiers, 109 kotlinTypeInfo: KotlinTypeInfo?, 110 ) : ClassTypeItem, PsiTypeItem(psiType, modifiers, kotlinTypeInfo) { 111 override val className: String = ClassTypeItem.computeClassName(qualifiedName) 112 113 private val asClassCache by <lambda>null114 lazy(LazyThreadSafetyMode.NONE) { codebase.resolveClass(qualifiedName) } 115 asClassnull116 override fun asClass() = asClassCache 117 118 override fun isFunctionalType(): Boolean { 119 return LambdaUtil.isFunctionalType(psiType) 120 } 121 122 @Deprecated( 123 "implementation detail of this class", 124 replaceWith = ReplaceWith("substitute(modifiers, outerClassType, arguments)"), 125 ) duplicatenull126 override fun duplicate( 127 modifiers: TypeModifiers, 128 outerClassType: ClassTypeItem?, 129 arguments: List<TypeArgumentTypeItem> 130 ): ClassTypeItem = 131 PsiClassTypeItem( 132 codebase = codebase, 133 psiType = psiType, 134 qualifiedName = qualifiedName, 135 arguments = arguments, 136 outerClassType = outerClassType, 137 modifiers = modifiers, 138 kotlinTypeInfo = kotlinTypeInfo, 139 ) 140 } 141 142 internal class PsiLambdaTypeItem( 143 codebase: Codebase, 144 psiType: PsiType, 145 qualifiedName: String, 146 arguments: List<TypeArgumentTypeItem>, 147 outerClassType: ClassTypeItem?, 148 modifiers: TypeModifiers, 149 override val isSuspend: Boolean, 150 override val receiverType: TypeItem?, 151 override val parameterTypes: List<TypeItem>, 152 override val returnType: TypeItem, 153 kotlinTypeInfo: KotlinTypeInfo?, 154 ) : 155 PsiClassTypeItem( 156 codebase = codebase, 157 psiType = psiType, 158 qualifiedName = qualifiedName, 159 arguments = arguments, 160 outerClassType = outerClassType, 161 modifiers = modifiers, 162 kotlinTypeInfo = kotlinTypeInfo, 163 ), 164 LambdaTypeItem { 165 166 @Deprecated( 167 "implementation detail of this class", 168 replaceWith = ReplaceWith("substitute(modifiers, outerClassType, arguments)"), 169 ) 170 override fun duplicate( 171 modifiers: TypeModifiers, 172 outerClassType: ClassTypeItem?, 173 arguments: List<TypeArgumentTypeItem> 174 ): LambdaTypeItem { 175 return PsiLambdaTypeItem( 176 codebase = codebase, 177 psiType = psiType, 178 qualifiedName = qualifiedName, 179 arguments = arguments, 180 outerClassType = outerClassType, 181 modifiers = modifiers, 182 isSuspend = isSuspend, 183 receiverType = receiverType, 184 parameterTypes = parameterTypes, 185 returnType = returnType, 186 kotlinTypeInfo = kotlinTypeInfo, 187 ) 188 } 189 } 190 191 /** A [PsiTypeItem] backed by a [PsiClassType] that represents a type variable.e */ 192 internal class PsiVariableTypeItem( 193 psiType: PsiType, 194 modifiers: TypeModifiers, 195 override val asTypeParameter: TypeParameterItem, 196 kotlinTypeInfo: KotlinTypeInfo?, 197 ) : VariableTypeItem, PsiTypeItem(psiType, modifiers, kotlinTypeInfo) { 198 199 override val name: String = asTypeParameter.name() 200 201 @Deprecated( 202 "implementation detail of this class", 203 replaceWith = ReplaceWith("substitute(modifiers)"), 204 ) duplicatenull205 override fun duplicate(modifiers: TypeModifiers): PsiVariableTypeItem = 206 PsiVariableTypeItem( 207 psiType = psiType, 208 modifiers = modifiers, 209 asTypeParameter = asTypeParameter, 210 kotlinTypeInfo = kotlinTypeInfo, 211 ) 212 } 213 214 /** A [PsiTypeItem] backed by a [PsiWildcardType]. */ 215 internal class PsiWildcardTypeItem( 216 psiType: PsiType, 217 override val extendsBound: ReferenceTypeItem?, 218 override val superBound: ReferenceTypeItem?, 219 modifiers: TypeModifiers, 220 kotlinTypeInfo: KotlinTypeInfo?, 221 ) : WildcardTypeItem, PsiTypeItem(psiType, modifiers, kotlinTypeInfo) { 222 @Deprecated( 223 "implementation detail of this class", 224 replaceWith = ReplaceWith("substitute(modifiers, extendsBound, superBound)") 225 ) 226 override fun duplicate( 227 modifiers: TypeModifiers, 228 extendsBound: ReferenceTypeItem?, 229 superBound: ReferenceTypeItem? 230 ): WildcardTypeItem = 231 PsiWildcardTypeItem( 232 psiType = psiType, 233 extendsBound = extendsBound, 234 superBound = superBound, 235 modifiers = modifiers, 236 kotlinTypeInfo = kotlinTypeInfo, 237 ) 238 } 239