[PSI, FE] Support functional types

This commit is contained in:
Anastasiya Shadrina
2021-08-12 01:15:58 +07:00
committed by TeamCityServer
parent e53cee77a3
commit e3f987459c
45 changed files with 507 additions and 40 deletions
@@ -346,7 +346,12 @@ class TypeResolver(
override fun visitFunctionType(type: KtFunctionType) {
val receiverTypeRef = type.receiverTypeReference
val receiverType = if (receiverTypeRef == null) null else resolveType(c.noBareTypes(), receiverTypeRef)
val receiverType = if (receiverTypeRef?.typeElement == null) null else resolveType(c.noBareTypes(), receiverTypeRef)
val contextReceiversTypeRefs = type.contextReceiversTypeReferences
val contextReceiversTypes = contextReceiversTypeRefs?.mapNotNull {
resolveType(c.noBareTypes(), it)
} ?: emptyList()
val parameterDescriptors = resolveParametersOfFunctionType(type.parameters)
checkParametersOfFunctionType(parameterDescriptors)
@@ -362,7 +367,7 @@ class TypeResolver(
result = type(
createFunctionType(
moduleDescriptor.builtIns, annotations, receiverType,
moduleDescriptor.builtIns, annotations, receiverType, contextReceiversTypes,
parameterDescriptors.map { it.type },
parameterDescriptors.map { it.name },
returnType,
@@ -44,6 +44,7 @@ import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.jetbrains.kotlin.psi.KtPsiUtil.getLastElementDeparenthesized;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getRecordedTypeInfo;
@@ -334,7 +335,7 @@ public class ArgumentTypeResolver {
}
return FunctionTypesKt.createFunctionType(
builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), null, TypeUtils.DONT_CARE
builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), Collections.emptyList(), null, TypeUtils.DONT_CARE
);
}
@@ -372,7 +373,7 @@ public class ArgumentTypeResolver {
return expectedTypeIsUnknown
? functionPlaceholders.createFunctionPlaceholderType(Collections.emptyList(), /* hasDeclaredArguments = */ false)
: FunctionTypesKt.createFunctionType(
builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), null, DONT_CARE
builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), Collections.emptyList(), null, DONT_CARE
);
}
List<KtParameter> valueParameters = function.getValueParameters();
@@ -391,11 +392,14 @@ public class ArgumentTypeResolver {
KotlinType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE);
assert returnType != null;
KotlinType receiverType = resolveTypeRefWithDefault(function.getReceiverTypeReference(), scope, temporaryTrace, null);
List<KotlinType> contextReceiversTypes = function.getContextReceivers().stream().map(contextReceiver ->
resolveTypeRefWithDefault(contextReceiver.typeReference(), scope, temporaryTrace, null)
).collect(Collectors.toList());
return expectedTypeIsUnknown && isFunctionLiteral
? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true)
: FunctionTypesKt.createFunctionType(
builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, parameterNames, returnType, suspendFunctionTypeExpected
builtIns, Annotations.Companion.getEMPTY(), receiverType, contextReceiversTypes, parameterTypes, parameterNames, returnType, suspendFunctionTypeExpected
);
}
@@ -357,7 +357,7 @@ public class CallResolver {
parameterTypes.add(NO_EXPECTED_TYPE);
}
expectedType = FunctionTypesKt.createFunctionType(
builtIns, Annotations.Companion.getEMPTY(), null, parameterTypes, null, context.expectedType
builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), parameterTypes, null, context.expectedType
);
}
KotlinType calleeType = expressionTypingServices.safeGetType(
@@ -177,7 +177,7 @@ class BuilderInferenceSupport(
approximationSubstitutor.buildSubstitutor().substitute(lambdaExpectedType, Variance.IN_VARIANCE) ?: return
val newExpectedType = createFunctionType(
newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType,
newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType, emptyList(), // TODO: Context receivers?
approximatedLambdaType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType),
parameterNames = null, // TODO: parameterNames
returnType = approximatedLambdaType.getReturnTypeFromFunctionType(),
@@ -16,9 +16,7 @@
package org.jetbrains.kotlin.resolve.calls.inference
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL
@@ -471,8 +469,9 @@ internal fun createTypeForFunctionPlaceholder(
functionPlaceholderTypeConstructor.argumentTypes
}
val receiverType = if (isExtension) DONT_CARE else null
val contextReceiverTypes = (0 until expectedType.contextFunctionTypeParamsCount()).map { DONT_CARE }
return createFunctionType(
functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, null, DONT_CARE,
functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, contextReceiverTypes, newArgumentTypes, null, DONT_CARE,
suspendFunction = expectedType.isSuspendFunctionType
)
}
@@ -186,9 +186,11 @@ class DynamicCallableDescriptors(private val storageManager: StorageManager, bui
val funLiteral = funLiteralExpr.functionLiteral
val receiverType = funLiteral.receiverTypeReference?.let { dynamicType }
val contextReceiversTypes = funLiteral.contextReceivers.map { dynamicType }
val parameterTypes = funLiteral.valueParameters.map { dynamicType }
return createFunctionType(owner.builtIns, Annotations.EMPTY, receiverType, parameterTypes, null, dynamicType)
return createFunctionType(owner.builtIns, Annotations.EMPTY, receiverType, contextReceiversTypes, parameterTypes, null, dynamicType)
}
for (arg in call.valueArguments) {
@@ -171,8 +171,9 @@ class KotlinResolutionCallbacksImpl(
@OptIn(TypeRefinement::class) callComponents.kotlinTypeChecker.kotlinTypeRefiner.refineType(it)
}
// TODO: Context receivers?
val expectedType = createFunctionType(
builtIns, annotations, refinedReceiverType, parameters, null,
builtIns, annotations, refinedReceiverType, emptyList(), parameters, null,
lambdaInfo.expectedType, isSuspend
)
@@ -334,6 +334,7 @@ class ResolvedAtomCompleter(
builtIns,
existingLambdaType.annotations,
substitutedLambdaTypes.receiverType?.substitutedType,
emptyList(),
substitutedLambdaTypes.parameterTypes.map { it.substitutedType },
null, // parameter names transforms to special annotations, so they are already taken from parameter types
substitutedLambdaTypes.returnType.substitutedType,
@@ -830,6 +830,9 @@ class DoubleColonExpressionResolver(
}
companion object {
private fun contextReceiverTypesFor(descriptor: CallableDescriptor): List<KotlinType> =
descriptor.contextReceiverParameters.map { it.type }
private fun receiverTypeFor(descriptor: CallableDescriptor, lhs: DoubleColonLHS?): KotlinType? =
(descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter)?.let { (lhs as? DoubleColonLHS.Type)?.type }
@@ -849,6 +852,7 @@ class DoubleColonExpressionResolver(
reflectionTypes: ReflectionTypes,
scopeOwnerDescriptor: DeclarationDescriptor
): KotlinType? {
val contextReceiverTypes = contextReceiverTypesFor(descriptor)
val receiverType = receiverTypeFor(descriptor, lhs)
return when (descriptor) {
is FunctionDescriptor -> {
@@ -857,7 +861,7 @@ class DoubleColonExpressionResolver(
val parametersNames = descriptor.valueParameters.map { it.name }
return reflectionTypes.getKFunctionType(
Annotations.EMPTY, receiverType,
parametersTypes, parametersNames, returnType, descriptor.builtIns, descriptor.isSuspend
contextReceiverTypes, parametersTypes, parametersNames, returnType, descriptor.builtIns, descriptor.isSuspend
)
}
is PropertyDescriptor -> {
@@ -397,6 +397,7 @@ fun SimpleFunctionDescriptor.createFunctionType(
builtIns,
Annotations.EMPTY,
extensionReceiverParameter?.type,
contextReceiverParameters.map { it.type },
if (shouldUseVarargType) valueParameters.map { it.varargElementType ?: it.type } else valueParameters.map { it.type },
null,
returnType ?: return null,