From 000d2f0cd13308853524aa1d4a6d52be6442e76f Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 12 Aug 2015 22:29:07 +0300 Subject: [PATCH] Lower priority for extensions on own type parameters --- .../kotlin/idea/completion/CompletionUtils.kt | 1 + .../idea/completion/LookupElementFactory.kt | 21 +++++++++++++++---- .../basic/common/NonPredictableSmartCast.kt | 2 +- .../ImmediateExtensionMembersGeneric.kt | 11 ++++++++++ .../testData/weighers/basic/Callables.kt | 11 ++++++---- .../testData/weighers/smart/SmartPriority.kt | 2 +- .../test/JSBasicCompletionTestGenerated.java | 6 ++++++ .../test/JvmBasicCompletionTestGenerated.java | 6 ++++++ 8 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index f018ce9fb6b..3e0185f0ae0 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -135,6 +135,7 @@ enum class CallableWeight { thisTypeExtension, baseTypeExtension, globalOrStatic, // global non-extension + typeParameterExtension, receiverCastRequired } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index bca88cf5c9d..24bd0cc72ea 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -334,12 +334,19 @@ public class LookupElementFactory( val receiverParameter = descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter if (receiverParameter != null) { - return if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParameter.type) }) - if (descriptor.isExtension) CallableWeight.thisTypeExtension else CallableWeight.thisClassMember - else if (receiverTypes.any { it.isSubtypeOf(receiverParameter.type) }) + return if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParameter.type) }) { + when { + descriptor.isExtensionForTypeParameter() -> CallableWeight.typeParameterExtension + descriptor.isExtension -> CallableWeight.thisTypeExtension + else -> CallableWeight.thisClassMember + } + } + else if (receiverTypes.any { it.isSubtypeOf(receiverParameter.type) }) { if (descriptor.isExtension) CallableWeight.baseTypeExtension else CallableWeight.baseClassMember - else + } + else { CallableWeight.receiverCastRequired + } } return when (descriptor.containingDeclaration) { @@ -348,6 +355,12 @@ public class LookupElementFactory( } } + private fun CallableDescriptor.isExtensionForTypeParameter(): Boolean { + val receiverParameter = original.extensionReceiverParameter ?: return false + val typeParameter = receiverParameter.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false + return typeParameter.containingDeclaration == original + } + companion object { public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler { return when (descriptor) { diff --git a/idea/idea-completion/testData/basic/common/NonPredictableSmartCast.kt b/idea/idea-completion/testData/basic/common/NonPredictableSmartCast.kt index 57d2508257c..5c9a3f2400e 100644 --- a/idea/idea-completion/testData/basic/common/NonPredictableSmartCast.kt +++ b/idea/idea-completion/testData/basic/common/NonPredictableSmartCast.kt @@ -12,4 +12,4 @@ fun f(pair: Pair) { // EXIST: { lookupString: "hashCode", attributes: "bold" } // EXIST: { lookupString: "forString", attributes: "grayed" } // EXIST: { lookupString: "forAny", attributes: "bold" } -// EXIST: { lookupString: "forT", attributes: "bold" } +// EXIST: { lookupString: "forT", attributes: "" } diff --git a/idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt b/idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt new file mode 100644 index 00000000000..560520bc33d --- /dev/null +++ b/idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt @@ -0,0 +1,11 @@ +fun List.forListT(){} +fun Collection.forCollectionT(){} +fun T.forT() {} + +fun foo(list: List) { + list. +} + +// EXIST: { itemText: "forListT", attributes: "bold" } +// EXIST: { itemText: "forCollectionT", attributes: "" } +// EXIST: { itemText: "forT", attributes: "" } diff --git a/idea/idea-completion/testData/weighers/basic/Callables.kt b/idea/idea-completion/testData/weighers/basic/Callables.kt index c925c28d9d2..1ed734ed68a 100644 --- a/idea/idea-completion/testData/weighers/basic/Callables.kt +++ b/idea/idea-completion/testData/weighers/basic/Callables.kt @@ -18,12 +18,14 @@ class Derived : Base() { } } -fun Any.aAnyExtensionFun(){} +fun Any.aaAnyExtensionFun(){} fun Derived.aaExtensionFun(){} -val Any.aAnyExtensionProp: Int get() = 1 +val Any.aaAnyExtensionProp: Int get() = 1 val Derived.aaExtensionProp: Int get() = 1 +fun T.aaTypeParamExt(){} + // ORDER: aaLocalVal // ORDER: aaLocalFun // ORDER: aaDerivedProp @@ -32,7 +34,8 @@ val Derived.aaExtensionProp: Int get() = 1 // ORDER: aaBaseFun // ORDER: aaExtensionProp // ORDER: aaExtensionFun -// ORDER: aAnyExtensionProp -// ORDER: aAnyExtensionFun +// ORDER: aaAnyExtensionProp +// ORDER: aaAnyExtensionFun // ORDER: aaGlobalProp // ORDER: aaGlobalFun +// ORDER: aaTypeParamExt diff --git a/idea/idea-completion/testData/weighers/smart/SmartPriority.kt b/idea/idea-completion/testData/weighers/smart/SmartPriority.kt index 222f72095ab..366f4fba05d 100644 --- a/idea/idea-completion/testData/weighers/smart/SmartPriority.kt +++ b/idea/idea-completion/testData/weighers/smart/SmartPriority.kt @@ -16,8 +16,8 @@ class C { // ORDER: "pFoo, s" // ORDER: this // ORDER: local -// ORDER: apply // ORDER: nonNullable +// ORDER: apply // ORDER: nullableX // ORDER: nullableX // ORDER: C diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index f86e4b0cbfb..ef19fede95e 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1425,6 +1425,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("ImmediateExtensionMembersGeneric.kt") + public void testImmediateExtensionMembersGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt"); + doTest(fileName); + } + @TestMetadata("ImmediateMembers1.kt") public void testImmediateMembers1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/immediateMembers/ImmediateMembers1.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 67e2363c86b..507b46a1aa4 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1425,6 +1425,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("ImmediateExtensionMembersGeneric.kt") + public void testImmediateExtensionMembersGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/immediateMembers/ImmediateExtensionMembersGeneric.kt"); + doTest(fileName); + } + @TestMetadata("ImmediateMembers1.kt") public void testImmediateMembers1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/immediateMembers/ImmediateMembers1.kt");