From 6dfa8ca8c6ff409b29ae59f7fbd55131e52d5767 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 27 May 2011 18:11:42 +0400 Subject: [PATCH] don't forget to put receiver on stack when calling extension functions --- .../jet/codegen/ExpressionCodegen.java | 10 ++++-- .../codegen/extensionFunctions/whenFail.jet | 14 ++++++++ .../jet/codegen/CodegenTestCase.java | 35 +++++++++++++------ .../jet/codegen/ExtensionFunctionsTest.java | 6 ++++ .../jet/codegen/PatternMatchingTest.java | 10 +----- 5 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 idea/testData/codegen/extensionFunctions/whenFail.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 3f17fcb2d2a..cc0a20b79f3 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -722,13 +722,17 @@ public class ExpressionCodegen extends JetVisitor { methodDescriptor.getDescriptor()); } else { - methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement); - if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) { + final JetFunction jetFunction = (JetFunction) declarationPsiElement; + methodDescriptor = typeMapper.mapSignature(jetFunction); + if (functionParent instanceof NamespaceDescriptorImpl) { + if (jetFunction.getReceiverTypeRef() != null) { + ensureReceiverOnStack(expression); + } pushMethodArguments(expression, methodDescriptor); final String owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor()); } - else if (functionParent instanceof ClassDescriptor && declarationPsiElement instanceof JetFunction) { + else if (functionParent instanceof ClassDescriptor) { ensureReceiverOnStack(expression); pushMethodArguments(expression, methodDescriptor); final String owner = JetTypeMapper.jvmNameForInterface((ClassDescriptor) functionParent); diff --git a/idea/testData/codegen/extensionFunctions/whenFail.jet b/idea/testData/codegen/extensionFunctions/whenFail.jet new file mode 100644 index 00000000000..252fe893a86 --- /dev/null +++ b/idea/testData/codegen/extensionFunctions/whenFail.jet @@ -0,0 +1,14 @@ +fun StringBuilder.takeFirst(): Char { + if (this.length() == 0) return '\0' + val c = this.charAt(0) + this.deleteCharAt(0) + return c +} + +fun foo(expr: StringBuilder): Int { + val c = expr.takeFirst() + when(c) { + '\0' => throw new Exception("zero") + else => throw new Exception("nonzero" + c) + } +} diff --git a/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 71453d13979..b8d2823880c 100644 --- a/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -12,9 +12,8 @@ import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.parsing.JetParsingTest; -import javax.swing.JComponent; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.nio.channels.NonWritableChannelException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -25,6 +24,17 @@ import java.util.Map; public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase { private MyClassLoader myClassLoader; + protected static void assertThrows(Method foo, Class exceptionClass, Object instance, Object... args) throws IllegalAccessException { + boolean caught = false; + try { + foo.invoke(instance, args); + } + catch(InvocationTargetException ex) { + caught = exceptionClass.isInstance(ex.getTargetException()); + } + assertTrue(caught); + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -128,14 +138,19 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase { } protected Codegens generateClassesInFile() { - Codegens state = new Codegens(getProject(), false); - JetFile jetFile = (JetFile) myFixture.getFile(); - AnalyzingUtils.checkForSyntacticErrors(jetFile); - final JetNamespace namespace = jetFile.getRootNamespace(); - - NamespaceCodegen codegen = state.forNamespace(namespace); - codegen.generate(namespace); - return state; + try { + Codegens state = new Codegens(getProject(), false); + JetFile jetFile = (JetFile) myFixture.getFile(); + AnalyzingUtils.checkForSyntacticErrors(jetFile); + final JetNamespace namespace = jetFile.getRootNamespace(); + + NamespaceCodegen codegen = state.forNamespace(namespace); + codegen.generate(namespace); + return state; + } catch (RuntimeException e) { + System.out.println(generateToText()); + throw e; + } } protected Method generateFunction() { diff --git a/idea/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java b/idea/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java index 59d78daf88a..3305c6f551e 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ExtensionFunctionsTest.java @@ -17,4 +17,10 @@ public class ExtensionFunctionsTest extends CodegenTestCase { final Character c = (Character) foo.invoke(null); assertEquals('f', c.charValue()); } + + public void testWhenFail() throws Exception { + loadFile(); + Method foo = generateFunction("foo"); + assertThrows(foo, Exception.class, null, new StringBuilder()); + } } diff --git a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java index 6f27ac9ebf6..5ac5d30fb4c 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PatternMatchingTest.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen; import jet.NoPatternMatchedException; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** @@ -25,14 +24,7 @@ public class PatternMatchingTest extends CodegenTestCase { loadFile(); Method foo = generateFunction(); assertTrue((Boolean) foo.invoke(null, 0)); - boolean caught = false; - try { - foo.invoke(null, 1); - } - catch(InvocationTargetException ex) { - caught = ex.getTargetException() instanceof NoPatternMatchedException; - } - assertTrue(caught); + assertThrows(foo, NoPatternMatchedException.class, null, 1); } public void testPattern() throws Exception { -- GitLab