diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index 6f279e2cc94..50ed2aa717b 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -100,10 +100,9 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, else null - private val smartCastCalculator = if (expression != null) - SmartCastCalculator(bindingContext, moduleDescriptor, expression) - else - null + private val smartCompletion = expression?.let { + SmartCompletion(it, resolutionFacade, moduleDescriptor, bindingContext, isVisibleFilter, inDescriptor, prefixMatcher, GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory) + } private fun calcCompletionKind(): CompletionKind { if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) { @@ -252,12 +251,9 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } if (completionKind != CompletionKind.KEYWORDS_ONLY) { - if (expectedInfos != null && expectedInfos.isNotEmpty()) { + if (smartCompletion != null && expectedInfos != null && expectedInfos.isNotEmpty()) { @suppress("UNUSED_VARIABLE") // we don't use InheritanceSearcher - val (additionalItems, inheritanceSearcher) = SmartCompletion( - expression!!, resolutionFacade, moduleDescriptor, bindingContext, isVisibleFilter, inDescriptor, - prefixMatcher, GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, lookupElementFactory) - .additionalItems(expectedInfos, smartCastCalculator!!, forOrdinaryCompletion = true) + val (additionalItems, inheritanceSearcher) = smartCompletion.additionalItems(expectedInfos, forOrdinaryCompletion = true) collector.addElements(additionalItems) } @@ -304,8 +300,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, sorter = sorter.weighBefore(DeprecatedWeigher.toString(), ParameterNameAndTypeCompletion.Weigher) } - if (expectedInfos != null && expectedInfos.isNotEmpty()) { - sorter = sorter.weighBefore(KindWeigher.toString(), ExpectedInfoMatchWeigher(expectedInfos, smartCastCalculator!!), SmartCompletionPriorityWeigher) + if (smartCompletion != null && expectedInfos != null && expectedInfos.isNotEmpty()) { + sorter = sorter.weighBefore(KindWeigher.toString(), ExpectedInfoMatchWeigher(expectedInfos, smartCompletion), SmartCompletionPriorityWeigher) } 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 4f34f367fdc..f238b53824b 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 @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementWeigher import com.intellij.codeInsight.lookup.WeighingContext +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.idea.completion.smart.* @@ -70,6 +72,7 @@ object KindWeigher : LookupElementWeigher("kotlin.kind") { when (descriptor) { is VariableDescriptor -> CompoundWeight(Weight.variable, element.getUserData(CALLABLE_WEIGHT_KEY)) is FunctionDescriptor -> CompoundWeight(Weight.function, element.getUserData(CALLABLE_WEIGHT_KEY)) + is ClassDescriptor -> if (descriptor.kind == ClassKind.ENUM_ENTRY) CompoundWeight(Weight.variable) else CompoundWeight(Weight.default) else -> CompoundWeight(Weight.default) } } @@ -185,9 +188,12 @@ class DeclarationRemotenessWeigher(private val file: JetFile) : LookupElementWei class ExpectedInfoMatchWeigher( private val expectedInfos: Collection, - private val smartCastCalculator: SmartCastCalculator + private val smartCompletion: SmartCompletion ) : LookupElementWeigher("kotlin.expectedInfoMatch") { + private val smartCastCalculator = smartCompletion.smartCastCalculator + private val descriptorsToSkip = smartCompletion.descriptorsToSkip + private fun fullMatchWeight(nameSimilarity: Int): Long { return -((3L shl 32) + nameSimilarity) } @@ -202,6 +208,8 @@ class ExpectedInfoMatchWeigher( 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 + override fun weigh(element: LookupElement): Long { val smartCompletionPriority = element.getUserData(SMART_COMPLETION_ITEM_PRIORITY_KEY) if (smartCompletionPriority != null) { // it's an "additional item" came from smart completion, don't match it against expected type @@ -213,6 +221,7 @@ class ExpectedInfoMatchWeigher( val (fuzzyTypes, name) = when (o) { is DeclarationLookupObject -> { val descriptor = o.descriptor ?: return NO_MATCH_WEIGHT + if (descriptor in descriptorsToSkip) return DESCRIPTOR_TO_SKIP_WEIGHT descriptor.fuzzyTypesForSmartCompletion(smartCastCalculator) to descriptor.name } 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 13860effaa3..36266b9ff1d 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 @@ -61,6 +61,8 @@ class SmartCompletion( ) { private val receiver = if (expression is JetSimpleNameExpression) expression.getReceiverExpression() else null + public val smartCastCalculator: SmartCastCalculator = SmartCastCalculator(bindingContext, moduleDescriptor, expression) + public class Result( val declarationFilter: ((DeclarationDescriptor) -> Collection)?, val additionalItems: Collection, @@ -108,11 +110,8 @@ class SmartCompletion( val asTypePositionResult = buildForAsTypePosition() if (asTypePositionResult != null) return asTypePositionResult - val expressionWithType = expression.toExpressionWithType() - - val expectedInfos = calcExpectedInfos(expressionWithType) ?: return null - - val smartCastCalculator = SmartCastCalculator(bindingContext, moduleDescriptor, expression) + val expectedInfos = calcExpectedInfos(expression.toExpressionWithType()) + if (expectedInfos == null || expectedInfos.isEmpty()) return null fun filterDeclaration(descriptor: DeclarationDescriptor): Collection { if (descriptor in descriptorsToSkip) return emptyList() @@ -138,14 +137,13 @@ class SmartCompletion( return result } - val (additionalItems, inheritanceSearcher) = additionalItems(expectedInfos, smartCastCalculator) + val (additionalItems, inheritanceSearcher) = additionalItems(expectedInfos) return Result(::filterDeclaration, additionalItems, inheritanceSearcher) } public fun additionalItems( expectedInfos: Collection, - smartCastCalculator: SmartCastCalculator, forOrdinaryCompletion: Boolean = false ): Pair, InheritanceItemsSearcher?> { val items = ArrayList() diff --git a/idea/idea-completion/testData/weighers/basic/expectedInfo/EnumEntries.kt b/idea/idea-completion/testData/weighers/basic/expectedInfo/EnumEntries.kt index 2af414f82ea..65fa396db02 100644 --- a/idea/idea-completion/testData/weighers/basic/expectedInfo/EnumEntries.kt +++ b/idea/idea-completion/testData/weighers/basic/expectedInfo/EnumEntries.kt @@ -7,7 +7,7 @@ fun foo(): EE { return E } -// ORDER: valueOf // ORDER: A // ORDER: B +// ORDER: valueOf // ORDER: EE diff --git a/idea/idea-completion/testData/weighers/basic/expectedInfo/NoStupidComparison.kt b/idea/idea-completion/testData/weighers/basic/expectedInfo/NoStupidComparison.kt new file mode 100644 index 00000000000..ad48b621c30 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/expectedInfo/NoStupidComparison.kt @@ -0,0 +1,7 @@ +class X + +fun foo(aaa: X, bbb: X) { + if (aaa == ) +} + +// ORDER: bbb diff --git a/idea/idea-completion/testData/weighers/basic/expectedInfo/WhenByEnum.kt b/idea/idea-completion/testData/weighers/basic/expectedInfo/WhenByEnum.kt new file mode 100644 index 00000000000..df40d98f73c --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/expectedInfo/WhenByEnum.kt @@ -0,0 +1,19 @@ +enum class E { + A, + B, + C +} + +fun foo(e: E) { + when (e) { + E.A -> {} + + E. + } +} + +// ORDER: B +// ORDER: C +// ORDER: valueOf +// ORDER: values +// ORDER: A 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 1bfd1b46cef..5308f8ee4ae 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 @@ -199,11 +199,23 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("NoStupidComparison.kt") + public void testNoStupidComparison() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/NoStupidComparison.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("WhenByEnum.kt") + public void testWhenByEnum() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/weighers/basic/expectedInfo/WhenByEnum.kt"); + doTest(fileName); + } } @TestMetadata("idea/idea-completion/testData/weighers/basic/parameterNameAndType")