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 dfef82ca864..2f862a31a55 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 @@ -31,6 +31,9 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.resolve.ImportPath +import org.jetbrains.kotlin.types.typeUtil.TypeNullability +import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean +import org.jetbrains.kotlin.types.typeUtil.nullability import java.util.HashSet object PriorityWeigher : LookupElementWeigher("kotlin.priority") { @@ -186,25 +189,24 @@ class DeclarationRemotenessWeigher(private val file: JetFile) : LookupElementWei } } -class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion) : LookupElementWeigher("kotlin.smartInBasic") { +class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion) : LookupElementWeigher("kotlin.smartInBasic", true, false) { private val descriptorsToSkip = smartCompletion.descriptorsToSkip private val expectedInfos = smartCompletion.expectedInfos - private fun fullMatchWeight(nameSimilarity: Int): Long { - return -((3L shl 32) + nameSimilarity) - } + private fun fullMatchWeight(nameSimilarity: Int) = (3L shl 32) + nameSimilarity * 3 // true and false should be in between zero-nameSimilarity and 1-nameSimilarity - private fun ifNotNullMatchWeight(nameSimilarity: Int): Long { - return -((2L shl 32) + nameSimilarity) - } + private val MATCHED_TRUE_WEIGHT = (3L shl 32) + 2 + private val MATCHED_FALSE_WEIGHT = (3L shl 32) + 1 - private fun smartCompletionItemWeight(nameSimilarity: Int): Long { - return -((1L shl 32) + nameSimilarity) - } + private fun ifNotNullMatchWeight(nameSimilarity: Int) = (2L shl 32) + nameSimilarity + + private fun smartCompletionItemWeight(nameSimilarity: Int) = (1L shl 32) + nameSimilarity + + private val MATCHED_NULL_WEIGHT = 1L private val NO_MATCH_WEIGHT = 0L - private val DESCRIPTOR_TO_SKIP_WEIGHT = 1L // if descriptor is skipped from smart completion then it's probably irrelevant + private val DESCRIPTOR_TO_SKIP_WEIGHT = -1L // if descriptor is skipped from smart completion then it's probably irrelevant override fun weigh(element: LookupElement): Long { val smartCompletionPriority = element.getUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY) @@ -212,13 +214,34 @@ class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion return smartCompletionItemWeight(element.getUserData(NAME_SIMILARITY_KEY) ?: 0) } - // TODO: keywords with type val o = element.`object` if ((o as? DeclarationLookupObject)?.descriptor in descriptorsToSkip) return DESCRIPTOR_TO_SKIP_WEIGHT if (expectedInfos.isEmpty()) return NO_MATCH_WEIGHT + if (o is KeywordLookupObject) { + when (element.lookupString) { + "true", "false" -> { + if (expectedInfos.any { it.fuzzyType?.type?.isBooleanOrNullableBoolean() ?: false }) { + return if (element.lookupString == "true") MATCHED_TRUE_WEIGHT else MATCHED_FALSE_WEIGHT + } + else { + return NO_MATCH_WEIGHT + } + } + + "null" -> { + if (expectedInfos.any { it.fuzzyType?.type?.nullability()?.let { it != TypeNullability.NOT_NULL } ?: false }) { + return MATCHED_NULL_WEIGHT + } + else { + return NO_MATCH_WEIGHT + } + } + } + } + val smartCastCalculator = smartCompletion.smartCastCalculator val (fuzzyTypes, name) = when (o) { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index 75ec10fba44..f5ed6e8ea48 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -184,7 +184,7 @@ class SmartCompletion( LambdaItems.addToCollection(items, expectedInfos) - KeywordValues.addToCollection(items, expectedInfos, expression) //TODO: in ordinary completion? + KeywordValues.addToCollection(items, expectedInfos, expression) } MultipleArgumentsItemProvider(bindingContext, smartCastCalculator).addToCollection(items, expectedInfos, expression) diff --git a/idea/idea-completion/testData/weighers/basic/expectedInfo/Null.kt b/idea/idea-completion/testData/weighers/basic/expectedInfo/Null.kt new file mode 100644 index 00000000000..a49079316ef --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/expectedInfo/Null.kt @@ -0,0 +1,11 @@ +class X + +fun f(x: X?){} + +fun g(nn: Any, np: X) { + f(n) +} + +// ORDER: np +// ORDER: null +// ORDER: nn diff --git a/idea/idea-completion/testData/weighers/basic/expectedInfo/TrueFalse.kt b/idea/idea-completion/testData/weighers/basic/expectedInfo/TrueFalse.kt new file mode 100644 index 00000000000..33719b79a60 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/expectedInfo/TrueFalse.kt @@ -0,0 +1,10 @@ +fun ff(bbb: Boolean){} + +fun g(bbb: Boolean, ccc: Boolean) { + ff() +} + +// ORDER: bbb +// ORDER: true +// ORDER: false +// ORDER: ccc 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 f2191526b91..c3a817fa9d7 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 @@ -217,12 +217,24 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("Null.kt") + public void testNull() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/Null.kt"); + doTest(fileName); + } + @TestMetadata("PreferMatchingThis.kt") public void testPreferMatchingThis() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/PreferMatchingThis.kt"); doTest(fileName); } + @TestMetadata("TrueFalse.kt") + public void testTrueFalse() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/TrueFalse.kt"); + doTest(fileName); + } + @TestMetadata("WhenByEnum.kt") public void testWhenByEnum() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/WhenByEnum.kt");