From 470fef94fba092408fcfb2cd2ebaecfb105be8b9 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Tue, 26 May 2020 15:35:43 +0300 Subject: [PATCH] Use bound resolution facade in DeprecationResolver usages Resolution facade should be used consistently with direct usages of frontend components. Otherwise they can start processing descriptors from foreign resolvers which leads to memory leaks. Plain resolution API with provided facade is not suitable as-is for compiled declarations in KotlinIndicesHelper though. Resolution facade for module sources contained in helper can't handle decompiled sources from PSI indices (leads to "ModuleInfo not contained in resolver" errors). That's why "hacked" resolve via import references should be used there. #KT-39642 Fixed --- .../kotlin/idea/core/KotlinIndicesHelper.kt | 17 ++++++------ .../idea/KotlinDocumentationProvider.kt | 26 ++++++++++++------- .../ConflictingExtensionPropertyInspection.kt | 2 +- .../OverridingDeprecatedMemberInspection.kt | 5 ++-- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 5a107aafacd..bddfd30a5f0 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -26,8 +26,7 @@ import com.intellij.util.indexing.IdFilter import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.KotlinShortNamesCache -import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.* import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor import org.jetbrains.kotlin.idea.codeInsight.forceEnableSamAdapters @@ -264,7 +263,7 @@ class KotlinIndicesHelper( fun getKotlinEnumsByName(name: String): Collection { return KotlinClassShortNameIndex.getInstance()[name, project, scope] .filter { it is KtEnumEntry && it in scope } - .mapNotNull { it.unsafeResolveToDescriptor() } + .flatMap { it.resolveToDescriptors() } .filter(descriptorFilter) .toSet() } @@ -367,10 +366,12 @@ class KotlinIndicesHelper( for (declaration in functions + properties) { ProgressManager.checkCanceled() if (!filter(declaration)) continue - val descriptor = declaration.descriptor as? CallableDescriptor ?: continue - if (!processed.add(descriptor)) continue - if (!descriptorFilter(descriptor)) continue - processor(descriptor) + + for (descriptor in declaration.resolveToDescriptors()) { + if (!processed.add(descriptor)) continue + if (!descriptorFilter(descriptor)) continue + processor(descriptor) + } } } @@ -489,7 +490,7 @@ class KotlinIndicesHelper( for (field in shortNamesCache.getFieldsByName(name, scopeWithoutKotlin).filterNot { it is KtLightElement<*, *> }) { if (!field.hasModifierProperty(PsiModifier.STATIC)) continue if (filterOutPrivate && field.hasModifierProperty(PsiModifier.PRIVATE)) continue - val descriptor = field.getJavaMemberDescriptor() ?: continue + val descriptor = field.getJavaMemberDescriptor(resolutionFacade) ?: continue if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) { processor(descriptor) } diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt index f768b194e22..95ba6d86422 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinDocumentationProvider.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.idea.kdoc.KDocTemplate.DescriptionBodyTemplate import org.jetbrains.kotlin.idea.references.KtDescriptorsBasedReference import org.jetbrains.kotlin.idea.references.resolveToDescriptors import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.util.isRunningInCidrIde import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi @@ -142,10 +143,11 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider override fun getDocumentationElementForLink(psiManager: PsiManager, link: String, context: PsiElement?): PsiElement? { val navElement = context?.navigationElement as? KtElement ?: return null - val bindingContext = navElement.analyze(BodyResolveMode.PARTIAL) + val resolutionFacade = navElement.getResolutionFacade() + val bindingContext = navElement.analyze(resolutionFacade, BodyResolveMode.PARTIAL) val contextDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, navElement] ?: return null val descriptors = resolveKDocLink( - bindingContext, navElement.getResolutionFacade(), + bindingContext, resolutionFacade, contextDescriptor, null, link.split('.') ) val target = descriptors.firstOrNull() ?: return null @@ -318,7 +320,8 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider } private fun buildKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): KDocTemplate { - val context = declaration.analyze(BodyResolveMode.PARTIAL) + val resolutionFacade = declaration.getResolutionFacade() + val context = declaration.analyze(resolutionFacade, BodyResolveMode.PARTIAL) val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] if (declarationDescriptor == null) { @@ -330,29 +333,32 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider } } - return buildKotlin(context, declarationDescriptor, quickNavigation, declaration) + return buildKotlin(context, declarationDescriptor, quickNavigation, declaration, resolutionFacade) } private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? { - val context = element.analyze(BodyResolveMode.PARTIAL) + val resolutionFacade = element.getResolutionFacade() + val context = element.analyze(resolutionFacade, BodyResolveMode.PARTIAL) val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null - return renderKotlin(context, target, quickNavigation, element) + return renderKotlin(context, target, quickNavigation, element, resolutionFacade) } private fun renderKotlin( context: BindingContext, declarationDescriptor: DeclarationDescriptor, quickNavigation: Boolean, - ktElement: KtElement + ktElement: KtElement, + resolutionFacade: ResolutionFacade, ) = buildString { - insert(buildKotlin(context, declarationDescriptor, quickNavigation, ktElement)) {} + insert(buildKotlin(context, declarationDescriptor, quickNavigation, ktElement, resolutionFacade)) {} } private fun buildKotlin( context: BindingContext, declarationDescriptor: DeclarationDescriptor, quickNavigation: Boolean, - ktElement: KtElement + ktElement: KtElement, + resolutionFacade: ResolutionFacade, ): KDocTemplate { @Suppress("NAME_SHADOWING") var declarationDescriptor = declarationDescriptor @@ -363,7 +369,7 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider } } - val deprecationProvider = ktElement.getResolutionFacade().frontendService() + val deprecationProvider = resolutionFacade.frontendService() return KDocTemplate().apply { definition { diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt index 462db80b597..fb1e9cc8534 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt @@ -58,7 +58,7 @@ class ConflictingExtensionPropertyInspection : AbstractKotlinInspection() { return propertyVisitor(fun(property: KtProperty) { if (property.receiverTypeReference != null) { val nameElement = property.nameIdentifier ?: return - val propertyDescriptor = property.resolveToDescriptorIfAny() as? PropertyDescriptor ?: return + val propertyDescriptor = property.resolveToDescriptorIfAny(resolutionFacade) as? PropertyDescriptor ?: return val syntheticScopes = resolutionFacade.frontendService() val conflictingExtension = conflictingSyntheticExtension(propertyDescriptor, syntheticScopes) ?: return diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt index 4ebb9595dce..7eae573cfa3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/OverridingDeprecatedMemberInspection.kt @@ -35,9 +35,10 @@ class OverridingDeprecatedMemberInspection : AbstractKotlinInspection() { } private fun registerProblemIfNeeded(declaration: KtDeclaration, targetForProblem: PsiElement) { - val accessorDescriptor = declaration.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return + val resolutionFacade = declaration.getResolutionFacade() + val accessorDescriptor = declaration.resolveToDescriptorIfAny(resolutionFacade) as? CallableMemberDescriptor ?: return - val deprecationProvider = declaration.getResolutionFacade().frontendService() + val deprecationProvider = resolutionFacade.frontendService() val message = deprecationProvider.getDeprecations(accessorDescriptor) .firstOrNull()