From 147d1da1edac59abfeb671c454023d1a3365e70f Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 13 Sep 2016 12:07:59 +0300 Subject: [PATCH] Supported obtaining function type parameter names from KotlinType --- .../kotlin/codegen/JvmRuntimeTypes.java | 20 ++++++++++++++++-- .../java/sam/SingleAbstractMethodUtils.java | 5 ++++- .../jetbrains/kotlin/resolve/TypeResolver.kt | 5 ++++- .../resolve/calls/ArgumentTypeResolver.java | 14 ++++++++++--- .../kotlin/resolve/calls/CallResolver.java | 5 ++++- .../inference/ConstraintSystemBuilderImpl.kt | 6 +++++- .../resolve/calls/tasks/dynamicCalls.kt | 4 +++- .../expressions/FunctionsTypingVisitor.kt | 1 + .../calls/util/functionTypeResolveUtils.kt | 10 ++++----- .../kotlin/types/KotlinTypeFactory.kt | 10 +++++++++ .../jetbrains/kotlin/types/SpecialTypes.kt | 21 ++++++++++++++++++- .../extractionEngine/inferParameterInfo.kt | 2 ++ 12 files changed, 86 insertions(+), 17 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.java index f989a07fa64..8bdd92061b2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.java @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.codegen; +import kotlin.collections.CollectionsKt; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.coroutines.CoroutineUtilKt; import org.jetbrains.kotlin.descriptors.*; @@ -101,11 +103,18 @@ public class JvmRuntimeTypes { ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); //noinspection ConstantConditions + List parameters = descriptor.getValueParameters(); KotlinType functionType = FunctionTypeResolveUtilsKt.createFunctionType( DescriptorUtilsKt.getBuiltIns(descriptor), Annotations.Companion.getEMPTY(), receiverParameter == null ? null : receiverParameter.getType(), - ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()), + ExpressionTypingUtils.getValueParametersTypes(parameters), + CollectionsKt.map(parameters, new Function1() { + @Override + public Name invoke(ValueParameterDescriptor descriptor) { + return descriptor.getName(); + } + }), descriptor.getReturnType() ); @@ -128,11 +137,18 @@ public class JvmRuntimeTypes { extensionReceiver != null ? extensionReceiver.getType() : dispatchReceiver != null ? dispatchReceiver.getType() : null; //noinspection ConstantConditions + List parameters = descriptor.getValueParameters(); KotlinType functionType = FunctionTypeResolveUtilsKt.createFunctionType( DescriptorUtilsKt.getBuiltIns(descriptor), Annotations.Companion.getEMPTY(), isBound ? null : receiverType, - ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()), + ExpressionTypingUtils.getValueParametersTypes(parameters), + CollectionsKt.map(parameters, new Function1() { + @Override + public Name invoke(ValueParameterDescriptor descriptor) { + return descriptor.getName(); + } + }), descriptor.getReturnType() ); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java index 65ba56329d2..115c2ea42b1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SingleAbstractMethodUtils.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.load.java.descriptors.*; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.calls.util.FunctionTypeResolveUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; @@ -101,11 +102,13 @@ public class SingleAbstractMethodUtils { assert returnType != null : "function is not initialized: " + function; List valueParameters = function.getValueParameters(); List parameterTypes = new ArrayList(valueParameters.size()); + List parameterNames = new ArrayList(valueParameters.size()); for (ValueParameterDescriptor parameter : valueParameters) { parameterTypes.add(parameter.getType()); + parameterNames.add(function.hasSynthesizedParameterNames() ? SpecialNames.NO_NAME_PROVIDED : parameter.getName()); } return FunctionTypeResolveUtilsKt.createFunctionType( - DescriptorUtilsKt.getBuiltIns(function), Annotations.Companion.getEMPTY(), null, parameterTypes, returnType + DescriptorUtilsKt.getBuiltIns(function), Annotations.Companion.getEMPTY(), null, parameterTypes, parameterNames, returnType ); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index e49da6592bf..fa66d9d2941 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -213,7 +213,10 @@ class TypeResolver( else moduleDescriptor.builtIns.unitType result = type(createFunctionType( - moduleDescriptor.builtIns, annotations, receiverType, parameterDescriptors.map { it.type }, returnType + moduleDescriptor.builtIns, annotations, receiverType, + parameterDescriptors.map { it.type }, + parameterDescriptors.map { it.name }, + returnType )) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index e1e6d7f6fb5..fc5d1ddcec3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.ReflectionTypes; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.diagnostics.Errors; +import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.TemporaryBindingTrace; @@ -270,7 +272,7 @@ public class ArgumentTypeResolver { } return FunctionTypeResolveUtilsKt.createFunctionType( - builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), TypeUtils.DONT_CARE + builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), Collections.emptyList(), TypeUtils.DONT_CARE ); } @@ -301,15 +303,21 @@ public class ArgumentTypeResolver { ? functionPlaceholders .createFunctionPlaceholderType(Collections.emptyList(), /* hasDeclaredArguments = */ false) : FunctionTypeResolveUtilsKt.createFunctionType( - builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), DONT_CARE + builtIns, Annotations.Companion.getEMPTY(), null, Collections.emptyList(), Collections.emptyList(), DONT_CARE ); } List valueParameters = function.getValueParameters(); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create( trace, "trace to resolve function literal parameter types"); List parameterTypes = Lists.newArrayList(); + List parameterNames = Lists.newArrayList(); for (KtParameter parameter : valueParameters) { parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE)); + Name name = parameter.getNameAsName(); + if (name == null) { + name = SpecialNames.NO_NAME_PROVIDED; + } + parameterNames.add(name); } KotlinType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE); assert returnType != null; @@ -318,7 +326,7 @@ public class ArgumentTypeResolver { return expectedTypeIsUnknown && isFunctionLiteral ? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true) : FunctionTypeResolveUtilsKt.createFunctionType( - builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, returnType + builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, parameterNames, returnType ); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index e8cb54df785..837460de7d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.*; @@ -290,11 +291,13 @@ public class CallResolver { if (calleeExpression instanceof KtLambdaExpression) { int parameterNumber = ((KtLambdaExpression) calleeExpression).getValueParameters().size(); List parameterTypes = new ArrayList(parameterNumber); + List parameterNames = new ArrayList(parameterNumber); for (int i = 0; i < parameterNumber; i++) { parameterTypes.add(NO_EXPECTED_TYPE); + parameterNames.add(SpecialNames.NO_NAME_PROVIDED); } expectedType = FunctionTypeResolveUtilsKt.createFunctionType( - builtIns, Annotations.Companion.getEMPTY(), null, parameterTypes, context.expectedType + builtIns, Annotations.Companion.getEMPTY(), null, parameterTypes, parameterNames, context.expectedType ); } KotlinType calleeType = expressionTypingServices.safeGetType( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt index 92fec3c37fe..db8ee4ce113 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.SUB_TYPE import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound @@ -37,6 +38,8 @@ import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.defaultProjections import org.jetbrains.kotlin.types.typeUtil.isDefaultBound +import java.lang.IllegalArgumentException +import java.lang.IllegalStateException import java.util.* open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystemBuilderImpl.Mode.INFERENCE) : ConstraintSystem.Builder { @@ -446,5 +449,6 @@ internal fun createTypeForFunctionPlaceholder( functionPlaceholderTypeConstructor.argumentTypes } val receiverType = if (isExtension) DONT_CARE else null - return createFunctionType(functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, DONT_CARE) + val parameterNames = newArgumentTypes.map { SpecialNames.NO_NAME_PROVIDED } + return createFunctionType(functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, parameterNames, DONT_CARE) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt index 18bbc56e081..426fcf1304c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.calls.util.createFunctionType @@ -175,8 +176,9 @@ class DynamicCallableDescriptors(builtIns: KotlinBuiltIns) { val receiverType = funLiteral.receiverTypeReference?.let { dynamicType } val parameterTypes = funLiteral.valueParameters.map { dynamicType } + val parameterNames = funLiteral.valueParameters.map { it.nameAsName ?: SpecialNames.NO_NAME_PROVIDED } - return createFunctionType(owner.builtIns, Annotations.EMPTY, receiverType, parameterTypes, dynamicType) + return createFunctionType(owner.builtIns, Annotations.EMPTY, receiverType, parameterTypes, parameterNames, dynamicType) } for (arg in call.valueArguments) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index b63cb515ecb..5cb941af306 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -132,6 +132,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre Annotations.EMPTY, extensionReceiverParameter?.type, valueParameters.map { it.type }, + valueParameters.map { it.name }, returnType ?: return null ) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/util/functionTypeResolveUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/util/functionTypeResolveUtils.kt index c83179a2471..17298f068b1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/util/functionTypeResolveUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/util/functionTypeResolveUtils.kt @@ -28,10 +28,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.SimpleType -import org.jetbrains.kotlin.types.TypeProjection +import org.jetbrains.kotlin.types.* fun createValueParametersForInvokeInFunctionType( functionDescriptor: FunctionDescriptor, parameterTypes: List @@ -54,8 +51,9 @@ fun createFunctionType( annotations: Annotations, receiverType: KotlinType?, parameterTypes: List, + parameterNames: List, returnType: KotlinType -): SimpleType { +): FunctionType { val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType) val size = parameterTypes.size val classDescriptor = builtIns.getFunction(if (receiverType == null) size else size + 1) @@ -74,7 +72,7 @@ fun createFunctionType( AnnotationsImpl(annotations + extensionFunctionAnnotation) } - return KotlinTypeFactory.simpleNotNullType(typeAnnotations, classDescriptor, arguments) + return KotlinTypeFactory.functionType(typeAnnotations, classDescriptor, arguments, parameterNames) } fun getValueParametersCountFromFunctionType(type: KotlinType): Int { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt index 5f83a238060..aa10c2c1fd0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt @@ -20,7 +20,9 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope +import java.lang.IllegalStateException object KotlinTypeFactory { private fun computeMemberScope(constructor: TypeConstructor, arguments: List): MemberScope { @@ -49,6 +51,14 @@ object KotlinTypeFactory { arguments: List ): SimpleType = SimpleTypeImpl(annotations, descriptor.typeConstructor, arguments, false, descriptor.getMemberScope(arguments)) + @JvmStatic + fun functionType( + annotations: Annotations, + descriptor: ClassDescriptor, + arguments: List, + parameterNames: List + ): FunctionType = FunctionType(simpleNotNullType(annotations, descriptor, arguments), parameterNames) + @JvmStatic fun simpleType( baseType: SimpleType, diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt index 7219165c116..677c120f537 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.StorageManager @@ -42,13 +43,31 @@ class AbbreviatedType(override val delegate: SimpleType, val abbreviation: Simpl override val isError: Boolean get() = false } -fun KotlinType.getAbbreviatedType(): AbbreviatedType? = (unwrap() as? AbbreviatedType) +fun KotlinType.getAbbreviatedType(): AbbreviatedType? = unwrap() as? AbbreviatedType fun SimpleType.withAbbreviation(abbreviatedType: SimpleType): SimpleType { if (isError) return this return AbbreviatedType(this, abbreviatedType) } +class FunctionType( + override val delegate: SimpleType, + /** + * SpecialNames.NO_NAME_PROVIDED if no parameter name specified + */ + val parameterNames: List +) : DelegatingSimpleType() { + override fun replaceAnnotations(newAnnotations: Annotations) + = FunctionType(delegate.replaceAnnotations(newAnnotations), parameterNames) + + override fun makeNullableAsSpecified(newNullability: Boolean) + = FunctionType(delegate.makeNullableAsSpecified(newNullability), parameterNames) + + override val isError: Boolean get() = false +} + +fun KotlinType.getFunctionTypeParameterNames(): List? = (unwrap() as? FunctionType)?.parameterNames + class LazyWrappedType(storageManager: StorageManager, computation: () -> KotlinType): WrappedType() { private val lazyValue = storageManager.createLazyValue(computation) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt index 62d6a2b4947..2959cc64b35 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt @@ -53,6 +53,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.findFunction import org.jetbrains.kotlin.types.CommonSupertypes import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.OperatorConventions +import java.lang.AssertionError import java.util.* internal class ParametersInfo { @@ -303,6 +304,7 @@ private fun suggestParameterType( Annotations.EMPTY, originalDescriptor.extensionReceiverParameter?.type, originalDescriptor.valueParameters.map { it.type }, + originalDescriptor.valueParameters.map { it.name }, originalDescriptor.returnType ?: builtIns.defaultReturnType ) }