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.binary
19 
20 import com.google.devtools.ksp.KSObjectCache
21 import com.google.devtools.ksp.symbol.*
22 import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
23 import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
24 import org.jetbrains.kotlin.types.KotlinType
25 import org.jetbrains.kotlin.types.TypeProjection
26 
27 class KSClassifierReferenceDescriptorImpl private constructor(
28     val descriptor: ClassifierDescriptor,
29     val arguments: List<TypeProjection>,
30     override val origin: Origin,
31     override val parent: KSNode?
32 ) :
33     KSClassifierReference {
34     companion object : KSObjectCache<Triple<ClassifierDescriptor, List<TypeProjection>, Pair<KSNode?, Origin>>,
35         KSClassifierReferenceDescriptorImpl>() {
getCachednull36         fun getCached(kotlinType: KotlinType, origin: Origin, parent: KSNode?) = cache.getOrPut(
37             Triple(
38                 kotlinType.constructor.declarationDescriptor!!,
39                 kotlinType.arguments,
40                 Pair(parent, origin)
41             )
42         ) {
43             KSClassifierReferenceDescriptorImpl(
44                 kotlinType.constructor.declarationDescriptor!!, kotlinType.arguments, origin, parent
45             )
46         }
47 
getCachednull48         fun getCached(
49             descriptor: ClassifierDescriptor,
50             arguments: List<TypeProjection>,
51             origin: Origin,
52             parent: KSNode?
53         ) = cache.getOrPut(
54             Triple(descriptor, arguments, Pair(parent, origin))
55         ) { KSClassifierReferenceDescriptorImpl(descriptor, arguments, origin, parent) }
56     }
57 
<lambda>null58     private val nDeclaredArgs by lazy {
59         (descriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters?.size ?: 0
60     }
61 
62     override val location: Location = NonExistLocation
63 
<lambda>null64     override val qualifier: KSClassifierReference? by lazy {
65         val outerDescriptor = descriptor.containingDeclaration as? ClassifierDescriptor ?: return@lazy null
66         val outerArguments = arguments.drop(nDeclaredArgs)
67         getCached(outerDescriptor, outerArguments, origin, parent)
68     }
69 
<lambda>null70     override val typeArguments: List<KSTypeArgument> by lazy {
71         arguments.map { KSTypeArgumentDescriptorImpl.getCached(it, origin, this.parent) }
72     }
73 
referencedNamenull74     override fun referencedName(): String {
75         val declaredArgs = if (arguments.isEmpty() || nDeclaredArgs == 0)
76             emptyList()
77         else
78             arguments.subList(0, nDeclaredArgs)
79         return descriptor.name.asString() + if (declaredArgs.isNotEmpty()) "<${
80         declaredArgs.map { it.toString() }
81             .joinToString(", ")
82         }>" else ""
83     }
84 
toStringnull85     override fun toString() = referencedName()
86 }
87