No callable references to synthetic extensions (and ones for get/set)
This commit is contained in:
@@ -143,6 +143,8 @@ public class DescriptorKindFilter(
|
||||
return DescriptorKindFilter(mask, excludes)
|
||||
}
|
||||
|
||||
public fun intersect(other: DescriptorKindFilter) = DescriptorKindFilter(kindMask and other.kindMask, excludes + other.excludes)
|
||||
|
||||
override fun toString(): String {
|
||||
val predefinedFilterName = DEBUG_PREDEFINED_FILTERS_MASK_NAMES.firstOrNull { it.mask == kindMask } ?.name
|
||||
val kindString = predefinedFilterName ?: DEBUG_MASK_BIT_NAMES
|
||||
|
||||
+19
-23
@@ -86,6 +86,11 @@ public class ReferenceVariantsHelper(
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
|
||||
useRuntimeReceiverType: Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val callType = callTypeAndReceiver.callType
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val kindFilter = kindFilter.intersect(callType.descriptorKindFilter)
|
||||
|
||||
val receiverExpression: JetExpression?
|
||||
when (callTypeAndReceiver) {
|
||||
is CallTypeAndReceiver.IMPORT_DIRECTIVE -> {
|
||||
@@ -93,8 +98,7 @@ public class ReferenceVariantsHelper(
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.PACKAGE_DIRECTIVE -> {
|
||||
val packageKindFilter = kindFilter restrictedToKinds DescriptorKindFilter.PACKAGES_MASK
|
||||
return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, packageKindFilter, nameFilter)
|
||||
return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
is CallTypeAndReceiver.TYPE -> {
|
||||
@@ -124,15 +128,12 @@ public class ReferenceVariantsHelper(
|
||||
return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, implicitReceiverTypes, kindFilter, nameFilter)
|
||||
}
|
||||
|
||||
val callType = callTypeAndReceiver.callType
|
||||
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression]
|
||||
if (qualifier != null) {
|
||||
// It's impossible to add extension function for package or class (if it's companion object, expression type is not null)
|
||||
qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors) { callType.canCall(it) }
|
||||
descriptors.addAll(qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter))
|
||||
}
|
||||
|
||||
val expressionType = if (useRuntimeReceiverType)
|
||||
@@ -163,16 +164,15 @@ public class ReferenceVariantsHelper(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val accurateKindFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK)
|
||||
if (receiverExpression != null) {
|
||||
val qualifier = context[BindingContext.QUALIFIER, receiverExpression] ?: return emptyList()
|
||||
return qualifier.scope.getDescriptorsFiltered(accurateKindFilter, nameFilter)
|
||||
return qualifier.scope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
else {
|
||||
val lexicalScope = expression.getParentOfType<JetTypeReference>(strict = true)?.let {
|
||||
context[BindingContext.LEXICAL_SCOPE, it]
|
||||
} ?: return emptyList()
|
||||
return lexicalScope.getDescriptorsFiltered(accurateKindFilter, nameFilter)
|
||||
return lexicalScope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,23 +183,21 @@ public class ReferenceVariantsHelper(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val accurateKindFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.CALLABLES.kindMask)
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
if (qualifierTypeRef != null) {
|
||||
val type = context[BindingContext.TYPE, qualifierTypeRef] ?: return emptyList()
|
||||
|
||||
descriptors.addNonExtensionMembers(listOf(type), CallType.CALLABLE_REFERENCE, accurateKindFilter, nameFilter, constructorsForInnerClassesOnly = false)
|
||||
descriptors.addNonExtensionMembers(listOf(type), kindFilter, nameFilter, constructorsForInnerClassesOnly = false)
|
||||
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, listOf(type), CallType.CALLABLE_REFERENCE, accurateKindFilter, nameFilter)
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, listOf(type), CallType.CALLABLE_REFERENCE, kindFilter, nameFilter)
|
||||
}
|
||||
else {
|
||||
// process non-instance members and class constructors
|
||||
descriptors.addNonExtensionCallablesAndConstructors(resolutionScope, CallType.CALLABLE_REFERENCE, kindFilter, nameFilter, constructorsForInnerClassesOnly = false)
|
||||
descriptors.addNonExtensionCallablesAndConstructors(resolutionScope, kindFilter, nameFilter, constructorsForInnerClassesOnly = false)
|
||||
|
||||
descriptors.addNonExtensionMembers(implicitReceiverTypes, CallType.CALLABLE_REFERENCE, accurateKindFilter, nameFilter, constructorsForInnerClassesOnly = true)
|
||||
descriptors.addNonExtensionMembers(implicitReceiverTypes, kindFilter, nameFilter, constructorsForInnerClassesOnly = true)
|
||||
|
||||
//TODO: should we show synthetic extensions? get/set's?
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, implicitReceiverTypes, CallType.CALLABLE_REFERENCE, accurateKindFilter, nameFilter)
|
||||
descriptors.addScopeAndSyntheticExtensions(resolutionScope, implicitReceiverTypes, CallType.CALLABLE_REFERENCE, kindFilter, nameFilter)
|
||||
}
|
||||
return descriptors
|
||||
}
|
||||
@@ -227,7 +225,7 @@ public class ReferenceVariantsHelper(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
) {
|
||||
addNonExtensionMembers(receiverTypes, callType, kindFilter, nameFilter, constructorsForInnerClassesOnly = true)
|
||||
addNonExtensionMembers(receiverTypes, kindFilter, nameFilter, constructorsForInnerClassesOnly = true)
|
||||
addMemberExtensions(implicitReceiverTypes, receiverTypes, callType, kindFilter, nameFilter)
|
||||
addScopeAndSyntheticExtensions(resolutionScope, receiverTypes, callType, kindFilter, nameFilter)
|
||||
}
|
||||
@@ -249,24 +247,22 @@ public class ReferenceVariantsHelper(
|
||||
|
||||
private fun MutableSet<DeclarationDescriptor>.addNonExtensionMembers(
|
||||
receiverTypes: Collection<JetType>,
|
||||
callType: CallType<*>,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
constructorsForInnerClassesOnly: Boolean
|
||||
) {
|
||||
for (receiverType in receiverTypes) {
|
||||
addNonExtensionCallablesAndConstructors(receiverType.memberScope, callType, kindFilter, nameFilter, constructorsForInnerClassesOnly)
|
||||
addNonExtensionCallablesAndConstructors(receiverType.memberScope, kindFilter, nameFilter, constructorsForInnerClassesOnly)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableSet<DeclarationDescriptor>.addNonExtensionCallablesAndConstructors(
|
||||
scope: JetScope,
|
||||
callType: CallType<*>,
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
constructorsForInnerClassesOnly: Boolean
|
||||
) {
|
||||
var filterToUse = kindFilter.restrictedToKinds(DescriptorKindFilter.CALLABLES.kindMask).exclude(DescriptorKindExclude.Extensions)
|
||||
var filterToUse = DescriptorKindFilter(kindFilter.kindMask and DescriptorKindFilter.CALLABLES.kindMask).exclude(DescriptorKindExclude.Extensions)
|
||||
|
||||
// should process classes if we need constructors
|
||||
if (filterToUse.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) {
|
||||
@@ -277,9 +273,9 @@ public class ReferenceVariantsHelper(
|
||||
if (descriptor is ClassDescriptor) {
|
||||
if (constructorsForInnerClassesOnly && !descriptor.isInner) continue
|
||||
if (descriptor.modality == Modality.ABSTRACT || descriptor.modality == Modality.SEALED) continue
|
||||
descriptor.constructors.filterTo(this) { callType.canCall(it) && kindFilter.accepts(it) }
|
||||
descriptor.constructors.filterTo(this) { kindFilter.accepts(it) }
|
||||
}
|
||||
else if (callType.canCall(descriptor) && kindFilter.accepts(descriptor)) {
|
||||
else if (kindFilter.accepts(descriptor)) {
|
||||
this.add(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,47 +16,62 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
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.scopes.DescriptorKindExclude
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
|
||||
public sealed class CallType<TReceiver : JetElement?> {
|
||||
object DEFAULT : CallType<Nothing?>()
|
||||
public sealed class CallType<TReceiver : JetElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
||||
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
||||
|
||||
object DOT : CallType<JetExpression>()
|
||||
object DOT : CallType<JetExpression>(DescriptorKindFilter.ALL)
|
||||
|
||||
object SAFE : CallType<JetExpression>()
|
||||
object SAFE : CallType<JetExpression>(DescriptorKindFilter.ALL)
|
||||
|
||||
object INFIX : CallType<JetExpression>() {
|
||||
override fun canCall(descriptor: DeclarationDescriptor)
|
||||
= descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size() == 1
|
||||
object INFIX : CallType<JetExpression>(DescriptorKindFilter.FUNCTIONS exclude NonInfixExclude)
|
||||
|
||||
object UNARY : CallType<JetExpression>(DescriptorKindFilter.FUNCTIONS exclude NonUnaryExclude)
|
||||
|
||||
object CALLABLE_REFERENCE : CallType<JetTypeReference?>(DescriptorKindFilter.CALLABLES exclude LocalsAndSyntheticExclude/* currently not supported for locals and synthetic */)
|
||||
|
||||
object IMPORT_DIRECTIVE : CallType<JetExpression?>(DescriptorKindFilter.ALL)
|
||||
|
||||
object PACKAGE_DIRECTIVE : CallType<JetExpression?>(DescriptorKindFilter.PACKAGES)
|
||||
|
||||
object TYPE : CallType<JetExpression?>(DescriptorKindFilter(DescriptorKindFilter.CLASSIFIERS_MASK or DescriptorKindFilter.PACKAGES_MASK))
|
||||
|
||||
private object NonInfixExclude : DescriptorKindExclude {
|
||||
//TODO: check 'infix' modifier
|
||||
override fun excludes(descriptor: DeclarationDescriptor) =
|
||||
!(descriptor is SimpleFunctionDescriptor && descriptor.valueParameters.size() == 1)
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int
|
||||
get() = 0
|
||||
}
|
||||
|
||||
object UNARY : CallType<JetExpression>() {
|
||||
override fun canCall(descriptor: DeclarationDescriptor)
|
||||
= descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size() == 0
|
||||
private object NonUnaryExclude : DescriptorKindExclude {
|
||||
//TODO: check 'operator' modifier
|
||||
override fun excludes(descriptor: DeclarationDescriptor) =
|
||||
!(descriptor is SimpleFunctionDescriptor && descriptor.valueParameters.isEmpty())
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int
|
||||
get() = 0
|
||||
}
|
||||
|
||||
object CALLABLE_REFERENCE : CallType<JetTypeReference?>() {
|
||||
// currently callable references to locals and parameters are not supported
|
||||
override fun canCall(descriptor: DeclarationDescriptor)
|
||||
= descriptor is FunctionDescriptor || descriptor is PropertyDescriptor
|
||||
private object LocalsAndSyntheticExclude : DescriptorKindExclude {
|
||||
override fun excludes(descriptor: DeclarationDescriptor)
|
||||
= descriptor !is CallableMemberDescriptor || descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
|
||||
override val fullyExcludedDescriptorKinds: Int
|
||||
get() = 0
|
||||
}
|
||||
|
||||
//TODO: canCall
|
||||
object IMPORT_DIRECTIVE : CallType<JetExpression?>()
|
||||
|
||||
object PACKAGE_DIRECTIVE : CallType<JetExpression?>()
|
||||
|
||||
object TYPE : CallType<JetExpression?>()
|
||||
|
||||
public open fun canCall(descriptor: DeclarationDescriptor): Boolean = true
|
||||
}
|
||||
|
||||
public sealed class CallTypeAndReceiver<TReceiver : JetElement?, TCallType : CallType<TReceiver>>(
|
||||
|
||||
@@ -76,7 +76,7 @@ public fun CallableDescriptor.substituteExtensionIfCallable(
|
||||
receiverTypes: Collection<JetType>,
|
||||
callType: CallType<*>
|
||||
): Collection<CallableDescriptor> {
|
||||
if (!callType.canCall(this)) return listOf()
|
||||
if (!callType.descriptorKindFilter.accepts(this)) return listOf()
|
||||
|
||||
var types = receiverTypes.asSequence()
|
||||
if (callType == CallType.SAFE) {
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@ import java.io.File
|
||||
|
||||
val v = File::<caret>
|
||||
|
||||
// EXIST_JAVA_ONLY: { itemText: "freeSpace", tailText: " (from getFreeSpace())", attributes: "bold" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: " (from isFile())", attributes: "bold" }
|
||||
// ABSENT: { itemText: "isFile", tailText: "()" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "getFreeSpace", tailText: "()", attributes: "bold" }
|
||||
// ABSENT: freeSpace
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: "()", attributes: "bold" }
|
||||
// ABSENT: { itemText: "isFile", tailText: " (from isFile())" }
|
||||
|
||||
+4
-3
@@ -4,6 +4,7 @@ class MyFile : File("") {
|
||||
val v = ::<caret>
|
||||
}
|
||||
|
||||
// EXIST_JAVA_ONLY: { itemText: "freeSpace", tailText: " (from getFreeSpace())", attributes: "" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: " (from isFile())", attributes: "" }
|
||||
// ABSENT: { itemText: "isFile", tailText: "()" }
|
||||
// EXIST_JAVA_ONLY: { itemText: "getFreeSpace", tailText: "()", attributes: "" }
|
||||
// ABSENT: freeSpace
|
||||
// EXIST_JAVA_ONLY: { itemText: "isFile", tailText: "()", attributes: "" }
|
||||
// ABSENT: { itemText: "isFile", tailText: " (from isFile())" }
|
||||
|
||||
Reference in New Issue
Block a user