Refactor KotlinBuiltIns#isFunctionType/isExtensionFunctionType
This commit is contained in:
@@ -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
|
||||||
|
|||||||
+16
-11
@@ -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? {
|
||||||
|
|||||||
Reference in New Issue
Block a user