Generate bytecode for delegated properties
This commit is contained in:
@@ -263,10 +263,11 @@ public class CodegenUtil {
|
|||||||
return false;
|
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();
|
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||||
return isInsideClass &&
|
return isInsideClass &&
|
||||||
|
!isDelegated &&
|
||||||
!isExtensionProperty &&
|
!isExtensionProperty &&
|
||||||
(accessorDescriptor == null ||
|
(accessorDescriptor == null ||
|
||||||
accessorDescriptor.isDefault() &&
|
accessorDescriptor.isDefault() &&
|
||||||
|
|||||||
@@ -1660,6 +1660,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return myFrameMap.getIndex(descriptor);
|
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
|
@NotNull
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
PropertyDescriptor propertyDescriptor,
|
PropertyDescriptor propertyDescriptor,
|
||||||
@@ -1688,12 +1698,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
||||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
||||||
|
|
||||||
|
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
|
||||||
|
boolean isDelegatedProperty = delegateType != null;
|
||||||
|
|
||||||
CallableMethod callableGetter = null;
|
CallableMethod callableGetter = null;
|
||||||
CallableMethod callableSetter = null;
|
CallableMethod callableSetter = null;
|
||||||
|
|
||||||
if (!forceField) {
|
if (!forceField) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass)) {
|
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) {
|
||||||
callableGetter = null;
|
callableGetter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1715,7 +1728,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
if (propertyDescriptor.getSetter() != null) {
|
if (propertyDescriptor.getSetter() != null) {
|
||||||
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass)) {
|
if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty)) {
|
||||||
callableSetter = null;
|
callableSetter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1736,8 +1749,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
owner = callableMethod.getOwner();
|
owner = callableMethod.getOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
return StackValue.property(propertyDescriptor, owner, typeMapper.mapType(propertyDescriptor.getOriginal().getType()),
|
if (isDelegatedProperty && forceField) {
|
||||||
isStatic, callableGetter, callableSetter, state);
|
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
|
@Override
|
||||||
@@ -1864,7 +1883,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return (MemberDescriptor) descriptor;
|
return (MemberDescriptor) descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue invokeFunction(
|
public StackValue invokeFunction(
|
||||||
Call call,
|
Call call,
|
||||||
StackValue receiver,
|
StackValue receiver,
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall
|
ResolvedCall<? extends CallableDescriptor> resolvedCall
|
||||||
|
|||||||
@@ -1531,10 +1531,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
|
||||||
assert propertyDescriptor != null;
|
assert propertyDescriptor != null;
|
||||||
|
|
||||||
JetExpression initializer = property.getInitializer();
|
JetExpression initializer = property.getDelegateExpressionOrInitializer();
|
||||||
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
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);
|
Type type = codegen.expressionType(initializer);
|
||||||
if (jetType.isNullable()) {
|
if (jetType.isNullable()) {
|
||||||
type = boxType(type);
|
type = boxType(type);
|
||||||
@@ -1542,14 +1542,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
codegen.gen(initializer, type);
|
codegen.gen(initializer, type);
|
||||||
|
|
||||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||||
propValue.store(propValue.type, iv);
|
propValue.store(type, iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldInitializeProperty(
|
public static boolean shouldInitializeProperty(
|
||||||
@NotNull JetProperty property,
|
@NotNull JetProperty property,
|
||||||
@NotNull JetTypeMapper typeMapper
|
@NotNull JetTypeMapper typeMapper
|
||||||
) {
|
) {
|
||||||
JetExpression initializer = property.getInitializer();
|
JetExpression initializer = property.getDelegateExpressionOrInitializer();
|
||||||
if (initializer == null) return false;
|
if (initializer == null) return false;
|
||||||
|
|
||||||
CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
|
CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
|
||||||
@@ -1559,10 +1559,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
assert propertyDescriptor != null;
|
assert propertyDescriptor != null;
|
||||||
|
|
||||||
Object value = compileTimeValue.getValue();
|
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);
|
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) {
|
private static boolean skipDefaultValue(PropertyDescriptor propertyDescriptor, Object value, Type type) {
|
||||||
if (isPrimitive(type)) {
|
if (isPrimitive(type)) {
|
||||||
if (!propertyDescriptor.getType().isNullable() && value instanceof Number) {
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
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.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
@@ -86,38 +88,63 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
|
|
||||||
private void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
private void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
||||||
//noinspection ConstantConditions
|
//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();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
if (isInterface(containingDeclaration)) {
|
if (isInterface(containingDeclaration)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object value = null;
|
FieldVisitor fieldVisitor = hasBackingField
|
||||||
JetExpression initializer = p instanceof JetProperty ? ((JetProperty) p).getInitializer() : null;
|
? generateBackingFieldAccess(p, propertyDescriptor)
|
||||||
if (initializer != null) {
|
: generatePropertyDelegateAccess((JetProperty) p, propertyDescriptor);
|
||||||
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);
|
|
||||||
AnnotationCodegen.forField(fieldVisitor, typeMapper).genAnnotations(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) {
|
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);
|
getterDescriptor = getterDescriptor != null ? getterDescriptor : DescriptorResolver.createDefaultGetter(propertyDescriptor);
|
||||||
|
|
||||||
if (kind != OwnerKind.TRAIT_IMPL || !defaultGetter) {
|
if (kind != OwnerKind.TRAIT_IMPL || !defaultGetter) {
|
||||||
FunctionGenerationStrategy strategy =
|
FunctionGenerationStrategy strategy;
|
||||||
defaultGetter
|
if (defaultGetter) {
|
||||||
? new DefaultPropertyAccessorStrategy(getterDescriptor)
|
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||||
: new FunctionGenerationStrategy.FunctionDefault(state, getterDescriptor, getter);
|
strategy = new DefaultPropertyWithDelegateAccessorStrategy(getterDescriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strategy = new DefaultPropertyAccessorStrategy(getterDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strategy = new FunctionGenerationStrategy.FunctionDefault(state, getterDescriptor, getter);
|
||||||
|
}
|
||||||
functionCodegen.generateMethod(getter != null ? getter : p,
|
functionCodegen.generateMethod(getter != null ? getter : p,
|
||||||
signature,
|
signature,
|
||||||
true,
|
true,
|
||||||
@@ -153,10 +188,18 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
setterDescriptor = setterDescriptor != null ? setterDescriptor : DescriptorResolver.createDefaultSetter(propertyDescriptor);
|
setterDescriptor = setterDescriptor != null ? setterDescriptor : DescriptorResolver.createDefaultSetter(propertyDescriptor);
|
||||||
|
|
||||||
if (kind != OwnerKind.TRAIT_IMPL || !defaultSetter) {
|
if (kind != OwnerKind.TRAIT_IMPL || !defaultSetter) {
|
||||||
FunctionGenerationStrategy strategy =
|
FunctionGenerationStrategy strategy;
|
||||||
defaultSetter
|
if (defaultSetter) {
|
||||||
? new DefaultPropertyAccessorStrategy(setterDescriptor)
|
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||||
: new FunctionGenerationStrategy.FunctionDefault(state, setterDescriptor, setter);
|
strategy = new DefaultPropertyWithDelegateAccessorStrategy(setterDescriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strategy = new DefaultPropertyAccessorStrategy(setterDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strategy = new FunctionGenerationStrategy.FunctionDefault(state, setterDescriptor, setter);
|
||||||
|
}
|
||||||
functionCodegen.generateMethod(setter != null ? setter : p,
|
functionCodegen.generateMethod(setter != null ? setter : p,
|
||||||
signature,
|
signature,
|
||||||
true,
|
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(
|
public static void generateJetPropertyAnnotation(
|
||||||
MethodVisitor mv, @NotNull JvmPropertyAccessorSignature propertyAccessorSignature,
|
MethodVisitor mv, @NotNull JvmPropertyAccessorSignature propertyAccessorSignature,
|
||||||
@NotNull PropertyDescriptor propertyDescriptor, @NotNull Visibility visibility
|
@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.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
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.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
@@ -139,12 +140,12 @@ public abstract class StackValue {
|
|||||||
JvmClassName methodOwner,
|
JvmClassName methodOwner,
|
||||||
Type type,
|
Type type,
|
||||||
boolean isStatic,
|
boolean isStatic,
|
||||||
|
boolean isDelegated,
|
||||||
@Nullable CallableMethod getter,
|
@Nullable CallableMethod getter,
|
||||||
@Nullable CallableMethod setter,
|
@Nullable CallableMethod setter,
|
||||||
GenerationState state
|
GenerationState state
|
||||||
) {
|
) {
|
||||||
return new Property(descriptor, methodOwner, getter, setter, isStatic, type,
|
return new Property(descriptor, methodOwner, getter, setter, isStatic, isDelegated, type, state);
|
||||||
state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
|
public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
|
||||||
@@ -869,11 +870,12 @@ public abstract class StackValue {
|
|||||||
private final PropertyDescriptor descriptor;
|
private final PropertyDescriptor descriptor;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
private final boolean isDelegated;
|
||||||
|
|
||||||
public Property(
|
public Property(
|
||||||
@NotNull PropertyDescriptor descriptor, @NotNull JvmClassName methodOwner,
|
@NotNull PropertyDescriptor descriptor, @NotNull JvmClassName methodOwner,
|
||||||
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStatic,
|
@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);
|
super(type, isStatic);
|
||||||
this.methodOwner = methodOwner;
|
this.methodOwner = methodOwner;
|
||||||
@@ -881,12 +883,13 @@ public abstract class StackValue {
|
|||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
this.isDelegated = isDelegated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(Type type, InstructionAdapter v) {
|
public void put(Type type, InstructionAdapter v) {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), descriptor.getName().getName(),
|
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), getPropertyName(),
|
||||||
this.type.getDescriptor());
|
this.type.getDescriptor());
|
||||||
genNotNullAssertionForField(v, state, descriptor);
|
genNotNullAssertionForField(v, state, descriptor);
|
||||||
}
|
}
|
||||||
@@ -901,13 +904,17 @@ public abstract class StackValue {
|
|||||||
public void store(Type topOfStackType, InstructionAdapter v) {
|
public void store(Type topOfStackType, InstructionAdapter v) {
|
||||||
coerceFrom(topOfStackType, v);
|
coerceFrom(topOfStackType, v);
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), descriptor.getName().getName(),
|
v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, methodOwner.getInternalName(), getPropertyName(),
|
||||||
this.type.getDescriptor()); }
|
this.type.getDescriptor()); }
|
||||||
else {
|
else {
|
||||||
Method method = setter.getSignature().getAsmMethod();
|
Method method = setter.getSignature().getAsmMethod();
|
||||||
v.visitMethodInsn(setter.getInvokeOpcode(), setter.getOwner().getInternalName(), method.getName(), method.getDescriptor());
|
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 {
|
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_CLASS_NAME = "object";
|
||||||
public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME;
|
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 INSTANCE_FIELD = "instance$";
|
||||||
public static final String CLASS_OBJECT_FIELD = "object$";
|
public static final String CLASS_OBJECT_FIELD = "object$";
|
||||||
public static final String RECEIVER_PARAMETER = "$receiver";
|
public static final String RECEIVER_PARAMETER = "$receiver";
|
||||||
@@ -55,6 +57,10 @@ public class JvmAbi {
|
|||||||
return fqName.lastSegmentIs(Name.identifier(CLASS_OBJECT_CLASS_NAME));
|
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() {
|
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"
|
||||||
|
}
|
||||||
+140
-1
@@ -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 */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
@TestMetadata("compiler/testData/codegen/box")
|
@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 class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||||
public void testAllFilesPresentInBox() throws Exception {
|
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);
|
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")
|
@TestMetadata("compiler/testData/codegen/box/elvis")
|
||||||
public static class Elvis extends AbstractBlackBoxCodegenTest {
|
public static class Elvis extends AbstractBlackBoxCodegenTest {
|
||||||
public void testAllFilesPresentInElvis() throws Exception {
|
public void testAllFilesPresentInElvis() throws Exception {
|
||||||
@@ -3919,6 +4057,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
suite.addTest(Closures.innerSuite());
|
suite.addTest(Closures.innerSuite());
|
||||||
suite.addTestSuite(ControlStructures.class);
|
suite.addTestSuite(ControlStructures.class);
|
||||||
suite.addTest(DefaultArguments.innerSuite());
|
suite.addTest(DefaultArguments.innerSuite());
|
||||||
|
suite.addTestSuite(DelegatedProperty.class);
|
||||||
suite.addTestSuite(Elvis.class);
|
suite.addTestSuite(Elvis.class);
|
||||||
suite.addTestSuite(Enum.class);
|
suite.addTestSuite(Enum.class);
|
||||||
suite.addTestSuite(ExclExcl.class);
|
suite.addTestSuite(ExclExcl.class);
|
||||||
|
|||||||
Reference in New Issue
Block a user