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
This commit is contained in:
Pavel Kirpichenkov
2020-05-26 15:35:43 +03:00
parent 82ef6bf96c
commit 470fef94fb
4 changed files with 29 additions and 21 deletions
@@ -26,8 +26,7 @@ import com.intellij.util.indexing.IdFilter
import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.KotlinShortNamesCache import org.jetbrains.kotlin.idea.caches.KotlinShortNamesCache
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.caches.resolve.*
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor
import org.jetbrains.kotlin.idea.codeInsight.forceEnableSamAdapters import org.jetbrains.kotlin.idea.codeInsight.forceEnableSamAdapters
@@ -264,7 +263,7 @@ class KotlinIndicesHelper(
fun getKotlinEnumsByName(name: String): Collection<DeclarationDescriptor> { fun getKotlinEnumsByName(name: String): Collection<DeclarationDescriptor> {
return KotlinClassShortNameIndex.getInstance()[name, project, scope] return KotlinClassShortNameIndex.getInstance()[name, project, scope]
.filter { it is KtEnumEntry && it in scope } .filter { it is KtEnumEntry && it in scope }
.mapNotNull { it.unsafeResolveToDescriptor() } .flatMap { it.resolveToDescriptors<DeclarationDescriptor>() }
.filter(descriptorFilter) .filter(descriptorFilter)
.toSet() .toSet()
} }
@@ -367,10 +366,12 @@ class KotlinIndicesHelper(
for (declaration in functions + properties) { for (declaration in functions + properties) {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
if (!filter(declaration)) continue if (!filter(declaration)) continue
val descriptor = declaration.descriptor as? CallableDescriptor ?: continue
if (!processed.add(descriptor)) continue for (descriptor in declaration.resolveToDescriptors<CallableDescriptor>()) {
if (!descriptorFilter(descriptor)) continue if (!processed.add(descriptor)) continue
processor(descriptor) if (!descriptorFilter(descriptor)) continue
processor(descriptor)
}
} }
} }
@@ -489,7 +490,7 @@ class KotlinIndicesHelper(
for (field in shortNamesCache.getFieldsByName(name, scopeWithoutKotlin).filterNot { it is KtLightElement<*, *> }) { for (field in shortNamesCache.getFieldsByName(name, scopeWithoutKotlin).filterNot { it is KtLightElement<*, *> }) {
if (!field.hasModifierProperty(PsiModifier.STATIC)) continue if (!field.hasModifierProperty(PsiModifier.STATIC)) continue
if (filterOutPrivate && field.hasModifierProperty(PsiModifier.PRIVATE)) 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)) { if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) {
processor(descriptor) processor(descriptor)
} }
@@ -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.KtDescriptorsBasedReference
import org.jetbrains.kotlin.idea.references.resolveToDescriptors import org.jetbrains.kotlin.idea.references.resolveToDescriptors
import org.jetbrains.kotlin.idea.references.mainReference 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.resolve.frontendService
import org.jetbrains.kotlin.idea.util.isRunningInCidrIde import org.jetbrains.kotlin.idea.util.isRunningInCidrIde
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi 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? { override fun getDocumentationElementForLink(psiManager: PsiManager, link: String, context: PsiElement?): PsiElement? {
val navElement = context?.navigationElement as? KtElement ?: return null 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 contextDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, navElement] ?: return null
val descriptors = resolveKDocLink( val descriptors = resolveKDocLink(
bindingContext, navElement.getResolutionFacade(), bindingContext, resolutionFacade,
contextDescriptor, null, link.split('.') contextDescriptor, null, link.split('.')
) )
val target = descriptors.firstOrNull() ?: return null val target = descriptors.firstOrNull() ?: return null
@@ -318,7 +320,8 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider
} }
private fun buildKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): KDocTemplate { 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] val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
if (declarationDescriptor == null) { 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? { 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 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( private fun renderKotlin(
context: BindingContext, context: BindingContext,
declarationDescriptor: DeclarationDescriptor, declarationDescriptor: DeclarationDescriptor,
quickNavigation: Boolean, quickNavigation: Boolean,
ktElement: KtElement ktElement: KtElement,
resolutionFacade: ResolutionFacade,
) = buildString { ) = buildString {
insert(buildKotlin(context, declarationDescriptor, quickNavigation, ktElement)) {} insert(buildKotlin(context, declarationDescriptor, quickNavigation, ktElement, resolutionFacade)) {}
} }
private fun buildKotlin( private fun buildKotlin(
context: BindingContext, context: BindingContext,
declarationDescriptor: DeclarationDescriptor, declarationDescriptor: DeclarationDescriptor,
quickNavigation: Boolean, quickNavigation: Boolean,
ktElement: KtElement ktElement: KtElement,
resolutionFacade: ResolutionFacade,
): KDocTemplate { ): KDocTemplate {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
var declarationDescriptor = declarationDescriptor var declarationDescriptor = declarationDescriptor
@@ -363,7 +369,7 @@ open class KotlinDocumentationProviderCompatBase : AbstractDocumentationProvider
} }
} }
val deprecationProvider = ktElement.getResolutionFacade().frontendService<DeprecationResolver>() val deprecationProvider = resolutionFacade.frontendService<DeprecationResolver>()
return KDocTemplate().apply { return KDocTemplate().apply {
definition { definition {
@@ -58,7 +58,7 @@ class ConflictingExtensionPropertyInspection : AbstractKotlinInspection() {
return propertyVisitor(fun(property: KtProperty) { return propertyVisitor(fun(property: KtProperty) {
if (property.receiverTypeReference != null) { if (property.receiverTypeReference != null) {
val nameElement = property.nameIdentifier ?: return val nameElement = property.nameIdentifier ?: return
val propertyDescriptor = property.resolveToDescriptorIfAny() as? PropertyDescriptor ?: return val propertyDescriptor = property.resolveToDescriptorIfAny(resolutionFacade) as? PropertyDescriptor ?: return
val syntheticScopes = resolutionFacade.frontendService<SyntheticScopes>() val syntheticScopes = resolutionFacade.frontendService<SyntheticScopes>()
val conflictingExtension = conflictingSyntheticExtension(propertyDescriptor, syntheticScopes) ?: return val conflictingExtension = conflictingSyntheticExtension(propertyDescriptor, syntheticScopes) ?: return
@@ -35,9 +35,10 @@ class OverridingDeprecatedMemberInspection : AbstractKotlinInspection() {
} }
private fun registerProblemIfNeeded(declaration: KtDeclaration, targetForProblem: PsiElement) { 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<DeprecationResolver>() val deprecationProvider = resolutionFacade.frontendService<DeprecationResolver>()
val message = deprecationProvider.getDeprecations(accessorDescriptor) val message = deprecationProvider.getDeprecations(accessorDescriptor)
.firstOrNull() .firstOrNull()