Refactor KotlinBuiltIns#isFunctionType/isExtensionFunctionType

This commit is contained in:
Alexander Udalov
2015-05-25 11:56:47 +03:00
parent 6a0a703539
commit 7f0b5029eb
2 changed files with 30 additions and 38 deletions
@@ -22,6 +22,7 @@ import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory; import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory;
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl; 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 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 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; private static volatile KotlinBuiltIns instance = null;
@@ -164,13 +163,11 @@ public class KotlinBuiltIns {
public final FqNameUnsafe array = fqNameUnsafe("Array"); public final FqNameUnsafe array = fqNameUnsafe("Array");
public final FqNameUnsafe _boolean = fqNameUnsafe("Boolean"); public final FqNameUnsafe _boolean = fqNameUnsafe("Boolean");
public final FqNameUnsafe _char = fqNameUnsafe("Char"); public final FqNameUnsafe _char = fqNameUnsafe("Char");
public final FqNameUnsafe _byte = fqNameUnsafe("Byte"); public final FqNameUnsafe _byte = fqNameUnsafe("Byte");
public final FqNameUnsafe _short = fqNameUnsafe("Short"); public final FqNameUnsafe _short = fqNameUnsafe("Short");
public final FqNameUnsafe _int = fqNameUnsafe("Int"); public final FqNameUnsafe _int = fqNameUnsafe("Int");
public final FqNameUnsafe _long = fqNameUnsafe("Long"); public final FqNameUnsafe _long = fqNameUnsafe("Long");
public final FqNameUnsafe _float = fqNameUnsafe("Float"); public final FqNameUnsafe _float = fqNameUnsafe("Float");
public final FqNameUnsafe _double = fqNameUnsafe("Double"); public final FqNameUnsafe _double = fqNameUnsafe("Double");
@@ -195,8 +192,6 @@ public class KotlinBuiltIns {
} }
} }
public final Set<FqNameUnsafe> functionClasses = computeIndexedFqNames("Function", FUNCTION_TRAIT_COUNT);
@NotNull @NotNull
private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) { private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) {
return fqName(simpleName).toUnsafe(); return fqName(simpleName).toUnsafe();
@@ -206,15 +201,6 @@ public class KotlinBuiltIns {
private static FqName fqName(@NotNull String simpleName) { private static FqName fqName(@NotNull String simpleName) {
return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)); return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName));
} }
@NotNull
private static Set<FqNameUnsafe> computeIndexedFqNames(@NotNull String prefix, int count) {
Set<FqNameUnsafe> result = new HashSet<FqNameUnsafe>();
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) { 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) { 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) { 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) { public static boolean isNumberedFunctionClassFqName(@NotNull FqNameUnsafe fqName) {
return FQ_NAMES.functionClasses.contains(fqName); List<Name> segments = fqName.pathSegments();
} if (segments.size() != 2) return false;
private static boolean isTypeConstructorFqNameInSet(@NotNull JetType type, @NotNull Set<FqNameUnsafe> classes) { if (!BUILT_INS_PACKAGE_NAME.equals(first(segments))) return false;
ClassifierDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor == null) return false; return BuiltInFictitiousFunctionClassFactory.parseClassName(
last(segments).asString(),
FqNameUnsafe fqName = getFqName(declarationDescriptor); FunctionClassDescriptor.Kinds.Functions
return classes.contains(fqName); ) != null;
} }
@Nullable @Nullable
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
import org.jetbrains.kotlin.storage.StorageManager 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. * 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 data class KindWithArity(val kind: Kind, val arity: Int)
private fun parseClassName(className: String, allowedKinds: Set<Kind>): KindWithArity? { companion object {
for (kind in allowedKinds) { platformStatic public fun parseClassName(className: String, allowedKinds: Set<Kind>): KindWithArity? {
val prefix = kind.classNamePrefix for (kind in allowedKinds) {
if (!className.startsWith(prefix)) continue val prefix = kind.classNamePrefix
if (!className.startsWith(prefix)) continue
val arity = try { val arity = try {
className.substring(prefix.length()).toInt() 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 null
return KindWithArity(kind, arity)
} }
return null
} }
override fun createClass(classId: ClassId): ClassDescriptor? { override fun createClass(classId: ClassId): ClassDescriptor? {