use correct bytecode for calling methods on Java interfaces

This commit is contained in:
Dmitry Jemerov
2011-06-30 18:03:30 +02:00
parent cb1df5e2aa
commit e72aec943e
2 changed files with 38 additions and 23 deletions
@@ -775,29 +775,7 @@ public class ExpressionCodegen extends JetVisitor {
}
Method methodDescriptor;
if (declarationPsiElement instanceof PsiMethod) {
PsiMethod psiMethod = (PsiMethod) declarationPsiElement;
String owner = JetTypeMapper.jvmName(psiMethod.getContainingClass());
methodDescriptor = getMethodDescriptor(psiMethod);
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
if (!isStatic) {
ensureReceiverOnStack(expression, null);
if (expression.getParent() instanceof JetQualifiedExpression) {
final JetExpression receiver = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
JetType expressionType = bindingContext.getExpressionType(receiver);
DeclarationDescriptor declarationDescriptor = expressionType.getConstructor().getDeclarationDescriptor();
PsiElement ownerDeclaration = bindingContext.getDeclarationPsiElement(declarationDescriptor);
if (ownerDeclaration instanceof PsiClass) {
owner = typeMapper.mapType(expressionType).getInternalName();
}
}
}
pushMethodArguments(expression, methodDescriptor);
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL,
owner,
methodDescriptor.getName(),
methodDescriptor.getDescriptor());
methodDescriptor = generateJavaMethodCall(expression, (PsiMethod) declarationPsiElement);
}
else if (declarationPsiElement instanceof JetNamedFunction) {
final JetNamedFunction jetFunction = (JetNamedFunction) declarationPsiElement;
@@ -854,6 +832,35 @@ public class ExpressionCodegen extends JetVisitor {
}
}
private Method generateJavaMethodCall(JetCallExpression expression, PsiMethod psiMethod) {
final PsiClass containingClass = psiMethod.getContainingClass();
String owner = JetTypeMapper.jvmName(containingClass);
Method methodDescriptor = getMethodDescriptor(psiMethod);
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
if (!isStatic) {
ensureReceiverOnStack(expression, null);
if (expression.getParent() instanceof JetQualifiedExpression) {
final JetExpression receiver = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
JetType expressionType = bindingContext.getExpressionType(receiver);
DeclarationDescriptor declarationDescriptor = expressionType.getConstructor().getDeclarationDescriptor();
PsiElement ownerDeclaration = bindingContext.getDeclarationPsiElement(declarationDescriptor);
if (ownerDeclaration instanceof PsiClass) {
owner = typeMapper.mapType(expressionType).getInternalName();
}
}
}
pushMethodArguments(expression, methodDescriptor);
v.visitMethodInsn(isStatic
? Opcodes.INVOKESTATIC
: (containingClass.isInterface() ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL),
owner,
methodDescriptor.getName(),
methodDescriptor.getDescriptor());
return methodDescriptor;
}
private JetExpression getReceiverForSelector(JetElement expression) {
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
@@ -418,4 +418,12 @@ public class NamespaceGenTest extends CodegenTestCase {
public void testIncrementProperty() throws Exception {
blackBoxFile("incrementProperty.jet");
}
public void testJavaInterfaceMethod() throws Exception {
loadText("import java.util.*; fun foo(l: List<String>) { l.add(\"foo\") }");
final Method main = generateFunction();
final ArrayList<String> list = new ArrayList<String>();
main.invoke(null, list);
assertEquals("foo", list.get(0));
}
}