Support class literals (A::class)

This commit is contained in:
Alexander Udalov
2015-03-05 22:01:50 +03:00
parent 2b089e0f39
commit 6e45c6f17c
22 changed files with 316 additions and 39 deletions
@@ -30,11 +30,11 @@ import kotlin.KotlinPackage;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
import org.jetbrains.kotlin.codegen.context.*;
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
import org.jetbrains.kotlin.codegen.inline.*;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
@@ -2610,6 +2610,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return lookupLocalIndex(declarationDescriptor);
}
@Override
public StackValue visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, StackValue data) {
JetType type = bindingContext.get(EXPRESSION_TYPE, expression);
assert type != null;
assert state.getReflectionTypes().getkClass().getTypeConstructor().equals(type.getConstructor())
: "::class expression should be type checked to a KClass: " + type;
ClassifierDescriptor typeArgument = KotlinPackage.single(type.getArguments()).getType().getConstructor().getDeclarationDescriptor();
assert typeArgument instanceof ClassDescriptor : "KClass argument should be a class: " + typeArgument;
return generateClassLiteralReference((ClassDescriptor) typeArgument);
}
@Override
public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
@@ -2690,10 +2704,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public Unit invoke(InstructionAdapter v) {
v.visitLdcInsn(descriptor.getName().asString());
StackValue receiverClass = generateClassLiteralReference(containingClass);
receiverClass.put(receiverClass.type, v);
v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false);
Type classAsmType = typeMapper.mapClass(containingClass);
return Unit.INSTANCE$;
}
});
}
if (containingClass instanceof JavaClassDescriptor) {
@NotNull
private StackValue generateClassLiteralReference(@NotNull final ClassDescriptor descriptor) {
return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
Type classAsmType = typeMapper.mapClass(descriptor);
if (descriptor instanceof JavaClassDescriptor) {
v.aconst(classAsmType);
v.invokestatic(REFLECTION, "foreignKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false);
}
@@ -2701,8 +2727,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
}
v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false);
return Unit.INSTANCE$;
}
});
@@ -117,6 +117,8 @@ public class GenerationState {
@Nullable
private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
private final ReflectionTypes reflectionTypes;
private final JvmRuntimeTypes runtimeTypes;
@NotNull
@@ -187,7 +189,7 @@ public class GenerationState {
this.disableParamAssertions = disableParamAssertions;
this.generateClassFilter = generateClassFilter;
ReflectionTypes reflectionTypes = new ReflectionTypes(module);
this.reflectionTypes = new ReflectionTypes(module);
this.runtimeTypes = new JvmRuntimeTypes(reflectionTypes);
}
@@ -259,6 +261,11 @@ public class GenerationState {
return generateClassFilter;
}
@NotNull
public ReflectionTypes getReflectionTypes() {
return reflectionTypes;
}
@NotNull
public JvmRuntimeTypes getJvmRuntimeTypes() {
return runtimeTypes;