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