diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index 9d54db61173..acc2f298a1f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -223,7 +223,7 @@ class FunctionDescriptorResolver( private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List? = if (functionTypeExpected()) { - createValueParametersFromFunctionType(owner, getParameterTypeProjectionsFromFunctionType(this)) + createValueParametersFromFunctionType(owner, getValueParameterTypesFromFunctionType(this)) } else null diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt index 139524d0836..2521cd6ec28 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt @@ -104,7 +104,13 @@ fun getReturnTypeFromFunctionType(type: KotlinType): KotlinType { return type.arguments.last().type } -fun getParameterTypeProjectionsFromFunctionType(type: KotlinType): List { +fun getValueParametersCountFromFunctionType(type: KotlinType): Int { + assert(type.isFunctionType) { "Not a function type: $type" } + // Function type arguments = receiver? + parameters + return-type + return type.arguments.size - (if (type.isExtensionFunctionType) 1 else 0) - 1 +} + +fun getValueParameterTypesFromFunctionType(type: KotlinType): List { assert(type.isFunctionType) { "Not a function type: $type" } val arguments = type.arguments val first = if (type.isExtensionFunctionType) 1 else 0 diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt index 7a11b493227..a354b1e5af7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -319,7 +319,7 @@ internal class DescriptorRendererImpl( } append("(") - appendTypeProjections(getParameterTypeProjectionsFromFunctionType(type), this) + appendTypeProjections(getValueParameterTypesFromFunctionType(type), this) append(") ").append(arrow()).append(" ") append(renderNormalizedType(getReturnTypeFromFunctionType(type))) 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 69548985be0..c3bfb61490f 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 @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.InsertHandler import com.intellij.codeInsight.lookup.LookupElement -import org.jetbrains.kotlin.builtins.getParameterTypeProjectionsFromFunctionType import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParametersCountFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.completion.handlers.* @@ -54,10 +54,12 @@ class InsertHandlerProvider( if (callType != CallType.SUPER_MEMBERS) { // for super call we don't suggest to generate "super.foo { ... }" (seems to be non-typical use) val parameterType = parameters.single().type if (parameterType.isFunctionType) { - val parameterCount = getParameterTypeProjectionsFromFunctionType(parameterType).size - if (parameterCount <= 1) { + if (getValueParametersCountFromFunctionType(parameterType) <= 1) { // otherwise additional item with lambda template is to be added - return KotlinFunctionInsertHandler.Normal(needTypeArguments, inputValueArguments = false, lambdaInfo = GenerateLambdaInfo(parameterType, false)) + return KotlinFunctionInsertHandler.Normal( + needTypeArguments, inputValueArguments = false, + lambdaInfo = GenerateLambdaInfo(parameterType, false) + ) } } } @@ -98,7 +100,7 @@ class InsertHandlerProvider( potentiallyInferred.add(descriptor) } - if (type.isFunctionType && getParameterTypeProjectionsFromFunctionType(type).size <= 1) { + if (type.isFunctionType && getValueParametersCountFromFunctionType(type) <= 1) { // do not rely on inference from input of function type with one or no arguments - use only return type of functional type addPotentiallyInferred(getReturnTypeFromFunctionType(type)) return 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 ec8807577c9..1bc061ed321 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 @@ -22,7 +22,7 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator import com.intellij.codeInsight.lookup.LookupElementPresentation import com.intellij.codeInsight.lookup.impl.LookupCellRenderer import com.intellij.util.SmartList -import org.jetbrains.kotlin.builtins.getParameterTypeProjectionsFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParametersCountFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo @@ -112,7 +112,7 @@ class LookupElementFactory( val isSingleParameter = descriptor.valueParameters.size == 1 val parameterType = lastParameter.type - val functionParameterCount = getParameterTypeProjectionsFromFunctionType(parameterType).size + val functionParameterCount = getValueParametersCountFromFunctionType(parameterType) // we don't need special item inserting lambda for single functional parameter that does not need multiple arguments because the default item will be special in this case if (!isSingleParameter || functionParameterCount > 1) { add(createFunctionCallElementWithLambda(descriptor, parameterType, functionParameterCount > 1, useReceiverTypes)) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt index 044e99d6a3e..2ec5e3f96c0 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/handlers/GenerateLambda.kt @@ -25,7 +25,8 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.builtins.getParameterTypeProjectionsFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParametersCountFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.ExpectedInfos @@ -37,6 +38,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjection fun insertLambdaTemplate(context: InsertionContext, placeholderRange: TextRange, lambdaType: KotlinType) { val explicitParameterTypes = needExplicitParameterTypes(context, placeholderRange, lambdaType) @@ -88,8 +90,8 @@ private fun needExplicitParameterTypes(context: InsertionContext, placeholderRan .toSet() if (functionTypes.size <= 1) return false - val lambdaParameterCount = getParameterTypeProjectionsFromFunctionType(lambdaType).size - return functionTypes.filter { getParameterTypeProjectionsFromFunctionType(it).size == lambdaParameterCount }.size > 1 + val lambdaParameterCount = getValueParametersCountFromFunctionType(lambdaType) + return functionTypes.filter { getValueParametersCountFromFunctionType(it) == lambdaParameterCount }.size > 1 } private fun buildTemplate(lambdaType: KotlinType, explicitParameterTypes: Boolean, project: Project): Template { @@ -128,5 +130,5 @@ private class ParameterNameExpression(val nameSuggestions: Array) : Expr = Array(nameSuggestions.size, { LookupElementBuilder.create(nameSuggestions[it]) }) } -fun functionParameterTypes(functionType: KotlinType): List - = getParameterTypeProjectionsFromFunctionType(functionType).map { it.type } +fun functionParameterTypes(functionType: KotlinType): List = + getValueParameterTypesFromFunctionType(functionType).map(TypeProjection::getType) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt index 2ce3a8ae843..e7bb48ac81a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/LambdaItems.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.idea.completion.smart import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.openapi.util.TextRange -import org.jetbrains.kotlin.builtins.getParameterTypeProjectionsFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParametersCountFromFunctionType import org.jetbrains.kotlin.idea.completion.handlers.insertLambdaTemplate import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation import org.jetbrains.kotlin.idea.completion.suppressAutoInsertion @@ -43,7 +43,7 @@ object LambdaItems { .toSet() val singleType = if (distinctTypes.size == 1) distinctTypes.single() else null - val singleSignatureLength = singleType?.let { getParameterTypeProjectionsFromFunctionType(it).size } + val singleSignatureLength = singleType?.let(::getValueParametersCountFromFunctionType) val offerNoParametersLambda = singleSignatureLength == 0 || singleSignatureLength == 1 if (offerNoParametersLambda) { val lookupElement = LookupElementBuilder.create(lambdaPresentation(null)) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt index 09bdbab0545..6bca071ff7b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateFunctionFromCallableReferenceActionFactory.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable import com.intellij.util.SmartList -import org.jetbrains.kotlin.builtins.getParameterTypeProjectionsFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType @@ -55,7 +55,7 @@ object CreateFunctionFromCallableReferenceActionFactory : CreateCallableMemberFr add(ParameterInfo(TypeInfo(expectedReceiverType, Variance.IN_VARIANCE))) } - getParameterTypeProjectionsFromFunctionType(it) + getValueParameterTypesFromFunctionType(it) .let { if (actualReceiverTypeRef != null && expectedReceiverType == null && it.isNotEmpty()) it.subList(1, it.size)