working on @JetProperty.type

This commit is contained in:
Stepan Koltsov
2012-01-12 07:04:00 +04:00
parent 541fc8ec29
commit ec5d5e2dcf
13 changed files with 130 additions and 59 deletions
@@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null, null), funDescriptor);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null, null), null, funDescriptor);
return closureContext.outerWasUsed;
}
@@ -1097,7 +1097,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod();
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
else
getter = null;
}
@@ -1107,8 +1107,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) {
JvmMethodSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
setter = jvmMethodSignature != null ? jvmMethodSignature.getAsmMethod() : null;
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
} else {
setter = null;
}
@@ -43,18 +43,19 @@ public class FunctionCodegen {
final NamedFunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
assert functionDescriptor != null;
JvmMethodSignature method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
generateMethod(f, method, functionDescriptor);
generateMethod(f, method, null, functionDescriptor);
}
public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, FunctionDescriptor functionDescriptor) {
public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, @Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor) {
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
generatedMethod(bodyExpression, jvmMethod, propertyTypeSignature, funContext, functionDescriptor, f);
}
private void generatedMethod(JetExpression bodyExpressions,
JvmMethodSignature jvmSignature,
@Nullable String propertyTypeSignature,
CodegenContext.MethodContext context,
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{
@@ -92,9 +93,11 @@ public class FunctionCodegen {
int start = 0;
if(kind != OwnerKind.TRAIT_IMPL) {
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
AnnotationVisitor av = mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true);
av.visitEnd();
PropertyCodegen.generateJetPropertyAnnotation(mv, propertyTypeSignature);
} else if (functionDescriptor instanceof NamedFunctionDescriptor) {
if (propertyTypeSignature != null) {
throw new IllegalStateException();
}
AnnotationVisitor av = mv.visitAnnotation(JvmStdlibNames.JET_METHOD.getDescriptor(), true);
if(functionDescriptor.getReturnType().isNullable()) {
av.visit(JvmStdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
@@ -237,50 +237,58 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
InstructionAdapter iv = null;
if (v.generateCode()) {
mv.visitCode();
{
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature());
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
if(original.getVisibility() == Visibility.PRIVATE)
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.load(0, JetTypeMapper.TYPE_OBJECT);
if(original.getVisibility() == Visibility.PRIVATE)
iv.getfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getReturnType().getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
if (v.generateCode()) {
mv.visitCode();
{
iv = new InstructionAdapter(mv);
Method method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
JvmPropertyAccessorSignature originalSignature2 = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature());
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
if (v.generateCode()) {
mv.visitCode();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type[] argTypes = method.getArgumentTypes();
for (int i = 0, reg = 1; i < argTypes.length; i++) {
Type argType = argTypes[i];
iv.load(reg, argType);
//noinspection AssignmentToForLoopParameter
reg += argType.getSize();
}
if(original.getVisibility() == Visibility.PRIVATE)
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
if(original.getVisibility() == Visibility.PRIVATE)
iv.putfield(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), original.getName(), originalMethod.getArgumentTypes()[0].getDescriptor());
else
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
FunctionCodegen.endVisit(iv, "accessor", null);
}
}
else {
@@ -574,7 +574,7 @@ public class JetTypeMapper {
}
public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
public JvmPropertyAccessorSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
String name = PropertyCodegen.getterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>();
@@ -595,11 +595,13 @@ public class JetTypeMapper {
}
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null, null);
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null, null);
return new JvmPropertyAccessorSignature(jvmMethodSignature, "");
}
@Nullable
public JvmMethodSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
public JvmPropertyAccessorSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
if (!descriptor.isVar()) {
return null;
}
@@ -627,7 +629,8 @@ public class JetTypeMapper {
params.add(mapType(outType));
// TODO: proper generic signature
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null, null);
JvmMethodSignature jvmMethodSignature = new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null, null);
return new JvmPropertyAccessorSignature(jvmMethodSignature, "");
}
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -0,0 +1,28 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
/**
* @author Stepan Koltsov
*/
public class JvmPropertyAccessorSignature {
@NotNull
private final JvmMethodSignature jvmMethodSignature;
@NotNull
private final String propertyTypeKotlinSignature;
public JvmPropertyAccessorSignature(@NotNull JvmMethodSignature jvmMethodSignature, @NotNull String propertyTypeKotlinSignature) {
this.jvmMethodSignature = jvmMethodSignature;
this.propertyTypeKotlinSignature = propertyTypeKotlinSignature;
}
@NotNull
public JvmMethodSignature getJvmMethodSignature() {
return jvmMethodSignature;
}
@NotNull
public String getPropertyTypeKotlinSignature() {
return propertyTypeKotlinSignature;
}
}
@@ -2,6 +2,7 @@ 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.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
@@ -12,6 +13,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -86,7 +88,8 @@ public class PropertyCodegen {
final JetPropertyAccessor getter = p.getGetter();
if (getter != null) {
if (getter.getBodyExpression() != null) {
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind), propertyDescriptor.getGetter());
JvmPropertyAccessorSignature signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind);
functionCodegen.generateMethod(getter, signature.getJvmMethodSignature(), signature.getPropertyTypeKotlinSignature(), propertyDescriptor.getGetter());
}
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultGetter(p, getter);
@@ -107,7 +110,8 @@ public class PropertyCodegen {
if (setter.getBodyExpression() != null) {
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
assert setterDescriptor != null;
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind), setterDescriptor);
JvmPropertyAccessorSignature signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind);
functionCodegen.generateMethod(setter, signature.getJvmMethodSignature(), signature.getPropertyTypeKotlinSignature(), setterDescriptor);
}
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultSetter(p, setter);
@@ -138,10 +142,11 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
JvmPropertyAccessorSignature signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind);
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
MethodVisitor mv = v.newMethod(origin, flags, getterName, descriptor, null, null);
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature());
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -152,7 +157,7 @@ public class PropertyCodegen {
if (kind instanceof OwnerKind.DelegateKind) {
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
iv.invokeinterface(dk.getOwnerClass(), getterName, signature);
iv.invokeinterface(dk.getOwnerClass(), getterName, descriptor);
}
else {
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
@@ -164,6 +169,14 @@ public class PropertyCodegen {
}
}
public static void generateJetPropertyAnnotation(MethodVisitor mv, @NotNull String kotlinType) {
AnnotationVisitor annotationVisitor = mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true);
if (kotlinType.length() > 0) {
annotationVisitor.visit(JvmStdlibNames.JET_PROPERTY_TYPE_FIELD, kotlinType);
}
annotationVisitor.visitEnd();
}
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
@@ -184,9 +197,10 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
JvmPropertyAccessorSignature signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind);
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null);
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature());
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -203,7 +217,7 @@ public class PropertyCodegen {
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
iv.load(paramCode, type);
iv.invokeinterface(dk.getOwnerClass(), setterName(propertyDescriptor.getName()), signature);
iv.invokeinterface(dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor);
}
else {
iv.load(paramCode, type);
@@ -30,6 +30,8 @@ public class JvmStdlibNames {
public static final JvmClassName JET_PROPERTY = new JvmClassName("jet.runtime.typeinfo.JetProperty");
public static final String JET_PROPERTY_TYPE_FIELD = "type";
public static final JvmClassName JET_CONSTRUCTOR = new JvmClassName("jet.runtime.typeinfo.JetConstructor");
/**
@@ -0,0 +1,6 @@
package test
import java.lang.CharSequence
val Int.ggg: CharSequence
get() = throw Exception()
@@ -0,0 +1,6 @@
package test
import java.lang.CharSequence
val Int.ggg: CharSequence?
get() = throw Exception()
@@ -11,4 +11,5 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JetProperty {
String type() default "";
}