diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index 585a678e25a..05dbfa43bb3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -22,6 +22,7 @@ import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory; +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl; @@ -50,8 +51,6 @@ public class KotlinBuiltIns { public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin"); public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME); - public static final int FUNCTION_TRAIT_COUNT = 23; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static volatile KotlinBuiltIns instance = null; @@ -164,13 +163,11 @@ public class KotlinBuiltIns { public final FqNameUnsafe array = fqNameUnsafe("Array"); public final FqNameUnsafe _boolean = fqNameUnsafe("Boolean"); - public final FqNameUnsafe _char = fqNameUnsafe("Char"); public final FqNameUnsafe _byte = fqNameUnsafe("Byte"); public final FqNameUnsafe _short = fqNameUnsafe("Short"); public final FqNameUnsafe _int = fqNameUnsafe("Int"); public final FqNameUnsafe _long = fqNameUnsafe("Long"); - public final FqNameUnsafe _float = fqNameUnsafe("Float"); public final FqNameUnsafe _double = fqNameUnsafe("Double"); @@ -195,8 +192,6 @@ public class KotlinBuiltIns { } } - public final Set functionClasses = computeIndexedFqNames("Function", FUNCTION_TRAIT_COUNT); - @NotNull private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) { return fqName(simpleName).toUnsafe(); @@ -206,15 +201,6 @@ public class KotlinBuiltIns { private static FqName fqName(@NotNull String simpleName) { return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)); } - - @NotNull - private static Set computeIndexedFqNames(@NotNull String prefix, int count) { - Set result = new HashSet(); - for (int i = 0; i < count; i++) { - result.add(fqNameUnsafe(prefix + i)); - } - return result; - } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -764,31 +750,32 @@ public class KotlinBuiltIns { } public static boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) { - return isExactFunctionType(type) || isExactExtensionFunctionType(type); + ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); + return descriptor != null && isNumberedFunctionClassFqName(getFqName(descriptor)); } public static boolean isExactFunctionType(@NotNull JetType type) { - return isTypeConstructorFqNameInSet(type, FQ_NAMES.functionClasses) && !isTypeAnnotatedWithExtension(type); + return isExactFunctionOrExtensionFunctionType(type) && !isTypeAnnotatedWithExtension(type); } public static boolean isExactExtensionFunctionType(@NotNull JetType type) { - return isTypeConstructorFqNameInSet(type, FQ_NAMES.functionClasses) && isTypeAnnotatedWithExtension(type); + return isExactFunctionOrExtensionFunctionType(type) && isTypeAnnotatedWithExtension(type); } /** - * @return true if this is an FQ name of a fictitious class representing the function type, e.g. kotlin.Function1 + * @return true if this is an FQ name of a fictitious class representing the function type, + * e.g. kotlin.Function1 (but NOT kotlin.reflect.KFunction1) */ public static boolean isNumberedFunctionClassFqName(@NotNull FqNameUnsafe fqName) { - return FQ_NAMES.functionClasses.contains(fqName); - } + List segments = fqName.pathSegments(); + if (segments.size() != 2) return false; - private static boolean isTypeConstructorFqNameInSet(@NotNull JetType type, @NotNull Set classes) { - ClassifierDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); + if (!BUILT_INS_PACKAGE_NAME.equals(first(segments))) return false; - if (declarationDescriptor == null) return false; - - FqNameUnsafe fqName = getFqName(declarationDescriptor); - return classes.contains(fqName); + return BuiltInFictitiousFunctionClassFactory.parseClassName( + last(segments).asString(), + FunctionClassDescriptor.Kinds.Functions + ) != null; } @Nullable diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/BuiltInFictitiousFunctionClassFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/BuiltInFictitiousFunctionClassFactory.kt index d0e2ddf8522..c8b1f1247b2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/BuiltInFictitiousFunctionClassFactory.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/BuiltInFictitiousFunctionClassFactory.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory import org.jetbrains.kotlin.storage.StorageManager +import kotlin.platform.platformStatic /** * Produces descriptors representing the fictitious classes for function types, such as kotlin.Function1 or kotlin.reflect.KMemberFunction0. @@ -36,21 +37,25 @@ public class BuiltInFictitiousFunctionClassFactory( private data class KindWithArity(val kind: Kind, val arity: Int) - private fun parseClassName(className: String, allowedKinds: Set): KindWithArity? { - for (kind in allowedKinds) { - val prefix = kind.classNamePrefix - if (!className.startsWith(prefix)) continue + companion object { + platformStatic public fun parseClassName(className: String, allowedKinds: Set): KindWithArity? { + for (kind in allowedKinds) { + val prefix = kind.classNamePrefix + if (!className.startsWith(prefix)) continue - val arity = try { - className.substring(prefix.length()).toInt() + val arity = try { + className.substring(prefix.length()).toInt() + } + catch (e: NumberFormatException) { + continue + } + + // TODO: validate arity, should be <= 255 for functions, <= 254 for members/extensions + return KindWithArity(kind, arity) } - catch (e: NumberFormatException) { continue } - // TODO: validate arity, should be <= 255 for functions, <= 254 for members/extensions - return KindWithArity(kind, arity) + return null } - - return null } override fun createClass(classId: ClassId): ClassDescriptor? {