Support common calls on suspend function typed values

Also support multiple value parameters in suspend function type

 #KT-15379 Fixed
 #KT-15380 Fixed
This commit is contained in:
Denis Zharkov
2016-12-21 14:15:46 +03:00
parent d0ba048342
commit 8475869fb3
29 changed files with 299 additions and 77 deletions
@@ -18,25 +18,26 @@ package org.jetbrains.kotlin.resolve.calls.tasks
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind.Function
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor.Kind.SuspendFunction
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
private val BUILTIN_FUNCTIONS = setOf(Function, SuspendFunction)
fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collection<FunctionDescriptor> {
val result = ArrayList<FunctionDescriptor>(1)
for (invoke in functions) {
if (invoke !is FunctionInvokeDescriptor || invoke.getValueParameters().isEmpty()) continue
val synthesized = if ((invoke.getContainingDeclaration() as? FunctionClassDescriptor)?.functionKind == Function) {
val synthesized = if ((invoke.getContainingDeclaration() as? FunctionClassDescriptor)?.functionKind in BUILTIN_FUNCTIONS) {
createSynthesizedFunctionWithFirstParameterAsReceiver(invoke)
}
else {
@@ -59,40 +60,15 @@ fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collect
return result
}
private fun createSynthesizedFunctionWithFirstParameterAsReceiver(descriptor: FunctionDescriptor): FunctionDescriptor {
val result = SimpleFunctionDescriptorImpl.create(
descriptor.containingDeclaration,
descriptor.annotations,
descriptor.name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
descriptor.source
)
val original = descriptor.original
result.initialize(
original.valueParameters.first().type,
original.dispatchReceiverParameter,
original.typeParameters,
original.valueParameters.drop(1).map { p ->
ValueParameterDescriptorImpl(
result, null, p.index - 1, p.annotations, Name.identifier("p${p.index + 1}"), p.type,
p.declaresDefaultValue(), p.isCrossinline, p.isNoinline, p.varargElementType, p.source
)
},
original.returnType,
original.modality,
original.visibility
)
result.isOperator = original.isOperator
result.isInfix = original.isInfix
result.isExternal = original.isExternal
result.isInline = original.isInline
result.isTailrec = original.isTailrec
result.setHasStableParameterNames(false)
result.setHasSynthesizedParameterNames(true)
return result
}
private fun createSynthesizedFunctionWithFirstParameterAsReceiver(descriptor: FunctionDescriptor) =
descriptor.original.newCopyBuilder().apply {
setExtensionReceiverType(descriptor.original.valueParameters.first().type)
setValueParameters(
descriptor.original.valueParameters
.drop(1)
.map { p -> p.copy(descriptor.original, Name.identifier("p${p.index + 1}"), p.index - 1) }
)
}.build()!!
fun isSynthesizedInvoke(descriptor: DeclarationDescriptor): Boolean {
if (descriptor.name != OperatorNameConventions.INVOKE || descriptor !is FunctionDescriptor) return false
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.name.Name
@@ -147,7 +147,7 @@ private fun ImplicitScopeTower.getExtensionInvokeCandidateDescriptor(
extensionFunctionReceiver: ReceiverValueWithSmartCastInfo
): CandidateWithBoundDispatchReceiver<FunctionDescriptor>? {
val type = extensionFunctionReceiver.receiverValue.type
if (!type.isExtensionFunctionType) return null // todo: missing smart cast?
if (!type.isBuiltinExtensionFunctionalType) return null // todo: missing smart cast?
val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single()
val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single()
@@ -187,4 +187,4 @@ fun <F : Candidate<FunctionDescriptor>> createCallTowerProcessorForExplicitInvok
}
}
}
}