diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt index 8d06bbfe6da..51666f82525 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt @@ -54,7 +54,7 @@ public class ReferenceVariantsHelper( expression: JetSimpleNameExpression, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, - callTypeAndReceiver: CallTypeAndReceiver = CallTypeAndReceiver.detect(expression), + callTypeAndReceiver: CallTypeAndReceiver<*, *> = CallTypeAndReceiver.detect(expression), filterOutJavaGettersAndSetters: Boolean = false, useRuntimeReceiverType: Boolean = false ): Collection { @@ -83,22 +83,31 @@ public class ReferenceVariantsHelper( expression: JetSimpleNameExpression, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, - callTypeAndReceiver: CallTypeAndReceiver, + callTypeAndReceiver: CallTypeAndReceiver<*, *>, useRuntimeReceiverType: Boolean ): Collection { - val (callType, receiverElement) = callTypeAndReceiver + val receiverExpression: JetExpression? + when (callTypeAndReceiver) { + is CallTypeAndReceiver.IMPORT_DIRECTIVE -> { + return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, kindFilter, nameFilter) + } - if (callType == CallType.IMPORT_DIRECTIVE) { - return getVariantsForImportOrPackageDirective(receiverElement as JetExpression?, kindFilter, nameFilter) - } + is CallTypeAndReceiver.PACKAGE_DIRECTIVE -> { + val packageKindFilter = kindFilter restrictedToKinds DescriptorKindFilter.PACKAGES_MASK + return getVariantsForImportOrPackageDirective(callTypeAndReceiver.receiver, packageKindFilter, nameFilter) + } - if (callType == CallType.PACKAGE_DIRECTIVE) { - val packageKindFilter = kindFilter restrictedToKinds DescriptorKindFilter.PACKAGES_MASK - return getVariantsForImportOrPackageDirective(receiverElement as JetExpression?, packageKindFilter, nameFilter) - } + is CallTypeAndReceiver.TYPE -> { + return getVariantsForUserType(callTypeAndReceiver.receiver, expression, kindFilter, nameFilter) + } - if (expression.parent is JetUserType) { //TODO: special CallType? - return getVariantsForUserType(receiverElement as JetExpression?, expression, kindFilter, nameFilter) + is CallTypeAndReceiver.CALLABLE_REFERENCE -> receiverExpression = null // handled below + + is CallTypeAndReceiver.DEFAULT -> receiverExpression = null + is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.UNARY -> receiverExpression = null // can it happen at all? } val resolutionScope = resolutionScope(expression) ?: return emptyList() @@ -110,27 +119,27 @@ public class ReferenceVariantsHelper( smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, context, containingDeclaration, dataFlowInfo) }.toSet() - if (callType == CallType.CALLABLE_REFERENCE) { - return getVariantsForCallableReference(receiverElement as JetTypeReference?, resolutionScope, implicitReceiverTypes, kindFilter, nameFilter) + if (callTypeAndReceiver is CallTypeAndReceiver.CALLABLE_REFERENCE) { + return getVariantsForCallableReference(callTypeAndReceiver.receiver, resolutionScope, implicitReceiverTypes, kindFilter, nameFilter) } + val callType = callTypeAndReceiver.callType + val descriptors = LinkedHashSet() - if (receiverElement != null) { - receiverElement as JetExpression - - val qualifier = context[BindingContext.QUALIFIER, receiverElement] + if (receiverExpression != null) { + val qualifier = context[BindingContext.QUALIFIER, receiverExpression] if (qualifier != null) { // It's impossible to add extension function for package or class (if it's companion object, expression type is not null) qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors) { callType.canCall(it) } } val expressionType = if (useRuntimeReceiverType) - getQualifierRuntimeType(receiverElement) + getQualifierRuntimeType(receiverExpression) else - context.getType(receiverElement) + context.getType(receiverExpression) if (expressionType != null && !expressionType.isError()) { - val receiverValue = ExpressionReceiver(receiverElement, expressionType) + val receiverValue = ExpressionReceiver(receiverExpression, expressionType) val explicitReceiverTypes = smartCastManager .getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, containingDeclaration, dataFlowInfo) @@ -138,7 +147,7 @@ public class ReferenceVariantsHelper( } } else { - descriptors.processAll(implicitReceiverTypes, implicitReceiverTypes, resolutionScope, CallType.NORMAL, kindFilter, nameFilter) + descriptors.processAll(implicitReceiverTypes, implicitReceiverTypes, resolutionScope, callType, kindFilter, nameFilter) // add non-instance members descriptors.addAll(resolutionScope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter)) @@ -213,7 +222,7 @@ public class ReferenceVariantsHelper( implicitReceiverTypes: Collection, receiverTypes: Collection, resolutionScope: JetScope, - callType: CallType, + callType: CallType<*>, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean ) { @@ -225,7 +234,7 @@ public class ReferenceVariantsHelper( private fun MutableSet.addMemberExtensions( dispatchReceiverTypes: Collection, extensionReceiverTypes: Collection, - callType: CallType, + callType: CallType<*>, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean ) { @@ -239,7 +248,7 @@ public class ReferenceVariantsHelper( private fun MutableSet.addNonExtensionMembers( receiverTypes: Collection, - callType: CallType, + callType: CallType<*>, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, constructorsForInnerClassesOnly: Boolean @@ -251,7 +260,7 @@ public class ReferenceVariantsHelper( private fun MutableSet.addNonExtensionCallablesAndConstructors( scope: JetScope, - callType: CallType, + callType: CallType<*>, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, constructorsForInnerClassesOnly: Boolean @@ -278,7 +287,7 @@ public class ReferenceVariantsHelper( private fun MutableSet.addScopeAndSyntheticExtensions( resolutionScope: JetScope, receiverTypes: Collection, - callType: CallType, + callType: CallType<*>, kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean ) { diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt index 8d898ae22f9..fabff27b8a3 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt @@ -26,85 +26,99 @@ import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression import org.jetbrains.kotlin.psi.psiUtil.isPackageDirectiveExpression -public enum class CallType { - NORMAL, - SAFE, +public sealed class CallType { + object DEFAULT : CallType() - INFIX { + object DOT : CallType() + + object SAFE : CallType() + + object INFIX : CallType() { override fun canCall(descriptor: DeclarationDescriptor) = descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size() == 1 - }, + } - UNARY { + object UNARY : CallType() { override fun canCall(descriptor: DeclarationDescriptor) = descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size() == 0 - }, + } - CALLABLE_REFERENCE { + object CALLABLE_REFERENCE : CallType() { // currently callable references to locals and parameters are not supported override fun canCall(descriptor: DeclarationDescriptor) = descriptor is FunctionDescriptor || descriptor is PropertyDescriptor - }, + } //TODO: canCall - IMPORT_DIRECTIVE, + object IMPORT_DIRECTIVE : CallType() - PACKAGE_DIRECTIVE + object PACKAGE_DIRECTIVE : CallType() - ; + object TYPE : CallType() public open fun canCall(descriptor: DeclarationDescriptor): Boolean = true } -public data class CallTypeAndReceiver( - val callType: CallType, - val receiver: JetElement? +public sealed class CallTypeAndReceiver>( + val callType: TCallType, + val receiver: TReceiver ) { + object DEFAULT : CallTypeAndReceiver(CallType.DEFAULT, null) + class DOT(receiver: JetExpression) : CallTypeAndReceiver(CallType.DOT, receiver) + class SAFE(receiver: JetExpression) : CallTypeAndReceiver(CallType.SAFE, receiver) + class INFIX(receiver: JetExpression) : CallTypeAndReceiver(CallType.INFIX, receiver) + class UNARY(receiver: JetExpression) : CallTypeAndReceiver(CallType.UNARY, receiver) + class CALLABLE_REFERENCE(receiver: JetTypeReference?) : CallTypeAndReceiver(CallType.CALLABLE_REFERENCE, receiver) + class IMPORT_DIRECTIVE(receiver: JetExpression?) : CallTypeAndReceiver(CallType.IMPORT_DIRECTIVE, receiver) + class PACKAGE_DIRECTIVE(receiver: JetExpression?) : CallTypeAndReceiver(CallType.PACKAGE_DIRECTIVE, receiver) + class TYPE(receiver: JetExpression?) : CallTypeAndReceiver(CallType.TYPE, receiver) + companion object { - public fun detect(expression: JetSimpleNameExpression): CallTypeAndReceiver { + public fun detect(expression: JetSimpleNameExpression): CallTypeAndReceiver<*, *> { val parent = expression.parent if (parent is JetCallableReferenceExpression) { - return CallTypeAndReceiver(CallType.CALLABLE_REFERENCE, parent.typeReference) + return CallTypeAndReceiver.CALLABLE_REFERENCE(parent.typeReference) } val receiverExpression = expression.getReceiverExpression() if (expression.isImportDirectiveExpression()) { - return CallTypeAndReceiver(CallType.IMPORT_DIRECTIVE, receiverExpression) + return CallTypeAndReceiver.IMPORT_DIRECTIVE(receiverExpression) } if (expression.isPackageDirectiveExpression()) { - return CallTypeAndReceiver(CallType.PACKAGE_DIRECTIVE, receiverExpression) + return CallTypeAndReceiver.PACKAGE_DIRECTIVE(receiverExpression) + } + + if (parent is JetUserType) { + return CallTypeAndReceiver.TYPE(receiverExpression) } if (receiverExpression == null) { - return CallTypeAndReceiver(CallType.NORMAL, null) + return CallTypeAndReceiver.DEFAULT } - val callType = when (parent) { - is JetBinaryExpression -> CallType.INFIX + return when (parent) { + is JetBinaryExpression -> CallTypeAndReceiver.INFIX(receiverExpression) is JetCallExpression -> { - if ((parent.getParent() as JetQualifiedExpression).getOperationSign() == JetTokens.SAFE_ACCESS) - CallType.SAFE + if ((parent.parent as JetQualifiedExpression).operationSign == JetTokens.SAFE_ACCESS) + CallTypeAndReceiver.SAFE(receiverExpression) else - CallType.NORMAL + CallTypeAndReceiver.DOT(receiverExpression) } is JetQualifiedExpression -> { - if (parent.getOperationSign() == JetTokens.SAFE_ACCESS) - CallType.SAFE + if (parent.operationSign == JetTokens.SAFE_ACCESS) + CallTypeAndReceiver.SAFE(receiverExpression) else - CallType.NORMAL + CallTypeAndReceiver.DOT(receiverExpression) } - is JetUnaryExpression -> CallType.UNARY - - is JetUserType -> CallType.NORMAL + is JetUnaryExpression -> CallTypeAndReceiver.UNARY(receiverExpression) else -> error("Unknown parent for expression with receiver: $parent") } - return CallTypeAndReceiver(callType, receiverExpression) } } } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt index dbc7386043f..45730954c06 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt @@ -40,7 +40,7 @@ public class ShadowedDeclarationsFilter( private val bindingContext: BindingContext, private val resolutionFacade: ResolutionFacade, private val context: JetExpression, - callTypeAndReceiver: CallTypeAndReceiver + callTypeAndReceiver: CallTypeAndReceiver<*, *> ) { private val psiFactory = JetPsiFactory(resolutionFacade.project) private val dummyExpressionFactory = DummyExpressionFactory(psiFactory) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt index 93ca1425280..c44010001ae 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt @@ -18,7 +18,8 @@ package org.jetbrains.kotlin.idea.util -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.psi.JetPsiUtil import org.jetbrains.kotlin.psi.JetThisExpression import org.jetbrains.kotlin.resolve.BindingContext @@ -37,7 +38,7 @@ public fun CallableDescriptor.substituteExtensionIfCallable( receivers: Collection, context: BindingContext, dataFlowInfo: DataFlowInfo, - callType: CallType, + callType: CallType<*>, containingDeclarationOrModule: DeclarationDescriptor ): Collection { val sequence = receivers.asSequence().flatMap { substituteExtensionIfCallable(it, callType, context, dataFlowInfo, containingDeclarationOrModule).asSequence() } @@ -55,12 +56,12 @@ public fun CallableDescriptor.substituteExtensionIfCallableWithImplicitReceiver( dataFlowInfo: DataFlowInfo ): Collection { val receiverValues = scope.getImplicitReceiversWithInstance().map { it.getValue() } - return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.NORMAL, scope.getContainingDeclaration()) + return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.DEFAULT, scope.getContainingDeclaration()) } public fun CallableDescriptor.substituteExtensionIfCallable( receiver: ReceiverValue, - callType: CallType, + callType: CallType<*>, bindingContext: BindingContext, dataFlowInfo: DataFlowInfo, containingDeclarationOrModule: DeclarationDescriptor @@ -73,7 +74,7 @@ public fun CallableDescriptor.substituteExtensionIfCallable( public fun CallableDescriptor.substituteExtensionIfCallable( receiverTypes: Collection, - callType: CallType + callType: CallType<*> ): Collection { if (!callType.canCall(this)) return listOf() 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 546a585292c..a577c66d0b6 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 @@ -303,7 +303,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC val contextVariablesProvider = { nameExpression?.let { - referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver(CallType.NORMAL, null)) + referenceVariantsHelper.getReferenceVariants(it, DescriptorKindFilter.VARIABLES, { true }, CallTypeAndReceiver.DEFAULT) .map { it as VariableDescriptor } } ?: emptyList() } @@ -314,23 +314,38 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC insertHandlerProvider, contextVariablesProvider) } - private fun detectCallTypeAndReceiverTypes(): Pair> { + private fun detectCallTypeAndReceiverTypes(): Pair, Collection> { if (nameExpression == null) { - return CallType.NORMAL to emptyList() + return CallType.DEFAULT to emptyList() } - val (callType, receiverElement) = CallTypeAndReceiver.detect(nameExpression) + val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression) - if (callType == CallType.CALLABLE_REFERENCE && receiverElement != null) { - val type = bindingContext[BindingContext.TYPE, receiverElement as JetTypeReference] - return callType to type.singletonOrEmptyList() + val receiverExpression: JetExpression? + when (callTypeAndReceiver) { + is CallTypeAndReceiver.CALLABLE_REFERENCE -> { + if (callTypeAndReceiver.receiver != null) { + val type = bindingContext[BindingContext.TYPE, callTypeAndReceiver.receiver] + return callTypeAndReceiver.callType to type.singletonOrEmptyList() + } + else { + receiverExpression = null + } + } + + is CallTypeAndReceiver.DEFAULT -> receiverExpression = null + is CallTypeAndReceiver.DOT -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.SAFE -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.INFIX -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.UNARY -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.IMPORT_DIRECTIVE -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.PACKAGE_DIRECTIVE -> receiverExpression = callTypeAndReceiver.receiver + is CallTypeAndReceiver.TYPE -> receiverExpression = callTypeAndReceiver.receiver } - receiverElement as JetExpression? - - val receiverValues = if (receiverElement != null) { - val expressionType = bindingContext.getType(receiverElement) - expressionType?.let { listOf(ExpressionReceiver(receiverElement, expressionType)) } ?: emptyList() + val receiverValues = if (receiverExpression != null) { + val expressionType = bindingContext.getType(receiverExpression) + expressionType?.let { listOf(ExpressionReceiver(receiverExpression, expressionType)) } ?: emptyList() } else { val resolutionScope = referenceVariantsHelper.resolutionScope(nameExpression) @@ -350,10 +365,10 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC } } - if (callType == CallType.SAFE) { + if (callTypeAndReceiver is CallTypeAndReceiver.SAFE) { receiverTypes = receiverTypes.map { it.makeNotNullable() } } - return callType to receiverTypes + return callTypeAndReceiver.callType to receiverTypes } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt index 1bb68beed63..bae975f40e6 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/InsertHandlerProvider.kt @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.types.JetType import java.util.* class InsertHandlerProvider( - private val callType: CallType, + private val callType: CallType<*>, expectedInfosCalculator: () -> Collection ) { private val expectedInfos by lazy(LazyThreadSafetyMode.NONE) { expectedInfosCalculator() } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KDocCompletionContributor.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KDocCompletionContributor.kt index aa845ca87af..3173b00d95a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KDocCompletionContributor.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KDocCompletionContributor.kt @@ -100,7 +100,7 @@ class KDocNameCompletionSession(parameters: CompletionParameters, val extensionReceiver = descriptor.getExtensionReceiverParameter() if (extensionReceiver != null) { val substituted = descriptor.substituteExtensionIfCallable(implicitReceivers, bindingContext, DataFlowInfo.EMPTY, - CallType.NORMAL, moduleDescriptor) + CallType.DEFAULT, moduleDescriptor) return !substituted.isEmpty() } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt index 13b75391ad5..fe1e22330fb 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KeywordCompletion.kt @@ -77,7 +77,7 @@ object KeywordCompletion { .withInsertHandler(if (keywordToken !in FUNCTION_KEYWORDS) KotlinKeywordInsertHandler else - KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = false)) + KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = false)) consumer(element) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index 16a2ea21372..638edfc1072 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -45,7 +45,7 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf class LookupElementFactory( private val resolutionFacade: ResolutionFacade, private val receiverTypes: Collection, - private val callType: CallType, + private val callType: CallType<*>, private val isInStringTemplateAfterDollar: Boolean, public val insertHandlerProvider: InsertHandlerProvider, contextVariablesProvider: () -> Collection @@ -66,7 +66,7 @@ class LookupElementFactory( result.add(lookupElement) // add special item for function with one argument of function type with more than one parameter - if (descriptor is FunctionDescriptor && (callType == CallType.NORMAL || callType == CallType.SAFE)) { + if (descriptor is FunctionDescriptor && (callType == CallType.DEFAULT || callType == CallType.DOT || callType == CallType.SAFE)) { result.addSpecialFunctionCallElements(descriptor, useReceiverTypes) } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt index 2b0fcf4cb3f..1935039a37a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt @@ -54,7 +54,7 @@ object PackageDirectiveCompletion { val bindingContext = resolutionFacade.analyze(expression) val variants = ReferenceVariantsHelper(bindingContext, resolutionFacade, { true }).getPackageReferenceVariants(expression, prefixMatcher.asNameFilter()) - val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.NORMAL/*TODO*/, expectedInfosCalculator = { emptyList() })) + val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.PACKAGE_DIRECTIVE, expectedInfosCalculator = { emptyList() })) for (variant in variants) { val lookupElement = lookupElementFactory.createLookupElement(variant) if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt index 88d44c2cd63..4cf250b625a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/KotlinFunctionInsertHandler.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.types.JetType class GenerateLambdaInfo(val lambdaType: JetType, val explicitParameters: Boolean) class KotlinFunctionInsertHandler( - val callType: CallType, + val callType: CallType<*>, val inputTypeArguments: Boolean, val inputValueArguments: Boolean, val argumentText: String = "", diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt index f4ef4e14b1c..378ea2cc86c 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletionSession.kt @@ -22,12 +22,10 @@ import com.intellij.codeInsight.completion.CompletionSorter import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.completion.* -import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude import org.jetbrains.kotlin.psi.FunctionLiteralArgument import org.jetbrains.kotlin.psi.JetCodeFragment -import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.psi.ValueArgumentName import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall @@ -91,30 +89,28 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para // special completion for outside parenthesis lambda argument private fun addFunctionLiteralArgumentCompletions() { if (nameExpression != null) { - val (callType, receiverElement) = CallTypeAndReceiver.detect(nameExpression) - if (callType == CallType.INFIX) { - val call = (receiverElement as JetExpression).getCall(bindingContext) - if (call != null && call.getFunctionLiteralArguments().isEmpty()) { - val dummyArgument = object : FunctionLiteralArgument { - override fun getFunctionLiteral() = throw UnsupportedOperationException() - override fun getArgumentExpression() = throw UnsupportedOperationException() - override fun getArgumentName(): ValueArgumentName? = null - override fun isNamed() = false - override fun asElement() = throw UnsupportedOperationException() - override fun getSpreadElement(): LeafPsiElement? = null - override fun isExternal() = false - } - val dummyArguments = call.getValueArguments() + listOf(dummyArgument) - val dummyCall = object : DelegatingCall(call) { - override fun getValueArguments() = dummyArguments - override fun getFunctionLiteralArguments() = listOf(dummyArgument) - override fun getValueArgumentList() = throw UnsupportedOperationException() - } - - val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade) - .calculateForArgument(dummyCall, dummyArgument) - collector.addElements(LambdaItems.collect(expectedInfos)) + val callTypeAndReceiver = CallTypeAndReceiver.detect(nameExpression) as? CallTypeAndReceiver.INFIX ?: return + val call = callTypeAndReceiver.receiver.getCall(bindingContext) + if (call != null && call.getFunctionLiteralArguments().isEmpty()) { + val dummyArgument = object : FunctionLiteralArgument { + override fun getFunctionLiteral() = throw UnsupportedOperationException() + override fun getArgumentExpression() = throw UnsupportedOperationException() + override fun getArgumentName(): ValueArgumentName? = null + override fun isNamed() = false + override fun asElement() = throw UnsupportedOperationException() + override fun getSpreadElement(): LeafPsiElement? = null + override fun isExternal() = false } + val dummyArguments = call.getValueArguments() + listOf(dummyArgument) + val dummyCall = object : DelegatingCall(call) { + override fun getValueArguments() = dummyArguments + override fun getFunctionLiteralArguments() = listOf(dummyArgument) + override fun getValueArgumentList() = throw UnsupportedOperationException() + } + + val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade) + .calculateForArgument(dummyCall, dummyArgument) + collector.addElements(LambdaItems.collect(expectedInfos)) } } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt index e4cb6ded4ec..b0bb53f2385 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt @@ -204,9 +204,9 @@ class TypeInstantiationItems( } val baseInsertHandler = when (visibleConstructors.size()) { - 0 -> KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = false) + 0 -> KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = false) 1 -> lookupElementFactory.insertHandlerProvider.insertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler - else -> KotlinFunctionInsertHandler(CallType.NORMAL, inputTypeArguments = false, inputValueArguments = true) + else -> KotlinFunctionInsertHandler(CallType.DEFAULT, inputTypeArguments = false, inputValueArguments = true) } insertHandler = object : InsertHandler { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 1a7fe552956..463234d212c 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -131,8 +131,9 @@ public class KotlinIndicesHelper( constructor.getSupertypes().forEach { addTypeNames(it) } } - private fun receiverValues(expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection> { - val (callType, receiverElement) = CallTypeAndReceiver.detect(expression) + private fun receiverValues(expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection>> { + val callTypeAndReceiver = CallTypeAndReceiver.detect(expression) + val receiverElement = callTypeAndReceiver.receiver if (receiverElement != null) { if (receiverElement !is JetExpression) return emptyList() //TODO? @@ -141,11 +142,11 @@ public class KotlinIndicesHelper( val receiverValue = ExpressionReceiver(receiverElement, expressionType) - return listOf(receiverValue to callType) + return listOf(receiverValue to callTypeAndReceiver.callType) } else { val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, expression] ?: return emptyList() - return resolutionScope.getImplicitReceiversWithInstance().map { it.getValue() to callType } + return resolutionScope.getImplicitReceiversWithInstance().map { it.getValue() to callTypeAndReceiver.callType } } } @@ -154,7 +155,7 @@ public class KotlinIndicesHelper( */ private fun findSuitableExtensions( declarations: Sequence, - receiverValues: Collection>, + receiverValues: Collection>>, dataFlowInfo: DataFlowInfo, bindingContext: BindingContext ): Collection {