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.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<FqNameUnsafe> 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<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) {
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<Name> segments = fqName.pathSegments();
if (segments.size() != 2) return false;
private static boolean isTypeConstructorFqNameInSet(@NotNull JetType type, @NotNull Set<FqNameUnsafe> 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
@@ -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<Kind>): KindWithArity? {
for (kind in allowedKinds) {
val prefix = kind.classNamePrefix
if (!className.startsWith(prefix)) continue
companion object {
platformStatic public fun parseClassName(className: String, allowedKinds: Set<Kind>): 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? {