Callable reference completion for non-imported callables

This commit is contained in:
Valentin Kipyatkov
2015-10-01 19:07:18 +03:00
parent 3a2bc51445
commit 08335a2ac9
21 changed files with 193 additions and 127 deletions
@@ -116,8 +116,8 @@ public class ReferenceVariantsHelper(
else -> throw RuntimeException() //TODO: see KT-9394
}
val resolutionScope = resolutionScope(expression) ?: return emptyList()
val dataFlowInfo = dataFlowInfo(expression)
val resolutionScope = resolutionScope(expression, context) ?: return emptyList()
val dataFlowInfo = dataFlowInfo(expression, context)
val containingDeclaration = resolutionScope.getContainingDeclaration()
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
@@ -334,14 +334,16 @@ public class ReferenceVariantsHelper(
return resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.PACKAGES, nameFilter).filter(visibilityFilter)
}
//TODO: drop these methods
public fun resolutionScope(expression: JetSimpleNameExpression): JetScope? {
val parent = expression.parent
return context[BindingContext.RESOLUTION_SCOPE, if (parent is JetCallableReferenceExpression) parent else expression]
}
companion object {
//TODO: drop these methods
public fun resolutionScope(expression: JetExpression, bindingContext: BindingContext): JetScope? {
val parent = expression.parent
return bindingContext[BindingContext.RESOLUTION_SCOPE, if (parent is JetCallableReferenceExpression) parent else expression]
}
public fun dataFlowInfo(expression: JetSimpleNameExpression): DataFlowInfo {
val parent = expression.parent
return context.getDataFlowInfo(if (parent is JetCallableReferenceExpression) parent else expression)
public fun dataFlowInfo(expression: JetExpression, bindingContext: BindingContext): DataFlowInfo {
val parent = expression.parent
return bindingContext.getDataFlowInfo(if (parent is JetCallableReferenceExpression) parent else expression)
}
}
}
@@ -18,14 +18,22 @@ package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
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.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
public sealed class CallType<TReceiver : JetElement?>(val descriptorKindFilter: DescriptorKindFilter) {
object UNKNOWN : CallType<Nothing?>(DescriptorKindFilter.ALL)
@@ -140,3 +148,58 @@ public sealed class CallTypeAndReceiver<TReceiver : JetElement?, TCallType : Cal
}
}
}
public fun CallTypeAndReceiver<*, *>.receiverTypes(
bindingContext: BindingContext,
position: JetExpression,
moduleDescriptor: ModuleDescriptor,
predictableSmartCastsOnly: Boolean
): Collection<JetType>? {
val receiverExpression: JetExpression?
when (this) {
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
if (receiver != null) {
val type = bindingContext[BindingContext.TYPE, receiver]
return type.singletonOrEmptyList()
}
else {
receiverExpression = null
}
}
is CallTypeAndReceiver.DEFAULT -> receiverExpression = null
is CallTypeAndReceiver.DOT -> receiverExpression = receiver
is CallTypeAndReceiver.SAFE -> receiverExpression = receiver
is CallTypeAndReceiver.INFIX -> receiverExpression = receiver
is CallTypeAndReceiver.UNARY -> receiverExpression = receiver
is CallTypeAndReceiver.IMPORT_DIRECTIVE,
is CallTypeAndReceiver.PACKAGE_DIRECTIVE,
is CallTypeAndReceiver.TYPE,
is CallTypeAndReceiver.UNKNOWN ->
return null
else -> throw RuntimeException() //TODO: see KT-9394
}
val receiverValues = if (receiverExpression != null) {
val expressionType = bindingContext.getType(receiverExpression)
expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: return emptyList()
}
else {
val resolutionScope = ReferenceVariantsHelper.resolutionScope(position, bindingContext) ?: return emptyList()
resolutionScope.getImplicitReceiversWithInstance().map { it.value }
}
val dataFlowInfo = ReferenceVariantsHelper.dataFlowInfo(position, bindingContext)
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)
}
}
}