• 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.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.KSAnnotation
25 import com.google.devtools.ksp.symbol.KSNode
26 import com.google.devtools.ksp.symbol.KSReferenceElement
27 import com.google.devtools.ksp.symbol.KSType
28 import com.google.devtools.ksp.symbol.KSTypeReference
29 import com.google.devtools.ksp.symbol.KSVisitor
30 import com.google.devtools.ksp.symbol.Location
31 import com.google.devtools.ksp.symbol.Modifier
32 import com.google.devtools.ksp.symbol.Origin
33 import com.google.devtools.ksp.symbol.impl.toLocation
34 import com.google.devtools.ksp.toKSModifiers
35 import org.jetbrains.kotlin.psi.*
36 
37 class KSTypeReferenceImpl private constructor(val ktTypeReference: KtTypeReference) : KSTypeReference {
38     companion object : KSObjectCache<KtTypeReference, KSTypeReferenceImpl>() {
<lambda>null39         fun getCached(ktTypeReference: KtTypeReference) = cache.getOrPut(ktTypeReference) {
40             KSTypeReferenceImpl(ktTypeReference)
41         }
42     }
43 
44     override val origin = Origin.KOTLIN
45 
<lambda>null46     override val location: Location by lazy {
47         ktTypeReference.toLocation()
48     }
49     override val parent: KSNode? by lazy {
50         var parentPsi = ktTypeReference.parent
51         while (
52             parentPsi != null && parentPsi !is KtAnnotationEntry && parentPsi !is KtFunctionType &&
53             parentPsi !is KtClassOrObject && parentPsi !is KtFunction && parentPsi !is KtUserType &&
54             parentPsi !is KtProperty && parentPsi !is KtTypeAlias && parentPsi !is KtTypeProjection &&
55             parentPsi !is KtTypeParameter && parentPsi !is KtParameter
56         ) {
57             parentPsi = parentPsi.parent
58         }
59         when (parentPsi) {
60             is KtAnnotationEntry -> KSAnnotationImpl.getCached(parentPsi)
61             is KtFunctionType -> KSCallableReferenceImpl.getCached(parentPsi)
62             is KtClassOrObject -> KSClassDeclarationImpl.getCached(parentPsi)
63             is KtFunction -> KSFunctionDeclarationImpl.getCached(parentPsi)
64             is KtUserType -> KSClassifierReferenceImpl.getCached(parentPsi)
65             is KtProperty -> KSPropertyDeclarationImpl.getCached(parentPsi)
66             is KtTypeAlias -> KSTypeAliasImpl.getCached(parentPsi)
67             is KtTypeProjection -> KSTypeArgumentKtImpl.getCached(parentPsi)
68             is KtTypeParameter -> KSTypeParameterImpl.getCached(parentPsi)
69             is KtParameter -> KSValueParameterImpl.getCached(parentPsi)
70             else -> null
71         }
72     }
73 
74     // Parenthesized type in grammar seems to be implemented as KtNullableType.
visitNullableTypenull75     private fun visitNullableType(visit: (KtNullableType) -> Unit) {
76         var typeElement = ktTypeReference.typeElement
77         while (typeElement is KtNullableType) {
78             visit(typeElement)
79             typeElement = typeElement.innerType
80         }
81     }
82 
83     // Annotations and modifiers are only allowed in one of the parenthesized type.
84     // https://github.com/JetBrains/kotlin/blob/50e12239ef8141a45c4dca2bf0544be6191ecfb6/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java#L608
<lambda>null85     override val annotations: Sequence<KSAnnotation> by lazy {
86         fun List<KtAnnotationEntry>.toKSAnnotations(): Sequence<KSAnnotation> =
87             asSequence().map {
88                 KSAnnotationImpl.getCached(it)
89             }
90 
91         val innerAnnotations = mutableListOf<Sequence<KSAnnotation>>()
92         visitNullableType {
93             innerAnnotations.add(it.annotationEntries.toKSAnnotations())
94         }
95 
96         (ktTypeReference.annotationEntries.toKSAnnotations() + innerAnnotations.asSequence().flatten()).memoized()
97     }
98 
<lambda>null99     override val modifiers: Set<Modifier> by lazy {
100         val innerModifiers = mutableSetOf<Modifier>()
101         visitNullableType {
102             innerModifiers.addAll(it.modifierList.toKSModifiers())
103         }
104         ktTypeReference.toKSModifiers() + innerModifiers
105     }
106 
<lambda>null107     override val element: KSReferenceElement by lazy {
108         var typeElement = ktTypeReference.typeElement
109         while (typeElement is KtNullableType)
110             typeElement = typeElement.innerType
111         when (typeElement) {
112             is KtFunctionType -> KSCallableReferenceImpl.getCached(typeElement)
113             is KtUserType -> KSClassifierReferenceImpl.getCached(typeElement)
114             is KtDynamicType -> KSDynamicReferenceImpl.getCached(this)
115             is KtIntersectionType -> KSDefNonNullReferenceImpl.getCached(typeElement)
116             else -> throw IllegalStateException("Unexpected type element ${typeElement?.javaClass}, $ExceptionMessage")
117         }
118     }
119 
acceptnull120     override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
121         return visitor.visitTypeReference(this, data)
122     }
123 
resolvenull124     override fun resolve(): KSType = ResolverImpl.instance!!.resolveUserType(this)
125 
126     override fun toString(): String {
127         return element.toString()
128     }
129 }
130