1 /*
<lambda>null2 * 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.processing.impl
19
20 import com.google.devtools.ksp.*
21 import com.google.devtools.ksp.processing.KSBuiltIns
22 import com.google.devtools.ksp.processing.Resolver
23 import com.google.devtools.ksp.processing.SymbolProcessor
24 import com.google.devtools.ksp.symbol.*
25 import com.google.devtools.ksp.symbol.ClassKind
26 import com.google.devtools.ksp.symbol.Variance
27 import com.google.devtools.ksp.symbol.impl.binary.*
28 import com.google.devtools.ksp.symbol.impl.declarationsInSourceOrder
29 import com.google.devtools.ksp.symbol.impl.findParentAnnotated
30 import com.google.devtools.ksp.symbol.impl.findPsi
31 import com.google.devtools.ksp.symbol.impl.getInstanceForCurrentRound
32 import com.google.devtools.ksp.symbol.impl.java.*
33 import com.google.devtools.ksp.symbol.impl.jvmAccessFlag
34 import com.google.devtools.ksp.symbol.impl.kotlin.*
35 import com.google.devtools.ksp.symbol.impl.resolveContainingClass
36 import com.google.devtools.ksp.symbol.impl.synthetic.*
37 import com.google.devtools.ksp.visitor.CollectAnnotatedSymbolsVisitor
38 import com.intellij.openapi.project.Project
39 import com.intellij.psi.*
40 import com.intellij.psi.impl.source.PsiClassReferenceType
41 import org.jetbrains.kotlin.builtins.KotlinBuiltIns
42 import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
43 import org.jetbrains.kotlin.codegen.ClassBuilderMode
44 import org.jetbrains.kotlin.codegen.OwnerKind
45 import org.jetbrains.kotlin.codegen.state.JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME
46 import org.jetbrains.kotlin.codegen.state.JVM_WILDCARD_ANNOTATION_FQ_NAME
47 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
48 import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
49 import org.jetbrains.kotlin.container.ComponentProvider
50 import org.jetbrains.kotlin.container.get
51 import org.jetbrains.kotlin.container.tryGetService
52 import org.jetbrains.kotlin.descriptors.*
53 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
54 import org.jetbrains.kotlin.descriptors.annotations.Annotations
55 import org.jetbrains.kotlin.incremental.components.NoLookupLocation
56 import org.jetbrains.kotlin.load.java.components.TypeUsage
57 import org.jetbrains.kotlin.load.java.descriptors.JavaForKotlinOverridePropertyDescriptor
58 import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
59 import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
60 import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
61 import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
62 import org.jetbrains.kotlin.load.java.lazy.childForClassOrPackage
63 import org.jetbrains.kotlin.load.java.lazy.childForMethod
64 import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor
65 import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver
66 import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
67 import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
68 import org.jetbrains.kotlin.load.java.structure.JavaClass
69 import org.jetbrains.kotlin.load.java.structure.classId
70 import org.jetbrains.kotlin.load.java.structure.impl.JavaArrayTypeImpl
71 import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
72 import org.jetbrains.kotlin.load.java.structure.impl.JavaConstructorImpl
73 import org.jetbrains.kotlin.load.java.structure.impl.JavaFieldImpl
74 import org.jetbrains.kotlin.load.java.structure.impl.JavaMethodImpl
75 import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl
76 import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeParameterImpl
77 import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
78 import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaMethod
79 import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaMethodBase
80 import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
81 import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
82 import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass
83 import org.jetbrains.kotlin.load.kotlin.getOptimalModeForReturnType
84 import org.jetbrains.kotlin.load.kotlin.getOptimalModeForValueParameter
85 import org.jetbrains.kotlin.name.FqName
86 import org.jetbrains.kotlin.name.FqNameUnsafe
87 import org.jetbrains.kotlin.name.Name
88 import org.jetbrains.kotlin.psi.*
89 import org.jetbrains.kotlin.resolve.*
90 import org.jetbrains.kotlin.resolve.annotations.argumentValue
91 import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
92 import org.jetbrains.kotlin.resolve.calls.inference.components.composeWith
93 import org.jetbrains.kotlin.resolve.calls.inference.substitute
94 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
95 import org.jetbrains.kotlin.resolve.constants.*
96 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
97 import org.jetbrains.kotlin.resolve.descriptorUtil.classId
98 import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
99 import org.jetbrains.kotlin.resolve.descriptorUtil.module
100 import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
101 import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider
102 import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
103 import org.jetbrains.kotlin.resolve.lazy.ResolveSession
104 import org.jetbrains.kotlin.resolve.multiplatform.findActuals
105 import org.jetbrains.kotlin.resolve.multiplatform.findExpects
106 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
107 import org.jetbrains.kotlin.resolve.scopes.LexicalScope
108 import org.jetbrains.kotlin.resolve.scopes.MemberScope
109 import org.jetbrains.kotlin.types.*
110 import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
111 import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
112 import org.jetbrains.kotlin.types.typeUtil.substitute
113 import org.jetbrains.kotlin.types.typeUtil.supertypes
114 import org.jetbrains.kotlin.util.containingNonLocalDeclaration
115 import org.jetbrains.org.objectweb.asm.ClassReader
116 import org.jetbrains.org.objectweb.asm.ClassVisitor
117 import org.jetbrains.org.objectweb.asm.MethodVisitor
118 import org.jetbrains.org.objectweb.asm.Opcodes
119 import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
120 import java.io.File
121 import java.util.Stack
122
123 class ResolverImpl(
124 val module: ModuleDescriptor,
125 val allKSFiles: Collection<KSFile>,
126 val newKSFiles: Collection<KSFile>,
127 private val deferredSymbols: Map<SymbolProcessor, List<KSAnnotated>>,
128 val bindingTrace: BindingTrace,
129 val project: Project,
130 componentProvider: ComponentProvider,
131 val incrementalContext: IncrementalContext,
132 val options: KspOptions,
133 ) : Resolver {
134 val psiDocumentManager = PsiDocumentManager.getInstance(project)
135 private val nameToKSMap: MutableMap<KSName, KSClassDeclaration>
136 private val javaTypeParameterMap: MutableMap<LazyJavaTypeParameterDescriptor, PsiTypeParameter> = mutableMapOf()
137
138 /**
139 * Checking as member of is an expensive operation, hence we cache result values in this map.
140 */
141 private val functionAsMemberOfCache: MutableMap<Pair<KSFunctionDeclaration, KSType>, KSFunction>
142 private val propertyAsMemberOfCache: MutableMap<Pair<KSPropertyDeclaration, KSType>, KSType>
143
144 private val typeMapper = KotlinTypeMapper(
145 BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
146 module.name.getNonSpecialIdentifier(),
147 KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
148 true
149 )
150 private val qualifiedExpressionResolver = QualifiedExpressionResolver(LanguageVersionSettingsImpl.DEFAULT)
151
152 private val aliasingFqNs: MutableMap<String, KSTypeAlias> = mutableMapOf()
153 private val aliasingNames: MutableSet<String> = mutableSetOf()
154 private val topDownAnalysisContext by lazy {
155 TopDownAnalysisContext(TopDownAnalysisMode.TopLevelDeclarations, DataFlowInfo.EMPTY, declarationScopeProvider)
156 }
157
158 companion object {
159 var instance: ResolverImpl? = null
160 }
161
162 var resolveSession: ResolveSession
163 var bodyResolver: BodyResolver
164 var constantExpressionEvaluator: ConstantExpressionEvaluator
165 var declarationScopeProvider: DeclarationScopeProvider
166
167 lateinit var moduleClassResolver: ModuleClassResolver
168 lateinit var javaTypeResolver: JavaTypeResolver
169 lateinit var lazyJavaResolverContext: LazyJavaResolverContext
170
171 init {
172 resolveSession = componentProvider.get()
173 bodyResolver = componentProvider.get()
174 declarationScopeProvider = componentProvider.get()
175 constantExpressionEvaluator = componentProvider.get()
176
177 componentProvider.tryGetService(JavaResolverComponents::class.java)?.let {
178 lazyJavaResolverContext = LazyJavaResolverContext(it, TypeParameterResolver.EMPTY) { null }
179 javaTypeResolver = lazyJavaResolverContext.typeResolver
180 moduleClassResolver = lazyJavaResolverContext.components.moduleClassResolver
181 }
182 instance = this
183
184 nameToKSMap = mutableMapOf()
185 functionAsMemberOfCache = mutableMapOf()
186 propertyAsMemberOfCache = mutableMapOf()
187
188 val visitor = object : KSVisitorVoid() {
189 override fun visitFile(file: KSFile, data: Unit) {
190 file.declarations.forEach { it.accept(this, data) }
191
192 // TODO: evaluate with benchmarks: cost of getContainingFile v.s. name collision
193 // Import aliases are file-scoped. `aliasingNamesByFile` could be faster
194 (file as? KSFileImpl)?.file?.importDirectives?.forEach {
195 it.aliasName?.let { aliasingNames.add(it) }
196 }
197 }
198
199 override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
200 val qualifiedName = classDeclaration.qualifiedName
201 if (qualifiedName != null) {
202 nameToKSMap[qualifiedName] = classDeclaration
203 }
204 classDeclaration.declarations.forEach { it.accept(this, data) }
205 }
206
207 override fun visitTypeAlias(typeAlias: KSTypeAlias, data: Unit) {
208 typeAlias.qualifiedName?.asString()?.let { fqn ->
209 aliasingFqNs[fqn] = typeAlias
210 aliasingNames.add(fqn.substringAfterLast('.'))
211 }
212 }
213 }
214
215 // FIXME: reuse results from previous rounds and only loop through newKSFiles.
216 allKSFiles.forEach { it.accept(visitor, Unit) }
217 }
218
219 // Mitigation for processors with memory leaks
220 // https://github.com/google/ksp/issues/1063
221 fun tearDown() {
222 instance = null
223 }
224
225 override fun getNewFiles(): Sequence<KSFile> {
226 return newKSFiles.asSequence()
227 }
228
229 override fun getAllFiles(): Sequence<KSFile> {
230 return allKSFiles.asSequence()
231 }
232
233 override fun getClassDeclarationByName(name: KSName): KSClassDeclaration? {
234 nameToKSMap[name]?.let { return it }
235
236 return module.resolveClassByFqName(FqName(name.asString()), NoLookupLocation.WHEN_FIND_BY_FQNAME)
237 ?.let {
238 val psi = it.findPsi()
239 if (psi != null) {
240 when (psi) {
241 is KtClassOrObject -> KSClassDeclarationImpl.getCached(psi)
242 is PsiClass -> KSClassDeclarationJavaImpl.getCached(psi)
243 else -> throw IllegalStateException("unexpected psi: ${psi.javaClass}")
244 }
245 } else {
246 KSClassDeclarationDescriptorImpl.getCached(it)
247 }
248 }
249 }
250
251 override fun getFunctionDeclarationsByName(
252 name: KSName,
253 includeTopLevel: Boolean,
254 ): Sequence<KSFunctionDeclaration> {
255 val qualifier = name.getQualifier()
256 val functionName = name.getShortName()
257 val nonTopLevelResult = this.getClassDeclarationByName(qualifier)?.getDeclaredFunctions()
258 ?.filter { it.simpleName.asString() == functionName }?.asSequence() ?: emptySequence()
259 return if (!includeTopLevel) nonTopLevelResult else {
260 nonTopLevelResult.plus(
261 module.getPackage(FqName(qualifier))
262 .memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) {
263 it.asString() == functionName
264 }
265 .filterIsInstance<MemberDescriptor>().mapNotNull { it.toKSDeclaration() as? KSFunctionDeclaration }
266 )
267 }
268 }
269
270 override fun getPropertyDeclarationByName(name: KSName, includeTopLevel: Boolean): KSPropertyDeclaration? {
271 val qualifier = name.getQualifier()
272 val propertyName = name.getShortName()
273 val nonTopLevelResult = this.getClassDeclarationByName(qualifier)?.getDeclaredProperties()
274 ?.singleOrNull { it.simpleName.asString() == propertyName }
275 return if (!includeTopLevel) nonTopLevelResult else {
276 val topLevelResult = (
277 module.getPackage(FqName(qualifier))
278 .memberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES) {
279 it.asString() == propertyName
280 }
281 .also {
282 if (it.size > 1) {
283 throw IllegalStateException("Found multiple properties with same qualified name")
284 }
285 }
286 .singleOrNull() as? MemberDescriptor
287 )?.toKSDeclaration() as? KSPropertyDeclaration
288 if (topLevelResult != null && nonTopLevelResult != null) {
289 throw IllegalStateException("Found multiple properties with same qualified name")
290 }
291 nonTopLevelResult ?: topLevelResult
292 }
293 }
294
295 internal fun checkAnnotation(annotation: KSAnnotation, ksName: KSName, shortName: String): Boolean {
296 val annotationType = annotation.annotationType
297 val referencedName = (annotationType.element as? KSClassifierReference)?.referencedName()
298 val simpleName = referencedName?.substringAfterLast('.')
299 return (simpleName == shortName || simpleName in aliasingNames) &&
300 annotationType.resolveToUnderlying().declaration.qualifiedName == ksName
301 }
302
303 override fun getSymbolsWithAnnotation(annotationName: String, inDepth: Boolean): Sequence<KSAnnotated> {
304 // If annotationName is a typealias, resolve to underlying type.
305 val realAnnotationName =
306 aliasingFqNs[annotationName]?.type?.resolveToUnderlying()?.declaration?.qualifiedName?.asString()
307 ?: annotationName
308
309 val ksName = KSNameImpl.getCached(realAnnotationName)
310 val shortName = ksName.getShortName()
311
312 fun checkAnnotated(annotated: KSAnnotated): Boolean {
313 return annotated.annotations.any {
314 checkAnnotation(it, ksName, shortName)
315 }
316 }
317
318 val allAnnotated = if (inDepth) newAnnotatedSymbolsWithLocals else newAnnotatedSymbols
319 return allAnnotated.asSequence().filter(::checkAnnotated)
320 }
321
322 private fun collectAnnotatedSymbols(inDepth: Boolean): Collection<KSAnnotated> {
323 val visitor = CollectAnnotatedSymbolsVisitor(inDepth)
324
325 for (file in newKSFiles) {
326 file.accept(visitor, Unit)
327 }
328
329 return visitor.symbols
330 }
331
332 private val deferredSymbolsUpdated: Collection<KSAnnotated> by lazy {
333 deferredSymbols.values.flatten().mapNotNull { it.getInstanceForCurrentRound() }
334 }
335
336 private val newAnnotatedSymbols: Collection<KSAnnotated> by lazy {
337 collectAnnotatedSymbols(false) + deferredSymbolsUpdated
338 }
339
340 private val newAnnotatedSymbolsWithLocals: Collection<KSAnnotated> by lazy {
341 collectAnnotatedSymbols(true) + deferredSymbolsUpdated
342 }
343
344 override fun getKSNameFromString(name: String): KSName {
345 return KSNameImpl.getCached(name)
346 }
347
348 override fun createKSTypeReferenceFromKSType(type: KSType): KSTypeReference {
349 return KSTypeReferenceSyntheticImpl.getCached(type, null)
350 }
351
352 @KspExperimental
353 override fun mapToJvmSignature(declaration: KSDeclaration): String? = mapToJvmSignatureInternal(declaration)
354
355 internal fun mapToJvmSignatureInternal(declaration: KSDeclaration): String? = when (declaration) {
356 is KSClassDeclaration -> resolveClassDeclaration(declaration)?.let { typeMapper.mapType(it).descriptor }
357 is KSFunctionDeclaration -> resolveFunctionDeclaration(declaration)?.let {
358 when (it) {
359 is FunctionDescriptor -> typeMapper.mapAsmMethod(it).descriptor
360 is PropertyDescriptor -> typeMapper.mapFieldSignature(it.type, it) ?: typeMapper.mapType(it).descriptor
361 else -> throw IllegalStateException("Unexpected descriptor type for declaration: $declaration")
362 }
363 }
364 is KSPropertyDeclaration -> resolvePropertyDeclaration(declaration)?.let {
365 typeMapper.mapFieldSignature(it.type, it) ?: typeMapper.mapType(it).descriptor
366 }
367 else -> null
368 }
369
370 override fun overrides(overrider: KSDeclaration, overridee: KSDeclaration): Boolean {
371 fun resolveForOverride(declaration: KSDeclaration): DeclarationDescriptor? {
372 return when (declaration) {
373 is KSPropertyDeclaration -> resolvePropertyDeclaration(declaration)
374 is KSFunctionDeclarationJavaImpl -> resolveJavaDeclaration(declaration.psi)
375 is KSFunctionDeclaration -> resolveFunctionDeclaration(declaration)
376 else -> null
377 }
378 }
379
380 if (!overridee.isOpen())
381 return false
382 if (!overridee.isVisibleFrom(overrider))
383 return false
384 if (!(
385 overridee is KSFunctionDeclaration || overrider is KSFunctionDeclaration ||
386 (overridee is KSPropertyDeclaration && overrider is KSPropertyDeclaration)
387 )
388 )
389 return false
390
391 if (overrider is KSPropertyDeclarationJavaImpl)
392 return false
393
394 val superDescriptor = resolveForOverride(overridee) as? CallableMemberDescriptor ?: return false
395 val subDescriptor = resolveForOverride(overrider) as? CallableMemberDescriptor ?: return false
396 val subClassDescriptor = overrider.closestClassDeclaration()?.let {
397 resolveClassDeclaration(it)
398 } ?: return false
399 val superClassDescriptor = overridee.closestClassDeclaration()?.let {
400 resolveClassDeclaration(it)
401 } ?: return false
402
403 incrementalContext.recordLookupWithSupertypes(subClassDescriptor.defaultType)
404
405 val typeOverride = subClassDescriptor.getAllSuperClassifiers()
406 .filter { it != subClassDescriptor } // exclude subclass itself as it cannot override its own methods
407 .any {
408 it == superClassDescriptor
409 }
410 if (!typeOverride) return false
411
412 incrementalContext.recordLookupForDeclaration(overrider)
413 incrementalContext.recordLookupForDeclaration(overridee)
414
415 return OverridingUtil.overrides(subDescriptor, superDescriptor, true, true)
416 }
417
418 // check if the candidate is overridden from the original declaration.
419 private fun isOriginal(original: KSDeclaration, candidate: KSDeclaration): Boolean {
420 incrementalContext.recordLookupForDeclaration(original)
421 incrementalContext.recordLookupForDeclaration(candidate)
422 val originalDescriptor = when (original) {
423 is KSPropertyDeclaration -> resolvePropertyDeclaration(original)
424 is KSFunctionDeclaration ->
425 (resolveFunctionDeclaration(original) as? FunctionDescriptor)?.propertyIfAccessor
426 else -> return false
427 }
428
429 val candidateDescriptors = when (candidate) {
430 is KSPropertyDeclaration -> resolvePropertyDeclaration(candidate)?.overriddenDescriptors
431 is KSFunctionDeclaration -> resolveFunctionDeclaration(candidate)?.overriddenDescriptors
432 else -> return false
433 }
434 return candidateDescriptors?.any { it == originalDescriptor } ?: false
435 }
436
437 override fun overrides(
438 overrider: KSDeclaration,
439 overridee: KSDeclaration,
440 containingClass: KSClassDeclaration
441 ): Boolean {
442 incrementalContext.recordLookupForDeclaration(containingClass)
443 return when (overrider) {
444 is KSPropertyDeclaration -> containingClass.getAllProperties().singleOrNull {
445 it.simpleName.asString() == overrider.simpleName.asString() && isOriginal(overrider, it)
446 }?.let { overrides(it, overridee) } ?: false
447 is KSFunctionDeclaration -> {
448 val candidates = containingClass.getAllFunctions().filter {
449 it.simpleName.asString() == overridee.simpleName.asString()
450 }
451 if (overrider.simpleName.asString().startsWith("get") ||
452 overrider.simpleName.asString().startsWith("set")
453 ) {
454 candidates.plus(
455 containingClass.getAllProperties().filter {
456 val overriderName = overrider.simpleName.asString().substring(3)
457 .replaceFirstChar { it.lowercase() }
458 it.simpleName.asString() == overriderName ||
459 it.simpleName.asString().replaceFirstChar { it.lowercase() } == overriderName
460 }
461 // TODO: It is currently not possible to do the overridden descriptor optimization for java overrides.
462 ).any { overrides(it, overridee) }
463 } else {
464 candidates.singleOrNull { isOriginal(overrider, it) }?.let { overrides(it, overridee) } ?: false
465 }
466 }
467 else -> false
468 }
469 }
470
471 fun evaluateConstant(expression: KtExpression?, expectedType: KotlinType): ConstantValue<*>? {
472 return expression?.let {
473 if (it is KtClassLiteralExpression && it.receiverExpression != null) {
474 val parent = KtStubbedPsiUtil.getPsiOrStubParent(it, KtPrimaryConstructor::class.java, false)
475 val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(parent!!)
476 val result = qualifiedExpressionResolver
477 .resolveDescriptorForDoubleColonLHS(it.receiverExpression!!, scope, bindingTrace, false)
478 val classifier = result.classifierDescriptor ?: return null
479 val typeResolutionContext = TypeResolutionContext(scope, bindingTrace, true, true, false)
480 val possiblyBareType = resolveSession.typeResolver
481 .resolveTypeForClassifier(typeResolutionContext, classifier, result, it, Annotations.EMPTY)
482 var actualType = if (possiblyBareType.isBare)
483 possiblyBareType.bareTypeConstructor.declarationDescriptor!!.defaultType
484 else possiblyBareType.actualType
485 var arrayDimension = 0
486 while (KotlinBuiltIns.isArray(actualType)) {
487 actualType = actualType.arguments.single().type
488 arrayDimension += 1
489 }
490 KClassValue(actualType.constructor.declarationDescriptor.classId!!, arrayDimension)
491 } else {
492 constantExpressionEvaluator.evaluateExpression(it, bindingTrace)?.toConstantValue(expectedType) ?: run {
493 val parent = KtStubbedPsiUtil
494 .getPsiOrStubParent(expression, KtPrimaryConstructor::class.java, false)
495 val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(parent!!)
496 qualifiedExpressionResolver
497 .resolvePackageHeader(expression.containingKtFile.packageDirective!!, module, bindingTrace)
498 bodyResolver.resolveConstructorParameterDefaultValues(
499 topDownAnalysisContext.outerDataFlowInfo, bindingTrace,
500 parent, (scope.ownerDescriptor as ClassDescriptor).constructors.first(), scope,
501 resolveSession.inferenceSession
502 )
503 constantExpressionEvaluator.evaluateExpression(it, bindingTrace)?.toConstantValue(expectedType)
504 }
505 }
506 }
507 }
508
509 fun resolveDeclaration(declaration: KtDeclaration): DeclarationDescriptor? {
510 return if (KtPsiUtil.isLocal(declaration)) {
511 resolveDeclarationForLocal(declaration)
512 bindingTrace.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
513 } else {
514 resolveSession.resolveToDescriptor(declaration)
515 }
516 }
517
518 // TODO: Resolve Java variables is not supported by this function. Not needed currently.
519 fun resolveJavaDeclaration(psi: PsiElement): DeclarationDescriptor? {
520 return when (psi) {
521 is PsiClass -> moduleClassResolver.resolveClass(
522 JavaClassImpl(psi).apply { workaroundForNested(lazyJavaResolverContext) }
523 )
524 is PsiMethod -> {
525 // TODO: get rid of hardcoded check if possible.
526 val property = if (psi.name.startsWith("set") || psi.name.startsWith("get")) {
527 moduleClassResolver
528 .resolveContainingClass(psi)
529 ?.findEnclosedDescriptor(
530 kindFilter = DescriptorKindFilter.CALLABLES
531 ) {
532 (it as? PropertyDescriptor)?.getter?.findPsi() == psi ||
533 (it as? PropertyDescriptor)?.setter?.findPsi() == psi
534 }
535 } else null
536 property ?: moduleClassResolver
537 .resolveContainingClass(psi)?.let { containingClass ->
538 val filter = if (psi is SyntheticElement) {
539 { declaration: DeclarationDescriptor -> declaration.name.asString() == psi.name }
540 } else {
541 { declaration: DeclarationDescriptor -> declaration.findPsi() == psi }
542 }
543 containingClass.findEnclosedDescriptor(
544 kindFilter = DescriptorKindFilter.FUNCTIONS,
545 filter = filter
546 )
547 }
548 }
549 is PsiField -> {
550 moduleClassResolver
551 .resolveClass(
552 JavaFieldImpl(psi).containingClass.apply { workaroundForNested(lazyJavaResolverContext) }
553 )
554 ?.findEnclosedDescriptor(
555 kindFilter = DescriptorKindFilter.VARIABLES,
556 filter = { it.findPsi() == psi }
557 )
558 }
559 else -> throw IllegalStateException("unhandled psi element kind: ${psi.javaClass}")
560 }
561 }
562
563 fun resolveClassDeclaration(classDeclaration: KSClassDeclaration): ClassDescriptor? {
564 return when (classDeclaration) {
565 is KSClassDeclarationImpl -> resolveDeclaration(classDeclaration.ktClassOrObject)
566 is KSClassDeclarationDescriptorImpl -> classDeclaration.descriptor
567 is KSClassDeclarationJavaImpl -> resolveJavaDeclaration(classDeclaration.psi)
568 else -> throw IllegalStateException("unexpected class: ${classDeclaration.javaClass}")
569 } as ClassDescriptor?
570 }
571
572 fun resolveFunctionDeclaration(function: KSFunctionDeclaration): CallableDescriptor? {
573 return when (function) {
574 is KSFunctionDeclarationImpl -> resolveDeclaration(function.ktFunction)
575 is KSFunctionDeclarationDescriptorImpl -> function.descriptor
576 is KSFunctionDeclarationJavaImpl -> {
577 val descriptor = resolveJavaDeclaration(function.psi)
578 if (descriptor is JavaForKotlinOverridePropertyDescriptor) {
579 if (function.simpleName.asString().startsWith("set")) {
580 descriptor.setter
581 } else {
582 descriptor.getter
583 }
584 } else {
585 descriptor
586 }
587 }
588 is KSConstructorSyntheticImpl -> {
589 // we might create synthetic constructor when it is not declared in code
590 // it is either for kotlin, where we can use primary constructor, or for java
591 // where we can use the only available constructor
592 val resolved = resolveClassDeclaration(function.ksClassDeclaration)
593 resolved?.unsubstitutedPrimaryConstructor ?: resolved?.constructors?.singleOrNull()
594 }
595 else -> throw IllegalStateException("unexpected class: ${function.javaClass}")
596 } as? CallableDescriptor
597 }
598
599 fun resolvePropertyDeclaration(property: KSPropertyDeclaration): PropertyDescriptor? {
600 return when (property) {
601 is KSPropertyDeclarationImpl -> resolveDeclaration(property.ktProperty)
602 is KSPropertyDeclarationParameterImpl -> resolveDeclaration(property.ktParameter)
603 is KSPropertyDeclarationDescriptorImpl -> property.descriptor
604 is KSPropertyDeclarationJavaImpl -> resolveJavaDeclaration(property.psi)
605 else -> throw IllegalStateException("unexpected class: ${property.javaClass}")
606 } as PropertyDescriptor?
607 }
608
609 fun resolvePropertyAccessorDeclaration(accessor: KSPropertyAccessor): PropertyAccessorDescriptor? {
610 return when (accessor) {
611 is KSPropertyAccessorDescriptorImpl -> accessor.descriptor
612 is KSPropertyAccessorImpl -> resolveDeclaration(accessor.ktPropertyAccessor)
613 is KSPropertySetterSyntheticImpl -> resolvePropertyDeclaration(accessor.receiver)?.setter
614 is KSPropertyGetterSyntheticImpl -> resolvePropertyDeclaration(accessor.receiver)?.getter
615 else -> throw IllegalStateException("unexpected class: ${accessor.javaClass}")
616 } as PropertyAccessorDescriptor?
617 }
618
619 fun resolveJavaType(psi: PsiType, parentTypeReference: KSTypeReference? = null): KotlinType {
620 incrementalContext.recordLookup(psi)
621 val javaType = JavaTypeImpl.create(psi)
622
623 var parent: KSNode? = parentTypeReference
624
625 val stack = Stack<KSNode>()
626 while (parent != null) {
627 if (parent is KSFunctionDeclarationJavaImpl || parent is KSClassDeclarationJavaImpl) {
628 stack.push(parent)
629 }
630 parent = parent.parent
631 }
632 // Construct resolver context for the PsiType
633 var resolverContext = lazyJavaResolverContext
634
635 for (e in stack) {
636 when (e) {
637 is KSFunctionDeclarationJavaImpl -> {
638 // Non-physical methods have no interesting scope and may have no containing class
639 if (!e.psi.isPhysical || e.psi.containingClass == null)
640 continue
641 resolverContext = resolverContext
642 .childForMethod(
643 resolveJavaDeclaration(e.psi)!!,
644 if (e.psi.isConstructor) JavaConstructorImpl(e.psi) else JavaMethodImpl(e.psi)
645 )
646 }
647 is KSClassDeclarationJavaImpl -> {
648 resolverContext = resolverContext
649 .childForClassOrPackage(resolveJavaDeclaration(e.psi) as ClassDescriptor, JavaClassImpl(e.psi))
650 }
651 }
652 }
653 return if (javaType is JavaArrayTypeImpl)
654 resolverContext
655 .typeResolver.transformArrayType(javaType, TypeUsage.COMMON.toAttributes(), psi is PsiEllipsisType)
656 else
657 resolverContext.typeResolver.transformJavaType(javaType, TypeUsage.COMMON.toAttributes())
658 }
659
660 /*
661 * Don't map Java types in annotation parameters
662 *
663 * Users may specify Java types explicitly by instances of `Class<T>`.
664 * The situation is similar to `getClassDeclarationByName` where we have
665 * decided to keep those Java types not mapped.
666 *
667 * It would be troublesome if users try to use reflection on types that
668 * were mapped to Kotlin builtins, becuase some of those builtins don't
669 * even exist in classpath.
670 *
671 * Therefore, ResolverImpl.resolveJavaType cannot be used.
672 */
673 fun resolveJavaTypeInAnnotations(psiType: PsiType): KSType = if (options.mapAnnotationArgumentsInJava) {
674 getKSTypeCached(resolveJavaType(psiType))
675 } else {
676 when (psiType) {
677 is PsiPrimitiveType -> {
678 getClassDeclarationByName(psiType.boxedTypeName!!)!!.asStarProjectedType()
679 }
680 is PsiArrayType -> {
681 val componentType = resolveJavaTypeInAnnotations(psiType.componentType)
682 val componentTypeRef = createKSTypeReferenceFromKSType(componentType)
683 val typeArgs = listOf(getTypeArgument(componentTypeRef, Variance.INVARIANT))
684 builtIns.arrayType.replace(typeArgs)
685 }
686 else -> {
687 getClassDeclarationByName(psiType.canonicalText)?.asStarProjectedType() ?: KSErrorType
688 }
689 }
690 }
691
692 fun KotlinType.expandNonRecursively(): KotlinType =
693 (constructor.declarationDescriptor as? TypeAliasDescriptor)?.expandedType?.withAbbreviation(this as SimpleType)
694 ?: this
695
696 fun TypeProjection.expand(): TypeProjection {
697 val expandedType = type.expand()
698 return if (expandedType == type) this else substitute { expandedType }
699 }
700
701 // TODO: Is this the most efficient way?
702 fun KotlinType.expand(): KotlinType =
703 replace(arguments.map { it.expand() }).expandNonRecursively()
704
705 fun KtTypeReference.lookup(): KotlinType? =
706 bindingTrace.get(BindingContext.ABBREVIATED_TYPE, this)?.expand() ?: bindingTrace.get(BindingContext.TYPE, this)
707
708 fun resolveUserType(type: KSTypeReference): KSType {
709 when (type) {
710 is KSTypeReferenceImpl -> {
711 val typeReference = type.ktTypeReference
712 typeReference.lookup()?.let {
713 return getKSTypeCached(it, type.element.typeArguments, type.annotations)
714 }
715 KtStubbedPsiUtil.getContainingDeclaration(typeReference)?.let { containingDeclaration ->
716 resolveDeclaration(containingDeclaration)?.let {
717 // TODO: only resolve relevant branch.
718 ForceResolveUtil.forceResolveAllContents(it)
719 }
720 // TODO: Fix resolution look up to avoid fallback to file scope.
721 typeReference.lookup()?.let {
722 return getKSTypeCached(it, type.element.typeArguments, type.annotations)
723 }
724 }
725 val scope = resolveSession.fileScopeProvider.getFileResolutionScope(typeReference.containingKtFile)
726 return resolveSession.typeResolver.resolveType(scope, typeReference, bindingTrace, false).let {
727 getKSTypeCached(it, type.element.typeArguments, type.annotations)
728 }
729 }
730 is KSTypeReferenceDescriptorImpl -> {
731 return getKSTypeCached(type.kotlinType)
732 }
733 is KSTypeReferenceJavaImpl -> {
734 val psi = (type.psi as? PsiClassReferenceType)?.resolve()
735 if (psi is PsiTypeParameter) {
736 (type.psi as PsiClassReferenceType).typeArguments().forEach {
737 if (it is PsiType) {
738 incrementalContext.recordLookup(it)
739 }
740 }
741 val containingDeclaration = if (psi.owner is PsiClass) {
742 moduleClassResolver.resolveClass(
743 JavaClassImpl(psi.owner as PsiClass).apply { workaroundForNested(lazyJavaResolverContext) }
744 )
745 } else {
746 val owner = psi.owner
747 check(owner is PsiMethod) {
748 "unexpected owner type: $owner / ${owner?.javaClass}"
749 }
750 moduleClassResolver.resolveContainingClass(owner)
751 ?.findEnclosedDescriptor(
752 kindFilter = DescriptorKindFilter.FUNCTIONS,
753 filter = { it.findPsi() == owner }
754 ) as FunctionDescriptor
755 } as DeclarationDescriptor
756 val typeParameterDescriptor = LazyJavaTypeParameterDescriptor(
757 lazyJavaResolverContext,
758 JavaTypeParameterImpl(psi),
759 psi.index,
760 containingDeclaration
761 )
762 javaTypeParameterMap[typeParameterDescriptor] = psi
763 }
764 return getKSTypeCached(resolveJavaType(type.psi, type), type.element.typeArguments, type.annotations)
765 }
766 else -> throw IllegalStateException("Unable to resolve type for $type, $ExceptionMessage")
767 }
768 }
769
770 fun findDeclaration(kotlinType: KotlinType): KSDeclaration {
771 val descriptor = kotlinType.constructor.declarationDescriptor
772 val psi = descriptor?.findPsi()
773 return if (psi != null) {
774 when (psi) {
775 is KtClassOrObject -> KSClassDeclarationImpl.getCached(psi)
776 is PsiClass -> KSClassDeclarationJavaImpl.getCached(psi)
777 is KtTypeAlias -> KSTypeAliasImpl.getCached(psi)
778 is KtTypeParameter -> KSTypeParameterImpl.getCached(psi)
779 is PsiEnumConstant -> KSClassDeclarationJavaEnumEntryImpl.getCached(psi)
780 else -> throw IllegalStateException("Unexpected psi type: ${psi.javaClass}, $ExceptionMessage")
781 }
782 } else {
783 when (descriptor) {
784 is ClassDescriptor -> KSClassDeclarationDescriptorImpl.getCached(descriptor)
785 // LazyJavaTypeParameterDescriptor has `source` overridden to `NO_SOURCE`, therefore
786 // need to look up psi within KSP.
787 is TypeParameterDescriptor -> if (descriptor in javaTypeParameterMap) {
788 KSTypeParameterJavaImpl.getCached(javaTypeParameterMap[descriptor]!!)
789 } else {
790 KSTypeParameterDescriptorImpl.getCached(descriptor)
791 }
792 is TypeAliasDescriptor -> KSTypeAliasDescriptorImpl.getCached(descriptor)
793 null -> throw IllegalStateException("Failed to resolve descriptor for $kotlinType")
794 else -> throw IllegalStateException(
795 "Unexpected descriptor type: ${descriptor.javaClass}, $ExceptionMessage"
796 )
797 }
798 }
799 }
800
801 // Finds closest non-local scope.
802 fun KtElement.findLexicalScope(): LexicalScope {
803 return containingNonLocalDeclaration()?.let {
804 resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(it)
805 } ?: resolveSession.fileScopeProvider.getFileResolutionScope(this.containingKtFile)
806 }
807
808 fun resolveAnnotationEntry(ktAnnotationEntry: KtAnnotationEntry): AnnotationDescriptor? {
809 bindingTrace.get(BindingContext.ANNOTATION, ktAnnotationEntry)?.let { return it }
810 KtStubbedPsiUtil.getContainingDeclaration(ktAnnotationEntry)?.let { containingDeclaration ->
811 if (KtPsiUtil.isLocal(containingDeclaration)) {
812 resolveDeclarationForLocal(containingDeclaration)
813 } else {
814 resolveSession.resolveToDescriptor(containingDeclaration).annotations.forEach {}
815 }
816 } ?: ktAnnotationEntry.containingKtFile.let {
817 resolveSession.getFileAnnotations(it).forEach {}
818 }
819 return bindingTrace.get(BindingContext.ANNOTATION, ktAnnotationEntry)
820 }
821
822 fun resolveDeclarationForLocal(localDeclaration: KtDeclaration) {
823 var declaration = KtStubbedPsiUtil.getContainingDeclaration(localDeclaration) ?: return
824 while (KtPsiUtil.isLocal(declaration))
825 declaration = KtStubbedPsiUtil.getContainingDeclaration(declaration)!!
826
827 val containingFD = resolveSession.resolveToDescriptor(declaration).also {
828 ForceResolveUtil.forceResolveAllContents(it)
829 }
830
831 if (declaration is KtNamedFunction) {
832 val dataFlowInfo = DataFlowInfo.EMPTY
833 val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(declaration)
834 bodyResolver.resolveFunctionBody(
835 dataFlowInfo,
836 bindingTrace,
837 declaration,
838 containingFD as FunctionDescriptor,
839 scope,
840 null
841 )
842 }
843 }
844
845 @KspExperimental
846 override fun getJvmName(accessor: KSPropertyAccessor): String? {
847 val descriptor = resolvePropertyAccessorDeclaration(accessor)
848
849 return descriptor?.let {
850 // KotlinTypeMapper.mapSignature always uses OwnerKind.IMPLEMENTATION
851 typeMapper.mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION)
852 }
853 }
854
855 @KspExperimental
856 override fun getJvmName(declaration: KSFunctionDeclaration): String? {
857 // function names might be mangled if they receive inline class parameters or they are internal
858 val descriptor = resolveFunctionDeclaration(declaration)
859 return (descriptor as? FunctionDescriptor)?.let {
860 // KotlinTypeMapper.mapSignature always uses OwnerKind.IMPLEMENTATION
861 typeMapper.mapFunctionName(it, OwnerKind.IMPLEMENTATION)
862 }
863 }
864
865 @KspExperimental
866 override fun getOwnerJvmClassName(declaration: KSPropertyDeclaration): String? {
867 val descriptor = resolvePropertyDeclaration(declaration) ?: return null
868 return getJvmOwnerQualifiedName(descriptor)
869 }
870
871 @KspExperimental
872 override fun getOwnerJvmClassName(declaration: KSFunctionDeclaration): String? {
873 val descriptor = resolveFunctionDeclaration(declaration) ?: return null
874 return getJvmOwnerQualifiedName(descriptor)
875 }
876
877 private fun getJvmOwnerQualifiedName(descriptor: DeclarationDescriptor): String? {
878 return try {
879 typeMapper.mapImplementationOwner(descriptor).className
880 } catch (unsupported: UnsupportedOperationException) {
881 null
882 }
883 }
884
885 private fun extractThrowsFromClassFile(
886 virtualFileContent: ByteArray,
887 jvmDesc: String?,
888 simpleName: String?
889 ): Sequence<KSType> {
890 val exceptionNames = mutableListOf<String>()
891 ClassReader(virtualFileContent).accept(
892 object : ClassVisitor(API_VERSION) {
893 override fun visitMethod(
894 access: Int,
895 name: String?,
896 descriptor: String?,
897 signature: String?,
898 exceptions: Array<out String>?,
899 ): MethodVisitor {
900 if (name == simpleName && jvmDesc == descriptor) {
901 exceptions?.toList()?.let { exceptionNames.addAll(it) }
902 }
903 return object : MethodVisitor(API_VERSION) {
904 }
905 }
906 },
907 ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
908 )
909 return exceptionNames.mapNotNull {
910 this@ResolverImpl.getClassDeclarationByName(it.replace("/", "."))?.asStarProjectedType()
911 }.asSequence()
912 }
913
914 @SuppressWarnings("UNCHECKED_CAST")
915 private fun extractThrowsAnnotation(annotated: KSAnnotated): Sequence<KSType> {
916 return annotated.annotations
917 .singleOrNull {
918 it.shortName.asString() == "Throws" &&
919 it.annotationType.resolve().declaration.qualifiedName?.asString() == "kotlin.Throws"
920 }?.arguments
921 ?.singleOrNull()
922 ?.let { it.value as? ArrayList<KSType> }
923 ?.asSequence() ?: emptySequence()
924 }
925
926 // TODO: refactor and reuse BinaryClassInfoCache
927 @KspExperimental
928 override fun getJvmCheckedException(function: KSFunctionDeclaration): Sequence<KSType> {
929 return when (function.origin) {
930 Origin.JAVA -> {
931 val psi = (function as KSFunctionDeclarationJavaImpl).psi
932 psi.throwsList.referencedTypes.asSequence().map { getKSTypeCached(resolveJavaType(it)) }
933 }
934 Origin.KOTLIN -> {
935 extractThrowsAnnotation(function)
936 }
937 Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
938 val descriptor = (function as KSFunctionDeclarationDescriptorImpl).descriptor
939 val jvmDesc = this.mapToJvmSignature(function)
940 val virtualFileContent = if (function.origin == Origin.KOTLIN_LIB) {
941 (descriptor.getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass)?.file
942 ?.contentsToByteArray()
943 } else {
944 (
945 ((descriptor.source as? JavaSourceElement)?.javaElement as? BinaryJavaMethodBase)
946 ?.containingClass as? BinaryJavaClass
947 )?.virtualFile?.contentsToByteArray()
948 }
949 if (virtualFileContent == null) {
950 return emptySequence()
951 }
952 extractThrowsFromClassFile(virtualFileContent, jvmDesc, function.simpleName.asString())
953 }
954 else -> emptySequence()
955 }
956 }
957
958 @KspExperimental
959 override fun getJvmCheckedException(accessor: KSPropertyAccessor): Sequence<KSType> {
960 return when (accessor.origin) {
961 Origin.KOTLIN, Origin.SYNTHETIC -> {
962 extractThrowsAnnotation(accessor)
963 }
964 Origin.KOTLIN_LIB -> {
965 val descriptor = (accessor as KSPropertyAccessorDescriptorImpl).descriptor
966 val jvmDesc = typeMapper.mapAsmMethod(descriptor).descriptor
967 val virtualFileContent = if (accessor.origin == Origin.KOTLIN_LIB) {
968 (descriptor.correspondingProperty.getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass)
969 ?.file?.contentsToByteArray()
970 } else {
971 (
972 ((descriptor.source as? JavaSourceElement)?.javaElement as? BinaryJavaMethod)?.containingClass
973 as? BinaryJavaClass
974 )?.virtualFile?.contentsToByteArray()
975 }
976 if (virtualFileContent == null) {
977 return emptySequence()
978 }
979 extractThrowsFromClassFile(virtualFileContent, jvmDesc, getJvmName(accessor))
980 }
981 else -> emptySequence()
982 }
983 }
984
985 private val javaPackageToClassMap: Map<String, List<KSDeclaration>> by lazy {
986 val packageToClassMapping = mutableMapOf<String, List<KSDeclaration>>()
987 allKSFiles
988 .filter { file ->
989 file.origin == Origin.JAVA &&
990 options.javaSourceRoots.any { root ->
991 file.filePath.startsWith(root.absolutePath) &&
992 file.filePath.substringAfter(root.absolutePath)
993 .dropLastWhile { c -> c != File.separatorChar }.dropLast(1).drop(1)
994 .replace(File.separatorChar, '.') == file.packageName.asString()
995 }
996 }
997 .forEach {
998 packageToClassMapping.put(
999 it.packageName.asString(),
1000 packageToClassMapping.getOrDefault(it.packageName.asString(), emptyList())
1001 .plus(
1002 it.declarations.filterNot {
1003 it.containingFile?.fileName?.split(".")?.first() == it.simpleName.asString()
1004 }
1005 )
1006 )
1007 }
1008 packageToClassMapping
1009 }
1010
1011 @KspExperimental
1012 override fun getDeclarationsFromPackage(packageName: String): Sequence<KSDeclaration> {
1013 val noPackageFilter = DescriptorKindFilter.ALL.withoutKinds(DescriptorKindFilter.PACKAGES_MASK)
1014 return module.getPackage(FqName(packageName))
1015 .memberScope.getContributedDescriptors(noPackageFilter)
1016 .asSequence()
1017 .mapNotNull { (it as? MemberDescriptor)?.toKSDeclaration() }
1018 .plus(javaPackageToClassMap.getOrDefault(packageName, emptyList()).asSequence())
1019 }
1020
1021 override fun getTypeArgument(typeRef: KSTypeReference, variance: Variance): KSTypeArgument {
1022 return KSTypeArgumentLiteImpl.getCached(typeRef, variance)
1023 }
1024
1025 internal fun asMemberOf(
1026 property: KSPropertyDeclaration,
1027 containing: KSType,
1028 ): KSType {
1029 val key = property to containing
1030 return propertyAsMemberOfCache.getOrPut(key) {
1031 computeAsMemberOf(property, containing)
1032 }
1033 }
1034
1035 private fun computeAsMemberOf(
1036 property: KSPropertyDeclaration,
1037 containing: KSType,
1038 ): KSType {
1039 val propertyDeclaredIn = property.closestClassDeclaration()
1040 ?: throw IllegalArgumentException(
1041 "Cannot call asMemberOf with a property that is " +
1042 "not declared in a class or an interface"
1043 )
1044 val declaration = resolvePropertyDeclaration(property)
1045 if (declaration != null && containing is KSTypeImpl && !containing.isError) {
1046 incrementalContext.recordLookupWithSupertypes(containing.kotlinType)
1047 incrementalContext.recordLookupForDeclaration(property)
1048 if (!containing.kotlinType.isSubtypeOf(propertyDeclaredIn)) {
1049 throw IllegalArgumentException(
1050 "$containing is not a sub type of the class/interface that contains `$property` " +
1051 "($propertyDeclaredIn)"
1052 )
1053 }
1054 val typeSubstitutor = containing.kotlinType.createTypeSubstitutor()
1055 val substituted = declaration.substitute(typeSubstitutor) as? ValueDescriptor
1056 substituted?.let {
1057 return getKSTypeCached(substituted.type)
1058 }
1059 }
1060 // if substitution fails, fallback to the type from the property
1061 return KSErrorType
1062 }
1063
1064 internal fun asMemberOf(
1065 function: KSFunctionDeclaration,
1066 containing: KSType,
1067 ): KSFunction {
1068 val key = function to containing
1069 return functionAsMemberOfCache.getOrPut(key) {
1070 computeAsMemberOf(function, containing)
1071 }
1072 }
1073
1074 private fun computeAsMemberOf(
1075 function: KSFunctionDeclaration,
1076 containing: KSType,
1077 ): KSFunction {
1078 val functionDeclaredIn = function.closestClassDeclaration()
1079 ?: throw IllegalArgumentException(
1080 "Cannot call asMemberOf with a function that is " +
1081 "not declared in a class or an interface"
1082 )
1083 val declaration = resolveFunctionDeclaration(function)
1084 if (declaration != null && containing is KSTypeImpl && !containing.isError) {
1085 incrementalContext.recordLookupWithSupertypes(containing.kotlinType)
1086 incrementalContext.recordLookupForDeclaration(function)
1087 if (!containing.kotlinType.isSubtypeOf(functionDeclaredIn)) {
1088 throw IllegalArgumentException(
1089 "$containing is not a sub type of the class/interface that contains " +
1090 "`$function` ($functionDeclaredIn)"
1091 )
1092 }
1093 val typeSubstitutor = containing.kotlinType.createTypeSubstitutor()
1094 if (declaration is PropertyAccessorDescriptor) {
1095 val substitutedProperty = (declaration.correspondingProperty).substitute(typeSubstitutor)
1096 // TODO: Fix in upstream for property accessors: https://github.com/JetBrains/kotlin/blob/master/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java#L122
1097 return KSFunctionImpl(
1098 (substitutedProperty as PropertyDescriptor).accessors.single {
1099 it.name == declaration.name
1100 }
1101 )
1102 }
1103 val substituted = declaration.substitute(typeSubstitutor)
1104 return KSFunctionImpl(substituted)
1105 }
1106 // if substitution fails, return an error function that resembles the original declaration
1107 return KSFunctionErrorImpl(function)
1108 }
1109
1110 private fun KotlinType.isSubtypeOf(declaration: KSClassDeclaration): Boolean {
1111 val classDeclaration = resolveClassDeclaration(declaration)
1112 if (classDeclaration == null) {
1113 throw IllegalArgumentException(
1114 "Cannot find the declaration for class $classDeclaration"
1115 )
1116 }
1117 return constructor
1118 .declarationDescriptor
1119 ?.getAllSuperClassifiers()
1120 ?.any { it == classDeclaration } == true
1121 }
1122
1123 override val builtIns: KSBuiltIns by lazy {
1124 val builtIns = module.builtIns
1125 object : KSBuiltIns {
1126 override val anyType: KSType by lazy { getKSTypeCached(builtIns.anyType) }
1127 override val nothingType by lazy { getKSTypeCached(builtIns.nothingType) }
1128 override val unitType: KSType by lazy { getKSTypeCached(builtIns.unitType) }
1129 override val numberType: KSType by lazy { getKSTypeCached(builtIns.numberType) }
1130 override val byteType: KSType by lazy { getKSTypeCached(builtIns.byteType) }
1131 override val shortType: KSType by lazy { getKSTypeCached(builtIns.shortType) }
1132 override val intType: KSType by lazy { getKSTypeCached(builtIns.intType) }
1133 override val longType: KSType by lazy { getKSTypeCached(builtIns.longType) }
1134 override val floatType: KSType by lazy { getKSTypeCached(builtIns.floatType) }
1135 override val doubleType: KSType by lazy { getKSTypeCached(builtIns.doubleType) }
1136 override val charType: KSType by lazy { getKSTypeCached(builtIns.charType) }
1137 override val booleanType: KSType by lazy { getKSTypeCached(builtIns.booleanType) }
1138 override val stringType: KSType by lazy { getKSTypeCached(builtIns.stringType) }
1139 override val iterableType: KSType by lazy {
1140 getKSTypeCached(builtIns.iterableType.replaceArgumentsWithStarProjections())
1141 }
1142 override val annotationType: KSType by lazy { getKSTypeCached(builtIns.annotationType) }
1143 override val arrayType: KSType by lazy {
1144 getKSTypeCached(builtIns.array.defaultType.replaceArgumentsWithStarProjections())
1145 }
1146 }
1147 }
1148
1149 internal val mockSerializableType = module.builtIns.numberType.supertypes().singleOrNull {
1150 it.constructor.declarationDescriptor?.name?.asString() == "Serializable"
1151 }
1152
1153 internal val javaSerializableType = module.resolveClassByFqName(
1154 FqName("java.io.Serializable"), NoLookupLocation.WHEN_FIND_BY_FQNAME
1155 )?.defaultType
1156
1157 @KspExperimental
1158 override fun mapJavaNameToKotlin(javaName: KSName): KSName? =
1159 JavaToKotlinClassMap.mapJavaToKotlin(FqName(javaName.asString()))?.toKSName()
1160
1161 @KspExperimental
1162 override fun mapKotlinNameToJava(kotlinName: KSName): KSName? =
1163 JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(kotlinName.asString()))?.toKSName()
1164
1165 @KspExperimental
1166 internal fun mapToJvmSignature(accessor: KSPropertyAccessor): String {
1167 return resolvePropertyAccessorDeclaration(accessor)?.let {
1168 typeMapper.mapAsmMethod(it).descriptor
1169 } ?: ""
1170 }
1171
1172 @KspExperimental
1173 override fun getDeclarationsInSourceOrder(container: KSDeclarationContainer): Sequence<KSDeclaration> {
1174 return container.declarationsInSourceOrder
1175 }
1176
1177 @KspExperimental
1178 override fun effectiveJavaModifiers(declaration: KSDeclaration): Set<Modifier> {
1179 val modifiers = HashSet<Modifier>(declaration.modifiers.filter { it in javaModifiers })
1180
1181 // This is only needed by sources.
1182 // PUBLIC, PRIVATE, PROTECTED are already handled in descriptor based impls.
1183 fun addVisibilityModifiers() {
1184 when {
1185 declaration.isPublic() -> modifiers.add(Modifier.PUBLIC)
1186 declaration.isPrivate() -> modifiers.add(Modifier.PRIVATE)
1187 declaration.isProtected() -> modifiers.add(Modifier.PROTECTED)
1188 }
1189 }
1190
1191 when (declaration.origin) {
1192 Origin.JAVA -> {
1193 addVisibilityModifiers()
1194 if (declaration is KSClassDeclaration && declaration.classKind == ClassKind.INTERFACE)
1195 modifiers.add(Modifier.ABSTRACT)
1196 }
1197 Origin.KOTLIN -> {
1198 addVisibilityModifiers()
1199 if (!declaration.isOpen())
1200 modifiers.add(Modifier.FINAL)
1201 if (declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQN))
1202 modifiers.add(Modifier.JAVA_STATIC)
1203 if (declaration.hasAnnotation(JVM_DEFAULT_ANNOTATION_FQN))
1204 modifiers.add(Modifier.JAVA_DEFAULT)
1205 if (declaration.hasAnnotation(JVM_DEFAULT_WITHOUT_COMPATIBILITY_ANNOTATION_FQN))
1206 modifiers.add(Modifier.JAVA_DEFAULT)
1207 if (declaration.hasAnnotation(JVM_STRICTFP_ANNOTATION_FQN))
1208 modifiers.add(Modifier.JAVA_STRICT)
1209 if (declaration.hasAnnotation(JVM_SYNCHRONIZED_ANNOTATION_FQN))
1210 modifiers.add(Modifier.JAVA_SYNCHRONIZED)
1211 if (declaration.hasAnnotation(JVM_TRANSIENT_ANNOTATION_FQN))
1212 modifiers.add(Modifier.JAVA_TRANSIENT)
1213 if (declaration.hasAnnotation(JVM_VOLATILE_ANNOTATION_FQN))
1214 modifiers.add(Modifier.JAVA_VOLATILE)
1215 when (declaration) {
1216 is KSClassDeclaration -> {
1217 if (declaration.isCompanionObject)
1218 modifiers.add(Modifier.JAVA_STATIC)
1219 if (declaration.classKind == ClassKind.INTERFACE)
1220 modifiers.add(Modifier.ABSTRACT)
1221 }
1222 is KSPropertyDeclaration -> {
1223 if (declaration.isAbstract())
1224 modifiers.add(Modifier.ABSTRACT)
1225 }
1226 is KSFunctionDeclaration -> {
1227 if (declaration.isAbstract)
1228 modifiers.add(Modifier.ABSTRACT)
1229 }
1230 }
1231 }
1232 Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
1233 when (declaration) {
1234 is KSPropertyDeclaration -> {
1235 if (declaration.jvmAccessFlag and Opcodes.ACC_TRANSIENT != 0)
1236 modifiers.add(Modifier.JAVA_TRANSIENT)
1237 if (declaration.jvmAccessFlag and Opcodes.ACC_VOLATILE != 0)
1238 modifiers.add(Modifier.JAVA_VOLATILE)
1239 }
1240 is KSFunctionDeclaration -> {
1241 if (declaration.jvmAccessFlag and Opcodes.ACC_STRICT != 0)
1242 modifiers.add(Modifier.JAVA_STRICT)
1243 if (declaration.jvmAccessFlag and Opcodes.ACC_SYNCHRONIZED != 0)
1244 modifiers.add(Modifier.JAVA_SYNCHRONIZED)
1245 }
1246 }
1247 }
1248 else -> Unit
1249 }
1250 return modifiers
1251 }
1252
1253 private enum class RefPosition {
1254 PARAMETER_TYPE,
1255 RETURN_TYPE,
1256 SUPER_TYPE
1257 }
1258
1259 // Search in self and parents for the first type reference that is not part of a type argument.
1260 private fun KSTypeReference.findOuterMostRef(): Pair<KSTypeReference, List<Int>> {
1261 fun KSNode.findParentRef(): KSTypeReference? {
1262 var parent = parent
1263 while (parent != null && parent !is KSTypeReference)
1264 parent = parent.parent
1265 return parent as? KSTypeReference
1266 }
1267
1268 val fallback = Pair<KSTypeReference, List<Int>>(this, emptyList())
1269 val indexes = mutableListOf<Int>()
1270 var candidate: KSTypeReference = this
1271 // KSTypeArgument's parent can be either KSReferenceElement or KSType.
1272 while (candidate.parent is KSTypeArgument) {
1273 // If the parent is a KSType, it's a synthetic reference.
1274 // Do nothing and reply on the fallback behavior.
1275 val referenceElement = (candidate.parent!!.parent as? KSReferenceElement) ?: return fallback
1276 indexes.add(referenceElement.typeArguments.indexOf(candidate.parent))
1277 // In case the program isn't properly structured, fallback.
1278 candidate = referenceElement.findParentRef() ?: return fallback
1279 }
1280 return Pair(candidate, indexes)
1281 }
1282
1283 // TODO: Strict mode for catching unhandled cases.
1284 private fun findRefPosition(ref: KSTypeReference): RefPosition = when (val parent = ref.parent) {
1285 is KSCallableReference -> when (ref) {
1286 parent.returnType -> RefPosition.RETURN_TYPE
1287 else -> RefPosition.PARAMETER_TYPE
1288 }
1289 is KSFunctionDeclaration -> when (ref) {
1290 parent.returnType -> RefPosition.RETURN_TYPE
1291 else -> RefPosition.PARAMETER_TYPE
1292 }
1293 is KSPropertyGetter -> RefPosition.RETURN_TYPE
1294 is KSPropertyDeclaration -> when (ref) {
1295 parent.type -> RefPosition.RETURN_TYPE
1296 else -> RefPosition.PARAMETER_TYPE
1297 }
1298 is KSClassDeclaration -> RefPosition.SUPER_TYPE
1299 // is KSTypeArgument -> RefPosition.PARAMETER_TYPE
1300 // is KSAnnotation -> RefPosition.PARAMETER_TYPE
1301 // is KSTypeAlias -> RefPosition.PARAMETER_TYPE
1302 // is KSValueParameter -> RefPosition.PARAMETER_TYPE
1303 // is KSTypeParameter -> RefPosition.PARAMETER_TYPE
1304 else -> RefPosition.PARAMETER_TYPE
1305 }
1306
1307 private fun KSTypeReference.isReturnTypeOfAnnotationMethod(): Boolean {
1308 var candidate = this.parent
1309 while (candidate !is KSClassDeclaration && candidate != null)
1310 candidate = candidate.parent
1311 return (candidate as? KSClassDeclaration)?.classKind == ClassKind.ANNOTATION_CLASS
1312 }
1313
1314 // Convert type arguments for Java wildcard, recursively.
1315 private fun KotlinType.toWildcard(mode: TypeMappingMode): KotlinType? {
1316 val parameters = constructor.parameters
1317 val arguments = arguments
1318
1319 val wildcardArguments = parameters.zip(arguments).map { (parameter, argument) ->
1320 if (!argument.isStarProjection &&
1321 parameter.variance != argument.projectionKind &&
1322 parameter.variance != org.jetbrains.kotlin.types.Variance.INVARIANT &&
1323 argument.projectionKind != org.jetbrains.kotlin.types.Variance.INVARIANT
1324 ) {
1325 // conflicting variances
1326 // TODO: error message
1327 return null
1328 }
1329
1330 val argMode = mode.updateFromAnnotations(argument.type)
1331 val variance = KotlinTypeMapper.getVarianceForWildcard(parameter, argument, argMode)
1332 val genericMode = argMode.toGenericArgumentMode(
1333 getEffectiveVariance(parameter.variance, argument.projectionKind)
1334 )
1335 TypeProjectionImpl(variance, argument.type.toWildcard(genericMode) ?: return null)
1336 }
1337
1338 return replace(wildcardArguments)
1339 }
1340
1341 private val JVM_SUPPRESS_WILDCARDS_NAME = KSNameImpl.getCached("kotlin.jvm.JvmSuppressWildcards")
1342 private val JVM_SUPPRESS_WILDCARDS_SHORT = "JvmSuppressWildcards"
1343 private fun KSTypeReference.findJvmSuppressWildcards(): Boolean? {
1344 var candidate: KSNode? = this
1345
1346 while (candidate != null) {
1347 if ((candidate is KSTypeReference || candidate is KSDeclaration)) {
1348 (
1349 (candidate as KSAnnotated).annotations.firstOrNull {
1350 checkAnnotation(it, JVM_SUPPRESS_WILDCARDS_NAME, JVM_SUPPRESS_WILDCARDS_SHORT)
1351 }?.arguments?.firstOrNull()?.value as? Boolean
1352 )?.let {
1353 // KSAnnotated.getAnnotationsByType is handy but it uses reflection.
1354 return it
1355 }
1356 }
1357 candidate = candidate.parent
1358 }
1359
1360 return null
1361 }
1362
1363 private fun TypeMappingMode.updateFromAnnotations(
1364 type: KotlinType
1365 ): TypeMappingMode {
1366 (
1367 type.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)
1368 ?.argumentValue("suppress")?.value as? Boolean
1369 )?.let {
1370 return this.suppressJvmWildcards(it)
1371 }
1372
1373 if (type.annotations.hasAnnotation(JVM_WILDCARD_ANNOTATION_FQ_NAME)) {
1374 return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
1375 skipDeclarationSiteWildcards = false,
1376 isForAnnotationParameter = isForAnnotationParameter,
1377 fallbackMode = this,
1378 needInlineClassWrapping = needInlineClassWrapping,
1379 mapTypeAliases = mapTypeAliases
1380 )
1381 }
1382
1383 return this
1384 }
1385
1386 private fun TypeMappingMode.suppressJvmWildcards(
1387 suppress: Boolean
1388 ): TypeMappingMode {
1389 return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
1390 skipDeclarationSiteWildcards = suppress,
1391 isForAnnotationParameter = isForAnnotationParameter,
1392 needInlineClassWrapping = needInlineClassWrapping,
1393 mapTypeAliases = mapTypeAliases
1394 )
1395 }
1396
1397 private fun TypeMappingMode.updateFromParents(
1398 ref: KSTypeReference
1399 ): TypeMappingMode {
1400 ref.findJvmSuppressWildcards()?.let {
1401 return this.suppressJvmWildcards(it)
1402 }
1403
1404 return this
1405 }
1406
1407 // Type arguments need to be resolved recursively in a top-down manner. So we find and resolve the outer most
1408 // reference that contains this argument. Then locate and return the argument.
1409 @KspExperimental
1410 override fun getJavaWildcard(reference: KSTypeReference): KSTypeReference {
1411 // If the outer-most reference cannot be found, e.g., when this reference is nested in KSType.arguments,
1412 // fallback to PARAMETER_TYPE effectively.
1413 val (ref, indexes) = reference.findOuterMostRef()
1414
1415 val type = ref.resolve()
1416 if (type.isError)
1417 return reference
1418
1419 val position = findRefPosition(ref)
1420 val kotlinType = (type as KSTypeImpl).kotlinType
1421
1422 val typeSystem = SimpleClassicTypeSystemContext
1423 val typeMappingMode = when (position) {
1424 RefPosition.PARAMETER_TYPE -> typeSystem.getOptimalModeForValueParameter(kotlinType)
1425 RefPosition.RETURN_TYPE ->
1426 typeSystem.getOptimalModeForReturnType(kotlinType, ref.isReturnTypeOfAnnotationMethod())
1427 RefPosition.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE
1428 }.updateFromParents(ref)
1429
1430 val parameters = kotlinType.constructor.parameters
1431 val arguments = kotlinType.arguments
1432
1433 parameters.zip(arguments).forEach { (parameter, argument) ->
1434 if (position == RefPosition.SUPER_TYPE &&
1435 argument.projectionKind != org.jetbrains.kotlin.types.Variance.INVARIANT
1436 ) {
1437 // Type projection isn't allowed in immediate arguments to supertypes.
1438 // TODO: error message
1439 return KSTypeReferenceSyntheticImpl.getCached(KSErrorType, null)
1440 }
1441 }
1442
1443 val wildcardType = kotlinType.toWildcard(typeMappingMode)?.let {
1444 var candidate: KotlinType = it
1445 for (i in indexes.reversed()) {
1446 candidate = candidate.arguments[i].type
1447 }
1448 getKSTypeCached(candidate)
1449 } ?: KSErrorType
1450
1451 return KSTypeReferenceSyntheticImpl.getCached(wildcardType, null)
1452 }
1453
1454 @KspExperimental
1455 override fun isJavaRawType(type: KSType): Boolean {
1456 return type is KSTypeImpl && type.kotlinType.unwrap() is RawType
1457 }
1458
1459 private val psiJavaFiles = allKSFiles.filterIsInstance<KSFileJavaImpl>().map {
1460 Pair(it.psi.virtualFile.path, it.psi)
1461 }.toMap()
1462
1463 internal fun findPsiJavaFile(path: String): PsiFile? = psiJavaFiles.get(path)
1464 }
1465
1466 // TODO: cross module resolution
findExpectsInKSDeclarationnull1467 fun DeclarationDescriptor.findExpectsInKSDeclaration(): Sequence<KSDeclaration> =
1468 findExpects().asSequence().map {
1469 it.toKSDeclaration()
1470 }
1471
1472 // TODO: cross module resolution
findActualsInKSDeclarationnull1473 fun DeclarationDescriptor.findActualsInKSDeclaration(): Sequence<KSDeclaration> =
1474 findActuals(this.module).asSequence().map {
1475 it.toKSDeclaration()
1476 }
1477
toKSDeclarationnull1478 fun MemberDescriptor.toKSDeclaration(): KSDeclaration =
1479 when (val psi = findPsi()) {
1480 is KtClassOrObject -> KSClassDeclarationImpl.getCached(psi)
1481 is KtFunction -> KSFunctionDeclarationImpl.getCached(psi)
1482 is KtProperty -> KSPropertyDeclarationImpl.getCached((psi))
1483 is KtTypeAlias -> KSTypeAliasImpl.getCached(psi)
1484 is PsiClass -> KSClassDeclarationJavaImpl.getCached(psi)
1485 is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(psi)
1486 is PsiField -> KSPropertyDeclarationJavaImpl.getCached(psi)
1487 else -> when (this) {
1488 is ClassDescriptor -> KSClassDeclarationDescriptorImpl.getCached(this)
1489 is FunctionDescriptor -> KSFunctionDeclarationDescriptorImpl.getCached(this)
1490 is PropertyDescriptor -> KSPropertyDeclarationDescriptorImpl.getCached(this)
1491 else -> throw IllegalStateException("Unknown expect/actual implementation")
1492 }
1493 }
1494
1495 /**
1496 * [NewTypeSubstitutor] handles variance better than [TypeSubstitutor] so we use it when subtituting
1497 * types in [ResolverImpl.asMemberOf] implementations.
1498 */
TypeSubstitutornull1499 private fun TypeSubstitutor.toNewSubstitutor() = composeWith(
1500 org.jetbrains.kotlin.resolve.calls.inference.components.EmptySubstitutor
1501 )
1502
1503 private fun KotlinType.createTypeSubstitutor(): NewTypeSubstitutor {
1504 return SubstitutionUtils.buildDeepSubstitutor(this).toNewSubstitutor()
1505 }
1506
1507 /**
1508 * Extracts the identifier from a module Name.
1509 *
1510 * One caveat here is that kotlin passes a special name into the plugin which cannot be used as an identifier.
1511 * On the other hand, to construct the correct TypeMapper, we need a non-special name.
1512 * This function extracts the non-special name from a given name if it is special.
1513 *
1514 * @see: https://github.com/JetBrains/kotlin/blob/master/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt#L305
1515 */
getNonSpecialIdentifiernull1516 private fun Name.getNonSpecialIdentifier(): String {
1517 // the analyzer might pass down a special name which will break type mapper name computations.
1518 // If it is a special name, we turn it back to an id
1519 if (!isSpecial || asString().isBlank()) {
1520 return asString()
1521 }
1522 // special names starts with a `<` and usually end with `>`
1523 return if (asString().last() == '>') {
1524 asString().substring(1, asString().length - 1)
1525 } else {
1526 asString().substring(1)
1527 }
1528 }
1529
findEnclosedDescriptornull1530 private inline fun MemberScope.findEnclosedDescriptor(
1531 kindFilter: DescriptorKindFilter,
1532 crossinline filter: (DeclarationDescriptor) -> Boolean,
1533 ): DeclarationDescriptor? {
1534 return getContributedDescriptors(
1535 kindFilter = kindFilter
1536 ).firstOrNull(filter)
1537 }
1538
findEnclosedDescriptornull1539 private inline fun ClassDescriptor.findEnclosedDescriptor(
1540 kindFilter: DescriptorKindFilter,
1541 crossinline filter: (DeclarationDescriptor) -> Boolean,
1542 ): DeclarationDescriptor? {
1543 return this.unsubstitutedMemberScope.findEnclosedDescriptor(
1544 kindFilter = kindFilter,
1545 filter = filter
1546 ) ?: this.staticScope.findEnclosedDescriptor(
1547 kindFilter = kindFilter,
1548 filter = filter
1549 ) ?: constructors.firstOrNull {
1550 kindFilter.accepts(it) && filter(it)
1551 }
1552 }
1553
findAnnotationFromUseSiteTargetnull1554 internal fun KSAnnotated.findAnnotationFromUseSiteTarget(): Sequence<KSAnnotation> {
1555 return when (this) {
1556 is KSPropertyGetter -> (this.receiver as? KSDeclarationImpl)?.let {
1557 it.originalAnnotations.asSequence().filter { it.useSiteTarget == AnnotationUseSiteTarget.GET }
1558 }
1559 is KSPropertySetter -> (this.receiver as? KSDeclarationImpl)?.let {
1560 it.originalAnnotations.asSequence().filter { it.useSiteTarget == AnnotationUseSiteTarget.SET }
1561 }
1562 is KSValueParameter -> {
1563 var parent = when (this) {
1564 is KSValueParameterSyntheticImpl -> this.owner
1565 is KSValueParameterImpl -> this.ktParameter.findParentAnnotated()
1566 else -> null
1567 }
1568 // TODO: eliminate annotationsFromParents to make this fully sequence.
1569 val annotationsFromParents = mutableListOf<KSAnnotation>()
1570 (parent as? KSPropertyAccessorImpl)?.let {
1571 annotationsFromParents.addAll(
1572 it.originalAnnotations.asSequence()
1573 .filter { it.useSiteTarget == AnnotationUseSiteTarget.SETPARAM }
1574 )
1575 parent = (parent as KSPropertyAccessorImpl).receiver
1576 }
1577 (parent as? KSPropertyDeclarationImpl)?.let {
1578 annotationsFromParents.addAll(
1579 it.originalAnnotations.asSequence()
1580 .filter { it.useSiteTarget == AnnotationUseSiteTarget.SETPARAM }
1581 )
1582 }
1583 annotationsFromParents.asSequence()
1584 }
1585 else -> emptySequence()
1586 } ?: emptySequence()
1587 }
1588
1589 // Resolve to underlying type.
1590 // Only slightly slower than resolving a plain type, because everything is resolved and cached in the first resolve().
1591 // FIXME: add a resolution mode in resolveUserType() to resolve to underlying type directly.
resolveToUnderlyingnull1592 internal fun KSTypeReference.resolveToUnderlying(): KSType {
1593 var candidate = resolve()
1594 var declaration = candidate.declaration
1595 while (declaration is KSTypeAlias) {
1596 candidate = declaration.type.resolve()
1597 declaration = candidate.declaration
1598 }
1599 return candidate
1600 }
1601
1602 // TODO: Remove this after upgrading to Kotlin 1.8.20.
1603 // Temporary work around for https://github.com/google/ksp/issues/1034
1604 // Force resolve outer most class for Java nested classes.
workaroundForNestednull1605 internal fun JavaClass.workaroundForNested(
1606 lazyJavaResolverContext: LazyJavaResolverContext = ResolverImpl.instance!!.lazyJavaResolverContext
1607 ) {
1608 var outerMost = outerClass
1609 while (outerMost?.outerClass != null) {
1610 outerMost = outerMost.outerClass
1611 }
1612 outerMost?.classId?.let { lazyJavaResolverContext.components.finder.findClass(it) }
1613 }
1614