diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt index df3b922580c..3a2220ba727 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functionTypes.kt @@ -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()) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt index ef6300b9a4a..21d63154fbd 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt @@ -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) { - // 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 { + val result = hashSetOf() + 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) { if (typeArgumentProtoList.isEmpty()) { return diff --git a/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.kt b/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.kt index feaa33d0d72..232f2d1bffd 100644 --- a/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.kt +++ b/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.kt @@ -1,4 +1,6 @@ public class TypeModifiers { + val function: () -> Unit = null!! + val suspendFunction: suspend () -> Unit = null!! val suspendExtFunction: suspend Any.() -> Unit = null!! diff --git a/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.txt b/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.txt index d30b77a21ae..19fdad621ae 100644 --- a/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.txt +++ b/idea/testData/decompiler/stubBuilder/TypeModifiers/TypeModifiers.txt @@ -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