Overloading operations via extension functions.
Also inline useless TranslationUtils#zeroLiteral. Eliminate dead code.
This commit is contained in:
@@ -103,4 +103,20 @@ public final class OperatorOverloadingTest extends SingleFileTranslationTest {
|
|||||||
public void testOverloadPlusAssignArrayList() throws Exception {
|
public void testOverloadPlusAssignArrayList() throws Exception {
|
||||||
checkFooBoxIsOk("overloadPlusAssignArrayList.kt");
|
checkFooBoxIsOk("overloadPlusAssignArrayList.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testOverloadPlusAssignViaExtensionFunction() throws Exception {
|
||||||
|
fooBoxTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverloadPlusViaExtensionFunction() throws Exception {
|
||||||
|
fooBoxTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverloadPlusAssignViaPlusExtensionFunction() throws Exception {
|
||||||
|
fooBoxTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverloadUnaryOperationsViaExtensionFunctions() throws Exception {
|
||||||
|
fooBoxTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
|||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isCompareTo;
|
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isCompareTo;
|
||||||
@@ -69,6 +68,6 @@ public final class CompareToTranslator extends AbstractTranslator {
|
|||||||
private JsExpression translate() {
|
private JsExpression translate() {
|
||||||
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(getOperationToken(expression));
|
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(getOperationToken(expression));
|
||||||
JsExpression methodCall = BinaryOperationTranslator.translateAsOverloadedCall(expression, context());
|
JsExpression methodCall = BinaryOperationTranslator.translateAsOverloadedCall(expression, context());
|
||||||
return new JsBinaryOperation(correspondingOperator, methodCall, TranslationUtils.zeroLiteral(context()));
|
return new JsBinaryOperation(correspondingOperator, methodCall, context().program().getNumberLiteral(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-12
@@ -17,14 +17,12 @@
|
|||||||
package org.jetbrains.k2js.translate.operation;
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
|
||||||
import com.google.dart.compiler.util.AstUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.k2js.translate.reference.CallBuilder;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
|
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodReferenceForOverloadedOperation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
@@ -33,17 +31,20 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression doTranslate(@NotNull JetBinaryExpression expression,
|
public static JsExpression doTranslate(@NotNull JetBinaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
return (new OverloadedAssignmentTranslator(expression, context)).translate();
|
return (new OverloadedAssignmentTranslator(expression, context)).translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsNameRef operationReference;
|
private final FunctionDescriptor operationDescriptor;
|
||||||
|
|
||||||
private OverloadedAssignmentTranslator(@NotNull JetBinaryExpression expression,
|
private OverloadedAssignmentTranslator(@NotNull JetBinaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(expression, context);
|
super(expression, context);
|
||||||
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
|
FunctionDescriptor functionDescriptor =
|
||||||
|
BindingUtils.getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
|
||||||
|
assert functionDescriptor != null : "";
|
||||||
|
this.operationDescriptor = functionDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -61,8 +62,10 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression overloadedMethodInvocation() {
|
private JsExpression overloadedMethodInvocation() {
|
||||||
setQualifier(operationReference, accessTranslator.translateAsGet());
|
return CallBuilder.build(context())
|
||||||
return AstUtil.newInvocation(operationReference, right);
|
.descriptor(operationDescriptor)
|
||||||
|
.receiver(accessTranslator.translateAsGet())
|
||||||
|
.args(right)
|
||||||
|
.translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-8
@@ -17,14 +17,13 @@
|
|||||||
package org.jetbrains.k2js.translate.operation;
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
|
||||||
import com.google.dart.compiler.util.AstUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
|
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.k2js.translate.reference.CallBuilder;
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodReferenceForOverloadedOperation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
@@ -32,20 +31,24 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodRefer
|
|||||||
public final class OverloadedIncrementTranslator extends IncrementTranslator {
|
public final class OverloadedIncrementTranslator extends IncrementTranslator {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsNameRef operationReference;
|
private final FunctionDescriptor operationDescriptor;
|
||||||
|
|
||||||
/*package*/ OverloadedIncrementTranslator(@NotNull JetUnaryExpression expression,
|
/*package*/ OverloadedIncrementTranslator(@NotNull JetUnaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(expression, context);
|
super(expression, context);
|
||||||
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
|
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
|
||||||
|
assert functionDescriptor != null : "Descriptor should not be null for overloaded increment expression.";
|
||||||
|
this.operationDescriptor = functionDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected JsExpression operationExpression(@NotNull JsExpression receiver) {
|
protected JsExpression operationExpression(@NotNull JsExpression receiver) {
|
||||||
setQualifier(operationReference, receiver);
|
return CallBuilder.build(context())
|
||||||
return AstUtil.newInvocation(operationReference);
|
.receiver(receiver)
|
||||||
|
.descriptor(operationDescriptor)
|
||||||
|
.translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,17 +84,6 @@ public final class TranslationUtils {
|
|||||||
return or(isNull, isUndefined);
|
return or(isNull, isUndefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsBinaryOperation nullCheck(@NotNull TranslationContext context,
|
|
||||||
@NotNull JsExpression expressionToCheck, boolean shouldBeNull) {
|
|
||||||
if (shouldBeNull) {
|
|
||||||
return isNullCheck(context, expressionToCheck);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return notNullCheck(context, expressionToCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
|
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
|
||||||
@NotNull List<? extends ValueArgument> jetArguments) {
|
@NotNull List<? extends ValueArgument> jetArguments) {
|
||||||
@@ -213,22 +202,6 @@ public final class TranslationUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsNameRef getMethodReferenceForOverloadedOperation(@NotNull TranslationContext context,
|
|
||||||
@NotNull JetOperationExpression expression) {
|
|
||||||
FunctionDescriptor overloadedOperationDescriptor = getFunctionDescriptorForOperationExpression
|
|
||||||
(context.bindingContext(), expression);
|
|
||||||
assert overloadedOperationDescriptor != null;
|
|
||||||
JsNameRef overloadedOperationReference = context.getNameForDescriptor(overloadedOperationDescriptor).makeRef();
|
|
||||||
assert overloadedOperationReference != null;
|
|
||||||
return overloadedOperationReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsNumberLiteral zeroLiteral(@NotNull TranslationContext context) {
|
|
||||||
return context.program().getNumberLiteral(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
|
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
@@ -240,10 +213,6 @@ public final class TranslationUtils {
|
|||||||
return getThisObject(context, expectedThisDescriptor);
|
return getThisObject(context, expectedThisDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNullLiteral(@NotNull TranslationContext context, @NotNull JsExpression expression) {
|
|
||||||
return expression.equals(context.program().getNullLiteral());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void defineModule(@NotNull TranslationContext context, @NotNull List<JsStatement> statements,
|
public static void defineModule(@NotNull TranslationContext context, @NotNull List<JsStatement> statements,
|
||||||
String moduleId) {
|
String moduleId) {
|
||||||
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
|
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun <T> ArrayList<T>.plusAssign(other: Collection<T>) {
|
||||||
|
addAll(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): Boolean {
|
||||||
|
var v1 = ArrayList<String>()
|
||||||
|
val v2 = ArrayList<String>()
|
||||||
|
v1.add("foo")
|
||||||
|
v2.add("bar")
|
||||||
|
v1 += v2
|
||||||
|
return (v1.size() == 2 && v1[0] == "foo" && v1[1] == "bar")
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun <T> ArrayList<T>.plus(other: Collection<T>): List<T> {
|
||||||
|
val c = ArrayList<T>()
|
||||||
|
c.addAll(this)
|
||||||
|
c.addAll(other)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): Boolean {
|
||||||
|
var v1 = ArrayList<String>()
|
||||||
|
val v2 = ArrayList<String>()
|
||||||
|
v1.add("foo")
|
||||||
|
v2.add("bar")
|
||||||
|
v1 += v2
|
||||||
|
return (v1.size() == 2 && v1[0] == "foo" && v1[1] == "bar")
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun <T> ArrayList<T>.plus(other: Collection<T>): List<T> {
|
||||||
|
val c = ArrayList<T>()
|
||||||
|
c.addAll(this)
|
||||||
|
c.addAll(other)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): Boolean {
|
||||||
|
var v1 = ArrayList<String>()
|
||||||
|
v1.add("foo")
|
||||||
|
val v2 = ArrayList<String>()
|
||||||
|
v2.add("bar")
|
||||||
|
val v = v1 + v2
|
||||||
|
|
||||||
|
return (v.size() == 2 && v[0] == "foo" && v[1] == "bar")
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A(val c: Int) {}
|
||||||
|
|
||||||
|
|
||||||
|
fun A.inc() = A(5)
|
||||||
|
fun A.dec() = A(10)
|
||||||
|
|
||||||
|
fun box(): Boolean {
|
||||||
|
var a = A(1)
|
||||||
|
return ((++a).c == 5 && (a++).c == 5 && (--a).c == 10 && (a--).c == 10)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user