Refactoring to add CallType.IMPORT_DIRECTIVE and CallType.PACKAGE_DIRECTIVE
This commit is contained in:
+74
-63
@@ -51,30 +51,78 @@ import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
public data class CallTypeAndReceiver(
|
||||
val callType: CallType,
|
||||
val receiver: JetElement?
|
||||
) {
|
||||
companion object {
|
||||
public fun detect(expression: JetSimpleNameExpression): CallTypeAndReceiver {
|
||||
val parent = expression.parent
|
||||
if (parent is JetCallableReferenceExpression) {
|
||||
return CallTypeAndReceiver(CallType.CALLABLE_REFERENCE, parent.typeReference)
|
||||
}
|
||||
|
||||
val receiverExpression = expression.getReceiverExpression()
|
||||
|
||||
if (expression.isImportDirectiveExpression()) {
|
||||
return CallTypeAndReceiver(CallType.IMPORT_DIRECTIVE, receiverExpression)
|
||||
}
|
||||
|
||||
if (expression.isPackageDirectiveExpression()) {
|
||||
return CallTypeAndReceiver(CallType.PACKAGE_DIRECTIVE, receiverExpression)
|
||||
}
|
||||
|
||||
if (receiverExpression == null) {
|
||||
return CallTypeAndReceiver(CallType.NORMAL, null)
|
||||
}
|
||||
|
||||
val callType = when (parent) {
|
||||
is JetBinaryExpression -> CallType.INFIX
|
||||
|
||||
is JetCallExpression -> {
|
||||
if ((parent.getParent() as JetQualifiedExpression).getOperationSign() == JetTokens.SAFE_ACCESS)
|
||||
CallType.SAFE
|
||||
else
|
||||
CallType.NORMAL
|
||||
}
|
||||
|
||||
is JetQualifiedExpression -> {
|
||||
if (parent.getOperationSign() == JetTokens.SAFE_ACCESS)
|
||||
CallType.SAFE
|
||||
else
|
||||
CallType.NORMAL
|
||||
}
|
||||
|
||||
is JetUnaryExpression -> CallType.UNARY
|
||||
|
||||
is JetUserType -> CallType.NORMAL
|
||||
|
||||
else -> error("Unknown parent for expression with receiver: $parent")
|
||||
}
|
||||
return CallTypeAndReceiver(callType, receiverExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ReferenceVariantsHelper(
|
||||
private val context: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val visibilityFilter: (DeclarationDescriptor) -> Boolean
|
||||
) {
|
||||
public data class ExplicitReceiverData(
|
||||
val element: JetElement?,
|
||||
val callType: CallType
|
||||
)
|
||||
|
||||
@JvmOverloads
|
||||
public fun getReferenceVariants(
|
||||
expression: JetSimpleNameExpression,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
explicitReceiverData: ExplicitReceiverData? = getExplicitReceiverData(expression),
|
||||
callTypeAndReceiver: CallTypeAndReceiver = CallTypeAndReceiver.detect(expression),
|
||||
filterOutJavaGettersAndSetters: Boolean = false,
|
||||
useRuntimeReceiverType: Boolean = false
|
||||
): Collection<DeclarationDescriptor> {
|
||||
var variants: Collection<DeclarationDescriptor>
|
||||
= getReferenceVariantsNoVisibilityFilter(expression, kindFilter, nameFilter, explicitReceiverData, useRuntimeReceiverType)
|
||||
= getReferenceVariantsNoVisibilityFilter(expression, kindFilter, nameFilter, callTypeAndReceiver, useRuntimeReceiverType)
|
||||
.filter { !it.isAnnotatedAsHidden() && visibilityFilter(it) }
|
||||
|
||||
variants = ShadowedDeclarationsFilter(context, resolutionFacade, expression, explicitReceiverData).filter(variants)
|
||||
variants = ShadowedDeclarationsFilter(context, resolutionFacade, expression, callTypeAndReceiver).filter(variants)
|
||||
|
||||
if (filterOutJavaGettersAndSetters) {
|
||||
val accessorMethodsToRemove = HashSet<FunctionDescriptor>()
|
||||
@@ -95,20 +143,22 @@ public class ReferenceVariantsHelper(
|
||||
expression: JetSimpleNameExpression,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
explicitReceiverData: ExplicitReceiverData?,
|
||||
callTypeAndReceiver: CallTypeAndReceiver,
|
||||
useRuntimeReceiverType: Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
if (expression.isImportDirectiveExpression()) {
|
||||
return getVariantsForImportOrPackageDirective(explicitReceiverData, kindFilter, nameFilter)
|
||||
val (callType, receiverElement) = callTypeAndReceiver
|
||||
|
||||
if (callType == CallType.IMPORT_DIRECTIVE) {
|
||||
return getVariantsForImportOrPackageDirective(receiverElement as JetExpression?, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
if (expression.isPackageDirectiveExpression()) {
|
||||
if (callType == CallType.PACKAGE_DIRECTIVE) {
|
||||
val packageKindFilter = kindFilter restrictedToKinds DescriptorKindFilter.PACKAGES_MASK
|
||||
return getVariantsForImportOrPackageDirective(explicitReceiverData, packageKindFilter, nameFilter)
|
||||
return getVariantsForImportOrPackageDirective(receiverElement as JetExpression?, packageKindFilter, nameFilter)
|
||||
}
|
||||
|
||||
if (expression.parent is JetUserType) {
|
||||
return getVariantsForUserType(explicitReceiverData, expression, kindFilter, nameFilter)
|
||||
if (expression.parent is JetUserType) { //TODO: special CallType?
|
||||
return getVariantsForUserType(receiverElement as JetExpression?, expression, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
val resolutionScope = resolutionScope(expression) ?: return emptyList()
|
||||
@@ -120,15 +170,13 @@ public class ReferenceVariantsHelper(
|
||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, context, containingDeclaration, dataFlowInfo)
|
||||
}.toSet()
|
||||
|
||||
if (callType == CallType.CALLABLE_REFERENCE) {
|
||||
return getVariantsForCallableReference(receiverElement as JetTypeReference?, resolutionScope, implicitReceiverTypes, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
|
||||
if (explicitReceiverData != null) {
|
||||
val (receiverElement, callType) = explicitReceiverData
|
||||
|
||||
if (callType == CallType.CALLABLE_REFERENCE) {
|
||||
return getVariantsForCallableReference(receiverElement as JetTypeReference?, resolutionScope, implicitReceiverTypes, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
if (receiverElement != null) {
|
||||
receiverElement as JetExpression
|
||||
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverElement]
|
||||
@@ -160,14 +208,13 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
private fun getVariantsForUserType(
|
||||
explicitReceiverData: ExplicitReceiverData?,
|
||||
receiverExpression: JetExpression?,
|
||||
expression: JetSimpleNameExpression,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val accurateKindFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK)
|
||||
if (explicitReceiverData != null) {
|
||||
val receiverExpression = explicitReceiverData.element as? JetExpression ?: return emptyList()
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
return qualifier.scope.getDescriptorsFiltered(accurateKindFilter, nameFilter)
|
||||
}
|
||||
@@ -208,12 +255,11 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
private fun getVariantsForImportOrPackageDirective(
|
||||
explicitReceiverData: ExplicitReceiverData?,
|
||||
receiverExpression: JetExpression?,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
if (explicitReceiverData != null) {
|
||||
val receiverExpression = explicitReceiverData.element as? JetExpression ?: return emptyList()
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
@@ -351,39 +397,4 @@ public class ReferenceVariantsHelper(
|
||||
val parent = expression.parent
|
||||
return context.getDataFlowInfo(if (parent is JetCallableReferenceExpression) parent else expression)
|
||||
}
|
||||
|
||||
companion object {
|
||||
public fun getExplicitReceiverData(expression: JetSimpleNameExpression): ExplicitReceiverData? {
|
||||
val parent = expression.parent
|
||||
if (parent is JetCallableReferenceExpression) {
|
||||
return ExplicitReceiverData(parent.typeReference, CallType.CALLABLE_REFERENCE)
|
||||
}
|
||||
|
||||
val receiverExpression = expression.getReceiverExpression() ?: return null
|
||||
val callType = when (parent) {
|
||||
is JetBinaryExpression -> CallType.INFIX
|
||||
|
||||
is JetCallExpression -> {
|
||||
if ((parent.getParent() as JetQualifiedExpression).getOperationSign() == JetTokens.SAFE_ACCESS)
|
||||
CallType.SAFE
|
||||
else
|
||||
CallType.NORMAL
|
||||
}
|
||||
|
||||
is JetQualifiedExpression -> {
|
||||
if (parent.getOperationSign() == JetTokens.SAFE_ACCESS)
|
||||
CallType.SAFE
|
||||
else
|
||||
CallType.NORMAL
|
||||
}
|
||||
|
||||
is JetUnaryExpression -> CallType.UNARY
|
||||
|
||||
is JetUserType -> CallType.NORMAL
|
||||
|
||||
else -> return null
|
||||
}
|
||||
return ExplicitReceiverData(receiverExpression, callType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
@@ -41,15 +41,14 @@ public class ShadowedDeclarationsFilter(
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val context: JetExpression,
|
||||
explicitReceiverData: ReferenceVariantsHelper.ExplicitReceiverData?
|
||||
callTypeAndReceiver: CallTypeAndReceiver
|
||||
) {
|
||||
private val psiFactory = JetPsiFactory(resolutionFacade.project)
|
||||
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
|
||||
|
||||
private val explicitReceiverValue = explicitReceiverData?.let {
|
||||
val expression = it.element as? JetExpression ?: return@let null
|
||||
val type = bindingContext.getType(expression) ?: return@let null
|
||||
ExpressionReceiver(expression, type)
|
||||
private val explicitReceiverValue = (callTypeAndReceiver.receiver as? JetExpression)?.let {
|
||||
val type = bindingContext.getType(it) ?: return@let null
|
||||
ExpressionReceiver(it, type)
|
||||
} ?: ReceiverValue.NO_RECEIVER
|
||||
|
||||
public fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> {
|
||||
|
||||
@@ -51,7 +51,12 @@ public enum class CallType {
|
||||
// currently callable references to locals and parameters are not supported
|
||||
override fun canCall(descriptor: DeclarationDescriptor)
|
||||
= descriptor is FunctionDescriptor || descriptor is PropertyDescriptor
|
||||
}
|
||||
},
|
||||
|
||||
//TODO: canCall
|
||||
IMPORT_DIRECTIVE,
|
||||
|
||||
PACKAGE_DIRECTIVE
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
@@ -284,8 +285,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
}
|
||||
|
||||
private fun Collection<CallableDescriptor>.filterShadowedNonImported(): Collection<CallableDescriptor> {
|
||||
val explicitReceiverData = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression!!)
|
||||
return ShadowedDeclarationsFilter(bindingContext, resolutionFacade, nameExpression, explicitReceiverData).filterNonImported(this, referenceVariants)
|
||||
val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression!!)
|
||||
return ShadowedDeclarationsFilter(bindingContext, resolutionFacade, nameExpression, callTypeAndReceiver)
|
||||
.filterNonImported(this, referenceVariants)
|
||||
}
|
||||
|
||||
protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) {
|
||||
@@ -301,7 +303,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
|
||||
val contextVariablesProvider = {
|
||||
nameExpression?.let {
|
||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, explicitReceiverData = null)
|
||||
referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver(CallType.NORMAL, null))
|
||||
.map { it as VariableDescriptor }
|
||||
} ?: emptyList()
|
||||
}
|
||||
@@ -317,11 +319,9 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
return CallType.NORMAL to emptyList()
|
||||
}
|
||||
|
||||
val explicitReceiverData = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression)
|
||||
val receiverElement = explicitReceiverData?.element
|
||||
val callType = explicitReceiverData?.callType ?: CallType.NORMAL
|
||||
val (callType, receiverElement) = CallTypeAndReceiver.detect(nameExpression)
|
||||
|
||||
if (explicitReceiverData != null && callType == CallType.CALLABLE_REFERENCE && receiverElement != null) {
|
||||
if (callType == CallType.CALLABLE_REFERENCE && receiverElement != null) {
|
||||
val type = bindingContext[BindingContext.TYPE, receiverElement as JetTypeReference]
|
||||
return callType to type.singletonOrEmptyList()
|
||||
}
|
||||
|
||||
+3
-6
@@ -28,10 +28,8 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||
import org.jetbrains.kotlin.psi.JetTypeArgumentList
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
|
||||
class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean)
|
||||
@@ -60,11 +58,10 @@ class KotlinFunctionInsertHandler(
|
||||
val startOffset = context.getStartOffset()
|
||||
val element = context.getFile().findElementAt(startOffset) ?: return
|
||||
|
||||
when {
|
||||
//TODO: replace with CallType
|
||||
element.getStrictParentOfType<JetImportDirective>() != null || callType == CallType.CALLABLE_REFERENCE -> return
|
||||
when (callType) {
|
||||
CallType.PACKAGE_DIRECTIVE, CallType.IMPORT_DIRECTIVE, CallType.CALLABLE_REFERENCE -> return
|
||||
|
||||
callType == CallType.INFIX -> {
|
||||
CallType.INFIX -> {
|
||||
if (context.getCompletionChar() == ' ') {
|
||||
context.setAddCompletionChar(false)
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import com.intellij.codeInsight.completion.CompletionResultSet
|
||||
import com.intellij.codeInsight.completion.CompletionSorter
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.idea.completion.*
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
|
||||
@@ -91,7 +91,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
|
||||
// special completion for outside parenthesis lambda argument
|
||||
private fun addFunctionLiteralArgumentCompletions() {
|
||||
if (nameExpression != null) {
|
||||
val (receiverElement, callType) = ReferenceVariantsHelper.getExplicitReceiverData(nameExpression) ?: return
|
||||
val (callType, receiverElement) = CallTypeAndReceiver.detect(nameExpression)
|
||||
if (callType == CallType.INFIX) {
|
||||
val call = (receiverElement as JetExpression).getCall(bindingContext)
|
||||
if (call != null && call.getFunctionLiteralArguments().isEmpty()) {
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
@@ -132,12 +132,9 @@ public class KotlinIndicesHelper(
|
||||
}
|
||||
|
||||
private fun receiverValues(expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection<Pair<ReceiverValue, CallType>> {
|
||||
val receiverData = ReferenceVariantsHelper.getExplicitReceiverData(expression)
|
||||
if (receiverData != null) {
|
||||
val (receiverElement, callType) = receiverData
|
||||
|
||||
if (callType == CallType.CALLABLE_REFERENCE) return emptyList() //TODO?
|
||||
receiverElement as JetExpression
|
||||
val (callType, receiverElement) = CallTypeAndReceiver.detect(expression)
|
||||
if (receiverElement != null) {
|
||||
if (receiverElement !is JetExpression) return emptyList() //TODO?
|
||||
|
||||
val expressionType = bindingContext.getType(receiverElement)
|
||||
if (expressionType == null || expressionType.isError()) return emptyList()
|
||||
@@ -148,7 +145,7 @@ public class KotlinIndicesHelper(
|
||||
}
|
||||
else {
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, expression] ?: return emptyList()
|
||||
return resolutionScope.getImplicitReceiversWithInstance().map { it.getValue() to CallType.NORMAL }
|
||||
return resolutionScope.getImplicitReceiversWithInstance().map { it.getValue() to callType }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user