Supported simplest cases of SAM adapter in backend.

This commit is contained in:
Evgeny Gerashchenko
2013-04-16 19:17:46 +04:00
parent c5b9c6a7dc
commit 7bd11718de
9 changed files with 99 additions and 6 deletions
@@ -56,6 +56,7 @@ import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.JetType;
@@ -1790,6 +1791,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
@Nullable
private SimpleFunctionDescriptor getOriginalIfSamAdapter(@NotNull CallableDescriptor fun) {
if (!(fun instanceof SimpleFunctionDescriptor)) {
return null;
}
SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) fun).getOriginal();
return bindingContext.get(SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
}
private StackValue invokeSamConstructor(
JetCallExpression expression,
ResolvedCall<? extends CallableDescriptor> resolvedCall,
@@ -1967,7 +1977,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
callableMethod = typeMapper.asCallableMethod(invoke);
}
else {
callableMethod = typeMapper.mapToCallableMethod(fd, superCall,
SimpleFunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd);
callableMethod = typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall,
isCallInsideSameClassAsDeclared(fd, context),
isCallInsideSameModuleAsDeclared(fd, context),
OwnerKind.IMPLEMENTATION);
@@ -2214,12 +2225,27 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
int mask = 0;
SimpleFunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd);
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
if (resolvedValueArgument instanceof ExpressionValueArgument) {
ExpressionValueArgument valueArgument = (ExpressionValueArgument) resolvedValueArgument;
//noinspection ConstantConditions
gen(valueArgument.getValueArgument().getArgumentExpression(), valueParameterTypes.get(valueParameter.getIndex()));
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
assert valueArgument != null;
JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
if (originalOfSamAdapter != null) {
JetType samAdapterType = originalOfSamAdapter.getValueParameters().get(valueParameter.getIndex()).getType();
if (SingleAbstractMethodUtils.isSamType(samAdapterType)) {
ClassDescriptor samInterface = (ClassDescriptor) samAdapterType.getConstructor().getDeclarationDescriptor();
// TODO support not literals
genClosure(((JetFunctionLiteralExpression) argumentExpression).getFunctionLiteral(), samInterface);
continue;
}
}
gen(argumentExpression, valueParameterTypes.get(valueParameter.getIndex()));
}
else if (resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(valueParameter.getIndex());
@@ -134,7 +134,7 @@ public class SingleAbstractMethodUtils {
return result;
}
private static boolean isSamType(@NotNull JetType type) {
public static boolean isSamType(@NotNull JetType type) {
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
return classifier instanceof ClassDescriptorFromJvmBytecode &&
((ClassDescriptorFromJvmBytecode) classifier).isSamInterface() &&
@@ -0,0 +1,7 @@
import java.util.*;
class JavaClass {
public static void sortIntList(List<Integer> list, Comparator<Integer> comparator) {
Collections.sort(list, comparator);
}
}
@@ -0,0 +1,8 @@
import java.util.*
fun box(): String {
val list = ArrayList(Arrays.asList(3, 2, 4, 8, 1, 5))
val expected = ArrayList(Arrays.asList(8, 5, 4, 3, 2, 1))
JavaClass.sortIntList(list, { a, b -> b - a })
return if (list == expected) "OK" else list.toString()
}
@@ -0,0 +1,7 @@
import java.io.*;
class JavaClass {
public static String invokeFilter(FileFilter f, File file1, File file2) {
return f.accept(file1) + " " + f.accept(file2);
}
}
@@ -0,0 +1,11 @@
import java.io.*
fun box(): String {
val ACCEPT_NAME = "test"
val WRONG_NAME = "wrong"
val result = JavaClass.invokeFilter({ file -> ACCEPT_NAME == file?.getName() }, File(ACCEPT_NAME), File(WRONG_NAME))
if (result != "true false") return "Wrong result: $result"
return "OK"
}
@@ -0,0 +1,5 @@
class JavaClass {
public static void run(Runnable r) {
r.run();
}
}
@@ -0,0 +1,5 @@
fun box(): String {
var v = "FAIL"
JavaClass.run { v = "OK" }
return v
}
@@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/boxWithJava")
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.Enum.class, BlackBoxWithJavaCodegenTestGenerated.Functions.class, BlackBoxWithJavaCodegenTestGenerated.Property.class, BlackBoxWithJavaCodegenTestGenerated.StaticFun.class, BlackBoxWithJavaCodegenTestGenerated.Visibility.class})
@InnerTestClasses({BlackBoxWithJavaCodegenTestGenerated.Enum.class, BlackBoxWithJavaCodegenTestGenerated.Functions.class, BlackBoxWithJavaCodegenTestGenerated.Property.class, BlackBoxWithJavaCodegenTestGenerated.SamAdapters.class, BlackBoxWithJavaCodegenTestGenerated.StaticFun.class, BlackBoxWithJavaCodegenTestGenerated.Visibility.class})
public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInBoxWithJava() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -111,6 +111,29 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
}
@TestMetadata("compiler/testData/codegen/boxWithJava/samAdapters")
public static class SamAdapters extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInSamAdapters() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava/samAdapters"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("comparator.kt")
public void testComparator() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/comparator.kt");
}
@TestMetadata("fileFilter.kt")
public void testFileFilter() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/fileFilter.kt");
}
@TestMetadata("simplest.kt")
public void testSimplest() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/simplest.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxWithJava/staticFun")
public static class StaticFun extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInStaticFun() throws Exception {
@@ -271,6 +294,7 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
suite.addTestSuite(Enum.class);
suite.addTestSuite(Functions.class);
suite.addTestSuite(Property.class);
suite.addTestSuite(SamAdapters.class);
suite.addTestSuite(StaticFun.class);
suite.addTest(Visibility.innerSuite());
return suite;