1 /* 2 * Copyright (C) 2018 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.BoundsTypeItem 20 import com.android.tools.metalava.model.DefaultModifierList 21 import com.android.tools.metalava.model.TypeParameterItem 22 import com.android.tools.metalava.model.VariableTypeItem 23 import com.intellij.psi.PsiTypeParameter 24 import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterBuilder 25 import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration 26 import org.jetbrains.kotlin.lexer.KtTokens 27 import org.jetbrains.kotlin.psi.KtTypeParameter 28 29 internal class PsiTypeParameterItem( 30 codebase: PsiBasedCodebase, 31 private val psiClass: PsiTypeParameter, 32 private val name: String, 33 modifiers: DefaultModifierList 34 ) : 35 PsiItem( 36 codebase = codebase, 37 element = psiClass, 38 modifiers = modifiers, 39 documentation = "", 40 ), 41 TypeParameterItem { 42 namenull43 override fun name() = name 44 45 /** Must only be used by [type] to cache its result. */ 46 private lateinit var variableTypeItem: VariableTypeItem 47 48 override fun type(): VariableTypeItem { 49 if (!::variableTypeItem.isInitialized) { 50 variableTypeItem = codebase.globalTypeItemFactory.getVariableTypeForTypeParameter(this) 51 } 52 return variableTypeItem 53 } 54 psinull55 override fun psi() = psiClass 56 57 override fun typeBounds(): List<BoundsTypeItem> = bounds 58 59 override fun isReified(): Boolean { 60 return isReified(psiClass as? PsiTypeParameter) 61 } 62 63 internal lateinit var bounds: List<BoundsTypeItem> 64 equalsnull65 override fun equals(other: Any?): Boolean { 66 if (this === other) return true 67 if (other !is TypeParameterItem) return false 68 69 return name == other.name() 70 } 71 hashCodenull72 override fun hashCode(): Int { 73 return name.hashCode() 74 } 75 76 companion object { createnull77 fun create(codebase: PsiBasedCodebase, psiClass: PsiTypeParameter): PsiTypeParameterItem { 78 val simpleName = psiClass.name!! 79 val modifiers = modifiers(codebase, psiClass) 80 81 return PsiTypeParameterItem( 82 codebase = codebase, 83 psiClass = psiClass, 84 name = simpleName, 85 modifiers = modifiers 86 ) 87 } 88 isReifiednull89 fun isReified(element: PsiTypeParameter?): Boolean { 90 element ?: return false 91 // TODO(jsjeon): Handle PsiElementWithOrigin<*> when available 92 if ( 93 element is KtLightDeclaration<*, *> && 94 element.kotlinOrigin is KtTypeParameter && 95 element.kotlinOrigin?.text?.startsWith(KtTokens.REIFIED_KEYWORD.value) == true 96 ) { 97 return true 98 } else if ( 99 element is KotlinLightTypeParameterBuilder && 100 element.origin.text.startsWith(KtTokens.REIFIED_KEYWORD.value) 101 ) { 102 return true 103 } 104 return false 105 } 106 } 107 } 108