KT-12299 Completion: incorrect priority of property foo over method getFoo in Kotlin-only code

#KT-12299 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-05-12 22:55:53 +03:00
parent 97ad0d5c86
commit e04c6d1f5c
7 changed files with 65 additions and 1 deletions
@@ -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<String>("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)
@@ -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
@@ -0,0 +1,5 @@
package dependency
import test.A
fun A.getFaa() = 1
@@ -0,0 +1,16 @@
package test
class A {
val foo = 42
fun getFoo() = ""
fun test() {
getF<caret>
}
}
// ORDER: getFoo
// ORDER: getFaa
// ORDER: foo
@@ -0,0 +1,10 @@
interface Z {
companion object {
val instance: Z? = null
}
}
fun foo(): Z? = Z<caret>
// ORDER: instance
// ORDER: object
@@ -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");
@@ -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");