Conform functions to extension functions and vice versa

#KT-5989 Fixed
This commit is contained in:
Alexander Udalov
2015-04-30 20:55:38 +03:00
parent b08bd3bc67
commit 49004a8b8e
44 changed files with 299 additions and 226 deletions
@@ -25,7 +25,9 @@ import org.jetbrains.kotlin.idea.decompiler.stubBuilder.FlagsToModifiers.VISIBIL
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.JetClassBody
import org.jetbrains.kotlin.psi.JetDelegationSpecifierList
import org.jetbrains.kotlin.psi.JetDelegatorToSuperClass
import org.jetbrains.kotlin.psi.stubs.elements.JetClassElementType
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
import org.jetbrains.kotlin.psi.stubs.impl.KotlinClassStubImpl
@@ -103,11 +105,10 @@ private class ClassClsStubBuilder(
val isCompanionObject = classKind == ProtoBuf.Class.Kind.CLASS_OBJECT
val fqName = outerContext.containerFqName.child(classId.getShortClassName())
val shortName = fqName.shortName().ref()
val superTypeRefs = supertypeIds.filter {
val superTypeRefs = supertypeIds.filterNot {
//TODO: filtering function types should go away
!KotlinBuiltIns.isExactFunctionType(it.asSingleFqName().toUnsafe()) &&
!KotlinBuiltIns.isExactExtensionFunctionType(it.asSingleFqName().toUnsafe())
}.map { it.getShortClassName().ref() }.copyToArray()
KotlinBuiltIns.isNumberedFunctionClassFqName(it.asSingleFqName().toUnsafe())
}.map { it.getShortClassName().ref() }.toTypedArray()
return when (classKind) {
ProtoBuf.Class.Kind.OBJECT, ProtoBuf.Class.Kind.CLASS_OBJECT -> {
KotlinObjectStubImpl(
@@ -184,7 +185,7 @@ private class ClassClsStubBuilder(
classBody,
qualifiedName = c.containerFqName.child(name).ref(),
name = name.ref(),
superNames = array(),
superNames = arrayOf(),
isTrait = false,
isEnumEntry = true,
isLocal = false,
@@ -42,35 +42,31 @@ import java.util.ArrayList
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, typeProto: Type) {
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type) {
val typeReference = KotlinPlaceHolderStubImpl<JetTypeReference>(parent, JetStubElementTypes.TYPE_REFERENCE)
val typeAnnotations = c.components.annotationLoader.loadTypeAnnotations(typeProto, c.nameResolver).filterNot {
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
val isTopLevelClass = !it.isNestedClass()
isTopLevelClass && it.asSingleFqName() in JvmAnnotationNames.ANNOTATIONS_COPIED_TO_TYPES
}
if (typeAnnotations.isNotEmpty()) {
createAnnotationStubs(typeAnnotations, typeReference, needWrappingAnnotationEntries = true)
}
createTypeStub(typeReference, typeProto)
}
val effectiveParent =
if (type.getNullable()) KotlinPlaceHolderStubImpl<JetNullableType>(typeReference, JetStubElementTypes.NULLABLE_TYPE)
else typeReference
private fun createTypeStub(parent: StubElement<out PsiElement>, type: Type) {
val isNullable = type.getNullable()
val effectiveParent = if (isNullable) KotlinPlaceHolderStubImpl<JetNullableType>(parent, JetStubElementTypes.NULLABLE_TYPE) else parent
when (type.getConstructor().getKind()) {
Type.Constructor.Kind.CLASS -> {
createClassReferenceTypeStub(effectiveParent, type)
createClassReferenceTypeStub(effectiveParent, type, annotations)
}
Type.Constructor.Kind.TYPE_PARAMETER -> {
createTypeAnnotationStubs(effectiveParent, annotations)
val typeParameterName = c.typeParameters[type.getConstructor().getId()]
createStubForTypeName(ClassId.topLevel(FqName.topLevel(typeParameterName)), effectiveParent)
}
}
}
private fun createClassReferenceTypeStub(parent: StubElement<out PsiElement>, type: Type) {
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
if (type.hasFlexibleTypeCapabilitiesId()) {
val id = c.nameResolver.getString(type.getFlexibleTypeCapabilitiesId())
@@ -81,17 +77,19 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
val classId = c.nameResolver.getClassId(type.getConstructor().getId())
val fqName = classId.asSingleFqName().toUnsafe()
val isFunctionType = KotlinBuiltIns.isExactFunctionType(fqName)
val isExtensionFunctionType = KotlinBuiltIns.isExactExtensionFunctionType(fqName)
if (isFunctionType || isExtensionFunctionType) {
createFunctionTypeStub(parent, type, isExtensionFunctionType)
if (KotlinBuiltIns.isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe())) {
val extension = annotations.any { annotation -> annotation.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extension }
createFunctionTypeStub(parent, type, extension)
return
}
createTypeAnnotationStubs(parent, annotations)
val typeStub = createStubForTypeName(classId, parent)
val typeArgumentProtoList = type.getArgumentList()
createTypeArgumentListStub(typeStub, typeArgumentProtoList)
return
}
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, annotations: List<ClassId>) {
createAnnotationStubs(annotations, parent, needWrappingAnnotationEntries = true)
}
private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) {
@@ -129,7 +127,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
val parameterList = KotlinPlaceHolderStubImpl<JetParameterList>(functionType, JetStubElementTypes.VALUE_PARAMETER_LIST)
val typeArgumentsWithoutReceiverAndReturnType
= typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size - 1)
= typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size() - 1)
typeArgumentsWithoutReceiverAndReturnType.forEach { argument ->
val parameter = KotlinParameterStubImpl(parameterList, fqName = null, name = null, isMutable = false, hasValOrVarNode = false, hasDefaultValue = false)
createTypeReferenceStub(parameter, argument.getType())
@@ -62,8 +62,8 @@ private fun JetTypeElement.index<TDeclaration : JetCallableDeclaration>(declarat
is JetNullableType -> getInnerType()?.index(declaration, sink)
is JetFunctionType -> {
val typeName = (if (getReceiverTypeReference() != null) "ExtensionFunction" else "Function") + getParameters().size()
occurrence(typeName)
val arity = getParameters().size() + (if (getReceiverTypeReference() != null) 1 else 0)
occurrence("Function$arity")
}
is JetDynamicType -> occurrence("Any")