Realization of class object fields as static fields of outer class
#KT-2213 Fixed
This commit is contained in:
@@ -34,8 +34,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
||||
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
|
||||
Kind.DECLARATION);
|
||||
|
||||
JetType receiverType = DescriptorUtils.getReceiverParameterType(pd.getReceiverParameter());
|
||||
setType(pd.getType(), Collections.<TypeParameterDescriptorImpl>emptyList(), pd.getExpectedThisObject(), receiverType);
|
||||
boolean isStaticProperty = AsmUtil.isPropertyWithBackingFieldInOuterClass(pd)
|
||||
&& !AsmUtil.isClassObjectWithBackingFieldsInOuter(containingDeclaration);
|
||||
JetType receiverType = !isStaticProperty ? DescriptorUtils.getReceiverParameterType(pd.getReceiverParameter()) : null;
|
||||
|
||||
setType(pd.getType(), Collections.<TypeParameterDescriptorImpl>emptyList(), isStaticProperty ? null : pd.getExpectedThisObject(),
|
||||
receiverType);
|
||||
initialize(new Getter(this), new Setter(this));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
@@ -50,6 +49,7 @@ import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||
|
||||
public class AsmUtil {
|
||||
@@ -589,10 +589,57 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.CLASS);
|
||||
}
|
||||
|
||||
public static int getVisibilityForSpecialPropertyBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) {
|
||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||
if (isDelegate || isExtensionProperty) {
|
||||
return ACC_PRIVATE;
|
||||
} else {
|
||||
return areBothAccessorDefault(propertyDescriptor) ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) : ACC_PRIVATE;
|
||||
}
|
||||
}
|
||||
|
||||
private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
if (!propertyDescriptor.isVar() ) {
|
||||
return propertyDescriptor;
|
||||
} else {
|
||||
return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||
return !propertyDescriptor.isVar() && !isExtensionProperty
|
||||
&& isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.TRAIT)
|
||||
&& areBothAccessorDefault(propertyDescriptor)
|
||||
&& getVisibilityForSpecialPropertyBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||
}
|
||||
|
||||
public static boolean isClassObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor classObject) {
|
||||
return isPropertyWithSpecialBackingField(classObject, ClassKind.CLASS);
|
||||
}
|
||||
|
||||
private static boolean areBothAccessorDefault(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
return isAccessorWithEmptyBody(propertyDescriptor.getGetter())
|
||||
&& (!propertyDescriptor.isVar() || isAccessorWithEmptyBody(propertyDescriptor.getSetter()));
|
||||
}
|
||||
|
||||
private static boolean isAccessorWithEmptyBody(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
|
||||
return accessorDescriptor == null || !accessorDescriptor.hasBody();
|
||||
}
|
||||
|
||||
private static boolean isPropertyWithSpecialBackingField(@NotNull DeclarationDescriptor classObject, ClassKind kind) {
|
||||
return isClassObject(classObject) && isKindOf(classObject.getContainingDeclaration(), kind);
|
||||
}
|
||||
|
||||
public static Type comparisonOperandType(Type left, Type right) {
|
||||
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
|
||||
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
|
||||
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
@@ -40,12 +41,20 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
protected final OwnerKind kind;
|
||||
protected final ClassDescriptor descriptor;
|
||||
protected final ClassBuilder v;
|
||||
protected final CodegenContext context;
|
||||
protected final ClassContext context;
|
||||
|
||||
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
|
||||
private MethodVisitor clInitMethod;
|
||||
|
||||
protected ClassBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||
super(state);
|
||||
private ExpressionCodegen clInitCodegen;
|
||||
|
||||
protected ClassBodyCodegen(
|
||||
@NotNull JetClassOrObject aClass,
|
||||
@NotNull ClassContext context,
|
||||
@NotNull ClassBuilder v,
|
||||
@NotNull GenerationState state,
|
||||
@Nullable MemberCodegen parentCodegen
|
||||
) {
|
||||
super(state, parentCodegen);
|
||||
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
myClass = aClass;
|
||||
this.context = context;
|
||||
@@ -53,7 +62,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
public final void generate() {
|
||||
public void generate() {
|
||||
generateDeclaration();
|
||||
|
||||
generateClassBody();
|
||||
@@ -72,18 +81,20 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
|
||||
private void generateClassBody() {
|
||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen);
|
||||
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
|
||||
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (kind != OwnerKind.TRAIT_IMPL) {
|
||||
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
|
||||
if (shouldProcessFirst(declaration)) {
|
||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (shouldProcessFirst(declaration)) {
|
||||
generateDeclaration(propertyCodegen, declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (!shouldProcessFirst(declaration)) {
|
||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||
generateDeclaration(propertyCodegen, declaration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +105,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
return false == (declaration instanceof JetProperty || declaration instanceof JetNamedFunction);
|
||||
}
|
||||
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
|
||||
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
||||
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
|
||||
}
|
||||
@@ -137,23 +149,39 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
}
|
||||
|
||||
private void generateStaticInitializer() {
|
||||
if (staticInitializerChunks.size() > 0) {
|
||||
MethodVisitor mv = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
if (clInitMethod != null) {
|
||||
createOrGetClInitMethod();
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
|
||||
for (CodeChunk chunk : staticInitializerChunks) {
|
||||
chunk.generate(codegen);
|
||||
}
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
createOrGetClInitMethod().visitInsn(RETURN);
|
||||
FunctionCodegen.endVisit(codegen.v, "static initializer", myClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected MethodVisitor createOrGetClInitMethod() {
|
||||
if (clInitMethod == null) {
|
||||
clInitMethod = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
}
|
||||
return clInitMethod;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ExpressionCodegen createOrGetClInitCodegen() {
|
||||
assert state.getClassBuilderMode() == ClassBuilderMode.FULL;
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
if (clInitCodegen == null) {
|
||||
MethodVisitor method = createOrGetClInitMethod();
|
||||
method.visitCode();
|
||||
clInitCodegen = new ExpressionCodegen(method, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
}
|
||||
}
|
||||
return clInitCodegen;
|
||||
}
|
||||
|
||||
private void generateRemoveInIterator() {
|
||||
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
|
||||
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.codegen.context.NamespaceContext;
|
||||
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
@@ -263,14 +264,26 @@ public class CodegenUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass, boolean isDelegated) {
|
||||
public static boolean couldUseDirectAccessToProperty(@NotNull PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass, boolean isDelegated) {
|
||||
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||
boolean specialTypeProperty = isDelegated ||
|
||||
isExtensionProperty ||
|
||||
DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration()) ||
|
||||
JetTypeMapper.isAccessor(propertyDescriptor);
|
||||
return isInsideClass &&
|
||||
!isDelegated &&
|
||||
!isExtensionProperty &&
|
||||
!specialTypeProperty &&
|
||||
(accessorDescriptor == null ||
|
||||
accessorDescriptor.isDefault() &&
|
||||
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ImplementationBodyCodegen getParentBodyCodegen(@Nullable MemberCodegen classBodyCodegen) {
|
||||
assert classBodyCodegen != null &&
|
||||
classBodyCodegen
|
||||
.getParentCodegen() instanceof ImplementationBodyCodegen : "Class object should have appropriate parent BodyCodegen";
|
||||
|
||||
return ((ImplementationBodyCodegen) classBodyCodegen.getParentCodegen());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
private int myLastLineNumber = -1;
|
||||
|
||||
final InstructionAdapter v;
|
||||
final MethodVisitor methodVisitor;
|
||||
final FrameMap myFrameMap;
|
||||
final JetTypeMapper typeMapper;
|
||||
|
||||
@@ -121,8 +122,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
//noinspection SuspiciousMethodCalls
|
||||
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
|
||||
|
||||
CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this);
|
||||
ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state);
|
||||
ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this);
|
||||
ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, null);
|
||||
|
||||
implementationBodyCodegen.generate();
|
||||
|
||||
@@ -164,7 +165,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.returnType = returnType;
|
||||
this.state = state;
|
||||
this.v = new InstructionAdapter(v) {
|
||||
this.methodVisitor = v;
|
||||
this.v = createInstructionAdapter(methodVisitor);
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.context = context;
|
||||
this.statementVisitor = new CodegenStatementVisitor(this);
|
||||
}
|
||||
|
||||
protected InstructionAdapter createInstructionAdapter(MethodVisitor mv) {
|
||||
return new InstructionAdapter(methodVisitor) {
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
|
||||
super.visitLocalVariable(name, desc, signature, start, end,
|
||||
@@ -172,9 +181,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
localVariableNames.add(name);
|
||||
}
|
||||
};
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.context = context;
|
||||
this.statementVisitor = new CodegenStatementVisitor(this);
|
||||
}
|
||||
|
||||
public GenerationState getState() {
|
||||
@@ -275,9 +281,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
ClassBuilder classBuilder = state.getFactory().newVisitor(className.getInternalName(), declaration.getContainingFile()
|
||||
);
|
||||
|
||||
CodegenContext objectContext = context.intoAnonymousClass(descriptor, this);
|
||||
ClassContext objectContext = context.intoAnonymousClass(descriptor, this);
|
||||
|
||||
new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state).generate();
|
||||
new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, null).generate();
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
@@ -1673,26 +1679,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@NotNull
|
||||
public StackValue.Property intermediateValueForProperty(
|
||||
PropertyDescriptor propertyDescriptor,
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
boolean forceField,
|
||||
@Nullable JetSuperExpression superExpression
|
||||
) {
|
||||
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, false);
|
||||
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue.Property intermediateValueForProperty(
|
||||
PropertyDescriptor propertyDescriptor,
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
boolean forceField,
|
||||
@Nullable JetSuperExpression superExpression,
|
||||
@NotNull boolean forceSpecialFlag
|
||||
@NotNull MethodKind methodKind
|
||||
) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
assert containingDeclaration != null;
|
||||
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
||||
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor || isBackingFieldInAnotherClass;
|
||||
boolean isSuper = superExpression != null;
|
||||
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
||||
@@ -1700,10 +1706,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
|
||||
boolean isDelegatedProperty = delegateType != null;
|
||||
|
||||
|
||||
CallableMethod callableGetter = null;
|
||||
CallableMethod callableSetter = null;
|
||||
|
||||
if (!forceField) {
|
||||
boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
|
||||
|
||||
CodegenContext backingFieldContext = context.getParentContext();
|
||||
|
||||
if (isBackingFieldInAnotherClass && forceField) {
|
||||
//delegate call to classObject owner : OWNER
|
||||
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
||||
if (!skipPropertyAccessors) {
|
||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skipPropertyAccessors) {
|
||||
//noinspection ConstantConditions
|
||||
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) {
|
||||
callableGetter = null;
|
||||
@@ -1721,7 +1742,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
||||
|
||||
if (propertyDescriptor.getGetter() != null) {
|
||||
callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||
callableGetter = typeMapper
|
||||
.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind,
|
||||
isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1731,7 +1754,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
callableSetter = null;
|
||||
}
|
||||
else {
|
||||
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1742,7 +1765,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
|
||||
if (callableMethod == null) {
|
||||
owner = typeMapper.getOwner(propertyDescriptor, context.getContextKind(), isInsideModule);
|
||||
owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, context.getContextKind(), isInsideModule);
|
||||
}
|
||||
else {
|
||||
owner = callableMethod.getOwner();
|
||||
@@ -2316,8 +2339,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
@NotNull
|
||||
public Type expressionType(JetExpression expr) {
|
||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
|
||||
return asmTypeOrVoid(type);
|
||||
return typeMapper.expressionType(expr);
|
||||
}
|
||||
|
||||
public int indexOfLocal(JetReferenceExpression lhs) {
|
||||
|
||||
@@ -85,7 +85,7 @@ public abstract class FunctionGenerationStrategy<T extends CallableDescriptor> {
|
||||
|
||||
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
|
||||
|
||||
private final GenerationState state;
|
||||
protected final GenerationState state;
|
||||
|
||||
protected final T callableDescriptor;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.asm4.commons.Method;
|
||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.context.ConstructorContext;
|
||||
import org.jetbrains.jet.codegen.context.MethodContext;
|
||||
import org.jetbrains.jet.codegen.signature.*;
|
||||
@@ -67,6 +67,7 @@ import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||
|
||||
@@ -79,13 +80,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private final Type classAsmType;
|
||||
|
||||
private final FunctionCodegen functionCodegen;
|
||||
private final PropertyCodegen propertyCodegen;
|
||||
private final PropertyCodegen propertyCodegen;
|
||||
|
||||
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||
super(aClass, context, v, state);
|
||||
private List<PropertyDescriptor> classObjectPropertiesToCopy;
|
||||
|
||||
public ImplementationBodyCodegen(
|
||||
@NotNull JetClassOrObject aClass,
|
||||
@NotNull ClassContext context,
|
||||
@NotNull ClassBuilder v,
|
||||
@NotNull GenerationState state,
|
||||
@Nullable MemberCodegen parentCodegen
|
||||
) {
|
||||
super(aClass, context, v, state, parentCodegen);
|
||||
this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
|
||||
this.functionCodegen = new FunctionCodegen(context, v, state);
|
||||
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen);
|
||||
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -429,6 +438,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
protected void generateSyntheticParts() {
|
||||
generateFieldForSingleton();
|
||||
|
||||
generateClassObjectBackingFieldCopies();
|
||||
|
||||
try {
|
||||
generatePrimaryConstructor();
|
||||
}
|
||||
@@ -446,7 +457,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateSyntheticAccessors();
|
||||
|
||||
generateEnumMethods();
|
||||
generateEnumMethodsAndConstInitializers();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
@@ -750,25 +761,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
MethodContext functionContext = context.intoFunction(function);
|
||||
FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION,
|
||||
new DefaultParameterValueLoader() {
|
||||
@Override
|
||||
public void putValueOnStack(
|
||||
ValueParameterDescriptor descriptor,
|
||||
ExpressionCodegen codegen
|
||||
) {
|
||||
assert (KotlinBuiltIns.getInstance()
|
||||
.isData((ClassDescriptor) function.getContainingDeclaration()))
|
||||
: "Trying to create function with default arguments for function that isn't presented in code for class without data annotation";
|
||||
PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get(
|
||||
BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor);
|
||||
assert propertyDescriptor !=
|
||||
null : "Trying to generate default value for parameter of copy function that doesn't correspond to any property";
|
||||
codegen.v.load(0, thisDescriptorType);
|
||||
Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType());
|
||||
codegen.intermediateValueForProperty(propertyDescriptor, false, null)
|
||||
.put(propertyType, codegen.v);
|
||||
}
|
||||
});
|
||||
new DefaultParameterValueLoader() {
|
||||
@Override
|
||||
public void putValueOnStack(
|
||||
ValueParameterDescriptor descriptor,
|
||||
ExpressionCodegen codegen
|
||||
) {
|
||||
assert (KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration()))
|
||||
: "Trying to create function with default arguments for function that isn't presented in code for class without data annotation";
|
||||
PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get(
|
||||
BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor);
|
||||
assert propertyDescriptor != null
|
||||
: "Trying to generate default value for parameter of copy function that doesn't correspond to any property";
|
||||
codegen.v.load(0, thisDescriptorType);
|
||||
Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType());
|
||||
codegen.intermediateValueForProperty(propertyDescriptor, false, null).put(propertyType, codegen.v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void generateEnumMethodsAndConstInitializers() {
|
||||
if (!myEnumConstants.isEmpty()) {
|
||||
generateEnumMethods();
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
initializeEnumConstants(createOrGetClInitCodegen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateEnumMethods() {
|
||||
@@ -827,7 +846,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
});
|
||||
}
|
||||
else if (entry.getValue() instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||
final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||
|
||||
|
||||
@@ -837,9 +856,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
|
||||
@Override
|
||||
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||
StackValue.Property property = codegen.intermediateValueForProperty(original, false, null, true);
|
||||
InstructionAdapter iv = codegen.v;
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
|
||||
StackValue.Property property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
|
||||
if (!forceField) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
property.put(property.type, iv);
|
||||
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||
}
|
||||
@@ -854,12 +876,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
|
||||
@Override
|
||||
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||
StackValue.Property property = codegen.intermediateValueForProperty(original, false, null, true);
|
||||
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
|
||||
StackValue.Property property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
||||
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
||||
for (int i = 0, reg = 0; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
@@ -915,22 +937,64 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
if (!(isNonLiteralObject(myClass) || hasClassObject) || isEnumClass) return;
|
||||
|
||||
final ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
||||
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
||||
assert fieldTypeDescriptor != null;
|
||||
final StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
|
||||
StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
|
||||
JetClassOrObject original = hasClassObject ? ((JetClass) myClass).getClassObject().getObjectDeclaration() : myClass;
|
||||
|
||||
v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
||||
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(ExpressionCodegen codegen) {
|
||||
ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
|
||||
FunctionDescriptor fd = codegen.accessableFunctionDescriptor(constructorDescriptor);
|
||||
generateMethodCallTo(fd, codegen.v);
|
||||
field.store(field.type, codegen.v);
|
||||
if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
|
||||
genInitSingleton(fieldTypeDescriptor, field);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateClassObjectBackingFieldCopies() {
|
||||
if (classObjectPropertiesToCopy != null) {
|
||||
for (PropertyDescriptor propertyDescriptor : classObjectPropertiesToCopy) {
|
||||
|
||||
v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, propertyDescriptor.getName().asString(), typeMapper.mapType(propertyDescriptor).getDescriptor(), null, null);
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
int classObjectIndex = putClassObjectInLocalVar(codegen);
|
||||
StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
|
||||
copyFieldFromClassObject(propertyDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private int putClassObjectInLocalVar(ExpressionCodegen codegen) {
|
||||
FrameMap frameMap = codegen.myFrameMap;
|
||||
ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
|
||||
int classObjectIndex = frameMap.getIndex(classObjectDescriptor);
|
||||
if (classObjectIndex == -1) {
|
||||
classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
|
||||
StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
|
||||
classObject.put(classObject.type, codegen.v);
|
||||
StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
|
||||
}
|
||||
return classObjectIndex;
|
||||
}
|
||||
|
||||
private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
|
||||
property.put(property.type, codegen.v);
|
||||
StackValue.Field field = StackValue.field(property.type, JvmClassName.byClassDescriptor(descriptor),
|
||||
propertyDescriptor.getName().asString(), true);
|
||||
field.store(field.type, codegen.v);
|
||||
}
|
||||
|
||||
protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
FunctionDescriptor fd = codegen.accessableFunctionDescriptor(constructorDescriptor);
|
||||
generateMethodCallTo(fd, codegen.v);
|
||||
field.store(field.type, codegen.v);
|
||||
}
|
||||
}
|
||||
|
||||
protected void generatePrimaryConstructor() {
|
||||
@@ -981,9 +1045,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructorImpl(
|
||||
ConstructorDescriptor constructorDescriptor,
|
||||
ExpressionCodegen codegen,
|
||||
MutableClosure closure
|
||||
@Nullable ConstructorDescriptor constructorDescriptor,
|
||||
@NotNull final ExpressionCodegen codegen,
|
||||
@Nullable MutableClosure closure
|
||||
) {
|
||||
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
||||
? constructorDescriptor.getValueParameters()
|
||||
@@ -1035,7 +1099,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
curParam++;
|
||||
}
|
||||
|
||||
generateInitializers(codegen, iv, myClass.getDeclarations(), bindingContext, state);
|
||||
boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor);
|
||||
if (generateInitializerInOuter) {
|
||||
ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this);
|
||||
//generate object$
|
||||
parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper));
|
||||
parentCodegen.generateInitializers(parentCodegen.createOrGetClInitCodegen(),
|
||||
myClass.getDeclarations(), bindingContext, state);
|
||||
} else {
|
||||
generateInitializers(codegen, myClass.getDeclarations(), bindingContext, state);
|
||||
}
|
||||
|
||||
|
||||
iv.visitInsn(RETURN);
|
||||
}
|
||||
@@ -1225,7 +1299,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateTraitMethods() {
|
||||
if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
|
||||
if (JetPsiUtil.isTrait(myClass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1425,29 +1499,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
|
||||
if (declaration instanceof JetEnumEntry) {
|
||||
String name = declaration.getName();
|
||||
String desc = "L" + classAsmType.getInternalName() + ";";
|
||||
v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
|
||||
if (myEnumConstants.isEmpty()) {
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(ExpressionCodegen codegen) {
|
||||
initializeEnumConstants(codegen.v);
|
||||
}
|
||||
});
|
||||
}
|
||||
myEnumConstants.add((JetEnumEntry) declaration);
|
||||
}
|
||||
|
||||
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||
super.generateDeclaration(propertyCodegen, declaration);
|
||||
}
|
||||
|
||||
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
||||
|
||||
private void initializeEnumConstants(InstructionAdapter iv) {
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(iv, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
private void initializeEnumConstants(ExpressionCodegen codegen) {
|
||||
InstructionAdapter iv = codegen.v;
|
||||
int ordinal = -1;
|
||||
JetType myType = descriptor.getDefaultType();
|
||||
Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL);
|
||||
@@ -1509,14 +1575,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
public static void generateInitializers(
|
||||
@NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations,
|
||||
@NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations,
|
||||
@NotNull BindingContext bindingContext, @NotNull GenerationState state
|
||||
) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
|
||||
initializeProperty(codegen, bindingContext, iv, (JetProperty) declaration, false);
|
||||
initializeProperty(codegen, bindingContext, (JetProperty) declaration);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetClassInitializer) {
|
||||
@@ -1525,16 +1591,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void initializeProperty(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull JetProperty property,
|
||||
boolean isStatic
|
||||
@NotNull JetProperty property
|
||||
) {
|
||||
if (!isStatic) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
|
||||
assert propertyDescriptor != null;
|
||||
@@ -1543,14 +1605,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
||||
|
||||
JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor);
|
||||
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER);
|
||||
|
||||
if (!propValue.isStatic) {
|
||||
codegen.v.load(0, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
Type type = codegen.expressionType(initializer);
|
||||
if (jetType.isNullable()) {
|
||||
type = boxType(type);
|
||||
}
|
||||
codegen.gen(initializer, type);
|
||||
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
||||
propValue.store(type, iv);
|
||||
propValue.store(type, codegen.v);
|
||||
}
|
||||
|
||||
public static boolean shouldInitializeProperty(
|
||||
@@ -1699,4 +1767,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return r;
|
||||
}
|
||||
|
||||
public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor) {
|
||||
if (classObjectPropertiesToCopy == null) {
|
||||
classObjectPropertiesToCopy = new ArrayList<PropertyDescriptor>();
|
||||
}
|
||||
classObjectPropertiesToCopy.add(descriptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,22 +17,32 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
||||
|
||||
public class MemberCodegen extends GenerationStateAware {
|
||||
public MemberCodegen(@NotNull GenerationState state) {
|
||||
|
||||
@Nullable
|
||||
private MemberCodegen parentCodegen;
|
||||
|
||||
public MemberCodegen(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) {
|
||||
super(state);
|
||||
this.parentCodegen = parentCodegen;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MemberCodegen getParentCodegen() {
|
||||
return parentCodegen;
|
||||
}
|
||||
|
||||
public void genFunctionOrProperty(
|
||||
@@ -54,7 +64,7 @@ public class MemberCodegen extends GenerationStateAware {
|
||||
}
|
||||
else if (functionOrProperty instanceof JetProperty) {
|
||||
try {
|
||||
new PropertyCodegen(context, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty);
|
||||
new PropertyCodegen(context, classBuilder, functionCodegen, this).gen((JetProperty) functionOrProperty);
|
||||
}
|
||||
catch (CompilationException e) {
|
||||
throw e;
|
||||
@@ -80,8 +90,8 @@ public class MemberCodegen extends GenerationStateAware {
|
||||
}
|
||||
|
||||
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
|
||||
CodegenContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
|
||||
ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, this).generate();
|
||||
classBuilder.done();
|
||||
|
||||
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
public enum MethodKind {
|
||||
GENERAL,
|
||||
INITIALIZER,
|
||||
SYNTHETIC_ACCESSOR
|
||||
}
|
||||
@@ -26,11 +26,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.AnnotationVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -56,7 +54,7 @@ public class NamespaceCodegen extends MemberCodegen {
|
||||
GenerationState state,
|
||||
Collection<JetFile> namespaceFiles
|
||||
) {
|
||||
super(state);
|
||||
super(state, null);
|
||||
checkAllFilesHaveSameNamespace(namespaceFiles);
|
||||
|
||||
this.v = v;
|
||||
@@ -218,7 +216,7 @@ public class NamespaceCodegen extends MemberCodegen {
|
||||
|
||||
for (JetDeclaration declaration : properties) {
|
||||
ImplementationBodyCodegen.
|
||||
initializeProperty(codegen, state.getBindingContext(), new InstructionAdapter(mv), (JetProperty) declaration, true);
|
||||
initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
|
||||
}
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
|
||||
@@ -19,24 +19,29 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.FieldVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.context.MethodContext;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
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.DescriptorUtils;
|
||||
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.JvmClassName;
|
||||
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;
|
||||
@@ -46,31 +51,44 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityForSpecialPropertyBackingField;
|
||||
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||
|
||||
public class PropertyCodegen extends GenerationStateAware {
|
||||
@NotNull
|
||||
private final FunctionCodegen functionCodegen;
|
||||
|
||||
@NotNull
|
||||
private final ClassBuilder v;
|
||||
|
||||
@NotNull
|
||||
private final CodegenContext context;
|
||||
|
||||
@Nullable
|
||||
private MemberCodegen classBodyCodegen;
|
||||
|
||||
@NotNull
|
||||
private final OwnerKind kind;
|
||||
|
||||
public PropertyCodegen(CodegenContext context, ClassBuilder v, FunctionCodegen functionCodegen) {
|
||||
public PropertyCodegen(
|
||||
@NotNull CodegenContext context,
|
||||
@NotNull ClassBuilder v,
|
||||
@NotNull FunctionCodegen functionCodegen,
|
||||
@Nullable MemberCodegen classBodyCodegen
|
||||
) {
|
||||
super(functionCodegen.getState());
|
||||
this.v = v;
|
||||
this.functionCodegen = functionCodegen;
|
||||
this.context = context;
|
||||
this.classBodyCodegen = classBodyCodegen;
|
||||
this.kind = context.getContextKind();
|
||||
}
|
||||
|
||||
public void gen(JetProperty p) {
|
||||
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, p);
|
||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||
}
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
PropertyDescriptor propertyDescriptor = DescriptorUtils.getPropertyDescriptor(p, bindingContext);
|
||||
assert kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
|
||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
||||
: "Generating property with a wrong kind (" + kind + "): " + propertyDescriptor;
|
||||
|
||||
if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) {
|
||||
generateBackingField(p, propertyDescriptor);
|
||||
@@ -89,7 +107,7 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
||||
private void generateBackingField(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||
//noinspection ConstantConditions
|
||||
boolean hasBackingField = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
||||
boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null;
|
||||
@@ -108,25 +126,56 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
|
||||
}
|
||||
|
||||
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
int modifiers = ACC_PRIVATE | ACC_FINAL | getDeprecatedAccessFlag(propertyDescriptor);
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
modifiers |= ACC_STATIC;
|
||||
}
|
||||
private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
|
||||
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
|
||||
|
||||
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
|
||||
modifiers |= ACC_VOLATILE;
|
||||
}
|
||||
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
modifiers |= ACC_STATIC;
|
||||
}
|
||||
|
||||
if (!propertyDescriptor.isVar() || isDelegate) {
|
||||
modifiers |= ACC_FINAL;
|
||||
}
|
||||
|
||||
Type type = typeMapper.mapType(jetType);
|
||||
|
||||
ClassBuilder builder = v;
|
||||
|
||||
if (AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
|
||||
modifiers |= ACC_STATIC | getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegate);
|
||||
builder = getParentBodyCodegen(classBodyCodegen).v;
|
||||
} else {
|
||||
if (kind != OwnerKind.NAMESPACE || isDelegate) {
|
||||
modifiers |= ACC_PRIVATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
|
||||
ImplementationBodyCodegen parentBodyCodegen = getParentBodyCodegen(classBodyCodegen);
|
||||
parentBodyCodegen.addClassObjectPropertyToCopy(propertyDescriptor);
|
||||
}
|
||||
|
||||
String name = isDelegate ? JvmAbi.getPropertyDelegateName(propertyDescriptor.getName()) : propertyDescriptor.getName().asString();
|
||||
|
||||
return builder.newField(element, modifiers, name, type.getDescriptor(),
|
||||
null, defaultValue);
|
||||
}
|
||||
|
||||
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
|
||||
if (delegateType == null) {
|
||||
// If delegate expression is unresolved reference
|
||||
delegateType = ErrorUtils.createErrorType("Delegate type");
|
||||
}
|
||||
Type type = typeMapper.mapType(delegateType);
|
||||
return v.newField(p, modifiers, JvmAbi.getPropertyDelegateName(propertyDescriptor.getName()), type.getDescriptor(),
|
||||
null, null);
|
||||
|
||||
return generateBackingField(p, propertyDescriptor, true, delegateType, null);
|
||||
}
|
||||
|
||||
private FieldVisitor generateBackingFieldAccess(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
||||
private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||
Object value = null;
|
||||
if (p instanceof JetProperty && !ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) p, typeMapper)) {
|
||||
JetExpression initializer = ((JetProperty) p).getInitializer();
|
||||
@@ -135,22 +184,8 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
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().asString(), type.getDescriptor(), null, value);
|
||||
|
||||
return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
|
||||
}
|
||||
|
||||
private void generateGetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor getter) {
|
||||
@@ -166,10 +201,10 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
FunctionGenerationStrategy strategy;
|
||||
if (defaultGetter) {
|
||||
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(getterDescriptor);
|
||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(state, getterDescriptor);
|
||||
}
|
||||
else {
|
||||
strategy = new DefaultPropertyAccessorStrategy(getterDescriptor);
|
||||
strategy = new DefaultPropertyAccessorStrategy(state, getterDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -197,10 +232,10 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
FunctionGenerationStrategy strategy;
|
||||
if (defaultSetter) {
|
||||
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(setterDescriptor);
|
||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(state, setterDescriptor);
|
||||
}
|
||||
else {
|
||||
strategy = new DefaultPropertyAccessorStrategy(setterDescriptor);
|
||||
strategy = new DefaultPropertyAccessorStrategy(state, setterDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -216,90 +251,82 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
}
|
||||
|
||||
|
||||
private class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy {
|
||||
private final PropertyAccessorDescriptor descriptor;
|
||||
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
||||
|
||||
public DefaultPropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
public DefaultPropertyAccessorStrategy(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull PropertyAccessorDescriptor callableDescriptor
|
||||
) {
|
||||
super(state, callableDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateBody(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull MethodContext context
|
||||
public void doGenerateBody(
|
||||
ExpressionCodegen codegen, JvmMethodSignature signature
|
||||
) {
|
||||
generateDefaultAccessor(descriptor, new InstructionAdapter(mv), typeMapper, context);
|
||||
generateDefaultAccessor(callableDescriptor, codegen.v, codegen);
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateDefaultAccessor(
|
||||
@NotNull PropertyAccessorDescriptor accessorDescriptor,
|
||||
@NotNull InstructionAdapter iv,
|
||||
@NotNull JetTypeMapper typeMapper,
|
||||
@NotNull CodegenContext context
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
JetTypeMapper typeMapper = codegen.typeMapper;
|
||||
CodegenContext context = codegen.context;
|
||||
OwnerKind kind = context.getContextKind();
|
||||
|
||||
PropertyDescriptor propertyDescriptor = accessorDescriptor.getCorrespondingProperty();
|
||||
Type type = typeMapper.mapType(propertyDescriptor);
|
||||
|
||||
int paramCode = 0;
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
paramCode = 1;
|
||||
}
|
||||
|
||||
StackValue property = codegen.intermediateValueForProperty(accessorDescriptor.getCorrespondingProperty(), true, null);
|
||||
|
||||
if (accessorDescriptor instanceof PropertyGetterDescriptor) {
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
iv.visitFieldInsn(
|
||||
kind == OwnerKind.NAMESPACE ? GETSTATIC : GETFIELD,
|
||||
typeMapper.getOwner(propertyDescriptor, kind, isCallInsideSameModuleAsDeclared(propertyDescriptor, context)).getInternalName(),
|
||||
propertyDescriptor.getName().asString(),
|
||||
type.getDescriptor());
|
||||
property.put(type, iv);
|
||||
iv.areturn(type);
|
||||
}
|
||||
else if (accessorDescriptor instanceof PropertySetterDescriptor) {
|
||||
int paramCode = 0;
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
paramCode = 1;
|
||||
}
|
||||
ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter();
|
||||
if (receiverParameter != null) {
|
||||
paramCode += typeMapper.mapType(receiverParameter.getType()).getSize();
|
||||
}
|
||||
iv.load(paramCode, type);
|
||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? PUTSTATIC : PUTFIELD,
|
||||
typeMapper.getOwner(propertyDescriptor, kind, isCallInsideSameModuleAsDeclared(propertyDescriptor, context)).getInternalName(),
|
||||
propertyDescriptor.getName().asString(),
|
||||
type.getDescriptor());
|
||||
|
||||
property.store(type, iv);
|
||||
iv.visitInsn(RETURN);
|
||||
} else {
|
||||
assert false : "Unreachable state";
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy {
|
||||
private final PropertyAccessorDescriptor descriptor;
|
||||
|
||||
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
private static class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
||||
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
|
||||
super(state, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateBody(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull MethodContext context
|
||||
public void doGenerateBody(
|
||||
@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature
|
||||
) {
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(
|
||||
mv, getFrameMap(typeMapper, context), signature.getAsmMethod().getReturnType(), context, state);
|
||||
JetTypeMapper typeMapper = codegen.typeMapper;
|
||||
OwnerKind kind = codegen.context.getContextKind();
|
||||
InstructionAdapter iv = codegen.v;
|
||||
BindingContext bindingContext = state.getBindingContext();
|
||||
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall =
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, descriptor);
|
||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, callableDescriptor);
|
||||
|
||||
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, descriptor);
|
||||
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, callableDescriptor);
|
||||
assert call != null : "Call should be recorded for delegate call " + signature.toString();
|
||||
|
||||
PropertyDescriptor property = descriptor.getCorrespondingProperty();
|
||||
PropertyDescriptor property = callableDescriptor.getCorrespondingProperty();
|
||||
Type asmType = typeMapper.mapType(property);
|
||||
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
private Method scriptConstructorMethod;
|
||||
|
||||
public ScriptCodegen(@NotNull GenerationState state) {
|
||||
super(state);
|
||||
super(state, null);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -145,7 +145,6 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
|
||||
ImplementationBodyCodegen.generateInitializers(
|
||||
new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state),
|
||||
instructionAdapter,
|
||||
scriptDeclaration.getDeclarations(),
|
||||
bindingContext,
|
||||
state);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
@@ -24,8 +24,8 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
|
||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
public TraitImplBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||
super(aClass, context, v, state);
|
||||
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
|
||||
super(aClass, context, v, state, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,9 +22,8 @@ import org.jetbrains.jet.codegen.OwnerKind;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLOSURE;
|
||||
public class AnonymousClassContext extends ClassContext {
|
||||
|
||||
public class AnonymousClassContext extends CodegenContext {
|
||||
public AnonymousClassContext(
|
||||
@NotNull JetTypeMapper typeMapper,
|
||||
@NotNull ClassDescriptor contextDescriptor,
|
||||
@@ -33,14 +32,7 @@ public class AnonymousClassContext extends CodegenContext {
|
||||
@Nullable LocalLookup localLookup
|
||||
) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor),
|
||||
contextDescriptor, localLookup);
|
||||
initOuterExpression(typeMapper, contextDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return false;
|
||||
super(typeMapper, contextDescriptor, contextKind, parentContext, localLookup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -146,31 +146,37 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return contextKind;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CodegenContext intoNamespace(@NotNull NamespaceDescriptor descriptor) {
|
||||
return new NamespaceContext(descriptor, this, OwnerKind.NAMESPACE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor) {
|
||||
return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||
return new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
||||
}
|
||||
|
||||
public CodegenContext intoAnonymousClass(
|
||||
ClassDescriptor descriptor,
|
||||
ExpressionCodegen expressionCodegen
|
||||
@NotNull
|
||||
public ClassContext intoAnonymousClass(
|
||||
@NotNull ClassDescriptor descriptor,
|
||||
@NotNull ExpressionCodegen expressionCodegen
|
||||
) {
|
||||
JetTypeMapper typeMapper = expressionCodegen.getState().getTypeMapper();
|
||||
return new AnonymousClassContext(typeMapper, descriptor, OwnerKind.IMPLEMENTATION, this,
|
||||
expressionCodegen);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||
if (descriptor == null) {
|
||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||
@@ -180,6 +186,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
|
||||
return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
||||
import org.jetbrains.jet.codegen.signature.*;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
@@ -961,4 +962,15 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
}
|
||||
return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner.getAsmType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Type expressionType(JetExpression expr) {
|
||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
|
||||
return asmTypeOrVoid(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Type asmTypeOrVoid(@Nullable JetType type) {
|
||||
return type == null ? Type.VOID_TYPE : mapType(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,6 +553,10 @@ public class JetPsiUtil {
|
||||
return getOutermostClassOrObject(classOrObject) == null;
|
||||
}
|
||||
|
||||
public static boolean isTrait(@NotNull JetClassOrObject classOrObject) {
|
||||
return classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetClassOrObject getOutermostClassOrObject(@NotNull JetClassOrObject classOrObject) {
|
||||
JetClassOrObject current = classOrObject;
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
@@ -289,6 +290,10 @@ public class DescriptorUtils {
|
||||
return isKindOf(descriptor, ClassKind.ENUM_CLASS);
|
||||
}
|
||||
|
||||
public static boolean isClass(@NotNull DeclarationDescriptor descriptor) {
|
||||
return isKindOf(descriptor, ClassKind.CLASS);
|
||||
}
|
||||
|
||||
public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) {
|
||||
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
return isKindOf(descriptor, classKind);
|
||||
@@ -572,4 +577,13 @@ public class DescriptorUtils {
|
||||
}
|
||||
return allSuperclasses;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PropertyDescriptor getPropertyDescriptor(@NotNull JetProperty property, @NotNull BindingContext bindingContext) {
|
||||
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, property);
|
||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||
}
|
||||
return (PropertyDescriptor) descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user