From 97ad0d5c86d1f3fcc8dd1e10bcbbed7352d359dc Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 11 May 2016 19:48:55 +0300 Subject: [PATCH] KT-12124 No code completion for a java property in a specific position #KT-12124 Fixed --- .../org/jetbrains/kotlin/idea/util/Utils.kt | 28 +++++++++++++++++-- .../{KT12124.dependency.java => KT12124.java} | 0 2 files changed, 26 insertions(+), 2 deletions(-) rename idea/idea-completion/testData/basic/multifile/KT12124/{KT12124.dependency.java => KT12124.java} (100%) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt index 0ebd9af7caa..2e37c053ef9 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.types.Flexibility import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.checker.KotlinTypeChecker @@ -58,8 +59,31 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded( containingDeclarationOrModule: DeclarationDescriptor, dataFlowInfo: DataFlowInfo ): List { - val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo).distinct() + val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo) return variants.filter { type -> - variants.none { another -> another !== type && KotlinTypeChecker.DEFAULT.isSubtypeOf(another, type) } + variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } } + } +} + +private fun chooseMoreSpecific(type1: KotlinType, type2: KotlinType): KotlinType? { + val type1IsSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(type1, type2) + val type2IsSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(type2, type1) + + when { + type1IsSubtype && !type2IsSubtype -> return type1 + + type2IsSubtype && !type1IsSubtype -> return type2 + + !type1IsSubtype && !type2IsSubtype -> return null + + else -> { // type1IsSubtype && type2IsSubtype + val flexibility1 = type1.getCapability(Flexibility::class.java) + val flexibility2 = type2.getCapability(Flexibility::class.java) + when { + flexibility1 != null && flexibility2 == null -> return type2 + flexibility2 != null && flexibility1 == null -> return type1 + else -> return null //TODO? + } + } } } diff --git a/idea/idea-completion/testData/basic/multifile/KT12124/KT12124.dependency.java b/idea/idea-completion/testData/basic/multifile/KT12124/KT12124.java similarity index 100% rename from idea/idea-completion/testData/basic/multifile/KT12124/KT12124.dependency.java rename to idea/idea-completion/testData/basic/multifile/KT12124/KT12124.java