Supported SAM adapters as get/set operators.
This commit is contained in:
@@ -2849,7 +2849,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
|
private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
|
||||||
StackValue stackValue = gen(expression.getLeft());
|
StackValue stackValue = gen(expression.getLeft());
|
||||||
gen(expression.getRight(), stackValue.type);
|
JetExpression right = expression.getRight();
|
||||||
|
assert right != null : expression.getText();
|
||||||
|
samAwareGen(right, stackValue.type);
|
||||||
stackValue.store(stackValue.type, v);
|
stackValue.store(stackValue.type, v);
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
@@ -3374,7 +3376,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod();
|
Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod();
|
||||||
Type[] argumentTypes = asmMethod.getArgumentTypes();
|
Type[] argumentTypes = asmMethod.getArgumentTypes();
|
||||||
for (JetExpression jetExpression : expression.getIndexExpressions()) {
|
for (JetExpression jetExpression : expression.getIndexExpressions()) {
|
||||||
gen(jetExpression, argumentTypes[index]);
|
samAwareGen(jetExpression, argumentTypes[index]);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen.binding;
|
package org.jetbrains.jet.codegen.binding;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.util.containers.Stack;
|
import com.intellij.util.containers.Stack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -39,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
|||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -381,6 +383,43 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
|
||||||
|
super.visitArrayAccessExpression(expression);
|
||||||
|
|
||||||
|
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
||||||
|
if (operationDescriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isSetter = operationDescriptor.getName().asString().equals("set");
|
||||||
|
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(bindingContext, operationDescriptor);
|
||||||
|
if (original == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JetExpression> indexExpressions = expression.getIndexExpressions();
|
||||||
|
List<ValueParameterDescriptor> parameters = original.getValueParameters();
|
||||||
|
for (ValueParameterDescriptor valueParameter : parameters) {
|
||||||
|
ClassDescriptorFromJvmBytecode samInterface = getInterfaceIfSamType(valueParameter.getType());
|
||||||
|
if (samInterface == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSetter && valueParameter.getIndex() == parameters.size() - 1) {
|
||||||
|
PsiElement parent = expression.getParent();
|
||||||
|
if (parent instanceof JetBinaryExpression && ((JetBinaryExpression) parent).getOperationToken() == JetTokens.EQ) {
|
||||||
|
JetExpression right = ((JetBinaryExpression) parent).getRight();
|
||||||
|
bindingTrace.record(CodegenBinding.SAM_VALUE, right, samInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JetExpression indexExpression = indexExpressions.get(valueParameter.getIndex());
|
||||||
|
bindingTrace.record(CodegenBinding.SAM_VALUE, indexExpression, samInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static ClassDescriptorFromJvmBytecode getInterfaceIfSamType(@NotNull JetType originalType) {
|
private static ClassDescriptorFromJvmBytecode getInterfaceIfSamType(@NotNull JetType originalType) {
|
||||||
if (!SingleAbstractMethodUtils.isSamType(originalType)) {
|
if (!SingleAbstractMethodUtils.isSamType(originalType)) {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class JavaClass {
|
||||||
|
int get(Runnable i) {
|
||||||
|
i.run();
|
||||||
|
return 239;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val obj = JavaClass()
|
||||||
|
|
||||||
|
var v = "FAIL"
|
||||||
|
obj[{ v = "OK" }]
|
||||||
|
return v
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class JavaClass {
|
||||||
|
int get(Runnable i1, Runnable i2) {
|
||||||
|
i1.run();
|
||||||
|
i2.run();
|
||||||
|
return 239;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(Runnable i1, Runnable i2, Runnable value) {
|
||||||
|
i1.run();
|
||||||
|
i2.run();
|
||||||
|
value.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val obj = JavaClass()
|
||||||
|
|
||||||
|
var v1 = "FAIL"
|
||||||
|
obj[{ v1 = "O" }, { v1 += "K" }]
|
||||||
|
if (v1 != "OK") return "get: $v1"
|
||||||
|
|
||||||
|
var v2 = "FAIL"
|
||||||
|
obj[{ v2 = "" }, { v2 += "O" }] = { v2 += "K" }
|
||||||
|
if (v2 != "OK") return "set: $v2"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class JavaClass {
|
||||||
|
void set(Runnable i, Runnable value) {
|
||||||
|
i.run();
|
||||||
|
value.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val obj = JavaClass()
|
||||||
|
|
||||||
|
var v = "FAIL"
|
||||||
|
obj[{ v = "O" }] = { v += "K" }
|
||||||
|
return v
|
||||||
|
}
|
||||||
+31
-1
@@ -130,6 +130,7 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithJava/samAdapters")
|
@TestMetadata("compiler/testData/codegen/boxWithJava/samAdapters")
|
||||||
|
@InnerTestClasses({SamAdapters.Operators.class})
|
||||||
public static class SamAdapters extends AbstractBlackBoxCodegenTest {
|
public static class SamAdapters extends AbstractBlackBoxCodegenTest {
|
||||||
public void testAllFilesPresentInSamAdapters() throws Exception {
|
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);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava/samAdapters"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
@@ -225,6 +226,35 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/typeParameterOfOuterClass.kt");
|
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/typeParameterOfOuterClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxWithJava/samAdapters/operators")
|
||||||
|
public static class Operators extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInOperators() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava/samAdapters/operators"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("get.kt")
|
||||||
|
public void testGet() throws Exception {
|
||||||
|
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/operators/get.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multiGetSet.kt")
|
||||||
|
public void testMultiGetSet() throws Exception {
|
||||||
|
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/operators/multiGetSet.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("set.kt")
|
||||||
|
public void testSet() throws Exception {
|
||||||
|
doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/operators/set.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test innerSuite() {
|
||||||
|
TestSuite suite = new TestSuite("SamAdapters");
|
||||||
|
suite.addTestSuite(SamAdapters.class);
|
||||||
|
suite.addTestSuite(Operators.class);
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithJava/samWrappers")
|
@TestMetadata("compiler/testData/codegen/boxWithJava/samWrappers")
|
||||||
@@ -401,7 +431,7 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
suite.addTestSuite(Enum.class);
|
suite.addTestSuite(Enum.class);
|
||||||
suite.addTestSuite(Functions.class);
|
suite.addTestSuite(Functions.class);
|
||||||
suite.addTestSuite(Property.class);
|
suite.addTestSuite(Property.class);
|
||||||
suite.addTestSuite(SamAdapters.class);
|
suite.addTest(SamAdapters.innerSuite());
|
||||||
suite.addTestSuite(SamWrappers.class);
|
suite.addTestSuite(SamWrappers.class);
|
||||||
suite.addTestSuite(StaticFun.class);
|
suite.addTestSuite(StaticFun.class);
|
||||||
suite.addTest(Visibility.innerSuite());
|
suite.addTest(Visibility.innerSuite());
|
||||||
|
|||||||
Reference in New Issue
Block a user