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 ae1e77812c4..b59638dcaea 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 @@ -127,27 +127,35 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) } + protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) } + protected val lookupElementFactory: LookupElementFactory = run { - val receiverTypes = if (reference != null) { - val expression = reference.expression - val (receivers, callType) = referenceVariantsHelper.getReferenceVariantsReceivers(expression) + if (receiversData != null) { val dataFlowInfo = bindingContext.getDataFlowInfo(expression) - var receiverTypes = receivers.flatMap { + + var receiverTypes = receiversData.receivers.flatMap { SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, moduleDescriptor, dataFlowInfo) } - if (callType == CallType.SAFE) { + + if (receiversData.callType == CallType.SAFE) { receiverTypes = receiverTypes.map { it.makeNotNullable() } } - receiverTypes + + LookupElementFactory(receiverTypes) } else { - listOf() + LookupElementFactory(emptyList()) } - LookupElementFactory(receiverTypes) } - protected val collector: LookupElementsCollector = LookupElementsCollector( - prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, expression?.getParent() is JetSimpleNameStringTemplateEntry) + private val collectorContext = if (expression?.getParent() is JetSimpleNameStringTemplateEntry) + LookupElementsCollector.Context.STRING_TEMPLATE_AFTER_DOLLAR + else if (receiversData?.callType == CallType.INFIX) + LookupElementsCollector.Context.INFIX_CALL + else + LookupElementsCollector.Context.NORMAL + + protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, collectorContext) protected val project: Project = position.getProject() diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index e9e6e479a67..bc3721cd6a4 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler import org.jetbrains.kotlin.idea.util.FuzzyType +import org.jetbrains.kotlin.idea.util.fuzzyReturnType import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt index 2a109cd11fc..4295d0dac00 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt @@ -39,8 +39,14 @@ class LookupElementsCollector( private val resolutionFacade: ResolutionFacade, private val lookupElementFactory: LookupElementFactory, private val inDescriptor: DeclarationDescriptor?, - private val surroundCallsWithBraces: Boolean + private val context: LookupElementsCollector.Context ) { + public enum class Context { + NORMAL + STRING_TEMPLATE_AFTER_DOLLAR + INFIX_CALL + } + private val elements = ArrayList() public fun flushToResultSet(resultSet: CompletionResultSet) { @@ -63,7 +69,7 @@ class LookupElementsCollector( } } - public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) { + private fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) { run { var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) @@ -71,7 +77,7 @@ class LookupElementsCollector( lookupElement = lookupElement.withReceiverCast() } - if (surroundCallsWithBraces && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) { + if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) { lookupElement = lookupElement.withBracesSurrounding() } @@ -84,7 +90,7 @@ class LookupElementsCollector( } // add special item for function with one argument of function type with more than one parameter - if (descriptor is FunctionDescriptor) { + if (context != Context.INFIX_CALL && descriptor is FunctionDescriptor) { val parameters = descriptor.getValueParameters() if (parameters.size() == 1) { val parameterType = parameters.get(0).getType() @@ -108,7 +114,7 @@ class LookupElementsCollector( } } - if (surroundCallsWithBraces) { + if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR) { lookupElement = lookupElement.withBracesSurrounding() } @@ -121,10 +127,10 @@ class LookupElementsCollector( if (descriptor is PropertyDescriptor) { var lookupElement = lookupElementFactory.createBackingFieldLookupElement(descriptor, inDescriptor, resolutionFacade) if (lookupElement != null) { - if (surroundCallsWithBraces) { - lookupElement = lookupElement!!.withBracesSurrounding() + if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR) { + lookupElement = lookupElement.withBracesSurrounding() } - addElement(lookupElement!!) + addElement(lookupElement) } } } diff --git a/idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt b/idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt new file mode 100644 index 00000000000..ec3b7617b25 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt @@ -0,0 +1,11 @@ +// checks that no special item "ext1 { String, Int -> ... }" created for infix call +fun Int.ext1(handler: (String, Int) -> Unit){} +fun Int.ext2(c: Char){} + +fun foo() { + val pair = 1 ext +} + +// EXIST: ext1 +// EXIST: ext2 +// NUMBER: 2 diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 4a0c2cb1182..6291683fe5c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -631,6 +631,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("InfixCallNoSpecialLambdaArgumentItem.kt") + public void testInfixCallNoSpecialLambdaArgumentItem() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt"); + doTest(fileName); + } + @TestMetadata("InsideAnonymousClass.kt") public void testInsideAnonymousClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 40a51f37281..395f0382717 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -631,6 +631,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("InfixCallNoSpecialLambdaArgumentItem.kt") + public void testInfixCallNoSpecialLambdaArgumentItem() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt"); + doTest(fileName); + } + @TestMetadata("InsideAnonymousClass.kt") public void testInsideAnonymousClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt");