Refactored ReferenceVariantsHelper to not require KtSimpleNameExpression
This commit is contained in:
+38
-28
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
@@ -47,25 +48,34 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
public class ReferenceVariantsHelper(
|
||||
private val context: BindingContext,
|
||||
class ReferenceVariantsHelper(
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
||||
) {
|
||||
@JvmOverloads
|
||||
public fun getReferenceVariants(
|
||||
fun getReferenceVariants(
|
||||
expression: KtSimpleNameExpression,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *> = CallTypeAndReceiver.detect(expression),
|
||||
filterOutJavaGettersAndSetters: Boolean = false,
|
||||
useRuntimeReceiverType: Boolean = false
|
||||
): Collection<DeclarationDescriptor>
|
||||
= getReferenceVariants(expression, CallTypeAndReceiver.detect(expression),
|
||||
kindFilter, nameFilter, filterOutJavaGettersAndSetters, useRuntimeReceiverType)
|
||||
|
||||
fun getReferenceVariants(
|
||||
contextElement: PsiElement,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
filterOutJavaGettersAndSetters: Boolean = false,
|
||||
useRuntimeReceiverType: Boolean = false
|
||||
): Collection<DeclarationDescriptor> {
|
||||
var variants: Collection<DeclarationDescriptor>
|
||||
= getReferenceVariantsNoVisibilityFilter(expression, kindFilter, nameFilter, callTypeAndReceiver, useRuntimeReceiverType)
|
||||
= getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useRuntimeReceiverType)
|
||||
.filter { !it.isAnnotatedAsHidden() && visibilityFilter(it) }
|
||||
|
||||
ShadowedDeclarationsFilter.create(context, resolutionFacade, expression, callTypeAndReceiver)?.let {
|
||||
ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, contextElement, callTypeAndReceiver)?.let {
|
||||
variants = it.filter(variants)
|
||||
}
|
||||
|
||||
@@ -79,14 +89,14 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
}
|
||||
|
||||
variants = variants.filter { it.original !in accessorMethodsToRemove }
|
||||
variants = variants.filter { it !is FunctionDescriptor || it.original !in accessorMethodsToRemove }
|
||||
}
|
||||
|
||||
return variants
|
||||
}
|
||||
|
||||
private fun getReferenceVariantsNoVisibilityFilter(
|
||||
expression: KtSimpleNameExpression,
|
||||
contextElement: PsiElement,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||
@@ -108,15 +118,15 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.TYPE -> {
|
||||
return getVariantsForUserType(callTypeAndReceiver.receiver, expression, kindFilter, nameFilter)
|
||||
return getVariantsForUserType(callTypeAndReceiver.receiver, contextElement, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.ANNOTATION -> {
|
||||
return getVariantsForUserType(callTypeAndReceiver.receiver, expression, kindFilter, nameFilter)
|
||||
return getVariantsForUserType(callTypeAndReceiver.receiver, contextElement, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
||||
val resolutionScope = expression.getResolutionScope(context, resolutionFacade)
|
||||
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
@@ -129,19 +139,19 @@ public class ReferenceVariantsHelper(
|
||||
else -> throw RuntimeException() //TODO: see KT-9394
|
||||
}
|
||||
|
||||
val resolutionScope = expression.getResolutionScope(context, resolutionFacade)
|
||||
val dataFlowInfo = context.getDataFlowInfo(expression)
|
||||
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(contextElement)
|
||||
val containingDeclaration = resolutionScope.ownerDescriptor
|
||||
|
||||
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
|
||||
val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance().flatMap {
|
||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, context, containingDeclaration, dataFlowInfo)
|
||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, bindingContext, containingDeclaration, dataFlowInfo)
|
||||
}.toSet()
|
||||
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
||||
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression]
|
||||
if (qualifier != null) {
|
||||
descriptors.addAll(qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter))
|
||||
}
|
||||
@@ -149,11 +159,11 @@ public class ReferenceVariantsHelper(
|
||||
val expressionType = if (useRuntimeReceiverType)
|
||||
getQualifierRuntimeType(receiverExpression)
|
||||
else
|
||||
context.getType(receiverExpression)
|
||||
bindingContext.getType(receiverExpression)
|
||||
if (expressionType != null && !expressionType.isError()) {
|
||||
val receiverValue = ExpressionReceiver(receiverExpression, expressionType)
|
||||
val explicitReceiverTypes = smartCastManager
|
||||
.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, containingDeclaration, dataFlowInfo)
|
||||
.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, containingDeclaration, dataFlowInfo)
|
||||
|
||||
descriptors.processAll(implicitReceiverTypes, explicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter)
|
||||
}
|
||||
@@ -170,16 +180,16 @@ public class ReferenceVariantsHelper(
|
||||
|
||||
private fun getVariantsForUserType(
|
||||
receiverExpression: KtExpression?,
|
||||
expression: KtSimpleNameExpression,
|
||||
contextElement: PsiElement,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
else {
|
||||
val scope = expression.getResolutionScope(context, resolutionFacade)
|
||||
val scope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
return scope.collectDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
}
|
||||
@@ -192,7 +202,7 @@ public class ReferenceVariantsHelper(
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
if (qualifierTypeRef != null) {
|
||||
val type = context[BindingContext.TYPE, qualifierTypeRef] ?: return emptyList()
|
||||
val type = bindingContext[BindingContext.TYPE, qualifierTypeRef] ?: return emptyList()
|
||||
|
||||
descriptors.addNonExtensionMembers(listOf(type), kindFilter, nameFilter, constructorFilter = { true })
|
||||
|
||||
@@ -211,7 +221,7 @@ public class ReferenceVariantsHelper(
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
val qualifier = bindingContext[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
else {
|
||||
@@ -285,7 +295,7 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
private fun MutableSet<DeclarationDescriptor>.addScopeAndSyntheticExtensions(
|
||||
resolutionScope: LexicalScope,
|
||||
scope: LexicalScope,
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
callType: CallType<*>,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
@@ -299,26 +309,26 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
}
|
||||
|
||||
for (descriptor in resolutionScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter)) {
|
||||
for (descriptor in scope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter)) {
|
||||
// todo: sometimes resolution scope here is LazyJavaClassMemberScope. see ea.jetbrains.com/browser/ea_problems/72572
|
||||
process(descriptor as CallableDescriptor)
|
||||
}
|
||||
|
||||
if (kindFilter.acceptsKinds(DescriptorKindFilter.VARIABLES_MASK)) {
|
||||
for (extension in resolutionScope.collectSyntheticExtensionProperties(receiverTypes)) {
|
||||
for (extension in scope.collectSyntheticExtensionProperties(receiverTypes)) {
|
||||
process(extension)
|
||||
}
|
||||
}
|
||||
|
||||
if (kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) {
|
||||
for (extension in resolutionScope.collectSyntheticExtensionFunctions(receiverTypes)) {
|
||||
for (extension in scope.collectSyntheticExtensionFunctions(receiverTypes)) {
|
||||
process(extension)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getQualifierRuntimeType(receiver: KtExpression): KotlinType? {
|
||||
val type = context.getType(receiver)
|
||||
val type = bindingContext.getType(receiver)
|
||||
if (type != null && TypeUtils.canHaveSubtypes(KotlinTypeChecker.DEFAULT, type)) {
|
||||
val evaluator = receiver.getContainingFile().getCopyableUserData(KtCodeFragment.RUNTIME_TYPE_EVALUATOR)
|
||||
val runtimeType = evaluator?.invoke(receiver)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
@@ -40,14 +41,14 @@ import java.util.*
|
||||
public class ShadowedDeclarationsFilter private constructor(
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val context: KtExpression,
|
||||
private val context: PsiElement,
|
||||
private val explicitReceiverValue: ReceiverValue
|
||||
) {
|
||||
companion object {
|
||||
fun create(
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
context: KtExpression,
|
||||
context: PsiElement,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
||||
): ShadowedDeclarationsFilter? {
|
||||
val receiverExpression = when (callTypeAndReceiver) {
|
||||
|
||||
@@ -316,7 +316,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
private fun createLookupElementFactory(callType: CallType<*>?, receiverTypes: Collection<KotlinType>?): LookupElementFactory {
|
||||
val contextVariablesProvider = {
|
||||
nameExpression?.let {
|
||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT)
|
||||
referenceVariantsHelper.getReferenceVariants(it, CallTypeAndReceiver.DEFAULT, DescriptorKindFilter.VARIABLES, nameFilter = { true })
|
||||
.map { it as VariableDescriptor }
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public fun Call.resolveCandidates(
|
||||
val resolutionScope = callElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val inDescriptor = resolutionScope.ownerDescriptor
|
||||
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(calleeExpression)
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(callElement)
|
||||
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace")
|
||||
val callResolutionContext = BasicCallResolutionContext.create(
|
||||
bindingTrace, resolutionScope, this, expectedType, dataFlowInfo,
|
||||
|
||||
Reference in New Issue
Block a user