Completion and import popup for bound callable references
This commit is contained in:
+25
-13
@@ -152,8 +152,7 @@ class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
||||
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, kindFilter, nameFilter)
|
||||
return getVariantsForCallableReference(callTypeAndReceiver, contextElement, useReceiverType, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
|
||||
@@ -227,24 +226,37 @@ class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
private fun getVariantsForCallableReference(
|
||||
receiverExpression: KtExpression?,
|
||||
resolutionScope: LexicalScope,
|
||||
callTypeAndReceiver: CallTypeAndReceiver.CALLABLE_REFERENCE,
|
||||
contextElement: PsiElement,
|
||||
useReceiverType: KotlinType?,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
if (receiverExpression != null) {
|
||||
val type =
|
||||
(bindingContext.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression) as? DoubleColonLHS.Type)?.type
|
||||
?: return emptyList()
|
||||
|
||||
descriptors.addNonExtensionMembers(listOf(type), kindFilter, nameFilter, constructorFilter = { true })
|
||||
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, listOf(type), CallType.CALLABLE_REFERENCE, kindFilter, nameFilter)
|
||||
val receiver = callTypeAndReceiver.receiver
|
||||
if (receiver != null) {
|
||||
val isStatic = bindingContext[BindingContext.DOUBLE_COLON_LHS, receiver] is DoubleColonLHS.Type
|
||||
|
||||
val staticScope = (type.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope
|
||||
if (staticScope != null) {
|
||||
descriptors.addAll(staticScope.getDescriptorsFiltered(kindFilter, nameFilter))
|
||||
val explicitReceiverTypes = if (useReceiverType != null) {
|
||||
listOf(useReceiverType)
|
||||
}
|
||||
else {
|
||||
callTypeAndReceiver.receiverTypes(bindingContext, contextElement, moduleDescriptor, resolutionFacade, predictableSmartCastsOnly = false)!!
|
||||
}
|
||||
|
||||
val constructorFilter = { descriptor: ClassDescriptor -> if (isStatic) true else descriptor.isInner }
|
||||
descriptors.addNonExtensionMembers(explicitReceiverTypes, kindFilter, nameFilter, constructorFilter)
|
||||
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, explicitReceiverTypes, CallType.CALLABLE_REFERENCE, kindFilter, nameFilter)
|
||||
|
||||
if (isStatic) {
|
||||
explicitReceiverTypes
|
||||
.map { (it.constructor.declarationDescriptor as? ClassDescriptor)?.staticScope }
|
||||
.filterNotNull()
|
||||
.flatMapTo(descriptors) { scope -> scope.getDescriptorsFiltered(kindFilter, nameFilter) }
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.util.supertypesWithAny
|
||||
@@ -216,9 +218,20 @@ fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||
val receiverExpression: KtExpression?
|
||||
when (this) {
|
||||
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
||||
return receiver?.let {
|
||||
(bindingContext[BindingContext.DOUBLE_COLON_LHS, it] as? DoubleColonLHS.Type)?.type
|
||||
}.singletonOrEmptyList()
|
||||
if (receiver != null) {
|
||||
val lhs = bindingContext[BindingContext.DOUBLE_COLON_LHS, receiver] ?: return emptyList()
|
||||
when (lhs) {
|
||||
is DoubleColonLHS.Type -> return listOf(lhs.type)
|
||||
|
||||
is DoubleColonLHS.Expression -> {
|
||||
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
|
||||
return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext, moduleDescriptor, predictableSmartCastsOnly)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
|
||||
@@ -267,13 +280,23 @@ fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfo(contextElement)
|
||||
|
||||
return receiverValues.flatMap { receiverValue ->
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
if (dataFlowValue.isPredictable || !predictableSmartCastsOnly) { // we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed
|
||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)
|
||||
}
|
||||
else {
|
||||
listOf(receiverValue.type)
|
||||
}
|
||||
return receiverValues.flatMap {
|
||||
receiverValueTypes(it, dataFlowInfo, bindingContext, moduleDescriptor, predictableSmartCastsOnly)
|
||||
}
|
||||
}
|
||||
|
||||
private fun receiverValueTypes(
|
||||
receiverValue: ReceiverValue,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
bindingContext: BindingContext,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
predictableSmartCastsOnly: Boolean
|
||||
): List<KotlinType> {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
return if (dataFlowValue.isPredictable || !predictableSmartCastsOnly) { // we don't include smart cast receiver types for "unpredictable" receiver value to mark members grayed
|
||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)
|
||||
}
|
||||
else {
|
||||
listOf(receiverValue.type)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user