• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.kotlin
19 
20 import com.google.devtools.ksp.IdKey
21 import com.google.devtools.ksp.KSObjectCache
22 import com.google.devtools.ksp.processing.impl.ResolverImpl
23 import com.google.devtools.ksp.symbol.KSAnnotation
24 import com.google.devtools.ksp.symbol.KSDeclaration
25 import com.google.devtools.ksp.symbol.KSType
26 import com.google.devtools.ksp.symbol.KSTypeArgument
27 import com.google.devtools.ksp.symbol.Nullability
28 import com.google.devtools.ksp.symbol.Origin
29 import com.google.devtools.ksp.symbol.impl.binary.KSAnnotationDescriptorImpl
30 import com.google.devtools.ksp.symbol.impl.binary.KSTypeArgumentDescriptorImpl
31 import com.google.devtools.ksp.symbol.impl.convertKotlinType
32 import com.google.devtools.ksp.symbol.impl.replaceTypeArguments
33 import org.jetbrains.kotlin.builtins.isFunctionType
34 import org.jetbrains.kotlin.builtins.isKFunctionType
35 import org.jetbrains.kotlin.builtins.isKSuspendFunctionType
36 import org.jetbrains.kotlin.builtins.isSuspendFunctionType
37 import org.jetbrains.kotlin.descriptors.NotFoundClasses
38 import org.jetbrains.kotlin.descriptors.SourceElement
39 import org.jetbrains.kotlin.types.*
40 import org.jetbrains.kotlin.types.typeUtil.TypeNullability
41 import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
42 import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
43 import org.jetbrains.kotlin.types.typeUtil.makeNullable
44 import org.jetbrains.kotlin.types.typeUtil.nullability
45 import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
46 
47 class KSTypeImpl private constructor(
48     val kotlinType: KotlinType,
49     private val ksTypeArguments: List<KSTypeArgument>? = null,
50     override val annotations: Sequence<KSAnnotation> = sequenceOf()
51 ) : KSType {
52     companion object : KSObjectCache<IdKey<KotlinType>, KSTypeImpl>() {
getCachednull53         fun getCached(
54             kotlinType: KotlinType,
55             ksTypeArguments: List<KSTypeArgument>? = null,
56             annotations: Sequence<KSAnnotation> = sequenceOf()
57         ): KSTypeImpl {
58             return cache.getOrPut(IdKey(kotlinType)) { KSTypeImpl(kotlinType, ksTypeArguments, annotations) }
59         }
60     }
61 
<lambda>null62     override val declaration: KSDeclaration by lazy {
63         ResolverImpl.instance!!.findDeclaration(kotlinType.getAbbreviation() ?: kotlinType)
64     }
65 
<lambda>null66     override val nullability: Nullability by lazy {
67         when (kotlinType.nullability()) {
68             TypeNullability.NULLABLE -> Nullability.NULLABLE
69             TypeNullability.NOT_NULL -> Nullability.NOT_NULL
70             TypeNullability.FLEXIBLE -> Nullability.PLATFORM
71         }
72     }
73 
74     // TODO: fix calls to getKSTypeCached and use ksTypeArguments when available.
<lambda>null75     override val arguments: List<KSTypeArgument> by lazy {
76         (kotlinType.getAbbreviation() ?: kotlinType).arguments.map {
77             KSTypeArgumentDescriptorImpl.getCached(it, Origin.SYNTHETIC, null)
78         }
79     }
80 
isAssignableFromnull81     override fun isAssignableFrom(that: KSType): Boolean {
82         val subType = (that as? KSTypeImpl)?.kotlinType?.convertKotlinType() ?: return false
83         ResolverImpl.instance!!.incrementalContext.recordLookupWithSupertypes(subType)
84         val thisType = (this as? KSTypeImpl)?.kotlinType?.convertKotlinType() ?: return false
85         return subType.isSubtypeOf(thisType)
86     }
87 
88     // TODO: find a better way to reuse the logic in [DescriptorRendererImpl.renderFlexibleType].
isMutabilityFlexiblenull89     override fun isMutabilityFlexible(): Boolean {
90         return kotlinType.toString().startsWith("(Mutable)")
91     }
92 
93     // TODO: find a better way to reuse the logic in [DescriptorRendererImpl.renderFlexibleType].
isCovarianceFlexiblenull94     override fun isCovarianceFlexible(): Boolean {
95         return kotlinType.toString().startsWith("Array<(out) ")
96     }
97 
replacenull98     override fun replace(arguments: List<KSTypeArgument>): KSType {
99         return kotlinType.replaceTypeArguments(arguments)?.let {
100             getKSTypeCached(it, arguments)
101         } ?: KSErrorType
102     }
103 
starProjectionnull104     override fun starProjection(): KSType {
105         return getKSTypeCached(kotlinType.replaceArgumentsWithStarProjections())
106     }
107 
<lambda>null108     private val meNullable: KSType by lazy { getKSTypeCached(kotlinType.makeNullable()) }
makeNullablenull109     override fun makeNullable(): KSType = meNullable
110 
111     private val meNotNullable: KSType by lazy { getKSTypeCached(kotlinType.makeNotNullable()) }
makeNotNullablenull112     override fun makeNotNullable(): KSType = meNotNullable
113 
114     override val isMarkedNullable: Boolean = kotlinType.isMarkedNullable
115 
116     override val isError: Boolean = false
117 
118     override fun equals(other: Any?): Boolean {
119         if (other !is KSTypeImpl)
120             return false
121         return kotlinType.equals(other.kotlinType)
122     }
123 
hashCodenull124     override fun hashCode(): Int = kotlinType.hashCode()
125 
126     override fun toString(): String = (kotlinType.getAbbreviation() ?: kotlinType).toString()
127 
128     override val isFunctionType: Boolean
129         get() = kotlinType.isFunctionType || kotlinType.isKFunctionType
130 
131     override val isSuspendFunctionType: Boolean
132         get() = kotlinType.isSuspendFunctionType || kotlinType.isKSuspendFunctionType
133 }
134 
135 fun getKSTypeCached(
136     kotlinType: KotlinType,
137     ksTypeArguments: List<KSTypeArgument>? = null,
138     annotations: Sequence<KSAnnotation> = sequenceOf()
139 ): KSType {
140     return if (kotlinType.isError ||
141         kotlinType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor
142     ) {
143         KSErrorType
144     } else {
145         KSTypeImpl.getCached(
146             kotlinType,
147             ksTypeArguments,
148             annotations + kotlinType.annotations
149                 .filter { it.source == SourceElement.NO_SOURCE }
150                 .map { KSAnnotationDescriptorImpl.getCached(it, null) }
151                 .asSequence()
152         )
153     }
154 }
155