From 7d72875227fe8210ee0e1f9e7a59a19a4c70b506 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Tue, 19 Jan 2016 18:19:04 +0300 Subject: [PATCH] Create descriptors for parameters inside parameter list of KtFunctionType Do not throw when trying to resolveToDescriptor those parameters --- .../jetbrains/kotlin/resolve/TypeResolver.kt | 64 ++++++++++++++++--- .../kotlin/idea/ResolveElementCacheTest.kt | 17 +++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index f4474468396..c2c36e9f513 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -20,24 +20,25 @@ import com.intellij.util.SmartList import org.jetbrains.kotlin.context.TypeLazinessToken import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.resolve.PossiblyBareType.type -import org.jetbrains.kotlin.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.lazy.LazyEntity import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier +import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* @@ -196,18 +197,61 @@ class TypeResolver( } override fun visitFunctionType(type: KtFunctionType) { - val receiverTypeRef = type.getReceiverTypeReference() - type.parameters.forEach { identifierChecker.checkDeclaration(it, c.trace) } + val receiverTypeRef = type.receiverTypeReference val receiverType = if (receiverTypeRef == null) null else resolveType(c.noBareTypes(), receiverTypeRef) - type.parameters.forEach { checkParameterInFunctionType(it) } - val parameterTypes = type.getParameters().map { resolveType(c.noBareTypes(), it.getTypeReference()!!) } + val parameterDescriptors = resolveParametersOfFunctionType(type.parameters) - val returnTypeRef = type.getReturnTypeReference() - val returnType = if (returnTypeRef != null) - resolveType(c.noBareTypes(), returnTypeRef) + val returnTypeRef = type.returnTypeReference + val returnType = if (returnTypeRef != null) resolveType(c.noBareTypes(), returnTypeRef) else moduleDescriptor.builtIns.unitType - result = type(moduleDescriptor.builtIns.getFunctionType(annotations, receiverType, parameterTypes, returnType)) + + result = type( + moduleDescriptor.builtIns.getFunctionType( + annotations, receiverType, parameterDescriptors.map { it.type }, returnType + ) + ) + } + + private fun resolveParametersOfFunctionType(parameters: List): List { + class ParameterOfFunctionTypeDescriptor( + containingDeclaration: DeclarationDescriptor, + annotations: Annotations, + name: Name, + type: KotlinType, + source: SourceElement + ) : VariableDescriptorImpl(containingDeclaration, annotations, name, type, source) { + override fun getVisibility() = Visibilities.LOCAL + + override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor? { + throw UnsupportedOperationException("Should not be called for descriptor of type $javaClass") + } + + override fun isVar() = false + + override fun getCompileTimeInitializer() = null + + override fun accept(visitor: DeclarationDescriptorVisitor, data: D): R { + return visitor.visitVariableDescriptor(this, data) + } + } + + parameters.forEach { + identifierChecker.checkDeclaration(it, c.trace) + checkParameterInFunctionType(it) + } + return parameters.map { parameter -> + val parameterType = resolveType(c.noBareTypes(), parameter.typeReference!!) + val descriptor = ParameterOfFunctionTypeDescriptor( + c.scope.ownerDescriptor, + Annotations.EMPTY, + parameter.nameAsSafeName, + parameterType, + parameter.toSourceElement() + ) + c.trace.record(BindingContext.VALUE_PARAMETER, parameter, descriptor) + descriptor + } } override fun visitDynamicType(type: KtDynamicType) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt index 698782d28ff..9b0115e7976 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt @@ -18,9 +18,11 @@ package org.jetbrains.kotlin.idea import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext @@ -300,4 +302,19 @@ class C(param1: String = "", param2: Int = 0) { val fileAnnotationList = file.fileAnnotationList!! fileAnnotationList.analyze(BodyResolveMode.PARTIAL) } + + fun testNamedParametersInFunctionType() { + val file = myFixture.configureByText("Test.kt", """ + fun intercept(block: (key: K, next: (K) -> V, K) -> V) {} + """) as KtFile + + val function = file.declarations[0] as KtNamedFunction + val functionType = function.valueParameters.first().typeReference!!.typeElement as KtFunctionType + val descriptorsForParameters = functionType.parameters.map { it.resolveToDescriptor() } + + assert( + listOf("key", "next", SpecialNames.NO_NAME_PROVIDED.asString()) == + descriptorsForParameters.map { it.name.asString() } + ) + } }