1 /* 2 * Copyright 2020 Google LLC 3 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.google.devtools.ksp.symbol.impl.java 19 20 import com.google.devtools.ksp.ExceptionMessage 21 import com.google.devtools.ksp.KSObjectCache 22 import com.google.devtools.ksp.memoized 23 import com.google.devtools.ksp.processing.impl.ResolverImpl 24 import com.google.devtools.ksp.symbol.KSAnnotated 25 import com.google.devtools.ksp.symbol.KSAnnotation 26 import com.google.devtools.ksp.symbol.KSNode 27 import com.google.devtools.ksp.symbol.KSReferenceElement 28 import com.google.devtools.ksp.symbol.KSType 29 import com.google.devtools.ksp.symbol.KSTypeReference 30 import com.google.devtools.ksp.symbol.KSVisitor 31 import com.google.devtools.ksp.symbol.Location 32 import com.google.devtools.ksp.symbol.Modifier 33 import com.google.devtools.ksp.symbol.NonExistLocation 34 import com.google.devtools.ksp.symbol.Origin 35 import com.google.devtools.ksp.symbol.impl.binary.KSClassDeclarationDescriptorImpl 36 import com.google.devtools.ksp.symbol.impl.binary.KSClassifierReferenceDescriptorImpl 37 import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType 38 import com.google.devtools.ksp.symbol.impl.kotlin.KSTypeImpl 39 import com.google.devtools.ksp.symbol.impl.toLocation 40 import com.intellij.psi.PsiArrayType 41 import com.intellij.psi.PsiClassType 42 import com.intellij.psi.PsiPrimitiveType 43 import com.intellij.psi.PsiType 44 import com.intellij.psi.PsiWildcardType 45 import com.intellij.psi.impl.source.PsiClassReferenceType 46 import org.jetbrains.kotlin.descriptors.NotFoundClasses 47 import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS 48 import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS 49 import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe 50 import org.jetbrains.kotlin.types.KotlinType 51 import org.jetbrains.kotlin.types.Variance 52 import org.jetbrains.kotlin.types.typeUtil.makeNullable 53 54 class KSTypeReferenceJavaImpl private constructor(val psi: PsiType, override val parent: KSNode?) : KSTypeReference { 55 companion object : KSObjectCache<Pair<PsiType, KSNode?>, KSTypeReferenceJavaImpl>() { getCachednull56 fun getCached(psi: PsiType, parent: KSNode?) = cache 57 .getOrPut(Pair(psi, parent)) { KSTypeReferenceJavaImpl(psi, parent) } 58 } 59 60 override val origin = Origin.JAVA 61 <lambda>null62 override val location: Location by lazy { 63 (psi as? PsiClassReferenceType)?.reference?.toLocation() ?: NonExistLocation 64 } 65 <lambda>null66 override val annotations: Sequence<KSAnnotation> by lazy { 67 psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized() 68 } 69 70 override val modifiers: Set<Modifier> = emptySet() 71 <lambda>null72 override val element: KSReferenceElement by lazy { 73 fun PsiPrimitiveType.toKotlinType(): KotlinType { 74 return when (this.name) { 75 "int" -> ResolverImpl.instance!!.module.builtIns.intType 76 "short" -> ResolverImpl.instance!!.module.builtIns.shortType 77 "byte" -> ResolverImpl.instance!!.module.builtIns.byteType 78 "long" -> ResolverImpl.instance!!.module.builtIns.longType 79 "float" -> ResolverImpl.instance!!.module.builtIns.floatType 80 "double" -> ResolverImpl.instance!!.module.builtIns.doubleType 81 "char" -> ResolverImpl.instance!!.module.builtIns.charType 82 "boolean" -> ResolverImpl.instance!!.module.builtIns.booleanType 83 "void" -> ResolverImpl.instance!!.module.builtIns.unitType 84 else -> throw IllegalStateException("Unexpected primitive type ${this.name}, $ExceptionMessage") 85 } 86 } 87 88 val type = if (psi is PsiWildcardType) { 89 psi.bound 90 } else { 91 psi 92 } 93 when (type) { 94 is PsiClassType -> KSClassifierReferenceJavaImpl.getCached(type, this) 95 is PsiWildcardType -> KSClassifierReferenceJavaImpl.getCached(type.extendsBound as PsiClassType, this) 96 is PsiPrimitiveType -> KSClassifierReferenceDescriptorImpl.getCached(type.toKotlinType(), origin, this) 97 is PsiArrayType -> { 98 val componentType = ResolverImpl.instance!!.resolveJavaType(type.componentType, this) 99 if (type.componentType !is PsiPrimitiveType) { 100 KSClassifierReferenceDescriptorImpl.getCached( 101 ResolverImpl.instance!!.module.builtIns.getArrayType(Variance.INVARIANT, componentType), 102 origin, 103 this 104 ) 105 } else { 106 KSClassifierReferenceDescriptorImpl.getCached( 107 ResolverImpl.instance!!.module.builtIns 108 .getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(componentType)!!, 109 origin, this 110 ) 111 } 112 } 113 null -> 114 KSClassifierReferenceDescriptorImpl.getCached( 115 (ResolverImpl.instance!!.builtIns.anyType as KSTypeImpl).kotlinType.makeNullable(), origin, this 116 ) 117 else -> throw IllegalStateException("Unexpected psi type for ${type.javaClass}, $ExceptionMessage") 118 } 119 } 120 resolvenull121 override fun resolve(): KSType { 122 val resolvedType = ResolverImpl.instance!!.resolveUserType(this) 123 val relatedAnnotations = (annotations + ((parent as? KSAnnotated)?.annotations ?: emptySequence())) 124 .mapNotNull { 125 (it.annotationType.resolve() as? KSTypeImpl)?.kotlinType?.constructor?.declarationDescriptor?.fqNameSafe 126 } 127 val resolved = if ((resolvedType.declaration as? KSClassDeclarationDescriptorImpl) 128 ?.descriptor is NotFoundClasses.MockClassDescriptor 129 ) { 130 KSErrorType 131 } else resolvedType 132 val hasNotNull = relatedAnnotations.any { it in NOT_NULL_ANNOTATIONS } 133 val hasNullable = relatedAnnotations.any { it in NULLABLE_ANNOTATIONS } 134 return if (hasNullable && !hasNotNull) { 135 resolved.makeNullable() 136 } else if (!hasNullable && hasNotNull) { 137 resolved.makeNotNullable() 138 } else resolved 139 } 140 acceptnull141 override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R { 142 return visitor.visitTypeReference(this, data) 143 } 144 toStringnull145 override fun toString(): String { 146 return element.toString() 147 } 148 } 149