From 99b35257c670bb0ad29cd227abb6acbcdf23f98c Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 3 Nov 2015 20:54:05 +0300 Subject: [PATCH] Preference of right member after "super." and not only --- .../idea/completion/CompletionSession.kt | 8 +++++ .../kotlin/idea/completion/Weighers.kt | 35 ++++++++++++++++--- .../weighers/basic/DelegateToOtherObject.kt | 23 ++++++++++++ .../testData/weighers/basic/SuperMembers.kt | 17 +++++++++ .../testData/weighers/smart/SuperMembers.kt | 15 ++++++++ .../BasicCompletionWeigherTestGenerated.java | 12 +++++++ .../SmartCompletionWeigherTestGenerated.java | 6 ++++ 7 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 idea/idea-completion/testData/weighers/basic/DelegateToOtherObject.kt create mode 100644 idea/idea-completion/testData/weighers/basic/SuperMembers.kt create mode 100644 idea/idea-completion/testData/weighers/smart/SuperMembers.kt diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index a078ee1c528..94de219ce86 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -250,6 +250,14 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC sorter = sorter.weighAfter("stats", VariableOrFunctionWeigher, ImportedWeigher(importableFqNameClassifier)) + val preferContextElementsWeigher = PreferContextElementsWeigher(inDescriptor) + if (callTypeAndReceiver is CallTypeAndReceiver.SUPER_MEMBERS) { // for completion after "super." strictly prefer the current member + sorter = sorter.weighBefore("kotlin.deprecated", preferContextElementsWeigher) + } + else { + sorter = sorter.weighBefore("kotlin.proximity", preferContextElementsWeigher) + } + sorter = sorter.weighBefore("middleMatching", PreferMatchingItemWeigher) return sorter diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt index c7ca4aad309..41f39bd7008 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/Weighers.kt @@ -23,10 +23,7 @@ import com.intellij.codeInsight.lookup.LookupElementWeigher import com.intellij.codeInsight.lookup.WeighingContext import com.intellij.openapi.util.Key import com.intellij.psi.util.proximity.PsiProximityComparator -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.completion.smart.* import org.jetbrains.kotlin.idea.core.ImportableFqNameClassifier import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject @@ -34,6 +31,8 @@ import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.FuzzyType +import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf +import org.jetbrains.kotlin.resolve.getOriginalTopmostOverriddenDescriptors object PriorityWeigher : LookupElementWeigher("kotlin.priority") { override fun weigh(element: LookupElement, context: WeighingContext) @@ -246,4 +245,32 @@ class SmartCompletionInBasicWeigher( else ifNotNullMatchWeight(nameSimilarity) } +} + +class PreferContextElementsWeigher(private val context: DeclarationDescriptor) : LookupElementWeigher("kotlin.preferContextElements", true, false) { + private val contextElements = context.parentsWithSelf + .takeWhile { it !is PackageFragmentDescriptor } + .toList() + .flatMap { if (it is CallableDescriptor) it.getOriginalTopmostOverriddenDescriptors() else listOf(it) } + .toSet() + private val contextElementNames = contextElements.map { it.name }.toSet() + + override fun weigh(element: LookupElement): Boolean { + val lookupObject = element.`object` as? DeclarationLookupObject ?: return false + val descriptor = lookupObject.descriptor ?: return false + return descriptor.isContextElement() + } + + private fun DeclarationDescriptor.isContextElement(): Boolean { + if (name !in contextElementNames) return false // optimization + + if (this is CallableMemberDescriptor) { + val overridden = this.overriddenDescriptors + if (overridden.isNotEmpty()) { + return overridden.any { it.isContextElement() } + } + } + + return original in contextElements + } } \ No newline at end of file diff --git a/idea/idea-completion/testData/weighers/basic/DelegateToOtherObject.kt b/idea/idea-completion/testData/weighers/basic/DelegateToOtherObject.kt new file mode 100644 index 00000000000..2d00b03e8e1 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/DelegateToOtherObject.kt @@ -0,0 +1,23 @@ +interface I { + fun foo1() + fun foo2() + fun foo3() +} + +abstract class Base1 : I +abstract class Base2 : I + +abstract class A : Base1() { + override fun foo2() { + } +} + +abstract class B(val a: A) : Base2() { + override fun foo2() { + a. + } +} + +// ORDER: foo2 +// ORDER: foo1 +// ORDER: foo3 \ No newline at end of file diff --git a/idea/idea-completion/testData/weighers/basic/SuperMembers.kt b/idea/idea-completion/testData/weighers/basic/SuperMembers.kt new file mode 100644 index 00000000000..8a50eaef4ed --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/SuperMembers.kt @@ -0,0 +1,17 @@ +class B { + open fun foo1(): String = "" + open fun foo2(): String = "" + open fun foo3(): Int = "" +} + +class C : B() { + override fun foo2(): String { + takeInt(super.fo) + } +} + +fun takeInt(p: Int){} + +// ORDER: foo2 +// ORDER: foo3 +// ORDER: foo1 diff --git a/idea/idea-completion/testData/weighers/smart/SuperMembers.kt b/idea/idea-completion/testData/weighers/smart/SuperMembers.kt new file mode 100644 index 00000000000..b06fb5d9b9b --- /dev/null +++ b/idea/idea-completion/testData/weighers/smart/SuperMembers.kt @@ -0,0 +1,15 @@ +class B { + open fun foo1(): String = "" + open fun foo2(): String = "" + open fun foo3(): String = "" +} + +class C : B() { + override fun foo2(): String { + return super.fo + } +} + +// ORDER: foo2 +// ORDER: foo1 +// ORDER: foo3 \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java index 4fc8118f0c3..b27e97ce71b 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java @@ -47,6 +47,12 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("DelegateToOtherObject.kt") + public void testDelegateToOtherObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/DelegateToOtherObject.kt"); + doTest(fileName); + } + @TestMetadata("DeprecatedFun.kt") public void testDeprecatedFun() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/DeprecatedFun.kt"); @@ -143,6 +149,12 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("SuperMembers.kt") + public void testSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/SuperMembers.kt"); + doTest(fileName); + } + @TestMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/SmartCompletionWeigherTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/SmartCompletionWeigherTestGenerated.java index 121722da927..e434b151d84 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/SmartCompletionWeigherTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/SmartCompletionWeigherTestGenerated.java @@ -232,4 +232,10 @@ public class SmartCompletionWeigherTestGenerated extends AbstractSmartCompletion String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/smart/SmartPriority3.kt"); doTest(fileName); } + + @TestMetadata("SuperMembers.kt") + public void testSuperMembers() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/smart/SuperMembers.kt"); + doTest(fileName); + } }