Generate bytecode for delegated properties

This commit is contained in:
Natalia.Ukhorskaya
2013-04-22 13:59:37 +04:00
parent 3297c0e9d3
commit 6e2584d0de
33 changed files with 731 additions and 50 deletions
@@ -263,10 +263,11 @@ public class CodegenUtil {
return false;
}
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass) {
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass, boolean isDelegated) {
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
return isInsideClass &&
!isDelegated &&
!isExtensionProperty &&
(accessorDescriptor == null ||
accessorDescriptor.isDefault() &&
@@ -1660,6 +1660,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return myFrameMap.getIndex(descriptor);
}
@Nullable
private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) {
PropertyGetterDescriptor getter = descriptor.getGetter();
if (getter != null) {
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, getter);
return call != null ? call.getExplicitReceiver().getType() : null;
}
return null;
}
@NotNull
public StackValue.Property intermediateValueForProperty(
PropertyDescriptor propertyDescriptor,
@@ -1688,12 +1698,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
boolean isDelegatedProperty = delegateType != null;
CallableMethod callableGetter = null;
CallableMethod callableSetter = null;
if (!forceField) {
//noinspection ConstantConditions
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass)) {
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) {
callableGetter = null;
}
else {
@@ -1715,7 +1728,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (propertyDescriptor.isVar()) {
if (propertyDescriptor.getSetter() != null) {
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass)) {
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty)) {
callableSetter = null;
}
else {
@@ -1736,8 +1749,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
owner = callableMethod.getOwner();
}
return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(propertyDescriptor.getOriginal().getType()),
isStatic, callableGetter, callableSetter, state);
if (isDelegatedProperty && forceField) {
return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(delegateType),
isStatic, true, callableGetter, callableSetter, state);
}
else {
return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(propertyDescriptor.getOriginal().getType()),
isStatic, false, callableGetter, callableSetter, state);
}
}
@Override
@@ -1864,7 +1883,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return (MemberDescriptor) descriptor;
}
private StackValue invokeFunction(
public StackValue invokeFunction(
Call call,
StackValue receiver,
ResolvedCall<? extends CallableDescriptor> resolvedCall
@@ -1531,10 +1531,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
assert propertyDescriptor != null;
JetExpression initializer = property.getInitializer();
JetExpression initializer = property.getDelegateExpressionOrInitializer();
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
JetType jetType = propertyDescriptor.getType();
JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor);
Type type = codegen.expressionType(initializer);
if (jetType.isNullable()) {
type = boxType(type);
@@ -1542,14 +1542,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
codegen.gen(initializer, type);
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
propValue.store(propValue.type, iv);
propValue.store(type, iv);
}
public static boolean shouldInitializeProperty(
@NotNull JetProperty property,
@NotNull JetTypeMapper typeMapper
) {
JetExpression initializer = property.getInitializer();
JetExpression initializer = property.getDelegateExpressionOrInitializer();
if (initializer == null) return false;
CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
@@ -1559,10 +1559,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert propertyDescriptor != null;
Object value = compileTimeValue.getValue();
Type type = typeMapper.mapType(propertyDescriptor.getType());
JetType jetType = getPropertyOrDelegateType(typeMapper.getBindingContext(), property, propertyDescriptor);
Type type = typeMapper.mapType(jetType);
return !skipDefaultValue(propertyDescriptor, value, type);
}
@NotNull
private static JetType getPropertyOrDelegateType(@NotNull BindingContext bindingContext, @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) {
JetExpression delegateExpression = property.getDelegateExpression();
if (delegateExpression != null) {
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression);
assert delegateType != null : "Type of delegate expression should be recorded";
return delegateType;
}
return descriptor.getType();
}
private static boolean skipDefaultValue(PropertyDescriptor propertyDescriptor, Object value, Type type) {
if (isPrimitive(type)) {
if (!propertyDescriptor.getType().isNullable() && value instanceof Number) {
@@ -34,11 +34,13 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import static org.jetbrains.asm4.Opcodes.*;
@@ -86,38 +88,63 @@ public class PropertyCodegen extends GenerationStateAware {
private void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
//noinspection ConstantConditions
if (bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
boolean hasBackingField = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null;
if (hasBackingField || isDelegated) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration)) {
return;
}
Object value = null;
JetExpression initializer = p instanceof JetProperty ? ((JetProperty) p).getInitializer() : null;
if (initializer != null) {
if (initializer instanceof JetConstantExpression && !propertyDescriptor.getType().isNullable()) {
CompileTimeConstant<?> compileTimeValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, initializer);
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
}
}
int modifiers;
if (kind == OwnerKind.NAMESPACE) {
modifiers = ACC_STATIC;
}
else {
modifiers = ACC_PRIVATE;
}
if (!propertyDescriptor.isVar()) {
modifiers |= ACC_FINAL;
}
modifiers |= getDeprecatedAccessFlag(propertyDescriptor);
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
modifiers |= ACC_VOLATILE;
}
Type type = typeMapper.mapType(propertyDescriptor);
FieldVisitor fieldVisitor = v.newField(p, modifiers, propertyDescriptor.getName().getName(), type.getDescriptor(), null, value);
FieldVisitor fieldVisitor = hasBackingField
? generateBackingFieldAccess(p, propertyDescriptor)
: generatePropertyDelegateAccess((JetProperty) p, propertyDescriptor);
AnnotationCodegen.forField(fieldVisitor, typeMapper).genAnnotations(propertyDescriptor);
}
}
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
int modifiers = ACC_PRIVATE | ACC_FINAL | getDeprecatedAccessFlag(propertyDescriptor);
if (kind == OwnerKind.NAMESPACE) {
modifiers |= ACC_STATIC;
}
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
modifiers |= ACC_VOLATILE;
}
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
assert delegateType != null : "Type of delegate should be recorded: " + p.getText();
Type type = typeMapper.mapType(delegateType);
return v.newField(p, modifiers, JvmAbi.getPropertyDelegateName(propertyDescriptor.getName()), type.getDescriptor(),
null, null);
}
private FieldVisitor generateBackingFieldAccess(PsiElement p, PropertyDescriptor propertyDescriptor) {
Object value = null;
JetExpression initializer = p instanceof JetProperty ? ((JetProperty) p).getInitializer() : null;
if (initializer != null) {
if (initializer instanceof JetConstantExpression && !propertyDescriptor.getType().isNullable()) {
CompileTimeConstant<?> compileTimeValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, initializer);
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
}
}
int modifiers;
if (kind == OwnerKind.NAMESPACE) {
modifiers = ACC_STATIC;
}
else {
modifiers = ACC_PRIVATE;
}
if (!propertyDescriptor.isVar()) {
modifiers |= ACC_FINAL;
}
modifiers |= getDeprecatedAccessFlag(propertyDescriptor);
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
modifiers |= ACC_VOLATILE;
}
Type type = typeMapper.mapType(propertyDescriptor);
return v.newField(p, modifiers, propertyDescriptor.getName().getName(), type.getDescriptor(), null, value);
}
private void generateGetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor getter) {
@@ -130,10 +157,18 @@ public class PropertyCodegen extends GenerationStateAware {
getterDescriptor = getterDescriptor != null ? getterDescriptor : DescriptorResolver.createDefaultGetter(propertyDescriptor);
if (kind != OwnerKind.TRAIT_IMPL || !defaultGetter) {
FunctionGenerationStrategy strategy =
defaultGetter
? new DefaultPropertyAccessorStrategy(getterDescriptor)
: new FunctionGenerationStrategy.FunctionDefault(state, getterDescriptor, getter);
FunctionGenerationStrategy strategy;
if (defaultGetter) {
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
strategy = new DefaultPropertyWithDelegateAccessorStrategy(getterDescriptor);
}
else {
strategy = new DefaultPropertyAccessorStrategy(getterDescriptor);
}
}
else {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, getterDescriptor, getter);
}
functionCodegen.generateMethod(getter != null ? getter : p,
signature,
true,
@@ -153,10 +188,18 @@ public class PropertyCodegen extends GenerationStateAware {
setterDescriptor = setterDescriptor != null ? setterDescriptor : DescriptorResolver.createDefaultSetter(propertyDescriptor);
if (kind != OwnerKind.TRAIT_IMPL || !defaultSetter) {
FunctionGenerationStrategy strategy =
defaultSetter
? new DefaultPropertyAccessorStrategy(setterDescriptor)
: new FunctionGenerationStrategy.FunctionDefault(state, setterDescriptor, setter);
FunctionGenerationStrategy strategy;
if (defaultSetter) {
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
strategy = new DefaultPropertyWithDelegateAccessorStrategy(setterDescriptor);
}
else {
strategy = new DefaultPropertyAccessorStrategy(setterDescriptor);
}
}
else {
strategy = new FunctionGenerationStrategy.FunctionDefault(state, setterDescriptor, setter);
}
functionCodegen.generateMethod(setter != null ? setter : p,
signature,
true,
@@ -227,6 +270,49 @@ public class PropertyCodegen extends GenerationStateAware {
}
}
private class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy {
private final PropertyAccessorDescriptor descriptor;
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) {
this.descriptor = descriptor;
}
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context
) {
InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(
mv, getFrameMap(typeMapper, context), signature.getAsmMethod().getReturnType(), context, state);
ResolvedCall<FunctionDescriptor> resolvedCall =
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, descriptor);
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, descriptor);
assert call != null : "Call should be recorded for delegate call " + signature.toString();
PropertyDescriptor property = descriptor.getCorrespondingProperty();
Type asmType = typeMapper.mapType(property);
if (kind != OwnerKind.NAMESPACE) {
iv.load(0, OBJECT_TYPE);
}
StackValue.Property delegatedProperty = codegen.intermediateValueForProperty(property, true, null);
StackValue lastValue = codegen.invokeFunction(call, delegatedProperty, resolvedCall);
if (lastValue.type != Type.VOID_TYPE) {
lastValue.put(asmType, iv);
iv.areturn(asmType);
}
else {
iv.areturn(Type.VOID_TYPE);
}
}
}
public static void generateJetPropertyAnnotation(
MethodVisitor mv, @NotNull JvmPropertyAccessorSignature propertyAccessorSignature,
@NotNull PropertyDescriptor propertyDescriptor, @NotNull Visibility visibility
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
@@ -139,12 +140,12 @@ public abstract class StackValue {
JvmClassName methodOwner,
Type type,
boolean isStatic,
boolean isDelegated,
@Nullable CallableMethod getter,
@Nullable CallableMethod setter,
GenerationState state
) {
return new Property(descriptor, methodOwner, getter, setter, isStatic, type,
state);
return new Property(descriptor, methodOwner, getter, setter, isStatic, isDelegated, type, state);
}
public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
@@ -869,11 +870,12 @@ public abstract class StackValue {
private final PropertyDescriptor descriptor;
@NotNull
private final GenerationState state;
private final boolean isDelegated;
public Property(
@NotNull PropertyDescriptor descriptor, @NotNull JvmClassName methodOwner,
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStatic,
@NotNull Type type, @NotNull GenerationState state
boolean isDelegated, @NotNull Type type, @NotNull GenerationState state
) {
super(type, isStatic);
this.methodOwner = methodOwner;
@@ -881,12 +883,13 @@ public abstract class StackValue {
this.setter = setter;
this.descriptor = descriptor;
this.state = state;
this.isDelegated = isDelegated;
}
@Override
public void put(Type type, InstructionAdapter v) {
if (getter == null) {
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), descriptor.getName().getName(),
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), getPropertyName(),
this.type.getDescriptor());
genNotNullAssertionForField(v, state, descriptor);
}
@@ -901,13 +904,17 @@ public abstract class StackValue {
public void store(Type topOfStackType, InstructionAdapter v) {
coerceFrom(topOfStackType, v);
if (setter == null) {
v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), descriptor.getName().getName(),
v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), getPropertyName(),
this.type.getDescriptor()); }
else {
Method method = setter.getSignature().getAsmMethod();
v.visitMethodInsn(setter.getInvokeOpcode(), setter.getOwner().getInternalName(), method.getName(), method.getDescriptor());
}
}
private String getPropertyName() {
return isDelegated ? JvmAbi.getPropertyDelegateName(descriptor.getName()) : descriptor.getName().getName();
}
}
private static class Expression extends StackValue {
@@ -39,6 +39,8 @@ public class JvmAbi {
public static final String CLASS_OBJECT_CLASS_NAME = "object";
public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME;
public static final String DELEGATED_PROPERTY_NAME_POSTFIX = "$delegate";
public static final String INSTANCE_FIELD = "instance$";
public static final String CLASS_OBJECT_FIELD = "object$";
public static final String RECEIVER_PARAMETER = "$receiver";
@@ -55,6 +57,10 @@ public class JvmAbi {
return fqName.lastSegmentIs(Name.identifier(CLASS_OBJECT_CLASS_NAME));
}
public static String getPropertyDelegateName(@NotNull Name name) {
return name.getName() + DELEGATED_PROPERTY_NAME_POSTFIX;
}
private JvmAbi() {
}
}
@@ -0,0 +1,21 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
class B {
private var value: Int by Delegate()
public fun test() {
fun foo() {
value = 1
}
foo()
}
}
fun box(): String {
B().test()
return "OK"
}
@@ -0,0 +1,11 @@
class Delegate {
fun get(t: Any?, p: String): Int = 1
}
class AImpl {
val prop: Number by Delegate()
}
fun box(): String {
return if(AImpl().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,24 @@
class Delegate {
var inner = Derived()
fun get(t: Any?, p: String): Derived {
inner = Derived(inner.a + "-get")
return inner
}
fun set(t: Any?, p: String, i: Base) { inner = Derived(inner.a + "-" + i.a + "-set") }
}
class A {
var prop: Derived by Delegate()
}
fun box(): String {
val c = A()
if(c.prop.a != "derived-get") return "fail get ${c.prop.a}"
c.prop = Derived()
if (c.prop.a != "derived-get-derived-set-get") return "fail set ${c.prop.a}"
return "OK"
}
open class Base(open val a: String = "base")
class Derived(override val a: String = "derived"): Base()
@@ -0,0 +1,9 @@
class Delegate {
fun get(t: Any?, p: String, s: String = ""): Int = 1
}
val prop: Int by Delegate()
fun box(): String {
return if(prop == 1) "OK" else "fail"
}
@@ -0,0 +1,17 @@
class A {
var prop: Int by Delegate()
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,18 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
class A {
val p = Delegate()
var prop: Int by p
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,19 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
fun foo() = Delegate()
class A {
var prop: Int by foo()
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,19 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
val p = Delegate()
class A {
var prop: Int by p
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,12 @@
class Delegate {
fun get(t: A, p: String): Int = 1
}
val A.prop: Int by Delegate()
class A {
}
fun box(): String {
return if(A().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,18 @@
class Delegate {
fun get(t: F.A, p: String): Int = 1
}
class F {
val A.prop: Int by Delegate()
class A {
}
fun foo(): Int {
return A().prop
}
}
fun box(): String {
return if(F().foo() == 1) "OK" else "fail"
}
@@ -0,0 +1,18 @@
class Delegate<T>(var inner: T) {
fun get(t: Any?, p: String): T = inner
fun set(t: Any?, p: String, i: T) { inner = i }
}
class A {
inner class B {
var prop: Int by Delegate(1)
}
}
fun box(): String {
val c = A().B()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,12 @@
class Delegate {
}
fun Delegate.get(t: Any?, p: String): Int = 1
class A {
val prop: Int by Delegate()
}
fun box(): String {
return if(A().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,11 @@
class Delegate {
}
class A {
fun Delegate.get(t: Any?, p: String): Int = 1
val prop: Int by Delegate()
}
fun box(): String {
return if(A().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,11 @@
class Delegate {
fun get(t: Any?, p: String): Int = 1
}
class A {
val prop: Int by Delegate()
}
fun box(): String {
return if(A().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,18 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
class A {
var prop: Int by Delegate()
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,15 @@
class Delegate {
fun get(t: Any?, p: String): Int = 1
}
trait A {
val prop: Int
}
class AImpl: A {
override val prop: Int by Delegate()
}
fun box(): String {
return if(AImpl().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,18 @@
class Delegate<T>(var inner: T) {
fun get(t: Any?, p: String): T = inner
fun set(t: Any?, p: String, i: T) { inner = i }
}
class A {
inner class B {
var prop by Delegate(1)
}
}
fun box(): String {
val c = A().B()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,20 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
class A {
private var prop: Int by Delegate()
fun test(): String {
if(prop != 1) return "fail get"
prop = 2
if (prop != 2) return "fail set"
return "OK"
}
}
fun box(): String {
return A().test()
}
@@ -0,0 +1,18 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
}
fun Delegate.set(t: Any?, p: String, i: Int) { inner = i }
class A {
var prop: Int by Delegate()
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,18 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
}
class A {
fun Delegate.set(t: Any?, p: String, i: Int) { inner = i }
var prop: Int by Delegate()
}
fun box(): String {
val c = A()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,9 @@
class Delegate {
fun get(t: Any?, p: String): Int = 1
}
val prop: Int by Delegate()
fun box(): String {
return if(prop == 1) "OK" else "fail"
}
@@ -0,0 +1,14 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
var prop: Int by Delegate()
fun box(): String {
if(prop != 1) return "fail get"
prop = 2
if (prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,20 @@
class Delegate<T>(val f: (T) -> Int) {
fun get(t: T, p: String): Int = f(t)
}
val p = Delegate<A> { t -> t.foo() }
class A(val i: Int) {
val prop: Int by p
fun foo(): Int {
return i
}
}
fun box(): String {
if(A(1).prop != 1) return "fail get1"
if(A(10).prop != 10) return "fail get2"
return "OK"
}
@@ -0,0 +1,13 @@
class Delegate {
fun get(t: Any?, p: String): Int = 1
}
class A {
inner class B {
val prop: Int by Delegate()
}
}
fun box(): String {
return if(A().B().prop == 1) "OK" else "fail"
}
@@ -0,0 +1,19 @@
class Delegate {
var inner = 1
fun get(t: Any?, p: String): Int = inner
fun set(t: Any?, p: String, i: Int) { inner = i }
}
class A {
inner class B {
var prop: Int by Delegate()
}
}
fun box(): String {
val c = A().B()
if(c.prop != 1) return "fail get"
c.prop = 2
if (c.prop != 2) return "fail set"
return "OK"
}
@@ -0,0 +1,9 @@
class Delegate {
fun get(t: Any?, vararg p: String): Int = 1
}
val prop: Int by Delegate()
fun box(): String {
return if(prop == 1) "OK" else "fail"
}
@@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/box")
@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.CallableReference.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Namespace.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.Sam.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class})
@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.CallableReference.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Namespace.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.Sam.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class})
public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInBox() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -1620,6 +1620,144 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/delegatedProperty")
public static class DelegatedProperty extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInDelegatedProperty() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/delegatedProperty"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("capturePropertyInClosure.kt")
public void testCapturePropertyInClosure() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/capturePropertyInClosure.kt");
}
@TestMetadata("castGetReturnType.kt")
public void testCastGetReturnType() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/castGetReturnType.kt");
}
@TestMetadata("castSetParameter.kt")
public void testCastSetParameter() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/castSetParameter.kt");
}
@TestMetadata("defaultArgs.kt")
public void testDefaultArgs() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/defaultArgs.kt");
}
@TestMetadata("delegateAsInnerClass.kt")
public void testDelegateAsInnerClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateAsInnerClass.kt");
}
@TestMetadata("delegateByOtherProperty.kt")
public void testDelegateByOtherProperty() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateByOtherProperty.kt");
}
@TestMetadata("delegateByTopLevelFun.kt")
public void testDelegateByTopLevelFun() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateByTopLevelFun.kt");
}
@TestMetadata("delegateByTopLevelProperty.kt")
public void testDelegateByTopLevelProperty() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateByTopLevelProperty.kt");
}
@TestMetadata("delegateForExtProperty.kt")
public void testDelegateForExtProperty() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtProperty.kt");
}
@TestMetadata("delegateForExtPropertyInClass.kt")
public void testDelegateForExtPropertyInClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/delegateForExtPropertyInClass.kt");
}
@TestMetadata("genericDelegate.kt")
public void testGenericDelegate() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/genericDelegate.kt");
}
@TestMetadata("getAsExtensionFun.kt")
public void testGetAsExtensionFun() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/getAsExtensionFun.kt");
}
@TestMetadata("getAsExtensionFunInClass.kt")
public void testGetAsExtensionFunInClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/getAsExtensionFunInClass.kt");
}
@TestMetadata("inClassVal.kt")
public void testInClassVal() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/inClassVal.kt");
}
@TestMetadata("inClassVar.kt")
public void testInClassVar() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/inClassVar.kt");
}
@TestMetadata("inTrait.kt")
public void testInTrait() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/inTrait.kt");
}
@TestMetadata("inferredPropertyType.kt")
public void testInferredPropertyType() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/inferredPropertyType.kt");
}
@TestMetadata("privateVar.kt")
public void testPrivateVar() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/privateVar.kt");
}
@TestMetadata("setAsExtensionFun.kt")
public void testSetAsExtensionFun() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/setAsExtensionFun.kt");
}
@TestMetadata("setAsExtensionFunInClass.kt")
public void testSetAsExtensionFunInClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/setAsExtensionFunInClass.kt");
}
@TestMetadata("topLevelVal.kt")
public void testTopLevelVal() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/topLevelVal.kt");
}
@TestMetadata("topLevelVar.kt")
public void testTopLevelVar() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/topLevelVar.kt");
}
@TestMetadata("twoPropByOneDelegete.kt")
public void testTwoPropByOneDelegete() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/twoPropByOneDelegete.kt");
}
@TestMetadata("valInInnerClass.kt")
public void testValInInnerClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/valInInnerClass.kt");
}
@TestMetadata("varInInnerClass.kt")
public void testVarInInnerClass() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/varInInnerClass.kt");
}
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
doTest("compiler/testData/codegen/box/delegatedProperty/vararg.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/elvis")
public static class Elvis extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInElvis() throws Exception {
@@ -3919,6 +4057,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
suite.addTest(Closures.innerSuite());
suite.addTestSuite(ControlStructures.class);
suite.addTest(DefaultArguments.innerSuite());
suite.addTestSuite(DelegatedProperty.class);
suite.addTestSuite(Elvis.class);
suite.addTestSuite(Enum.class);
suite.addTestSuite(ExclExcl.class);