diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index bd025258beb..702875665e8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.codegen.binding; import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,6 +54,9 @@ import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; class CodegenAnnotatingVisitor extends JetVisitorVoid { + private static final TokenSet BINARY_OPERATIONS = + TokenSet.create(JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE); + private final Map anonymousSubclassesCount = new HashMap(); private final Stack classStack = new Stack(); @@ -383,6 +387,34 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { } } + @Override + public void visitBinaryExpression(JetBinaryExpression expression) { + super.visitBinaryExpression(expression); + + FunctionDescriptor operationDescriptor = + (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); + if (operationDescriptor == null) { + return; + } + + FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(bindingContext, operationDescriptor); + if (original == null) { + return; + } + + + ClassDescriptorFromJvmBytecode samInterfaceOfRight = getInterfaceIfSamType(original.getValueParameters().get(0).getType()); + + if (samInterfaceOfRight == null) { + return; + } + + if (BINARY_OPERATIONS.contains(expression.getOperationToken())) { + bindingTrace.record(CodegenBinding.SAM_VALUE, expression.getRight(), samInterfaceOfRight); + } + + } + @Override public void visitArrayAccessExpression(JetArrayAccessExpression expression) { super.visitArrayAccessExpression(expression); diff --git a/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.java b/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.java new file mode 100644 index 00000000000..c15741b0dba --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.java @@ -0,0 +1,31 @@ +class JavaClass { + JavaClass plus(Runnable i) { + i.run(); + return this; + } + + JavaClass minus(Runnable i) { + i.run(); + return this; + } + + JavaClass times(Runnable i) { + i.run(); + return this; + } + + JavaClass div(Runnable i) { + i.run(); + return this; + } + + JavaClass mod(Runnable i) { + i.run(); + return this; + } + + JavaClass rangeTo(Runnable i) { + i.run(); + return this; + } +} diff --git a/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.kt b/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.kt new file mode 100644 index 00000000000..3840de1fd48 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.kt @@ -0,0 +1,29 @@ +fun box(): String { + val obj = JavaClass() + + var v1 = "FAIL" + obj + { v1 = "OK" } + if (v1 != "OK") return "plus: $v1" + + var v2 = "FAIL" + obj - { v2 = "OK" } + if (v2 != "OK") return "minus: $v2" + + var v3 = "FAIL" + obj * { v3 = "OK" } + if (v3 != "OK") return "times: $v3" + + var v4 = "FAIL" + obj / { v4 = "OK" } + if (v4 != "OK") return "div: $v4" + + var v5 = "FAIL" + obj % { v5 = "OK" } + if (v5 != "OK") return "mod: $v5" + + var v6 = "FAIL" + obj .. { v6 = "OK" } + if (v6 != "OK") return "rangeTo: $v6" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index e58f94bc8cb..d5db3611429 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -232,6 +232,11 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava/samAdapters/operators"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("binary.kt") + public void testBinary() throws Exception { + doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/operators/binary.kt"); + } + @TestMetadata("get.kt") public void testGet() throws Exception { doTestWithJava("compiler/testData/codegen/boxWithJava/samAdapters/operators/get.kt");