Create descriptors for parameters inside parameter list of KtFunctionType

Do not throw when trying to resolveToDescriptor those parameters
This commit is contained in:
Pavel V. Talanov
2016-01-19 18:19:04 +03:00
parent 23480a5698
commit 7d72875227
2 changed files with 71 additions and 10 deletions
@@ -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<KtParameter>): List<VariableDescriptor> {
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 <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, 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) {
@@ -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 <K, V> 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() }
)
}
}