Build proper modifier list stubs for 'SuspendFunction$n<...>' types.

This commit is contained in:
Dmitry Petrov
2016-12-14 15:32:25 +03:00
committed by Stanislav Erokhin
parent cf4fb1eb25
commit 9dc458375a
4 changed files with 46 additions and 7 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
@@ -72,6 +73,12 @@ val KotlinType.isBuiltinFunctionalType: Boolean
kind == FunctionClassDescriptor.Kind.SuspendFunction
}
fun isBuiltinFunctionClass(classId: ClassId): Boolean {
val kind = classId.asSingleFqName().toUnsafe().getFunctionalClassKind()
return kind == FunctionClassDescriptor.Kind.Function ||
kind == FunctionClassDescriptor.Kind.SuspendFunction
}
val KotlinType.isNonExtensionFunctionType: Boolean
get() = isBuiltinFunctionalType && !isTypeAnnotatedWithExtensionFunctionType
@@ -99,8 +106,12 @@ fun DeclarationDescriptor.getFunctionalClassKind(): FunctionClassDescriptor.Kind
if (this !is ClassDescriptor) return null
val fqNameUnsafe = this.fqNameUnsafe
if (!fqNameUnsafe.isSafe || fqNameUnsafe.isRoot) return null
val fqName = fqNameUnsafe.toSafe()
return fqNameUnsafe.getFunctionalClassKind()
}
fun FqNameUnsafe.getFunctionalClassKind(): FunctionClassDescriptor.Kind? {
if (!isSafe || isRoot) return null
val fqName = toSafe()
return BuiltInFictitiousFunctionClassFactory.getFunctionalClassKind(fqName.shortName().asString(), fqName.parent())
}
@@ -19,7 +19,9 @@ package org.jetbrains.kotlin.idea.decompiler.stubBuilder
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isNumberedFunctionClassFqName
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.builtins.isBuiltinFunctionClass
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.ANNOTATIONS_COPIED_TO_TYPES
@@ -89,7 +91,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName)
val shouldBuildAsFunctionType = isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe())
val shouldBuildAsFunctionType = isBuiltinFunctionClass(classId)
&& type.argumentList.none { it.projection == Projection.STAR }
if (shouldBuildAsFunctionType) {
val (extensionAnnotations, notExtensionAnnotations) =
@@ -114,13 +116,24 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
// TODO Calculate type modifiers mask, see 'ModifierMaskUtils.computeMask'
val typeModifiersMask = 0
if (annotations.isEmpty()) return
val typeModifiers = getTypeModifiersAsWritten(type)
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
val typeModifiersMask = ModifierMaskUtils.computeMask { it in typeModifiers }
val modifiersList = KotlinModifierListStubImpl(parent, typeModifiersMask, KtStubElementTypes.MODIFIER_LIST)
createAnnotationStubs(annotations, modifiersList)
}
private fun getTypeModifiersAsWritten(type: Type): Set<KtModifierKeywordToken> {
val result = hashSetOf<KtModifierKeywordToken>()
val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName)
if (classId.asSingleFqName().toUnsafe().getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction) {
result.add(KtTokens.SUSPEND_KEYWORD)
}
return result
}
private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) {
if (typeArgumentProtoList.isEmpty()) {
return
@@ -1,4 +1,6 @@
public class TypeModifiers {
val function: () -> Unit = null!!
val suspendFunction: suspend () -> Unit = null!!
val suspendExtFunction: suspend Any.() -> Unit = null!!
@@ -7,12 +7,23 @@ PsiJetFileStubImpl[package=]
MODIFIER_LIST[public]
VALUE_PARAMETER_LIST
CLASS_BODY
PROPERTY[fqName=TypeModifiers.function, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=function]
MODIFIER_LIST[public final]
TYPE_REFERENCE
FUNCTION_TYPE
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
PROPERTY[fqName=TypeModifiers.functionOnSuspendFunction, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=functionOnSuspendFunction]
MODIFIER_LIST[public final]
TYPE_REFERENCE
FUNCTION_TYPE
FUNCTION_TYPE_RECEIVER
TYPE_REFERENCE
MODIFIER_LIST[suspend]
FUNCTION_TYPE
VALUE_PARAMETER_LIST
TYPE_REFERENCE
@@ -29,6 +40,7 @@ PsiJetFileStubImpl[package=]
PROPERTY[fqName=TypeModifiers.suspendExtFunction, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=suspendExtFunction]
MODIFIER_LIST[public final]
TYPE_REFERENCE
MODIFIER_LIST[suspend]
FUNCTION_TYPE
FUNCTION_TYPE_RECEIVER
TYPE_REFERENCE
@@ -45,6 +57,7 @@ PsiJetFileStubImpl[package=]
PROPERTY[fqName=TypeModifiers.suspendFunction, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=suspendFunction]
MODIFIER_LIST[public final]
TYPE_REFERENCE
MODIFIER_LIST[suspend]
FUNCTION_TYPE
VALUE_PARAMETER_LIST
TYPE_REFERENCE