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.BaseModifierList 20 import com.android.tools.metalava.model.VariableTypeItem 21 import com.android.tools.metalava.model.item.DefaultTypeParameterItem 22 import com.intellij.psi.PsiTypeParameter 23 import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterBuilder 24 import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration 25 import org.jetbrains.kotlin.lexer.KtTokens 26 import org.jetbrains.kotlin.psi.KtTypeParameter 27 28 internal class PsiTypeParameterItem( 29 override val codebase: PsiBasedCodebase, 30 private val psiTypeParameter: PsiTypeParameter, 31 name: String, 32 modifiers: BaseModifierList 33 ) : 34 DefaultTypeParameterItem( 35 codebase = codebase, 36 modifiers = modifiers, 37 name = name, 38 isReified = isReified(psiTypeParameter), 39 ) { psinull40 fun psi() = psiTypeParameter 41 42 override fun createVariableTypeItem(): VariableTypeItem { 43 return codebase.globalTypeItemFactory.getVariableTypeForTypeParameter(this) 44 } 45 46 companion object { createnull47 fun create( 48 codebase: PsiBasedCodebase, 49 psiTypeParameter: PsiTypeParameter, 50 ): PsiTypeParameterItem { 51 val simpleName = psiTypeParameter.name!! 52 val modifiers = PsiModifierItem.create(codebase, psiTypeParameter) 53 54 return PsiTypeParameterItem( 55 codebase = codebase, 56 psiTypeParameter = psiTypeParameter, 57 name = simpleName, 58 modifiers = modifiers 59 ) 60 } 61 isReifiednull62 fun isReified(element: PsiTypeParameter?): Boolean { 63 element ?: return false 64 // TODO(jsjeon): Handle PsiElementWithOrigin<*> when available 65 if ( 66 element is KtLightDeclaration<*, *> && 67 element.kotlinOrigin is KtTypeParameter && 68 element.kotlinOrigin?.text?.startsWith(KtTokens.REIFIED_KEYWORD.value) == true 69 ) { 70 return true 71 } else if ( 72 element is KotlinLightTypeParameterBuilder && 73 element.origin.text.startsWith(KtTokens.REIFIED_KEYWORD.value) 74 ) { 75 return true 76 } 77 return false 78 } 79 80 /** 81 * Creates a [DefaultTypeParameterItem] using the [ktTypeParameter]. Should be used only 82 * when there is no [PsiTypeParameter] available. 83 * 84 * The returned type parameter uses the default type implementation, which does not create a 85 * [PsiVariableTypeItem], as the analysis API doesn't have a direct way to create a psi type 86 * from the [KtTypeParameter]. 87 */ createnull88 fun create( 89 codebase: PsiBasedCodebase, 90 ktTypeParameter: KtTypeParameter 91 ): DefaultTypeParameterItem { 92 return DefaultTypeParameterItem( 93 codebase = codebase, 94 modifiers = PsiModifierItem.createForKtDeclaration(codebase, ktTypeParameter), 95 name = ktTypeParameter.name!!, 96 isReified = ktTypeParameter.text.startsWith(KtTokens.REIFIED_KEYWORD.value) 97 ) 98 } 99 } 100 } 101