From e04c6d1f5cab40aa0a32848b8abbcb89c6617491 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 12 May 2016 22:55:53 +0300 Subject: [PATCH] KT-12299 Completion: incorrect priority of property foo over method getFoo in Kotlin-only code #KT-12299 Fixed --- .../kotlin/idea/completion/CompletionSession.kt | 10 +++++++++- .../jetbrains/kotlin/idea/completion/Weighers.kt | 13 +++++++++++++ .../basic/PreferGetMethodToProperty.Data.kt | 5 +++++ .../weighers/basic/PreferGetMethodToProperty.kt | 16 ++++++++++++++++ .../weighers/smart/StaticMemberAndPrefix.kt | 10 ++++++++++ .../BasicCompletionWeigherTestGenerated.java | 6 ++++++ .../SmartCompletionWeigherTestGenerated.java | 6 ++++++ 7 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.Data.kt create mode 100644 idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.kt create mode 100644 idea/idea-completion/testData/weighers/smart/StaticMemberAndPrefix.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 695b8cbbf5b..2acd3773a28 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 @@ -22,8 +22,10 @@ import com.intellij.codeInsight.completion.CompletionSorter import com.intellij.codeInsight.completion.CompletionUtil import com.intellij.codeInsight.completion.impl.CamelHumpMatcher import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.patterns.PatternCondition import com.intellij.patterns.StandardPatterns import com.intellij.psi.search.GlobalSearchScope +import com.intellij.util.ProcessingContext import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.* import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper @@ -221,6 +223,12 @@ abstract class CompletionSession( } fun complete(): Boolean { + // we restart completion when prefix becomes "get" or "set" to ensure that properties get lower priority comparing to get/set functions (see KT-12299) + val prefixPattern = StandardPatterns.string().with(object : PatternCondition("get or set prefix") { + override fun accepts(prefix: String, context: ProcessingContext?) = prefix == "get" || prefix == "set" + }) + collector.restartCompletionOnPrefixChange(prefixPattern) + val statisticsContext = calcContextForStatisticsInfo() if (statisticsContext != null) { collector.addLookupElementPostProcessor { lookupElement -> @@ -250,7 +258,7 @@ abstract class CompletionSession( protected open fun createSorter(): CompletionSorter { var sorter = CompletionSorter.defaultSorter(parameters, prefixMatcher)!! - sorter = sorter.weighBefore("stats", DeprecatedWeigher, PriorityWeigher, + sorter = sorter.weighBefore("stats", DeprecatedWeigher, PriorityWeigher, PreferGetSetMethodsToPropertyWeigher, NotImportedWeigher(importableFqNameClassifier), NotImportedStaticMemberWeigher(importableFqNameClassifier), KindWeigher, CallableWeigher) 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 b67ccb88104..5cae7296712 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 @@ -155,6 +155,19 @@ object VariableOrFunctionWeigher : LookupElementWeigher("kotlin.variableOrFuncti } } +/** + * Decreases priority of properties when prefix starts with "get" or "set" (and the property name does not) + */ +object PreferGetSetMethodsToPropertyWeigher : LookupElementWeigher("kotlin.preferGetSetMethodsToProperty", false, true){ + override fun weigh(element: LookupElement, context: WeighingContext): Int { + val property = (element.`object` as? DeclarationLookupObject)?.descriptor as? PropertyDescriptor ?: return 0 + val prefixMatcher = context.itemMatcher(element) + if (prefixMatcher.prefixMatches(property.name.asString())) return 0 + val matchedLookupStrings = element.allLookupStrings.filter { prefixMatcher.prefixMatches(it) } + if (matchedLookupStrings.all { it.startsWith("get") || it.startsWith("set") }) return 1 else return 0 + } +} + object DeprecatedWeigher : LookupElementWeigher("kotlin.deprecated") { override fun weigh(element: LookupElement): Int { val o = element.`object` as? DeclarationLookupObject ?: return 0 diff --git a/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.Data.kt b/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.Data.kt new file mode 100644 index 00000000000..84485a61f38 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.Data.kt @@ -0,0 +1,5 @@ +package dependency + +import test.A + +fun A.getFaa() = 1 diff --git a/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.kt b/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.kt new file mode 100644 index 00000000000..804b8e630e4 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.kt @@ -0,0 +1,16 @@ +package test + +class A { + val foo = 42 + + fun getFoo() = "" + + fun test() { + getF + } + +} + +// ORDER: getFoo +// ORDER: getFaa +// ORDER: foo \ No newline at end of file diff --git a/idea/idea-completion/testData/weighers/smart/StaticMemberAndPrefix.kt b/idea/idea-completion/testData/weighers/smart/StaticMemberAndPrefix.kt new file mode 100644 index 00000000000..9bfb3adb38d --- /dev/null +++ b/idea/idea-completion/testData/weighers/smart/StaticMemberAndPrefix.kt @@ -0,0 +1,10 @@ +interface Z { + companion object { + val instance: Z? = null + } +} + +fun foo(): Z? = Z + +// ORDER: instance +// ORDER: object \ 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 b1ecee1ae41..23553d48674 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 @@ -161,6 +161,12 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("PreferGetMethodToProperty.kt") + public void testPreferGetMethodToProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/PreferGetMethodToProperty.kt"); + doTest(fileName); + } + @TestMetadata("PropertiesBeforeKeywords.kt") public void testPropertiesBeforeKeywords() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/PropertiesBeforeKeywords.kt"); 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 8e7dad0a769..33190e8d545 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 @@ -245,6 +245,12 @@ public class SmartCompletionWeigherTestGenerated extends AbstractSmartCompletion doTest(fileName); } + @TestMetadata("StaticMemberAndPrefix.kt") + public void testStaticMemberAndPrefix() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/smart/StaticMemberAndPrefix.kt"); + doTest(fileName); + } + @TestMetadata("SuperMembers.kt") public void testSuperMembers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/smart/SuperMembers.kt");