提交 85f46abc 编写于 作者: D Dmitry Jemerov

handle getters/setters without body; generate initializers for class-level properties

上级 9e33922b
......@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PropertyDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
......@@ -161,15 +162,44 @@ public class ClassCodegen {
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode();
FrameMap frameMap = new FrameMap();
frameMap.enterTemp(); // this
final InstructionAdapter iv = new InstructionAdapter(mv);
String superClass = getSuperClass(aClass, kind);
iv.load(0, Type.getType("L" + superClass + ";"));
iv.invokespecial(superClass, "<init>", method.getDescriptor());
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap,
typeMapper, Type.VOID_TYPE);
generateInitializers(aClass, kind, codegen, iv, typeMapper);
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateInitializers(JetClass aClass, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter iv, JetTypeMapper typeMapper) {
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetProperty) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
if (bindingContext.hasBackingField(propertyDescriptor)) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
codegen.genToJVMStack(initializer);
iv.putfield(JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor());
}
}
}
}
}
private void generateClassBody(JetClass aClass, ClassVisitor v, OwnerKind kind) {
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final FunctionCodegen functionCodegen = new FunctionCodegen(v, standardLibrary, bindingContext);
......
......@@ -60,7 +60,7 @@ public class ExpressionCodegen extends JetVisitor {
}
}
private void genToJVMStack(JetExpression expr) {
public void genToJVMStack(JetExpression expr) {
gen(expr, expressionType(expr));
}
......
package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.jet.lang.psi.JetConstantExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
......@@ -71,28 +68,38 @@ public class PropertyCodegen {
}
final JetPropertyAccessor getter = p.getGetter();
if (getter != null) {
functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor),
Collections.<ValueParameterDescriptor>emptyList());
if (getter.getBodyExpression() != null) {
functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor),
Collections.<ValueParameterDescriptor>emptyList());
}
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultGetter(p, getter, kind);
}
}
else if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
generateDefaultGetter(p, kind);
generateDefaultGetter(p, p, kind);
}
final JetPropertyAccessor setter = p.getSetter();
if (setter != null) {
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
assert setterDescriptor != null;
functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor),
setterDescriptor.getUnsubstitutedValueParameters());
if (setter.getBodyExpression() != null) {
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
assert setterDescriptor != null;
functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor),
setterDescriptor.getUnsubstitutedValueParameters());
}
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultSetter(p, setter, kind);
}
}
else if (p.hasModifier(JetTokens.PUBLIC_KEYWORD) && p.isVar()) {
generateDefaultSetter(p, kind);
generateDefaultSetter(p, p, kind);
}
}
}
private void generateDefaultGetter(JetProperty p, OwnerKind kind) {
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
int flags = JetTypeMapper.getAccessModifiers(p, Opcodes.ACC_PUBLIC);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
......@@ -112,9 +119,9 @@ public class PropertyCodegen {
mv.visitEnd();
}
private void generateDefaultSetter(JetProperty p, OwnerKind kind) {
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
int flags = JetTypeMapper.getAccessModifiers(p, Opcodes.ACC_PUBLIC);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
......
......@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetLightProjectDescriptor;
import org.jetbrains.jet.lang.JetFileType;
import org.jetbrains.jet.lang.psi.JetFile;
......@@ -97,16 +98,21 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
protected Method generateFunction(String name) {
Class aClass = generateNamespaceClass();
return findMethodByName(aClass, name);
final Method method = findMethodByName(aClass, name);
if (method == null) {
throw new IllegalArgumentException("couldn't find method " + name);
}
return method;
}
@Nullable
protected static Method findMethodByName(Class aClass, String name) {
for (Method method : aClass.getMethods()) {
if (method.getName().equals(name)) {
return method;
}
}
throw new IllegalArgumentException("couldn't find method " + name);
return null;
}
protected static void assertIsCurrentTime(long returnValue) {
......
......@@ -73,4 +73,13 @@ public class PropertyGenTest extends CodegenTestCase {
String value = (String) method.invoke(null, "IDEA");
assertEquals(value, "IntelliJ IDEA");
}
public void testAccessorsWithoutBody() throws Exception {
loadText("class AccessorsWithoutBody { public var foo: Int = 349\n get\n private set } ");
final Class aClass = loadImplementationClass(generateClassesInFile(), "AccessorsWithoutBody");
final Object instance = aClass.newInstance();
final Method getFoo = findMethodByName(aClass, "getFoo");
assertEquals(349, getFoo.invoke(instance));
assertNull(findMethodByName(aClass, "setFoo"));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册